Mercurial > hg > orthanc
changeset 0:3959d33612cc
initial commit
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AUTHORS Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,18 @@ +Palantir - A Lightweight, RESTful DICOM Server +============================================== + + +Authors of Palantir +------------------- + +* Sebastien Jodogne <s.jodogne@gmail.com> + Department of Medical Physics, CHU of Liege, Belgium + + Overall design and main developper. + + + +Contributors +------------ + +See the file "THANKS" for the occasional contributors.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMakeLists.txt Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,170 @@ +cmake_minimum_required(VERSION 2.8) + +project(Palantir) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/AutoGeneratedCode.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/DownloadPackage.cmake) +include(CheckIncludeFiles) + +SET(STATIC_BUILD ON CACHE BOOL "Static build of the third-party libraries (necessary for Windows)") +SET(RELEASE_BUILD OFF CACHE BOOL "Release build") + +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 ("${HAVE_UUID_H}" STREQUAL "") + message(FATAL_ERROR "Please install the uuid-dev package") +endif() + + +SET(THIRD_PARTY_SOURCES) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/BoostConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/DcmtkConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/GoogleTestConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/MongooseConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/ZlibConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/SQLiteConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/JsonCppConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/LibCurlConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/LibPngConfiguration.cmake) + + +if (${CMAKE_COMPILER_IS_GNUCXX}) + set(CMAKE_C_FLAGS "-Wall -pedantic -Wno-implicit-function-declaration") # --std=c99 makes libcurl not to compile + set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wno-long-long -Wno-variadic-macros") +elseif (${MSVC}) + add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) +endif() + + +if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + add_definitions( + -D_LARGEFILE64_SOURCE=1 + -D_FILE_OFFSET_BITS=64 + ) + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--no-undefined") + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") + + # http://www.mail-archive.com/cmake@cmake.org/msg08837.html + set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + link_libraries(uuid pthread rt) + +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + add_definitions( + -DWINVER=0x0501 + -D_CRT_SECURE_NO_WARNINGS=1 + ) + link_libraries(rpcrt4 ws2_32) +endif() + + +if (${STATIC_BUILD}) + add_definitions(-DPALANTIR_STATIC=1) +else() + add_definitions(-DPALANTIR_STATIC=0) +endif() + +if (${RELEASE_BUILD}) + add_definitions( + -DPALANTIR_RELEASE=1 + ) + + EmbedResources( + PREPARE_DATABASE PalantirServer/PrepareDatabase.sql + PALANTIR_EXPLORER PalantirExplorer + ) + +else() + add_definitions( + -DPALANTIR_RELEASE=0 + -DPALANTIR_PATH=\"${CMAKE_SOURCE_DIR}\" + ) + + EmbedResources( + PREPARE_DATABASE PalantirServer/PrepareDatabase.sql + ) +endif() + + +add_library(CoreLibrary + STATIC + ${AUTOGENERATED_SOURCES} + ${THIRD_PARTY_SOURCES} + + Core/ChunkedBuffer.cpp + Core/Compression/BufferCompressor.cpp + Core/Compression/ZlibCompressor.cpp + Core/PalantirException.cpp + Core/DicomFormat/DicomArray.cpp + Core/DicomFormat/DicomMap.cpp + Core/DicomFormat/DicomTag.cpp + Core/FileStorage.cpp + Core/HttpServer/EmbeddedResourceHttpHandler.cpp + Core/HttpServer/FilesystemHttpHandler.cpp + Core/HttpServer/HttpHandler.cpp + Core/HttpServer/HttpOutput.cpp + Core/HttpServer/MongooseServer.cpp + Core/MultiThreading/BagOfRunnablesBySteps.cpp + Core/PngWriter.cpp + Core/SQLite/Connection.cpp + Core/SQLite/FunctionContext.cpp + Core/SQLite/Statement.cpp + Core/SQLite/StatementId.cpp + Core/SQLite/StatementReference.cpp + Core/SQLite/Transaction.cpp + Core/Toolbox.cpp + Core/Uuid.cpp + + PalantirCppClient/HttpClient.cpp + PalantirCppClient/HttpException.cpp + ) + +add_library(ServerLibrary + PalantirServer/DicomIntegerPixelAccessor.cpp + PalantirServer/DicomProtocol/DicomFindAnswers.cpp + PalantirServer/DicomProtocol/DicomServer.cpp + PalantirServer/DicomProtocol/DicomUserConnection.cpp + PalantirServer/FromDcmtkBridge.cpp + PalantirServer/Internals/CommandDispatcher.cpp + PalantirServer/Internals/FindScp.cpp + PalantirServer/Internals/MoveScp.cpp + PalantirServer/Internals/StoreScp.cpp + PalantirServer/PalantirInitialization.cpp + PalantirServer/PalantirRestApi.cpp + PalantirServer/ServerIndex.cpp + PalantirServer/ToDcmtkBridge.cpp + PalantirServer/ToDcmtkBridge.cpp + PalantirServer/DicomIntegerPixelAccessor.cpp + ) + +add_executable(Palantir + PalantirServer/main.cpp + ) + +add_executable(UnitTests + ${GTEST_SOURCES} + UnitTests/main.cpp + UnitTests/SQLite.cpp + UnitTests/SQLiteChromium.cpp + UnitTests/Versions.cpp + ) + +TARGET_LINK_LIBRARIES(Palantir ServerLibrary CoreLibrary) +TARGET_LINK_LIBRARIES(UnitTests ServerLibrary CoreLibrary) + + +find_package(Doxygen) +if (DOXYGEN_FOUND) + configure_file( + ${CMAKE_SOURCE_DIR}/Resources/Palantir.doxygen + ${CMAKE_CURRENT_BINARY_DIR}/Palantir.doxygen + @ONLY) + add_custom_target(doc + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Palantir.doxygen + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM + ) +endif(DOXYGEN_FOUND)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/ChunkedBuffer.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,77 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "ChunkedBuffer.h" + +#include <cassert> +#include <string.h> + + +namespace Palantir +{ + void ChunkedBuffer::Clear() + { + numBytes_ = 0; + + for (Chunks::iterator it = chunks_.begin(); + it != chunks_.end(); it++) + { + delete *it; + } + } + + + void ChunkedBuffer::AddChunk(const char* chunkData, + size_t chunkSize) + { + if (chunkSize == 0) + { + return; + } + + assert(chunkData != NULL); + chunks_.push_back(new std::string(chunkData, chunkSize)); + numBytes_ += chunkSize; + } + + + void ChunkedBuffer::Flatten(std::string& result) + { + result.resize(numBytes_); + + size_t pos = 0; + for (Chunks::iterator it = chunks_.begin(); + it != chunks_.end(); it++) + { + assert(*it != NULL); + + size_t s = (*it)->size(); + if (s != 0) + { + memcpy(&result[pos], (*it)->c_str(), s); + pos += s; + } + + delete *it; + } + + chunks_.clear(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/ChunkedBuffer.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,57 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <list> +#include <string> + +namespace Palantir +{ + class ChunkedBuffer + { + private: + typedef std::list<std::string*> Chunks; + size_t numBytes_; + Chunks chunks_; + + void Clear(); + + public: + ChunkedBuffer() : numBytes_(0) + { + } + + ~ChunkedBuffer() + { + Clear(); + } + + size_t GetNumBytes() const + { + return numBytes_; + } + + void AddChunk(const char* chunkData, + size_t chunkSize); + + void Flatten(std::string& result); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Compression/BufferCompressor.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,60 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "BufferCompressor.h" + +namespace Palantir +{ + void BufferCompressor::Compress(std::string& output, + const std::vector<uint8_t>& input) + { + if (input.size() > 0) + Compress(output, &input[0], input.size()); + else + Compress(output, NULL, 0); + } + + void BufferCompressor::Uncompress(std::string& output, + const std::vector<uint8_t>& input) + { + if (input.size() > 0) + Uncompress(output, &input[0], input.size()); + else + Uncompress(output, NULL, 0); + } + + void BufferCompressor::Compress(std::string& output, + const std::string& input) + { + if (input.size() > 0) + Compress(output, &input[0], input.size()); + else + Compress(output, NULL, 0); + } + + void BufferCompressor::Uncompress(std::string& output, + const std::string& input) + { + if (input.size() > 0) + Uncompress(output, &input[0], input.size()); + else + Uncompress(output, NULL, 0); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Compression/BufferCompressor.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,57 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> +#include <cstddef> +#include <stdint.h> +#include <vector> + +namespace Palantir +{ + class BufferCompressor + { + public: + virtual ~BufferCompressor() + { + } + + virtual void Compress(std::string& compressed, + const void* uncompressed, + size_t uncompressedSize) = 0; + + virtual void Uncompress(std::string& uncompressed, + const void* compressed, + size_t compressedSize) = 0; + + virtual void Compress(std::string& compressed, + const std::vector<uint8_t>& uncompressed); + + virtual void Uncompress(std::string& uncompressed, + const std::vector<uint8_t>& compressed); + + virtual void Compress(std::string& compressed, + const std::string& uncompressed); + + virtual void Uncompress(std::string& uncompressed, + const std::string& compressed); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Compression/ZlibCompressor.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,125 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "ZlibCompressor.h" + +#include <stdio.h> +#include <string.h> +#include <zlib.h> +#include "../PalantirException.h" + +namespace Palantir +{ + void ZlibCompressor::SetCompressionLevel(uint8_t level) + { + if (level >= 10) + { + throw PalantirException("Zlib compression level must be between 0 (no compression) and 9 (highest compression"); + } + } + + + void ZlibCompressor::Compress(std::string& compressed, + const void* uncompressed, + size_t uncompressedSize) + { + if (uncompressedSize == 0) + { + compressed.clear(); + return; + } + + uLongf compressedSize = compressBound(uncompressedSize); + compressed.resize(compressedSize + sizeof(size_t)); + + int error = compress2 + (reinterpret_cast<uint8_t*>(&compressed[0]) + sizeof(size_t), + &compressedSize, + const_cast<Bytef *>(static_cast<const Bytef *>(uncompressed)), + uncompressedSize, + compressionLevel_); + + memcpy(&compressed[0], &uncompressedSize, sizeof(size_t)); + + if (error == Z_OK) + { + compressed.resize(compressedSize + sizeof(size_t)); + return; + } + else + { + compressed.clear(); + + switch (error) + { + case Z_MEM_ERROR: + throw PalantirException(ErrorCode_NotEnoughMemory); + + default: + throw PalantirException(ErrorCode_InternalError); + } + } + } + + + void ZlibCompressor::Uncompress(std::string& uncompressed, + const void* compressed, + size_t compressedSize) + { + if (compressedSize == 0) + { + uncompressed.clear(); + return; + } + + if (compressedSize < sizeof(size_t)) + { + throw PalantirException("Zlib: The compressed buffer is ill-formed"); + } + + size_t uncompressedLength; + memcpy(&uncompressedLength, compressed, sizeof(size_t)); + uncompressed.resize(uncompressedLength); + + uLongf tmp = uncompressedLength; + int error = uncompress + (reinterpret_cast<uint8_t*>(&uncompressed[0]), + &tmp, + reinterpret_cast<const uint8_t*>(compressed) + sizeof(size_t), + compressedSize - sizeof(size_t)); + + if (error != Z_OK) + { + uncompressed.clear(); + + switch (error) + { + case Z_DATA_ERROR: + throw PalantirException("Zlib: Corrupted or incomplete compressed buffer"); + + case Z_MEM_ERROR: + throw PalantirException(ErrorCode_NotEnoughMemory); + + default: + throw PalantirException(ErrorCode_InternalError); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Compression/ZlibCompressor.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,56 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "BufferCompressor.h" + +namespace Palantir +{ + class ZlibCompressor : public BufferCompressor + { + private: + uint8_t compressionLevel_; + + public: + using BufferCompressor::Compress; + using BufferCompressor::Uncompress; + + ZlibCompressor() + { + compressionLevel_ = 6; + } + + void SetCompressionLevel(uint8_t level); + + uint8_t GetCompressionLevel() const + { + return compressionLevel_; + } + + virtual void Compress(std::string& compressed, + const void* uncompressed, + size_t uncompressedSize); + + virtual void Uncompress(std::string& uncompressed, + const void* compressed, + size_t compressedSize); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomArray.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,57 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomArray.h" + +#include <stdio.h> + +namespace Palantir +{ + DicomArray::DicomArray(const DicomMap& map) + { + elements_.reserve(map.map_.size()); + + for (DicomMap::Map::const_iterator it = + map.map_.begin(); it != map.map_.end(); it++) + { + elements_.push_back(new DicomElement(it->first, *it->second)); + } + } + + + DicomArray::~DicomArray() + { + for (size_t i = 0; i < elements_.size(); i++) + { + delete elements_[i]; + } + } + + + void DicomArray::Print(FILE* fp) const + { + for (size_t i = 0; i < elements_.size(); i++) + { + DicomTag t = elements_[i]->GetTag(); + std::string s = elements_[i]->GetValue().AsString(); + printf("0x%04x 0x%04x [%s]\n", t.GetGroup(), t.GetElement(), s.c_str()); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomArray.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,54 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomElement.h" +#include "DicomMap.h" + +#include <vector> + +namespace Palantir +{ + class DicomArray : public boost::noncopyable + { + private: + typedef std::vector<DicomElement*> Elements; + + Elements elements_; + + public: + DicomArray(const DicomMap& map); + + ~DicomArray(); + + size_t GetSize() const + { + return elements_.size(); + } + + const DicomElement& GetElement(size_t i) const + { + return *elements_[i]; + } + + void Print(FILE* fp) const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomElement.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,80 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomValue.h" +#include "DicomTag.h" + +namespace Palantir +{ + class DicomElement : public boost::noncopyable + { + private: + DicomTag tag_; + DicomValue* value_; + + public: + DicomElement(uint16_t group, + uint16_t element, + const DicomValue& value) : + tag_(group, element), + value_(value.Clone()) + { + } + + DicomElement(const DicomTag& tag, + const DicomValue& value) : + tag_(tag), + value_(value.Clone()) + { + } + + ~DicomElement() + { + delete value_; + } + + const DicomTag& GetTag() const + { + return tag_; + } + + const DicomValue& GetValue() const + { + return *value_; + } + + uint16_t GetTagGroup() const + { + return tag_.GetGroup(); + } + + uint16_t GetTagElement() const + { + return tag_.GetElement(); + } + + bool operator< (const DicomElement& other) const + { + return GetTag() < other.GetTag(); + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomMap.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,248 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomMap.h" + +#include <stdio.h> +#include <memory> +#include "DicomString.h" +#include "../PalantirException.h" + + +namespace Palantir +{ + static DicomTag patientTags[] = + { + DicomTag(0x0008, 0x0050), // AccessionNumber + DicomTag(0x0010, 0x0010), // PatientName + DicomTag(0x0010, 0x0020), // PatientID + DicomTag(0x0010, 0x0030), // PatientBirthDate + DicomTag(0x0010, 0x0040), // PatientSex + DicomTag(0x0010, 0x1000), // OtherPatientIDs + DicomTag(0x0010, 0x1010), // PatientAge + DicomTag(0x0010, 0x1040) // PatientAddress + }; + + static DicomTag studyTags[] = + { + DicomTag(0x0008, 0x0020), // StudyDate + DicomTag(0x0008, 0x0030), // StudyTime + DicomTag(0x0008, 0x1030), // StudyDescription + DicomTag(0x0020, 0x000d), // StudyInstanceUID + DicomTag(0x0020, 0x0010), // StudyID + DicomTag(0x0010, 0x1020), // PatientSize + DicomTag(0x0010, 0x1030) // PatientWeight + }; + + static DicomTag seriesTags[] = + { + DicomTag(0x0008, 0x0021), // SeriesDate + DicomTag(0x0008, 0x0031), // SeriesTime + DicomTag(0x0008, 0x0060), // Modality + DicomTag(0x0008, 0x0070), // Manufacturer + DicomTag(0x0008, 0x1010), // StationName + DicomTag(0x0008, 0x103e), // SeriesDescription + DicomTag(0x0010, 0x1080), // MilitaryRank + DicomTag(0x0018, 0x0024), // SequenceName + DicomTag(0x0018, 0x1030), // ProtocolName + DicomTag(0x0020, 0x000e), // SeriesInstanceUID + DicomTag(0x0020, 0x0011), // SeriesNumber + DicomTag(0x0054, 0x0081) // NumberOfSlices + }; + + static DicomTag instanceTags[] = + { + DicomTag(0x0008, 0x0012), // InstanceCreationDate + DicomTag(0x0008, 0x0013), // InstanceCreationTime + DicomTag(0x0008, 0x0018), // SOPInstanceUID + DicomTag(0x0020, 0x0012), // AcquisitionNumber + DicomTag(0x0020, 0x0013), // InstanceNumber + DicomTag(0x0054, 0x1330) // ImageIndex + }; + + + + + void DicomMap::SetValue(uint16_t group, + uint16_t element, + DicomValue* value) + { + DicomTag tag(group, element); + Map::iterator it = map_.find(tag); + + if (it != map_.end()) + { + delete it->second; + it->second = value; + } + else + { + map_.insert(std::make_pair(tag, value)); + } + } + + void DicomMap::SetValue(DicomTag tag, + DicomValue* value) + { + SetValue(tag.GetGroup(), tag.GetElement(), value); + } + + + + + void DicomMap::Clear() + { + for (Map::iterator it = map_.begin(); it != map_.end(); it++) + { + delete it->second; + } + + map_.clear(); + } + + + void DicomMap::ExtractTags(DicomMap& result, + const DicomTag* tags, + size_t count) const + { + result.Clear(); + + for (unsigned int i = 0; i < count; i++) + { + Map::const_iterator it = map_.find(tags[i]); + if (it != map_.end()) + { + result.SetValue(it->first, it->second->Clone()); + } + } + } + + + void DicomMap::ExtractPatientInformation(DicomMap& result) const + { + ExtractTags(result, patientTags, sizeof(patientTags) / sizeof(DicomTag)); + } + + void DicomMap::ExtractStudyInformation(DicomMap& result) const + { + ExtractTags(result, studyTags, sizeof(studyTags) / sizeof(DicomTag)); + } + + void DicomMap::ExtractSeriesInformation(DicomMap& result) const + { + ExtractTags(result, seriesTags, sizeof(seriesTags) / sizeof(DicomTag)); + } + + void DicomMap::ExtractInstanceInformation(DicomMap& result) const + { + ExtractTags(result, instanceTags, sizeof(instanceTags) / sizeof(DicomTag)); + } + + + DicomMap* DicomMap::Clone() const + { + std::auto_ptr<DicomMap> result(new DicomMap); + + for (Map::const_iterator it = map_.begin(); it != map_.end(); it++) + { + result->map_.insert(std::make_pair(it->first, it->second->Clone())); + } + + return result.release(); + } + + + const DicomValue& DicomMap::GetValue(const DicomTag& tag) const + { + Map::const_iterator it = map_.find(tag); + + if (it == map_.end()) + { + throw PalantirException("Inexistent tag"); + } + else + { + return *it->second; + } + } + + + void DicomMap::Remove(const DicomTag& tag) + { + Map::iterator it = map_.find(tag); + if (it != map_.end()) + { + delete it->second; + map_.erase(it); + } + } + + + static void SetupFindTemplate(DicomMap& result, + const DicomTag* tags, + size_t count) + { + result.Clear(); + + for (size_t i = 0; i < count; i++) + { + result.SetValue(tags[i], ""); + } + } + + void DicomMap::SetupFindPatientTemplate(DicomMap& result) + { + SetupFindTemplate(result, patientTags, sizeof(patientTags) / sizeof(DicomTag)); + } + + void DicomMap::SetupFindStudyTemplate(DicomMap& result) + { + SetupFindTemplate(result, studyTags, sizeof(studyTags) / sizeof(DicomTag)); + result.SetValue(DicomTag::ACCESSION_NUMBER, ""); + result.SetValue(DicomTag::PATIENT_ID, ""); + } + + void DicomMap::SetupFindSeriesTemplate(DicomMap& result) + { + SetupFindTemplate(result, seriesTags, sizeof(seriesTags) / sizeof(DicomTag)); + result.SetValue(DicomTag::ACCESSION_NUMBER, ""); + result.SetValue(DicomTag::PATIENT_ID, ""); + result.SetValue(DicomTag::STUDY_UID, ""); + } + + void DicomMap::SetupFindInstanceTemplate(DicomMap& result) + { + SetupFindTemplate(result, instanceTags, sizeof(instanceTags) / sizeof(DicomTag)); + result.SetValue(DicomTag::ACCESSION_NUMBER, ""); + result.SetValue(DicomTag::PATIENT_ID, ""); + result.SetValue(DicomTag::STUDY_UID, ""); + result.SetValue(DicomTag::SERIES_UID, ""); + } + + + void DicomMap::CopyTagIfExists(const DicomMap& source, + const DicomTag& tag) + { + if (source.HasTag(tag)) + { + SetValue(tag, source.GetValue(tag)); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomMap.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,133 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomTag.h" +#include "DicomValue.h" +#include "DicomString.h" + +#include <map> +#include <json/json.h> + +namespace Palantir +{ + class DicomMap : public boost::noncopyable + { + private: + friend class DicomArray; + friend class FromDcmtkBridge; + friend class ToDcmtkBridge; + + typedef std::map<DicomTag, DicomValue*> Map; + + Map map_; + + // Warning: This takes the ownership of "value" + void SetValue(uint16_t group, + uint16_t element, + DicomValue* value); + + void SetValue(DicomTag tag, + DicomValue* value); + + void ExtractTags(DicomMap& source, + const DicomTag* tags, + size_t count) const; + + public: + DicomMap() + { + } + + ~DicomMap() + { + Clear(); + } + + DicomMap* Clone() const; + + void Clear(); + + void SetValue(uint16_t group, + uint16_t element, + const DicomValue& value) + { + SetValue(group, element, value.Clone()); + } + + void SetValue(const DicomTag& tag, + const DicomValue& value) + { + SetValue(tag, value.Clone()); + } + + void SetValue(const DicomTag& tag, + const std::string& str) + { + SetValue(tag, new DicomString(str)); + } + + void SetValue(uint16_t group, + uint16_t element, + const std::string& str) + { + SetValue(group, element, new DicomString(str)); + } + + bool HasTag(uint16_t group, uint16_t element) const + { + return HasTag(DicomTag(group, element)); + } + + bool HasTag(const DicomTag& tag) const + { + return map_.find(tag) != map_.end(); + } + + const DicomValue& GetValue(uint16_t group, uint16_t element) const + { + return GetValue(DicomTag(group, element)); + } + + const DicomValue& GetValue(const DicomTag& tag) const; + + void Remove(const DicomTag& tag); + + void ExtractPatientInformation(DicomMap& result) const; + + void ExtractStudyInformation(DicomMap& result) const; + + void ExtractSeriesInformation(DicomMap& result) const; + + void ExtractInstanceInformation(DicomMap& result) const; + + static void SetupFindPatientTemplate(DicomMap& result); + + static void SetupFindStudyTemplate(DicomMap& result); + + static void SetupFindSeriesTemplate(DicomMap& result); + + static void SetupFindInstanceTemplate(DicomMap& result); + + void CopyTagIfExists(const DicomMap& source, + const DicomTag& tag); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomNullValue.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,49 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomValue.h" + +namespace Palantir +{ + class DicomNullValue : public DicomValue + { + public: + DicomNullValue() + { + } + + virtual DicomValue* Clone() const + { + return new DicomNullValue(); + } + + virtual std::string AsString() const + { + return "(null)"; + } + + virtual bool IsNull() const + { + return true; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomString.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,55 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomValue.h" + +namespace Palantir +{ + class DicomString : public DicomValue + { + private: + std::string value_; + + public: + DicomString(const std::string& v) : value_(v) + { + } + + DicomString(const char* v) + { + if (v) + value_ = v; + else + value_ = ""; + } + + virtual DicomValue* Clone() const + { + return new DicomString(value_); + } + + virtual std::string AsString() const + { + return value_; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomTag.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,62 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomTag.h" + +#include "../PalantirException.h" + +#include <iostream> +#include <iomanip> + +namespace Palantir +{ + bool DicomTag::operator< (const DicomTag& other) const + { + if (group_ < other.group_) + return true; + + if (group_ > other.group_) + return false; + + return element_ < other.element_; + } + + + std::ostream& operator<< (std::ostream& o, const DicomTag& tag) + { + using namespace std; + ios_base::fmtflags state = o.flags(); + o.flags(ios::right | ios::hex); + o << "(" << setfill('0') << setw(4) << tag.GetGroup() + << "," << setw(4) << tag.GetElement() << ")"; + o.flags(state); + return o; + } + + + const DicomTag DicomTag::ACCESSION_NUMBER = DicomTag(0x0008, 0x0050); + const DicomTag DicomTag::IMAGE_INDEX = DicomTag(0x0054, 0x1330); + const DicomTag DicomTag::INSTANCE_UID = DicomTag(0x0008, 0x0018); + const DicomTag DicomTag::NUMBER_OF_SLICES = DicomTag(0x0054, 0x0081); + const DicomTag DicomTag::PATIENT_ID = DicomTag(0x0010, 0x0020); + const DicomTag DicomTag::SERIES_UID = DicomTag(0x0020, 0x000e); + const DicomTag DicomTag::STUDY_UID = DicomTag(0x0020, 0x000d); + const DicomTag DicomTag::PIXEL_DATA = DicomTag(0x7fe0, 0x0010); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomTag.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,69 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> +#include <stdint.h> + + +namespace Palantir +{ + class DicomTag + { + // This must stay a POD (plain old data structure) + + private: + uint16_t group_; + uint16_t element_; + + public: + DicomTag(uint16_t group, + uint16_t element) : + group_(group), + element_(element) + { + } + + uint16_t GetGroup() const + { + return group_; + } + + uint16_t GetElement() const + { + return element_; + } + + bool operator< (const DicomTag& other) const; + + friend std::ostream& operator<< (std::ostream& o, const DicomTag& tag); + + // Alias for the most useful tags + static const DicomTag ACCESSION_NUMBER; + static const DicomTag IMAGE_INDEX; + static const DicomTag INSTANCE_UID; + static const DicomTag NUMBER_OF_SLICES; + static const DicomTag PATIENT_ID; + static const DicomTag SERIES_UID; + static const DicomTag STUDY_UID; + static const DicomTag PIXEL_DATA; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/DicomFormat/DicomValue.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,44 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <boost/noncopyable.hpp> +#include <string> + +namespace Palantir +{ + class DicomValue : public boost::noncopyable + { + public: + virtual ~DicomValue() + { + } + + virtual DicomValue* Clone() const = 0; + + virtual std::string AsString() const = 0; + + virtual bool IsNull() const + { + return false; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Enumerations.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,51 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../PalantirCppClient/HttpEnumerations.h" + +namespace Palantir +{ + enum ErrorCode + { + // Generic error codes + ErrorCode_Success, + ErrorCode_Custom, + ErrorCode_InternalError, + ErrorCode_NotImplemented, + ErrorCode_ParameterOutOfRange, + ErrorCode_NotEnoughMemory, + ErrorCode_BadParameterType, + + // Specific error codes + ErrorCode_UriSyntax, + ErrorCode_InexistentFile, + ErrorCode_CannotWriteFile, + ErrorCode_BadFileFormat + }; + + enum PixelFormat + { + PixelFormat_RGB, + PixelFormat_Grayscale8, + PixelFormat_Grayscale16 + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileStorage.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,274 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "FileStorage.h" + +// http://stackoverflow.com/questions/1576272/storing-large-number-of-files-in-file-system +// http://stackoverflow.com/questions/446358/storing-a-large-number-of-images + +#include "PalantirException.h" +#include "Toolbox.h" +#include "Uuid.h" + +#include <boost/filesystem/fstream.hpp> + +namespace Palantir +{ + boost::filesystem::path FileStorage::GetPath(const std::string& uuid) const + { + namespace fs = boost::filesystem; + + if (!Toolbox::IsUuid(uuid)) + { + throw PalantirException(ErrorCode_ParameterOutOfRange); + } + + fs::path path = root_; + + path /= std::string(&uuid[0], &uuid[2]); + path /= std::string(&uuid[2], &uuid[4]); + path /= uuid; + path.make_preferred(); + + return path; + } + + FileStorage::FileStorage(std::string root) + { + namespace fs = boost::filesystem; + + root_ = fs::absolute(root); + + if (fs::exists(root)) + { + if (!fs::is_directory(root)) + { + throw PalantirException("The file storage root directory is a file"); + } + } + else + { + if (!fs::create_directories(root)) + { + throw PalantirException("Unable to create the file storage root directory"); + } + } + } + + std::string FileStorage::CreateFileWithoutCompression(const void* content, size_t size) + { + std::string uuid; + boost::filesystem::path path; + + for (;;) + { + uuid = Toolbox::GenerateUuid(); + path = GetPath(uuid); + + if (!boost::filesystem::exists(path)) + { + // OK, this is indeed a new file + break; + } + + // Extremely improbable case: This Uuid has already been created + // in the past. Try again. + } + + if (boost::filesystem::exists(path.parent_path())) + { + if (!boost::filesystem::is_directory(path.parent_path())) + { + throw PalantirException("The subdirectory to be created is already occupied by a regular file"); + } + } + else + { + if (!boost::filesystem::create_directories(path.parent_path())) + { + throw PalantirException("Unable to create a subdirectory in the file storage"); + } + } + + boost::filesystem::ofstream f; + f.open(path, std::ofstream::out | std::ios::binary); + if (!f.good()) + { + throw PalantirException("Unable to create a new file in the file storage"); + } + + if (size != 0) + { + f.write(static_cast<const char*>(content), size); + if (!f.good()) + { + f.close(); + throw PalantirException("Unable to write to the new file in the file storage"); + } + } + + f.close(); + + return uuid; + } + + + std::string FileStorage::Create(const void* content, size_t size) + { + if (!HasBufferCompressor() || size == 0) + { + return CreateFileWithoutCompression(content, size); + } + else + { + std::string compressed; + compressor_->Compress(compressed, content, size); + assert(compressed.size() > 0); + return CreateFileWithoutCompression(&compressed[0], compressed.size()); + } + } + + + std::string FileStorage::Create(const std::vector<uint8_t>& content) + { + if (content.size() == 0) + return Create(NULL, 0); + else + return Create(&content[0], content.size()); + } + + std::string FileStorage::Create(const std::string& content) + { + if (content.size() == 0) + return Create(NULL, 0); + else + return Create(&content[0], content.size()); + } + + void FileStorage::ReadFile(std::string& content, + const std::string& uuid) const + { + content.clear(); + + if (HasBufferCompressor()) + { + std::string compressed; + Toolbox::ReadFile(compressed, GetPath(uuid).string()); + + if (compressed.size() != 0) + { + compressor_->Uncompress(content, compressed); + } + } + else + { + Toolbox::ReadFile(content, GetPath(uuid).string()); + } + } + + + uintmax_t FileStorage::GetCompressedSize(const std::string& uuid) const + { + boost::filesystem::path path = GetPath(uuid); + return boost::filesystem::file_size(path); + } + + + + void FileStorage::ListAllFiles(std::set<std::string>& result) const + { + namespace fs = boost::filesystem; + + result.clear(); + + if (fs::exists(root_) && fs::is_directory(root_)) + { + for (fs::recursive_directory_iterator current(root_), end; current != end ; ++current) + { + if (fs::is_regular_file(current->status())) + { + try + { + fs::path d = current->path(); + std::string uuid = d.filename().string(); + if (Toolbox::IsUuid(uuid)) + { + fs::path p0 = d.parent_path().parent_path().parent_path(); + std::string p1 = d.parent_path().parent_path().filename().string(); + std::string p2 = d.parent_path().filename().string(); + if (p1.length() == 2 && + p2.length() == 2 && + p1 == uuid.substr(0, 2) && + p2 == uuid.substr(2, 2) && + p0 == root_) + { + result.insert(uuid); + } + } + } + catch (fs::filesystem_error) + { + } + } + } + } + } + + + void FileStorage::Clear() + { + namespace fs = boost::filesystem; + typedef std::set<std::string> List; + + List result; + ListAllFiles(result); + + for (List::const_iterator it = result.begin(); it != result.end(); it++) + { + Remove(*it); + } + } + + + void FileStorage::Remove(const std::string& uuid) + { + namespace fs = boost::filesystem; + + fs::path p = GetPath(uuid); + fs::remove(p); + + // Remove the two parent directories, ignoring the error code if + // these directories are not empty + boost::system::error_code err; + fs::remove(p.parent_path(), err); + fs::remove(p.parent_path().parent_path(), err); + } + + + uintmax_t FileStorage::GetCapacity() const + { + return boost::filesystem::space(root_).capacity; + } + + uintmax_t FileStorage::GetAvailableSpace() const + { + return boost::filesystem::space(root_).available; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/FileStorage.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,82 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <boost/filesystem.hpp> +#include <set> + +#include "Compression/BufferCompressor.h" + +namespace Palantir +{ + class FileStorage : public boost::noncopyable + { + friend class HttpOutput; + + private: + std::auto_ptr<BufferCompressor> compressor_; + + boost::filesystem::path root_; + + boost::filesystem::path GetPath(const std::string& uuid) const; + + std::string CreateFileWithoutCompression(const void* content, size_t size); + + public: + FileStorage(std::string root); + + void SetBufferCompressor(BufferCompressor* compressor) // Takes the ownership + { + compressor_.reset(compressor); + } + + bool HasBufferCompressor() const + { + return compressor_.get() != NULL; + } + + std::string Create(const void* content, size_t size); + + std::string Create(const std::vector<uint8_t>& content); + + std::string Create(const std::string& content); + + void ReadFile(std::string& content, + const std::string& uuid) const; + + void ListAllFiles(std::set<std::string>& result) const; + + uintmax_t GetCompressedSize(const std::string& uuid) const; + + void Clear(); + + void Remove(const std::string& uuid); + + uintmax_t GetCapacity() const; + + uintmax_t GetAvailableSpace() const; + + std::string GetPath() const + { + return root_.string(); + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/EmbeddedResourceHttpHandler.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,73 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "EmbeddedResourceHttpHandler.h" + +#include "../PalantirException.h" + +#include <stdio.h> + + +namespace Palantir +{ + EmbeddedResourceHttpHandler::EmbeddedResourceHttpHandler( + const std::string& baseUri, + EmbeddedResources::DirectoryResourceId resourceId) + { + Toolbox::SplitUriComponents(baseUri_, baseUri); + resourceId_ = resourceId; + } + + + bool EmbeddedResourceHttpHandler::IsServedUri(const UriComponents& uri) + { + return Toolbox::IsChildUri(baseUri_, uri); + } + + + void EmbeddedResourceHttpHandler::Handle( + HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string&) + { + if (method != "GET") + { + output.SendMethodNotAllowedError("GET"); + return; + } + + std::string resourcePath = Toolbox::FlattenUri(uri, baseUri_.size()); + std::string contentType = Toolbox::AutodetectMimeType(resourcePath); + + try + { + const void* buffer = EmbeddedResources::GetDirectoryResourceBuffer(resourceId_, resourcePath.c_str()); + size_t size = EmbeddedResources::GetDirectoryResourceSize(resourceId_, resourcePath.c_str()); + output.AnswerBufferWithContentType(buffer, size, contentType); + } + catch (PalantirException& e) + { + output.SendHeader(HttpStatus_404_NotFound); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/EmbeddedResourceHttpHandler.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,51 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "HttpHandler.h" + +#include <EmbeddedResources.h> // Autogenerated file +#include <boost/shared_ptr.hpp> + +namespace Palantir +{ + class EmbeddedResourceHttpHandler : public HttpHandler + { + private: + UriComponents baseUri_; + EmbeddedResources::DirectoryResourceId resourceId_; + + public: + EmbeddedResourceHttpHandler( + const std::string& baseUri, + EmbeddedResources::DirectoryResourceId resourceId); + + virtual bool IsServedUri(const UriComponents& uri); + + virtual void Handle( + HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string&); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/FilesystemHttpHandler.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,142 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "FilesystemHttpHandler.h" + +#include "../PalantirException.h" + +#include <boost/filesystem.hpp> + + +namespace Palantir +{ + struct FilesystemHttpHandler::PImpl + { + UriComponents baseUri_; + boost::filesystem::path root_; + }; + + + + static void OutputDirectoryContent(HttpOutput& output, + const UriComponents& uri, + const boost::filesystem::path& p) + { + namespace fs = boost::filesystem; + + output.SendOkHeader("text/html"); + output.SendString("<html>"); + output.SendString(" <body>"); + output.SendString(" <h1>Subdirectories</h1>"); + output.SendString(" <ul>"); + + if (uri.size() > 0) + { + std::string h = Toolbox::FlattenUri(uri) + "/.."; + output.SendString("<li><a href=\"" + h + "\">..</a></li>"); + } + + fs::directory_iterator end; + for (fs::directory_iterator it(p) ; it != end; ++it) + { + std::string f = it->path().filename().string(); + std::string h = Toolbox::FlattenUri(uri) + "/" + f; + if (fs::is_directory(it->status())) + output.SendString("<li><a href=\"" + h + "\">" + f + "</a></li>"); + } + + output.SendString(" </ul>"); + output.SendString(" <h1>Files</h1>"); + output.SendString(" <ul>"); + + for (fs::directory_iterator it(p) ; it != end; ++it) + { + std::string f = it->path().filename().string(); + std::string h = Toolbox::FlattenUri(uri) + "/" + f; + if (fs::is_regular_file(it->status())) + output.SendString("<li><a href=\"" + h + "\">" + f + "</a></li>"); + } + + output.SendString(" </ul>"); + output.SendString(" </body>"); + output.SendString("</html>"); + } + + + FilesystemHttpHandler::FilesystemHttpHandler(const std::string& baseUri, + const std::string& root) : pimpl_(new PImpl) + { + Toolbox::SplitUriComponents(pimpl_->baseUri_, baseUri); + pimpl_->root_ = root; + listDirectoryContent_ = false; + + namespace fs = boost::filesystem; + if (!fs::exists(pimpl_->root_) || + !fs::is_directory(pimpl_->root_)) + { + throw PalantirException("The path does not point to a directory"); + } + } + + + bool FilesystemHttpHandler::IsServedUri(const UriComponents& uri) + { + return Toolbox::IsChildUri(pimpl_->baseUri_, uri); + } + + + void FilesystemHttpHandler::Handle( + HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string&) + { + if (method != "GET") + { + output.SendMethodNotAllowedError("GET"); + return; + } + + namespace fs = boost::filesystem; + + fs::path p = pimpl_->root_; + for (size_t i = pimpl_->baseUri_.size(); i < uri.size(); i++) + { + p /= uri[i]; + } + + if (fs::exists(p) && fs::is_regular_file(p)) + { + output.AnswerFileAutodetectContentType(p.string()); + } + else if (listDirectoryContent_ && + fs::exists(p) && + fs::is_directory(p)) + { + OutputDirectoryContent(output, uri, p); + } + else + { + output.SendHeader(HttpStatus_404_NotFound); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/FilesystemHttpHandler.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,63 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "HttpHandler.h" + +#include <boost/shared_ptr.hpp> + +namespace Palantir +{ + class FilesystemHttpHandler : public HttpHandler + { + private: + // PImpl idiom to avoid the inclusion of boost::filesystem + // throughout the software + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + bool listDirectoryContent_; + + public: + FilesystemHttpHandler(const std::string& baseUri, + const std::string& root); + + virtual bool IsServedUri(const UriComponents& uri); + + virtual void Handle( + HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string&); + + bool IsListDirectoryContent() const + { + return listDirectoryContent_; + } + + void SetListDirectoryContent(bool enabled) + { + listDirectoryContent_ = enabled; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/HttpHandler.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,81 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "HttpHandler.h" + +#include <string.h> + +namespace Palantir +{ + static void SplitGETNameValue(HttpHandler::Arguments& result, + const char* start, + const char* end) + { + const char* equal = strchr(start, '='); + if (equal == NULL || equal >= end) + { + result.insert(std::make_pair(std::string(start, end - start), "")); + } + else + { + result.insert(std::make_pair(std::string(start, equal - start), + std::string(equal + 1, end))); + } + } + + + void HttpHandler::ParseGetQuery(HttpHandler::Arguments& result, const char* query) + { + const char* pos = query; + + while (pos != NULL) + { + const char* ampersand = strchr(pos, '&'); + if (ampersand) + { + SplitGETNameValue(result, pos, ampersand); + pos = ampersand + 1; + } + else + { + // No more ampersand, this is the last argument + SplitGETNameValue(result, pos, pos + strlen(pos)); + pos = NULL; + } + } + } + + + + std::string HttpHandler::GetArgument(const Arguments& arguments, + const std::string& name, + const std::string& defaultValue) + { + Arguments::const_iterator it = arguments.find(name); + if (it == arguments.end()) + { + return defaultValue; + } + else + { + return it->second; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/HttpHandler.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,56 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <map> +#include <vector> +#include <stdint.h> +#include "HttpOutput.h" +#include "../Toolbox.h" + +namespace Palantir +{ + class HttpHandler + { + public: + typedef std::map<std::string, std::string> Arguments; + + virtual ~HttpHandler() + { + } + + virtual bool IsServedUri(const UriComponents& uri) = 0; + + virtual void Handle(HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string& postData) = 0; + + static void ParseGetQuery(HttpHandler::Arguments& result, + const char* query); + + static std::string GetArgument(const Arguments& arguments, + const std::string& name, + const std::string& defaultValue); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/HttpOutput.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,188 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "HttpOutput.h" + +#include <vector> +#include <stdio.h> +#include <boost/lexical_cast.hpp> +#include "../PalantirException.h" +#include "../Toolbox.h" +#include "../../PalantirCppClient/HttpException.h" + +namespace Palantir +{ + void HttpOutput::SendString(const std::string& s) + { + if (s.size() > 0) + Send(&s[0], s.size()); + } + + void HttpOutput::SendOkHeader(const std::string& contentType) + { + SendOkHeader(contentType.c_str(), false, 0); + } + + void HttpOutput::SendOkHeader() + { + SendOkHeader(NULL, false, 0); + } + + void HttpOutput::SendOkHeader(uint64_t contentLength) + { + SendOkHeader(NULL, true, contentLength); + } + + void HttpOutput::SendOkHeader(const std::string& contentType, + uint64_t contentLength) + { + SendOkHeader(contentType.c_str(), true, contentLength); + } + + + void HttpOutput::SendOkHeader(const char* contentType, + bool hasContentLength, + size_t contentLength) + { + std::string s = "HTTP/1.1 200 OK\r\n"; + + if (contentType) + { + s += "Content-Type: " + std::string(contentType) + "\r\n"; + } + + if (hasContentLength) + { + s += "Content-Length: " + boost::lexical_cast<std::string>(contentLength) + "\r\n"; + } + + s += "\r\n"; + + Send(&s[0], s.size()); + } + + + void HttpOutput::SendMethodNotAllowedError(const std::string& allowed) + { + std::string s = + "HTTP/1.1 405 " + std::string(HttpException::GetDescription(HttpStatus_405_MethodNotAllowed)) + + "\r\nAllow: " + allowed + + "\r\n\r\n"; + Send(&s[0], s.size()); + } + + + void HttpOutput::SendHeader(HttpStatus status) + { + if (status == HttpStatus_200_Ok || + status == HttpStatus_405_MethodNotAllowed) + { + throw PalantirException("Please use the dedicated methods to this HTTP status code in HttpOutput"); + } + + SendHeaderInternal(status); + } + + + void HttpOutput::SendHeaderInternal(HttpStatus status) + { + std::string s = "HTTP/1.1 " + + boost::lexical_cast<std::string>(status) + + " " + std::string(HttpException::GetDescription(status)) + + "\r\n\r\n"; + Send(&s[0], s.size()); + } + + + void HttpOutput::AnswerBufferWithContentType(const std::string& buffer, + const std::string& contentType) + { + SendOkHeader(contentType.c_str(), true, buffer.size()); + SendString(buffer); + } + + + void HttpOutput::AnswerBufferWithContentType(const void* buffer, + size_t size, + const std::string& contentType) + { + SendOkHeader(contentType.c_str(), true, size); + Send(buffer, size); + } + + + void HttpOutput::AnswerFileWithContentType(const std::string& path, + const std::string& contentType) + { + uint64_t fileSize = Toolbox::GetFileSize(path); + + FILE* fp = fopen(path.c_str(), "rb"); + if (!fp) + { + SendHeaderInternal(HttpStatus_500_InternalServerError); + return; + } + + SendOkHeader(contentType.c_str(), true, fileSize); + + std::vector<uint8_t> buffer(1024 * 1024); // Chunks of 1MB + + for (;;) + { + size_t nbytes = fread(&buffer[0], 1, buffer.size(), fp); + if (nbytes == 0) + { + break; + } + else + { + Send(&buffer[0], nbytes); + } + } + + fclose(fp); + } + + + void HttpOutput::AnswerFileAutodetectContentType(const std::string& path) + { + AnswerFileWithContentType(path, Toolbox::AutodetectMimeType(path)); + } + + + void HttpOutput::AnswerFile(const FileStorage& storage, + const std::string& uuid, + const std::string& contentType) + { + boost::filesystem::path p(storage.GetPath(uuid)); + AnswerFileWithContentType(p.string(), contentType); + } + + + + void HttpOutput::Redirect(const std::string& path) + { + std::string s = + "HTTP/1.1 301 " + std::string(HttpException::GetDescription(HttpStatus_301_MovedPermanently)) + + "\r\nLocation: " + path + + "\r\n\r\n"; + Send(&s[0], s.size()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/HttpOutput.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,98 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> +#include <stdint.h> +#include "../Enumerations.h" +#include "../FileStorage.h" + +namespace Palantir +{ + class HttpOutput + { + private: + void SendHeaderInternal(HttpStatus status); + + void SendOkHeader(const char* contentType, + bool hasContentLength, + size_t contentLength); + + public: + virtual ~HttpOutput() + { + } + + virtual void Send(const void* buffer, size_t length) = 0; + + void SendString(const std::string& s); + + void SendOkHeader(); + + void SendOkHeader(uint64_t contentLength); + + void SendOkHeader(const std::string& contentType); + + void SendOkHeader(const std::string& contentType, + uint64_t contentLength); + + void SendMethodNotAllowedError(const std::string& allowed); + + void SendHeader(HttpStatus status); + + + // Higher-level constructs to send entire files or buffers ------------------- + + void AnswerBuffer(const std::string& buffer) + { + AnswerBufferWithContentType(buffer, ""); + } + + void AnswerBufferWithContentType(const std::string& buffer, + const std::string& contentType); + + void AnswerBufferWithContentType(const void* buffer, + size_t size, + const std::string& contentType); + + void AnswerFile(const std::string& path) + { + AnswerFileWithContentType(path, ""); + } + + void AnswerFileWithContentType(const std::string& path, + const std::string& contentType); + + void AnswerFileAutodetectContentType(const std::string& path); + + void AnswerFile(const FileStorage& storage, + const std::string& uuid) + { + AnswerFile(storage, uuid, ""); + } + + void AnswerFile(const FileStorage& storage, + const std::string& uuid, + const std::string& contentType); + + void Redirect(const std::string& path); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/MongooseServer.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,569 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +// http://en.highscore.de/cpp/boost/stringhandling.html + +#include "MongooseServer.h" + +#include <algorithm> +#include <string.h> +#include <boost/lexical_cast.hpp> +#include <boost/algorithm/string.hpp> +#include <iostream> +#include <string.h> +#include <stdio.h> +#include <boost/thread.hpp> + +#include "../PalantirException.h" +#include "../ChunkedBuffer.h" +#include "mongoose.h" + + +namespace Palantir +{ + static const char multipart[] = "multipart/form-data; boundary="; + static unsigned int multipartLength = sizeof(multipart) / sizeof(char) - 1; + + + namespace + { + // Anonymous namespace to avoid clashes between compilation modules + class MongooseOutput : public HttpOutput + { + private: + struct mg_connection* connection_; + + public: + MongooseOutput(struct mg_connection* connection) : connection_(connection) + { + } + + virtual void Send(const void* buffer, size_t length) + { + mg_write(connection_, buffer, length); + } + }; + + + enum PostDataStatus + { + PostDataStatus_Success, + PostDataStatus_NoLength, + PostDataStatus_Pending, + PostDataStatus_Failure + }; + } + + +// TODO Move this to external file + + + class ChunkedFile : public ChunkedBuffer + { + private: + std::string filename_; + + public: + ChunkedFile(const std::string& filename) : + filename_(filename) + { + } + + const std::string& GetFilename() const + { + return filename_; + } + }; + + + + class ChunkStore + { + private: + typedef std::list<ChunkedFile*> Content; + Content content_; + unsigned int numPlaces_; + + boost::mutex mutex_; + std::set<std::string> discardedFiles_; + + void Clear() + { + for (Content::iterator it = content_.begin(); + it != content_.end(); it++) + { + delete *it; + } + } + + Content::iterator Find(const std::string& filename) + { + for (Content::iterator it = content_.begin(); + it != content_.end(); it++) + { + if ((*it)->GetFilename() == filename) + { + return it; + } + } + + return content_.end(); + } + + void Remove(const std::string& filename) + { + Content::iterator it = Find(filename); + if (it != content_.end()) + { + delete *it; + content_.erase(it); + } + } + + public: + ChunkStore() + { + numPlaces_ = 10; + } + + ~ChunkStore() + { + Clear(); + } + + PostDataStatus Store(std::string& completed, + const char* chunkData, + size_t chunkSize, + const std::string& filename, + size_t filesize) + { + boost::mutex::scoped_lock lock(mutex_); + + std::set<std::string>::iterator wasDiscarded = discardedFiles_.find(filename); + if (wasDiscarded != discardedFiles_.end()) + { + discardedFiles_.erase(wasDiscarded); + return PostDataStatus_Failure; + } + + ChunkedFile* f; + Content::iterator it = Find(filename); + if (it == content_.end()) + { + f = new ChunkedFile(filename); + + // Make some room + if (content_.size() >= numPlaces_) + { + discardedFiles_.insert(content_.front()->GetFilename()); + delete content_.front(); + content_.pop_front(); + } + + content_.push_back(f); + } + else + { + f = *it; + } + + f->AddChunk(chunkData, chunkSize); + + if (f->GetNumBytes() > filesize) + { + Remove(filename); + } + else if (f->GetNumBytes() == filesize) + { + f->Flatten(completed); + Remove(filename); + return PostDataStatus_Success; + } + + return PostDataStatus_Pending; + } + + /*void Print() + { + boost::mutex::scoped_lock lock(mutex_); + + printf("ChunkStore status:\n"); + for (Content::const_iterator i = content_.begin(); + i != content_.end(); i++) + { + printf(" [%s]: %d\n", (*i)->GetFilename().c_str(), (*i)->GetNumBytes()); + } + printf("-----\n"); + }*/ + }; + + + struct MongooseServer::PImpl + { + struct mg_context *context_; + ChunkStore chunkStore_; + }; + + + ChunkStore& MongooseServer::GetChunkStore() + { + return pimpl_->chunkStore_; + } + + + + HttpHandler* MongooseServer::FindHandler(const UriComponents& forUri) const + { + for (Handlers::const_iterator it = + handlers_.begin(); it != handlers_.end(); it++) + { + if ((*it)->IsServedUri(forUri)) + { + return *it; + } + } + + return NULL; + } + + + + + static PostDataStatus ReadPostData(std::string& postData, + struct mg_connection *connection, + const HttpHandler::Arguments& headers) + { + HttpHandler::Arguments::const_iterator cs = headers.find("content-length"); + if (cs == headers.end()) + { + return PostDataStatus_NoLength; + } + + int length; + try + { + length = boost::lexical_cast<int>(cs->second); + } + catch (boost::bad_lexical_cast) + { + return PostDataStatus_NoLength; + } + + if (length < 0) + { + length = 0; + } + + postData.resize(length); + + size_t pos = 0; + while (length > 0) + { + int r = mg_read(connection, &postData[pos], length); + if (r <= 0) + { + return PostDataStatus_Failure; + } + assert((unsigned int) r <= length); + length -= r; + pos += r; + } + + return PostDataStatus_Success; + } + + + + static PostDataStatus ParseMultipartPost(std::string &completedFile, + struct mg_connection *connection, + const HttpHandler::Arguments& headers, + const std::string& contentType, + ChunkStore& chunkStore) + { + std::string boundary = "--" + contentType.substr(multipartLength); + + std::string postData; + PostDataStatus status = ReadPostData(postData, connection, headers); + + if (status != PostDataStatus_Success) + { + return status; + } + + /*for (HttpHandler::Arguments::const_iterator i = headers.begin(); i != headers.end(); i++) + { + std::cout << "Header [" << i->first << "] = " << i->second << "\n"; + } + printf("CHUNK\n");*/ + + typedef HttpHandler::Arguments::const_iterator ArgumentIterator; + + ArgumentIterator requestedWith = headers.find("x-requested-with"); + ArgumentIterator fileName = headers.find("x-file-name"); + ArgumentIterator fileSizeStr = headers.find("x-file-size"); + + if (requestedWith == headers.end() || + requestedWith->second != "XMLHttpRequest") + { + return PostDataStatus_Failure; + } + + size_t fileSize = 0; + if (fileSizeStr != headers.end()) + { + try + { + fileSize = boost::lexical_cast<size_t>(fileSizeStr->second); + } + catch (boost::bad_lexical_cast) + { + return PostDataStatus_Failure; + } + } + + typedef boost::find_iterator<std::string::iterator> FindIterator; + typedef boost::iterator_range<std::string::iterator> Range; + + //chunkStore.Print(); + + try + { + FindIterator last; + for (FindIterator it = + make_find_iterator(postData, boost::first_finder(boundary)); + it!=FindIterator(); + ++it) + { + if (last != FindIterator()) + { + Range part(&last->back(), &it->front()); + Range content = boost::find_first(part, "\r\n\r\n"); + if (content != Range()) + { + Range c(&content.back() + 1, &it->front() - 2); + size_t chunkSize = c.size(); + + if (chunkSize > 0) + { + const char* chunkData = &c.front(); + + if (fileName == headers.end()) + { + // This file is stored in a single chunk + completedFile.resize(chunkSize); + if (chunkSize > 0) + { + memcpy(&completedFile[0], chunkData, chunkSize); + } + return PostDataStatus_Success; + } + else + { + return chunkStore.Store(completedFile, chunkData, chunkSize, fileName->second, fileSize); + } + } + } + } + + last = it; + } + } + catch (std::length_error) + { + return PostDataStatus_Failure; + } + + return PostDataStatus_Pending; + } + + + + static void* Callback(enum mg_event event, + struct mg_connection *connection, + const struct mg_request_info *request) + { + if (event == MG_NEW_REQUEST) + { + MongooseServer* that = (MongooseServer*) (request->user_data); + + HttpHandler::Arguments arguments, headers; + MongooseOutput c(connection); + + for (int i = 0; i < request->num_headers; i++) + { + std::string name = request->http_headers[i].name; + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + headers.insert(std::make_pair(name, request->http_headers[i].value)); + } + + std::string postData; + + if (!strcmp(request->request_method, "GET")) + { + HttpHandler::ParseGetQuery(arguments, request->query_string); + } + else if (!strcmp(request->request_method, "POST")) + { + HttpHandler::Arguments::const_iterator ct = headers.find("content-type"); + if (ct == headers.end()) + { + c.SendHeader(HttpStatus_400_BadRequest); + return (void*) ""; + } + + PostDataStatus status; + + std::string contentType = ct->second; + if (contentType.size() >= multipartLength && + !memcmp(contentType.c_str(), multipart, multipartLength)) + { + status = ParseMultipartPost(postData, connection, headers, contentType, that->GetChunkStore()); + } + else + { + status = ReadPostData(postData, connection, headers); + } + + switch (status) + { + case PostDataStatus_NoLength: + c.SendHeader(HttpStatus_411_LengthRequired); + return (void*) ""; + + case PostDataStatus_Failure: + c.SendHeader(HttpStatus_400_BadRequest); + return (void*) ""; + + case PostDataStatus_Pending: + c.AnswerBuffer(""); + return (void*) ""; + + default: + break; + } + } + + UriComponents uri; + Toolbox::SplitUriComponents(uri, request->uri); + + HttpHandler* handler = that->FindHandler(uri); + if (handler) + { + try + { + handler->Handle(c, std::string(request->request_method), + uri, headers, arguments, postData); + } + catch (PalantirException& e) + { + std::cerr << "MongooseServer Exception [" << e.What() << "]" << std::endl; + c.SendHeader(HttpStatus_500_InternalServerError); + } + } + else + { + c.SendHeader(HttpStatus_404_NotFound); + } + + // Mark as processed + return (void*) ""; + } + else + { + return NULL; + } + } + + + bool MongooseServer::IsRunning() const + { + return (pimpl_->context_ != NULL); + } + + + MongooseServer::MongooseServer() : pimpl_(new PImpl) + { + pimpl_->context_ = NULL; + port_ = 8000; + } + + + MongooseServer::~MongooseServer() + { + Stop(); + ClearHandlers(); + } + + + void MongooseServer::SetPort(uint16_t port) + { + Stop(); + port_ = port; + } + + void MongooseServer::Start() + { + if (!IsRunning()) + { + std::string port = boost::lexical_cast<std::string>(port_); + + const char *options[] = { + "listening_ports", port.c_str(), + NULL + }; + + pimpl_->context_ = mg_start(&Callback, this, options); + if (!pimpl_->context_) + { + throw PalantirException("Unable to launch the Mongoose server"); + } + } + } + + void MongooseServer::Stop() + { + if (IsRunning()) + { + mg_stop(pimpl_->context_); + pimpl_->context_ = NULL; + } + } + + + void MongooseServer::RegisterHandler(HttpHandler* handler) + { + Stop(); + + handlers_.push_back(handler); + } + + + void MongooseServer::ClearHandlers() + { + Stop(); + + for (Handlers::iterator it = + handlers_.begin(); it != handlers_.end(); it++) + { + delete *it; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/HttpServer/MongooseServer.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,72 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "HttpHandler.h" + +#include <list> +#include <stdint.h> +#include <boost/shared_ptr.hpp> + +namespace Palantir +{ + class ChunkStore; + + class MongooseServer + { + private: + // http://stackoverflow.com/questions/311166/stdauto-ptr-or-boostshared-ptr-for-pimpl-idiom + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + typedef std::list<HttpHandler*> Handlers; + Handlers handlers_; + + uint16_t port_; + + bool IsRunning() const; + + public: + MongooseServer(); + + ~MongooseServer(); + + void SetPort(uint16_t port); + + uint16_t GetPort() const + { + return port_; + } + + void Start(); + + void Stop(); + + void RegisterHandler(HttpHandler* handler); // This takes the ownership + + void ClearHandlers(); + + // Can return NULL if no handler is associated to this URI + HttpHandler* FindHandler(const UriComponents& forUri) const; + + ChunkStore& GetChunkStore(); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/BagOfRunnablesBySteps.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,147 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "BagOfRunnablesBySteps.h" + +#include <stack> +#include <boost/thread.hpp> + +namespace Palantir +{ + struct BagOfRunnablesBySteps::PImpl + { + bool continue_; + bool stopFinishListener_; + + boost::mutex mutex_; + boost::condition_variable oneThreadIsStopped_; + boost::condition_variable oneThreadIsJoined_; + + // The list of threads that are waiting to be joined. + typedef std::stack<IRunnableBySteps*> StoppedThreads; + StoppedThreads stoppedThreads_; + + // The set of active runnables, i.e. the runnables that have not + // finished their job yet, plus the runnables that have not been + // joined yet. + typedef std::map<IRunnableBySteps*, boost::thread*> ActiveThreads; + ActiveThreads activeThreads_; + + // The thread that joins the runnables after they stop + std::auto_ptr<boost::thread> finishListener_; + }; + + + + void BagOfRunnablesBySteps::RunnableThread(BagOfRunnablesBySteps* bag, + IRunnableBySteps* runnable) + { + while (bag->pimpl_->continue_) + { + if (!runnable->Step()) + { + break; + } + } + + { + // Register this runnable as having stopped + boost::mutex::scoped_lock lock(bag->pimpl_->mutex_); + bag->pimpl_->stoppedThreads_.push(runnable); + bag->pimpl_->oneThreadIsStopped_.notify_one(); + } + } + + + void BagOfRunnablesBySteps::FinishListener(BagOfRunnablesBySteps* bag) + { + boost::mutex::scoped_lock lock(bag->pimpl_->mutex_); + + while (!bag->pimpl_->stopFinishListener_) + { + while (!bag->pimpl_->stoppedThreads_.empty()) + { + std::auto_ptr<IRunnableBySteps> r(bag->pimpl_->stoppedThreads_.top()); + bag->pimpl_->stoppedThreads_.pop(); + + assert(r.get() != NULL); + assert(bag->pimpl_->activeThreads_.find(r.get()) != bag->pimpl_->activeThreads_.end()); + + std::auto_ptr<boost::thread> t(bag->pimpl_->activeThreads_[r.get()]); + bag->pimpl_->activeThreads_.erase(r.get()); + + assert(t.get() != NULL); + assert(bag->pimpl_->activeThreads_.find(r.get()) == bag->pimpl_->activeThreads_.end()); + + t->join(); + bag->pimpl_->oneThreadIsJoined_.notify_one(); + } + + bag->pimpl_->oneThreadIsStopped_.wait(lock); + } + } + + + BagOfRunnablesBySteps::BagOfRunnablesBySteps() : pimpl_(new PImpl) + { + pimpl_->continue_ = true; + pimpl_->stopFinishListener_ = false; + + // Everyting is set up, the finish listener can be started + pimpl_->finishListener_.reset(new boost::thread(FinishListener, this)); + } + + + BagOfRunnablesBySteps::~BagOfRunnablesBySteps() + { + StopAll(); + + // Stop the finish listener + pimpl_->stopFinishListener_ = true; + pimpl_->oneThreadIsStopped_.notify_one(); // Awakens the listener + pimpl_->finishListener_->join(); + } + + + void BagOfRunnablesBySteps::Add(IRunnableBySteps* runnable) + { + // Make sure the runnable is deleted is something goes wrong + std::auto_ptr<IRunnableBySteps> runnableRabi(runnable); + + boost::mutex::scoped_lock lock(pimpl_->mutex_); + boost::thread* t(new boost::thread(RunnableThread, this, runnable)); + + pimpl_->activeThreads_.insert(std::make_pair(runnableRabi.release(), t)); + } + + + void BagOfRunnablesBySteps::StopAll() + { + boost::mutex::scoped_lock lock(pimpl_->mutex_); + pimpl_->continue_ = false; + + while (pimpl_->activeThreads_.size() > 0) + { + pimpl_->oneThreadIsJoined_.wait(lock); + } + + pimpl_->continue_ = true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/BagOfRunnablesBySteps.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,50 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IRunnableBySteps.h" + +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace Palantir +{ + class BagOfRunnablesBySteps : public boost::noncopyable + { + private: + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + static void RunnableThread(BagOfRunnablesBySteps* bag, + IRunnableBySteps* runnable); + + static void FinishListener(BagOfRunnablesBySteps* bag); + + public: + BagOfRunnablesBySteps(); + + ~BagOfRunnablesBySteps(); + + void Add(IRunnableBySteps* runnable); + + void StopAll(); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/MultiThreading/IRunnableBySteps.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,41 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +namespace Palantir +{ + class IRunnableBySteps + { + public: + virtual ~IRunnableBySteps() + { + } + + // Must return "true" if the runnable wishes to continue. Must + // return "false" if the runnable has not finished its job. + virtual bool Step() = 0; + + static void RunUntilDone(IRunnableBySteps& runnable) + { + while (runnable.Step()); + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PalantirException.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,77 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "PalantirException.h" + +namespace Palantir +{ + const char* PalantirException::What() const + { + if (error_ == ErrorCode_Custom) + { + return custom_.c_str(); + } + else + { + return GetDescription(error_); + } + } + + + const char* PalantirException::GetDescription(ErrorCode error) + { + switch (error) + { + case ErrorCode_Success: + return "Success"; + + case ErrorCode_ParameterOutOfRange: + return "Parameter out of range"; + + case ErrorCode_NotImplemented: + return "Not implemented yet"; + + case ErrorCode_InternalError: + return "Internal error"; + + case ErrorCode_NotEnoughMemory: + return "Not enough memory"; + + case ErrorCode_UriSyntax: + return "Badly formatted URI"; + + case ErrorCode_BadParameterType: + return "Bad type for a parameter"; + + case ErrorCode_InexistentFile: + return "Inexistent file"; + + case ErrorCode_BadFileFormat: + return "Bad file format"; + + case ErrorCode_CannotWriteFile: + return "Cannot write to file"; + + case ErrorCode_Custom: + default: + return "???"; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PalantirException.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,55 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> +#include "Enumerations.h" + +namespace Palantir +{ + class PalantirException + { + private: + ErrorCode error_; + std::string custom_; + + public: + static const char* GetDescription(ErrorCode error); + + PalantirException(const std::string& custom) + { + error_ = ErrorCode_Custom; + custom_ = custom; + } + + PalantirException(ErrorCode error) + { + error_ = error; + } + + ErrorCode GetErrorCode() const + { + return error_; + } + + const char* What() const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PngWriter.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,235 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "PngWriter.h" + +#include <vector> +#include <stdint.h> +#include <png.h> +#include "PalantirException.h" +#include "ChunkedBuffer.h" + + +// http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-4 +// http://zarb.org/~gc/html/libpng.html +/* + void write_row_callback(png_ptr, png_uint_32 row, int pass) + { + }*/ + + + + +/* bool isError_; + +// http://www.libpng.org/pub/png/book/chapter14.html#png.ch14.div.2 + +static void ErrorHandler(png_structp png, png_const_charp message) +{ +printf("** [%s]\n", message); + +PngWriter* that = (PngWriter*) png_get_error_ptr(png); +that->isError_ = true; +printf("** %d\n", (int)that); + +//((PngWriter*) payload)->isError_ = true; +} + +static void WarningHandler(png_structp png, png_const_charp message) +{ + printf("++ %d\n", (int)message); +}*/ + + +namespace Palantir +{ + struct PngWriter::PImpl + { + png_structp png_; + png_infop info_; + + // Filled by Prepare() + std::vector<uint8_t*> rows_; + int bitDepth_; + int colorType_; + }; + + + + PngWriter::PngWriter() : pimpl_(new PImpl) + { + pimpl_->png_ = NULL; + pimpl_->info_ = NULL; + + pimpl_->png_ = png_create_write_struct + (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); //this, ErrorHandler, WarningHandler); + if (!pimpl_->png_) + { + throw PalantirException(ErrorCode_NotEnoughMemory); + } + + pimpl_->info_ = png_create_info_struct(pimpl_->png_); + if (!pimpl_->info_) + { + png_destroy_write_struct(&pimpl_->png_, NULL); + throw PalantirException(ErrorCode_NotEnoughMemory); + } + } + + PngWriter::~PngWriter() + { + if (pimpl_->info_) + { + png_destroy_info_struct(pimpl_->png_, &pimpl_->info_); + } + + if (pimpl_->png_) + { + png_destroy_write_struct(&pimpl_->png_, NULL); + } + } + + + + void PngWriter::Prepare(unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer) + { + pimpl_->rows_.resize(height); + for (unsigned int y = 0; y < height; y++) + { + pimpl_->rows_[y] = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(buffer)) + y * pitch; + } + + switch (format) + { + case PixelFormat_Grayscale8: + pimpl_->bitDepth_ = 8; + pimpl_->colorType_ = PNG_COLOR_TYPE_GRAY; + break; + + case PixelFormat_Grayscale16: + pimpl_->bitDepth_ = 16; + pimpl_->colorType_ = PNG_COLOR_TYPE_GRAY; + break; + + default: + throw PalantirException(ErrorCode_NotImplemented); + } + } + + + void PngWriter::Compress(unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format) + { + png_set_IHDR(pimpl_->png_, pimpl_->info_, width, height, + pimpl_->bitDepth_, pimpl_->colorType_, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(pimpl_->png_, pimpl_->info_); + + if (height > 0) + { + switch (format) + { + case PixelFormat_Grayscale16: + // Must swap the endianness!! + png_set_rows(pimpl_->png_, pimpl_->info_, &pimpl_->rows_[0]); + png_write_png(pimpl_->png_, pimpl_->info_, PNG_TRANSFORM_SWAP_ENDIAN, NULL); + break; + + default: + png_write_image(pimpl_->png_, &pimpl_->rows_[0]); + } + } + + png_write_end(pimpl_->png_, NULL); + } + + + void PngWriter::WriteToFile(const char* filename, + unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer) + { + Prepare(width, height, pitch, format, buffer); + + FILE* fp = fopen(filename, "wb"); + if (!fp) + { + throw PalantirException(ErrorCode_CannotWriteFile); + } + + png_init_io(pimpl_->png_, fp); + + if (setjmp(png_jmpbuf(pimpl_->png_))) + { + // Error during writing PNG + throw PalantirException(ErrorCode_CannotWriteFile); + } + + Compress(width, height, pitch, format); + + fclose(fp); + } + + + + + static void MemoryCallback(png_structp png_ptr, + png_bytep data, + png_size_t size) + { + ChunkedBuffer* buffer = (ChunkedBuffer*) png_get_io_ptr(png_ptr); + buffer->AddChunk(reinterpret_cast<const char*>(data), size); + } + + + + void PngWriter::WriteToMemory(std::string& png, + unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer) + { + ChunkedBuffer chunks; + + Prepare(width, height, pitch, format, buffer); + + if (setjmp(png_jmpbuf(pimpl_->png_))) + { + // Error during writing PNG + throw PalantirException(ErrorCode_InternalError); + } + + png_set_write_fn(pimpl_->png_, &chunks, MemoryCallback, NULL); + + Compress(width, height, pitch, format); + + chunks.Flatten(png); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PngWriter.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,66 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "Enumerations.h" + +#include <boost/shared_ptr.hpp> +#include <string> + +namespace Palantir +{ + class PngWriter + { + private: + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + void Compress(unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format); + + void Prepare(unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer); + + public: + PngWriter(); + + ~PngWriter(); + + void WriteToFile(const char* filename, + unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer); + + void WriteToMemory(std::string& png, + unsigned int width, + unsigned int height, + unsigned int pitch, + PixelFormat format, + const void* buffer); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/Connection.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,356 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "Connection.h" + +#include <memory> +#include <cassert> +#include <sqlite3.h> +#include <string.h> + + + +namespace Palantir +{ + namespace SQLite + { + Connection::Connection() : + db_(NULL), + transactionNesting_(0), + needsRollback_(false) + { + } + + + Connection::~Connection() + { + Close(); + } + + + void Connection::CheckIsOpen() const + { + if (!db_) + { + throw PalantirException("SQLite: The database is not opened"); + } + } + + void Connection::Open(const std::string& path) + { + if (db_) + { + throw PalantirException("SQLite: Connection is already open"); + } + + int err = sqlite3_open(path.c_str(), &db_); + if (err != SQLITE_OK) + { + Close(); + db_ = NULL; + throw PalantirException("SQLite: Unable to open the database"); + } + + // Execute PRAGMAs at this point + // http://www.sqlite.org/pragma.html + Execute("PRAGMA FOREIGN_KEYS=ON;"); + + // Performance tuning + Execute("PRAGMA SYNCHRONOUS=NORMAL;"); + Execute("PRAGMA JOURNAL_MODE=WAL;"); + Execute("PRAGMA LOCKING_MODE=EXCLUSIVE;"); + Execute("PRAGMA WAL_AUTOCHECKPOINT=1000;"); + //Execute("PRAGMA TEMP_STORE=memory"); + } + + void Connection::OpenInMemory() + { + Open(":memory:"); + } + + void Connection::Close() + { + ClearCache(); + + if (db_) + { + sqlite3_close(db_); + db_ = NULL; + } + } + + void Connection::ClearCache() + { + for (CachedStatements::iterator + it = cachedStatements_.begin(); + it != cachedStatements_.end(); it++) + { + delete it->second; + } + + cachedStatements_.clear(); + } + + + StatementReference& Connection::GetCachedStatement(const StatementId& id, + const char* sql) + { + CachedStatements::iterator i = cachedStatements_.find(id); + if (i != cachedStatements_.end()) + { + if (i->second->GetReferenceCount() >= 1) + { + throw PalantirException("SQLite: This cached statement is already being referred to"); + } + + return *i->second; + } + else + { + StatementReference* statement = new StatementReference(db_, sql); + cachedStatements_[id] = statement; + return *statement; + } + } + + + bool Connection::Execute(const char* sql) + { + CheckIsOpen(); + + int error = sqlite3_exec(db_, sql, NULL, NULL, NULL); + if (error == SQLITE_ERROR) + { + throw PalantirException("SQLite Execute error: " + std::string(sqlite3_errmsg(db_))); + } + else + { + return error == SQLITE_OK; + } + } + + int Connection::ExecuteAndReturnErrorCode(const char* sql) + { + CheckIsOpen(); + return sqlite3_exec(db_, sql, NULL, NULL, NULL); + } + + // Info querying ------------------------------------------------------------- + + bool Connection::IsSQLValid(const char* sql) + { + sqlite3_stmt* stmt = NULL; + if (sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL) != SQLITE_OK) + return false; + + sqlite3_finalize(stmt); + return true; + } + + bool Connection::DoesTableOrIndexExist(const char* name, + const char* type) const + { + // Our SQL is non-mutating, so this cast is OK. + Statement statement(const_cast<Connection&>(*this), + "SELECT name FROM sqlite_master WHERE type=? AND name=?"); + statement.BindString(0, type); + statement.BindString(1, name); + return statement.Step(); // Table exists if any row was returned. + } + + bool Connection::DoesTableExist(const char* table_name) const + { + return DoesTableOrIndexExist(table_name, "table"); + } + + bool Connection::DoesIndexExist(const char* index_name) const + { + return DoesTableOrIndexExist(index_name, "index"); + } + + bool Connection::DoesColumnExist(const char* table_name, const char* column_name) const + { + std::string sql("PRAGMA TABLE_INFO("); + sql.append(table_name); + sql.append(")"); + + // Our SQL is non-mutating, so this cast is OK. + Statement statement(const_cast<Connection&>(*this), sql.c_str()); + + while (statement.Step()) { + if (!statement.ColumnString(1).compare(column_name)) + return true; + } + return false; + } + + int64_t Connection::GetLastInsertRowId() const + { + return sqlite3_last_insert_rowid(db_); + } + + int Connection::GetLastChangeCount() const + { + return sqlite3_changes(db_); + } + + int Connection::GetErrorCode() const + { + return sqlite3_errcode(db_); + } + + int Connection::GetLastErrno() const + { + int err = 0; + if (SQLITE_OK != sqlite3_file_control(db_, NULL, SQLITE_LAST_ERRNO, &err)) + return -2; + + return err; + } + + const char* Connection::GetErrorMessage() const + { + return sqlite3_errmsg(db_); + } + + + bool Connection::BeginTransaction() + { + if (needsRollback_) + { + assert(transactionNesting_ > 0); + + // When we're going to rollback, fail on this begin and don't actually + // mark us as entering the nested transaction. + return false; + } + + bool success = true; + if (!transactionNesting_) + { + needsRollback_ = false; + + Statement begin(*this, SQLITE_FROM_HERE, "BEGIN TRANSACTION"); + if (!begin.Run()) + return false; + } + transactionNesting_++; + return success; + } + + void Connection::RollbackTransaction() + { + if (!transactionNesting_) + { + throw PalantirException("Rolling back a nonexistent transaction"); + } + + transactionNesting_--; + + if (transactionNesting_ > 0) + { + // Mark the outermost transaction as needing rollback. + needsRollback_ = true; + return; + } + + DoRollback(); + } + + bool Connection::CommitTransaction() + { + if (!transactionNesting_) + { + throw PalantirException("Committing a nonexistent transaction"); + } + transactionNesting_--; + + if (transactionNesting_ > 0) + { + // Mark any nested transactions as failing after we've already got one. + return !needsRollback_; + } + + if (needsRollback_) + { + DoRollback(); + return false; + } + + Statement commit(*this, SQLITE_FROM_HERE, "COMMIT"); + return commit.Run(); + } + + void Connection::DoRollback() + { + Statement rollback(*this, SQLITE_FROM_HERE, "ROLLBACK"); + rollback.Run(); + needsRollback_ = false; + } + + + + + + + static void ScalarFunctionCaller(sqlite3_context* rawContext, + int argc, + sqlite3_value** argv) + { + FunctionContext context(rawContext, argc, argv); + + void* payload = sqlite3_user_data(rawContext); + assert(payload != NULL); + + IScalarFunction& func = *(IScalarFunction*) payload; + func.Compute(context); + } + + + static void ScalarFunctionDestroyer(void* payload) + { + assert(payload != NULL); + delete (IScalarFunction*) payload; + } + + + IScalarFunction* Connection::Register(IScalarFunction* func) + { + int err = sqlite3_create_function_v2(db_, + func->GetName(), + func->GetCardinality(), + SQLITE_UTF8, + func, + ScalarFunctionCaller, + NULL, + NULL, + ScalarFunctionDestroyer); + + if (err != SQLITE_OK) + { + delete func; + throw PalantirException("SQLite: Unable to register a function"); + } + + return func; + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/Connection.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,159 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "Statement.h" +#include "IScalarFunction.h" + +#include <string> +#include <boost/noncopyable.hpp> +#include <map> + +struct sqlite3; +struct sqlite3_stmt; + +#define SQLITE_FROM_HERE SQLite::StatementId(__FILE__, __LINE__) + +namespace Palantir +{ + namespace SQLite + { + class Connection : boost::noncopyable + { + friend class Statement; + friend class Transaction; + + private: + // All cached statements. Keeping a reference to these statements means that + // they'll remain active. + typedef std::map<StatementId, StatementReference*> CachedStatements; + CachedStatements cachedStatements_; + + // The actual sqlite database. Will be NULL before Init has been called or if + // Init resulted in an error. + sqlite3* db_; + + // Number of currently-nested transactions. + int transactionNesting_; + + // True if any of the currently nested transactions have been rolled back. + // When we get to the outermost transaction, this will determine if we do + // a rollback instead of a commit. + bool needsRollback_; + + void ClearCache(); + + void CheckIsOpen() const; + + sqlite3* GetWrappedObject() + { + return db_; + } + + StatementReference& GetCachedStatement(const StatementId& id, + const char* sql); + + bool DoesTableOrIndexExist(const char* name, + const char* type) const; + + void DoRollback(); + + public: + // The database is opened by calling Open[InMemory](). Any uncommitted + // transactions will be rolled back when this object is deleted. + Connection(); + ~Connection(); + + void Open(const std::string& path); + + void OpenInMemory(); + + void Close(); + + bool Execute(const char* sql); + + bool Execute(const std::string& sql) + { + return Execute(sql.c_str()); + } + + IScalarFunction* Register(IScalarFunction* func); // Takes the ownership of the function + + // Info querying ------------------------------------------------------------- + + // Used to check a |sql| statement for syntactic validity. If the + // statement is valid SQL, returns true. + bool IsSQLValid(const char* sql); + + // Returns true if the given table exists. + bool DoesTableExist(const char* table_name) const; + + // Returns true if the given index exists. + bool DoesIndexExist(const char* index_name) const; + + // Returns true if a column with the given name exists in the given table. + bool DoesColumnExist(const char* table_name, const char* column_name) const; + + // Returns sqlite's internal ID for the last inserted row. Valid only + // immediately after an insert. + int64_t GetLastInsertRowId() const; + + // Returns sqlite's count of the number of rows modified by the last + // statement executed. Will be 0 if no statement has executed or the database + // is closed. + int GetLastChangeCount() const; + + // Errors -------------------------------------------------------------------- + + // Returns the error code associated with the last sqlite operation. + int GetErrorCode() const; + + // Returns the errno associated with GetErrorCode(). See + // SQLITE_LAST_ERRNO in SQLite documentation. + int GetLastErrno() const; + + // Returns a pointer to a statically allocated string associated with the + // last sqlite operation. + const char* GetErrorMessage() const; + + + // Diagnostics (for unit tests) ---------------------------------------------- + + int ExecuteAndReturnErrorCode(const char* sql); + + bool HasCachedStatement(const StatementId& id) const + { + return cachedStatements_.find(id) != cachedStatements_.end(); + } + + int GetTransactionNesting() const + { + return transactionNesting_; + } + + // Transactions -------------------------------------------------------------- + + bool BeginTransaction(); + void RollbackTransaction(); + bool CommitTransaction(); + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/FunctionContext.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,94 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "FunctionContext.h" + +#include <sqlite3.h> + +namespace Palantir +{ + namespace SQLite + { + FunctionContext::FunctionContext(struct sqlite3_context* context, + int argc, + struct ::Mem** argv) + { + assert(context != NULL); + assert(argc >= 0); + assert(argv != NULL); + + context_ = context; + argc_ = static_cast<unsigned int>(argc); + argv_ = argv; + } + + void FunctionContext::CheckIndex(unsigned int index) const + { + if (index >= argc_) + { + throw PalantirException(ErrorCode_ParameterOutOfRange); + } + } + + ColumnType FunctionContext::GetColumnType(unsigned int index) const + { + CheckIndex(index); + return static_cast<SQLite::ColumnType>(sqlite3_value_type(argv_[index])); + } + + int FunctionContext::GetIntValue(unsigned int index) const + { + CheckIndex(index); + return sqlite3_value_int(argv_[index]); + } + + double FunctionContext::GetDoubleValue(unsigned int index) const + { + CheckIndex(index); + return sqlite3_value_double(argv_[index]); + } + + std::string FunctionContext::GetStringValue(unsigned int index) const + { + CheckIndex(index); + return std::string(reinterpret_cast<const char*>(sqlite3_value_text(argv_[index]))); + } + + void FunctionContext::SetNullResult() + { + sqlite3_result_null(context_); + } + + void FunctionContext::SetIntResult(int value) + { + sqlite3_result_int(context_, value); + } + + void FunctionContext::SetDoubleResult(double value) + { + sqlite3_result_double(context_, value); + } + + void FunctionContext::SetStringResult(const std::string& str) + { + sqlite3_result_text(context_, str.data(), str.size(), SQLITE_TRANSIENT); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/FunctionContext.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,72 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <boost/noncopyable.hpp> + +#include "Statement.h" + +struct sqlite3_context; +struct Mem; // This corresponds to the opaque type "sqlite3_value" + +namespace Palantir +{ + namespace SQLite + { + class FunctionContext : public boost::noncopyable + { + friend class Connection; + + private: + struct sqlite3_context* context_; + unsigned int argc_; + struct ::Mem** argv_; + + void CheckIndex(unsigned int index) const; + + public: + FunctionContext(struct sqlite3_context* context, + int argc, + struct ::Mem** argv); + + ColumnType GetColumnType(unsigned int index) const; + + unsigned int GetParameterCount() const + { + return argc_; + } + + int GetIntValue(unsigned int index) const; + + double GetDoubleValue(unsigned int index) const; + + std::string GetStringValue(unsigned int index) const; + + void SetNullResult(); + + void SetIntResult(int value); + + void SetDoubleResult(double value); + + void SetStringResult(const std::string& str); + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/IScalarFunction.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,43 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "FunctionContext.h" + +namespace Palantir +{ + namespace SQLite + { + class IScalarFunction : public boost::noncopyable + { + public: + virtual ~IScalarFunction() + { + } + + virtual const char* GetName() const = 0; + + virtual unsigned int GetCardinality() const = 0; + + virtual void Compute(FunctionContext& context) = 0; + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/README.txt Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,9 @@ +This API is strongly inspired by Google Chromium's code, but has been +much simplified: + +http://src.chromium.org/viewvc/chrome/trunk/src/sql/ +http://maxradi.us/documents/sqlite/ + + +NOTES : +* A statement is always valid (is_valid() always return true)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/Statement.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,294 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "Statement.h" + +#include "Connection.h" +#include "../Toolbox.h" + +#include <boost/lexical_cast.hpp> +#include <sqlite3.h> +#include <string.h> + +namespace Palantir +{ + namespace SQLite + { + int Statement::CheckError(int err) const + { + bool succeeded = (err == SQLITE_OK || err == SQLITE_ROW || err == SQLITE_DONE); + if (!succeeded) + { + throw PalantirException("SQLite error code " + boost::lexical_cast<std::string>(err)); + } + + return err; + } + + void Statement::CheckOk(int err) const + { + if (err == SQLITE_RANGE) + { + // Binding to a non-existent variable is evidence of a serious error. + throw PalantirException("Bind value out of range"); + } + else if (err != SQLITE_OK) + { + throw PalantirException("SQLite error code " + boost::lexical_cast<std::string>(err)); + } + } + + + Statement::Statement(Connection& database, + const StatementId& id, + const std::string& sql) : + reference_(database.GetCachedStatement(id, sql.c_str())) + { + Reset(true); + } + + + Statement::Statement(Connection& database, + const StatementId& id, + const char* sql) : + reference_(database.GetCachedStatement(id, sql)) + { + Reset(true); + } + + + Statement::Statement(Connection& database, + const std::string& sql) : + reference_(database.GetWrappedObject(), sql.c_str()) + { + } + + + Statement::Statement(Connection& database, + const char* sql) : + reference_(database.GetWrappedObject(), sql) + { + } + + + bool Statement::Run() + { + return CheckError(sqlite3_step(GetStatement())) == SQLITE_DONE; + } + + bool Statement::Step() + { + return CheckError(sqlite3_step(GetStatement())) == SQLITE_ROW; + } + + void Statement::Reset(bool clear_bound_vars) + { + // We don't call CheckError() here because sqlite3_reset() returns + // the last error that Step() caused thereby generating a second + // spurious error callback. + if (clear_bound_vars) + sqlite3_clear_bindings(GetStatement()); + sqlite3_reset(GetStatement()); + } + + std::string Statement::GetOriginalSQLStatement() + { + return std::string(sqlite3_sql(GetStatement())); + } + + + void Statement::BindNull(int col) + { + CheckOk(sqlite3_bind_null(GetStatement(), col + 1)); + } + + void Statement::BindBool(int col, bool val) + { + BindInt(col, val ? 1 : 0); + } + + void Statement::BindInt(int col, int val) + { + CheckOk(sqlite3_bind_int(GetStatement(), col + 1, val)); + } + + void Statement::BindInt64(int col, int64_t val) + { + CheckOk(sqlite3_bind_int64(GetStatement(), col + 1, val)); + } + + void Statement::BindDouble(int col, double val) + { + CheckOk(sqlite3_bind_double(GetStatement(), col + 1, val)); + } + + void Statement::BindCString(int col, const char* val) + { + CheckOk(sqlite3_bind_text(GetStatement(), col + 1, val, -1, SQLITE_TRANSIENT)); + } + + void Statement::BindString(int col, const std::string& val) + { + CheckOk(sqlite3_bind_text(GetStatement(), + col + 1, + val.data(), + val.size(), + SQLITE_TRANSIENT)); + } + + /*void Statement::BindString16(int col, const string16& value) + { + BindString(col, UTF16ToUTF8(value)); + }*/ + + void Statement::BindBlob(int col, const void* val, int val_len) + { + CheckOk(sqlite3_bind_blob(GetStatement(), col + 1, val, val_len, SQLITE_TRANSIENT)); + } + + + int Statement::ColumnCount() const + { + return sqlite3_column_count(GetStatement()); + } + + + ColumnType Statement::GetColumnType(int col) const + { + // Verify that our enum matches sqlite's values. + assert(COLUMN_TYPE_INTEGER == SQLITE_INTEGER); + assert(COLUMN_TYPE_FLOAT == SQLITE_FLOAT); + assert(COLUMN_TYPE_TEXT == SQLITE_TEXT); + assert(COLUMN_TYPE_BLOB == SQLITE_BLOB); + assert(COLUMN_TYPE_NULL == SQLITE_NULL); + + return static_cast<ColumnType>(sqlite3_column_type(GetStatement(), col)); + } + + ColumnType Statement::GetDeclaredColumnType(int col) const + { + std::string column_type(sqlite3_column_decltype(GetStatement(), col)); + Toolbox::ToLowerCase(column_type); + + if (column_type == "integer") + return COLUMN_TYPE_INTEGER; + else if (column_type == "float") + return COLUMN_TYPE_FLOAT; + else if (column_type == "text") + return COLUMN_TYPE_TEXT; + else if (column_type == "blob") + return COLUMN_TYPE_BLOB; + + return COLUMN_TYPE_NULL; + } + + bool Statement::ColumnBool(int col) const + { + return !!ColumnInt(col); + } + + int Statement::ColumnInt(int col) const + { + return sqlite3_column_int(GetStatement(), col); + } + + int64_t Statement::ColumnInt64(int col) const + { + return sqlite3_column_int64(GetStatement(), col); + } + + double Statement::ColumnDouble(int col) const + { + return sqlite3_column_double(GetStatement(), col); + } + + std::string Statement::ColumnString(int col) const + { + const char* str = reinterpret_cast<const char*>( + sqlite3_column_text(GetStatement(), col)); + int len = sqlite3_column_bytes(GetStatement(), col); + + std::string result; + if (str && len > 0) + result.assign(str, len); + return result; + } + + /*string16 Statement::ColumnString16(int col) const + { + std::string s = ColumnString(col); + return !s.empty() ? UTF8ToUTF16(s) : string16(); + }*/ + + int Statement::ColumnByteLength(int col) const + { + return sqlite3_column_bytes(GetStatement(), col); + } + + const void* Statement::ColumnBlob(int col) const + { + return sqlite3_column_blob(GetStatement(), col); + } + + bool Statement::ColumnBlobAsString(int col, std::string* blob) + { + const void* p = ColumnBlob(col); + size_t len = ColumnByteLength(col); + blob->resize(len); + if (blob->size() != len) { + return false; + } + blob->assign(reinterpret_cast<const char*>(p), len); + return true; + } + + /*bool Statement::ColumnBlobAsString16(int col, string16* val) const + { + const void* data = ColumnBlob(col); + size_t len = ColumnByteLength(col) / sizeof(char16); + val->resize(len); + if (val->size() != len) + return false; + val->assign(reinterpret_cast<const char16*>(data), len); + return true; + }*/ + + bool Statement::ColumnBlobAsVector(int col, std::vector<char>* val) const + { + val->clear(); + + const void* data = sqlite3_column_blob(GetStatement(), col); + int len = sqlite3_column_bytes(GetStatement(), col); + if (data && len > 0) { + val->resize(len); + memcpy(&(*val)[0], data, len); + } + return true; + } + + bool Statement::ColumnBlobAsVector( + int col, + std::vector<unsigned char>* val) const + { + return ColumnBlobAsVector(col, reinterpret_cast< std::vector<char>* >(val)); + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/Statement.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,143 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../PalantirException.h" +#include "StatementId.h" +#include "StatementReference.h" + +#include <vector> +#include <stdint.h> +#include <boost/noncopyable.hpp> + +struct sqlite3_stmt; + + +namespace Palantir +{ + namespace SQLite + { + class Connection; + + // Possible return values from ColumnType in a statement. These + // should match the values in sqlite3.h. + enum ColumnType + { + COLUMN_TYPE_INTEGER = 1, + COLUMN_TYPE_FLOAT = 2, + COLUMN_TYPE_TEXT = 3, + COLUMN_TYPE_BLOB = 4, + COLUMN_TYPE_NULL = 5 + }; + + class Statement : public boost::noncopyable + { + friend class Connection; + + private: + StatementReference reference_; + + int CheckError(int err) const; + + void CheckOk(int err) const; + + struct sqlite3_stmt* GetStatement() const + { + return reference_.GetWrappedObject(); + } + + public: + Statement(Connection& database, + const std::string& sql); + + Statement(Connection& database, + const StatementId& id, + const std::string& sql); + + Statement(Connection& database, + const char* sql); + + Statement(Connection& database, + const StatementId& id, + const char* sql); + + bool Run(); + + bool Step(); + + // Resets the statement to its initial condition. This includes any current + // result row, and also the bound variables if the |clear_bound_vars| is true. + void Reset(bool clear_bound_vars = true); + + // Diagnostics -------------------------------------------------------------- + + std::string GetOriginalSQLStatement(); + + + // Binding ------------------------------------------------------------------- + + // These all take a 0-based argument index + void BindNull(int col); + void BindBool(int col, bool val); + void BindInt(int col, int val); + void BindInt64(int col, int64_t val); + void BindDouble(int col, double val); + void BindCString(int col, const char* val); + void BindString(int col, const std::string& val); + //void BindString16(int col, const string16& value); + void BindBlob(int col, const void* value, int value_len); + + + // Retrieving ---------------------------------------------------------------- + + // Returns the number of output columns in the result. + int ColumnCount() const; + + // Returns the type associated with the given column. + // + // Watch out: the type may be undefined if you've done something to cause a + // "type conversion." This means requesting the value of a column of a type + // where that type is not the native type. For safety, call ColumnType only + // on a column before getting the value out in any way. + ColumnType GetColumnType(int col) const; + ColumnType GetDeclaredColumnType(int col) const; + + // These all take a 0-based argument index. + bool ColumnBool(int col) const; + int ColumnInt(int col) const; + int64_t ColumnInt64(int col) const; + double ColumnDouble(int col) const; + std::string ColumnString(int col) const; + //string16 ColumnString16(int col) const; + + // When reading a blob, you can get a raw pointer to the underlying data, + // along with the length, or you can just ask us to copy the blob into a + // vector. Danger! ColumnBlob may return NULL if there is no data! + int ColumnByteLength(int col) const; + const void* ColumnBlob(int col) const; + bool ColumnBlobAsString(int col, std::string* blob); + //bool ColumnBlobAsString16(int col, string16* val) const; + bool ColumnBlobAsVector(int col, std::vector<char>* val) const; + bool ColumnBlobAsVector(int col, std::vector<unsigned char>* val) const; + + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/StatementId.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "StatementId.h" + +#include <string.h> + +namespace Palantir +{ + namespace SQLite + { + bool StatementId::operator< (const StatementId& other) const + { + if (line_ != other.line_) + return line_ < other.line_; + + return strcmp(file_, other.file_) < 0; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/StatementId.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,43 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +namespace Palantir +{ + namespace SQLite + { + class StatementId + { + private: + const char* file_; + int line_; + + StatementId(); // Forbidden + + public: + StatementId(const char* file, int line) : file_(file), line_(line) + { + } + + bool operator< (const StatementId& other) const; + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/StatementReference.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,116 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "StatementReference.h" + +#include "../PalantirException.h" + +#include <cassert> +#include "sqlite3.h" + +namespace Palantir +{ + namespace SQLite + { + bool StatementReference::IsRoot() const + { + return root_ == NULL; + } + + StatementReference::StatementReference() + { + root_ = NULL; + refCount_ = 0; + statement_ = NULL; + assert(IsRoot()); + } + + StatementReference::StatementReference(sqlite3* database, + const char* sql) + { + if (database == NULL || sql == NULL) + { + throw PalantirException(ErrorCode_ParameterOutOfRange); + } + + root_ = NULL; + refCount_ = 0; + + int error = sqlite3_prepare_v2(database, sql, -1, &statement_, NULL); + if (error != SQLITE_OK) + { + throw PalantirException("SQLite: " + std::string(sqlite3_errmsg(database))); + } + + assert(IsRoot()); + } + + StatementReference::StatementReference(StatementReference& other) + { + refCount_ = 0; + + if (other.IsRoot()) + { + root_ = &other; + } + else + { + root_ = other.root_; + } + + root_->refCount_++; + statement_ = root_->statement_; + + assert(!IsRoot()); + } + + StatementReference::~StatementReference() + { + if (IsRoot()) + { + if (refCount_ != 0) + { + // There remain references to this object + throw PalantirException(ErrorCode_InternalError); + } + else if (statement_ != NULL) + { + sqlite3_finalize(statement_); + } + } + else + { + if (root_->refCount_ == 0) + { + throw PalantirException(ErrorCode_InternalError); + } + else + { + root_->refCount_--; + } + } + } + + uint32_t StatementReference::GetReferenceCount() const + { + return refCount_; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/StatementReference.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,63 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <boost/noncopyable.hpp> +#include <stdint.h> +#include <cassert> +#include <stdlib.h> + +struct sqlite3; +struct sqlite3_stmt; + +namespace Palantir +{ + namespace SQLite + { + class StatementReference : boost::noncopyable + { + private: + StatementReference* root_; // Only used for non-root nodes + uint32_t refCount_; // Only used for root node + struct sqlite3_stmt* statement_; + + bool IsRoot() const; + + public: + StatementReference(); + + StatementReference(sqlite3* database, + const char* sql); + + StatementReference(StatementReference& other); + + ~StatementReference(); + + uint32_t GetReferenceCount() const; + + struct sqlite3_stmt* GetWrappedObject() const + { + assert(statement_ != NULL); + return statement_; + } + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/Transaction.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,84 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "Transaction.h" + +namespace Palantir +{ + namespace SQLite + { + Transaction::Transaction(Connection& connection) : + connection_(connection), + isOpen_(false) + { + } + + Transaction::~Transaction() + { + if (isOpen_) + { + connection_.RollbackTransaction(); + } + } + + void Transaction::Begin() + { + if (isOpen_) + { + throw PalantirException("SQLite: Beginning a transaction twice!"); + } + + isOpen_ = connection_.BeginTransaction(); + if (!isOpen_) + { + throw PalantirException("SQLite: Unable to create a transaction"); + } + } + + void Transaction::Rollback() + { + if (!isOpen_) + { + throw PalantirException("SQLite: Attempting to roll back a nonexistent transaction. " + "Did you remember to call Begin()?"); + } + + isOpen_ = false; + + connection_.RollbackTransaction(); + } + + void Transaction::Commit() + { + if (!isOpen_) + { + throw PalantirException("SQLite: Attempting to roll back a nonexistent transaction. " + "Did you remember to call Begin()?"); + } + + isOpen_ = false; + + if (!connection_.CommitTransaction()) + { + throw PalantirException("SQLite: Failure when committing the transaction"); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/SQLite/Transaction.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,58 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "Connection.h" + +namespace Palantir +{ + namespace SQLite + { + class Transaction : public boost::noncopyable + { + private: + Connection& connection_; + + // True when the transaction is open, false when it's already been committed + // or rolled back. + bool isOpen_; + + public: + explicit Transaction(Connection& connection); + ~Transaction(); + + // Returns true when there is a transaction that has been successfully begun. + bool IsOpen() const { return isOpen_; } + + // Begins the transaction. This uses the default sqlite "deferred" transaction + // type, which means that the DB lock is lazily acquired the next time the + // database is accessed, not in the begin transaction command. + void Begin(); + + // Rolls back the transaction. This will happen automatically if you do + // nothing when the transaction goes out of scope. + void Rollback(); + + // Commits the transaction, returning true on success. + void Commit(); + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Toolbox.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,295 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "Toolbox.h" + +#include "PalantirException.h" + +#include <string.h> +#include <boost/filesystem.hpp> +#include <boost/filesystem/fstream.hpp> +#include <algorithm> + +#if defined(_WIN32) +#include <windows.h> +#endif + +#if defined(__linux) +#include <unistd.h> +#endif + +#include <signal.h> + +namespace Palantir +{ + static bool finish; + + static void SignalHandler(int) + { + finish = true; + } + + + void Toolbox::Sleep(uint32_t seconds) + { +#if defined(_WIN32) + ::Sleep(static_cast<DWORD>(seconds) * static_cast<DWORD>(1000)); +#elif defined(__linux) + usleep(static_cast<uint64_t>(seconds) * static_cast<uint64_t>(1000000)); +#else +#error Support your platform here +#endif + } + + void Toolbox::USleep(uint64_t microSeconds) + { +#if defined(_WIN32) + ::Sleep(microSeconds / static_cast<uint64_t>(1000)); +#elif defined(__linux) + usleep(microSeconds); +#else +#error Support your platform here +#endif + } + + + void Toolbox::ServerBarrier() + { + signal(SIGINT, SignalHandler); + +#if !defined(_WIN32) + signal(SIGQUIT, SignalHandler); +#endif + + finish = false; + while (!finish) + { + USleep(100000); + } + + signal(SIGINT, NULL); + +#if !defined(_WIN32) + signal(SIGQUIT, NULL); +#endif + } + + + + void Toolbox::ToUpperCase(std::string& s) + { + std::transform(s.begin(), s.end(), s.begin(), toupper); + } + + + void Toolbox::ToLowerCase(std::string& s) + { + std::transform(s.begin(), s.end(), s.begin(), tolower); + } + + + + void Toolbox::ReadFile(std::string& content, + const std::string& path) + { + boost::filesystem::ifstream f; + f.open(path, std::ifstream::in | std::ios::binary); + if (!f.good()) + { + throw PalantirException("Unable to open a file"); + } + + // http://www.cplusplus.com/reference/iostream/istream/tellg/ + f.seekg(0, std::ios::end); + std::streamsize size = f.tellg(); + f.seekg(0, std::ios::beg); + + content.resize(size); + if (size != 0) + { + f.read(reinterpret_cast<char*>(&content[0]), size); + } + + f.close(); + } + + + void Toolbox::RemoveFile(const std::string& path) + { + if (boost::filesystem::exists(path)) + { + if (boost::filesystem::is_regular_file(path)) + boost::filesystem::remove(path); + else + throw PalantirException("The path is not a regular file: " + path); + } + } + + + + void Toolbox::SplitUriComponents(UriComponents& components, + const std::string& uri) + { + static const char URI_SEPARATOR = '/'; + + components.clear(); + + if (uri.size() == 0 || + uri[0] != URI_SEPARATOR) + { + throw PalantirException(ErrorCode_UriSyntax); + } + + // Count the number of slashes in the URI to make an assumption + // about the number of components in the URI + unsigned int estimatedSize = 0; + for (unsigned int i = 0; i < uri.size(); i++) + { + if (uri[i] == URI_SEPARATOR) + estimatedSize++; + } + + components.reserve(estimatedSize - 1); + + unsigned int start = 1; + unsigned int end = 1; + while (end < uri.size()) + { + // This is the loop invariant + assert(uri[start - 1] == '/' && (end >= start)); + + if (uri[end] == '/') + { + components.push_back(std::string(&uri[start], end - start)); + end++; + start = end; + } + else + { + end++; + } + } + + if (start < uri.size()) + { + components.push_back(std::string(&uri[start], end - start)); + } + } + + + bool Toolbox::IsChildUri(const UriComponents& baseUri, + const UriComponents& testedUri) + { + if (testedUri.size() < baseUri.size()) + { + return false; + } + + for (size_t i = 0; i < baseUri.size(); i++) + { + if (baseUri[i] != testedUri[i]) + return false; + } + + return true; + } + + + std::string Toolbox::AutodetectMimeType(const std::string& path) + { + std::string contentType; + size_t lastDot = path.rfind('.'); + size_t lastSlash = path.rfind('/'); + + if (lastDot == std::string::npos || + (lastSlash != std::string::npos && lastDot < lastSlash)) + { + // No trailing dot, unable to detect the content type + } + else + { + const char* extension = &path[lastDot + 1]; + + // http://en.wikipedia.org/wiki/Mime_types + // Text types + if (!strcmp(extension, "txt")) + contentType = "text/plain"; + else if (!strcmp(extension, "html")) + contentType = "text/html"; + else if (!strcmp(extension, "xml")) + contentType = "text/xml"; + else if (!strcmp(extension, "css")) + contentType = "text/css"; + + // Application types + else if (!strcmp(extension, "js")) + contentType = "application/javascript"; + else if (!strcmp(extension, "json")) + contentType = "application/json"; + else if (!strcmp(extension, "pdf")) + contentType = "application/pdf"; + + // Images types + else if (!strcmp(extension, "jpg") || !strcmp(extension, "jpeg")) + contentType = "image/jpeg"; + else if (!strcmp(extension, "gif")) + contentType = "image/gif"; + else if (!strcmp(extension, "png")) + contentType = "image/png"; + } + + return contentType; + } + + + std::string Toolbox::FlattenUri(const UriComponents& components, + size_t fromLevel) + { + if (components.size() <= fromLevel) + { + return "/"; + } + else + { + std::string r; + + for (size_t i = fromLevel; i < components.size(); i++) + { + r += "/" + components[i]; + } + + return r; + } + } + + + + uint64_t Toolbox::GetFileSize(const std::string& path) + { + try + { + return static_cast<uint64_t>(boost::filesystem::file_size(path)); + } + catch (boost::filesystem::filesystem_error) + { + throw PalantirException(ErrorCode_InexistentFile); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Toolbox.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,61 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <stdint.h> +#include <vector> +#include <string> + +namespace Palantir +{ + typedef std::vector<std::string> UriComponents; + + namespace Toolbox + { + void ServerBarrier(); + + void ToUpperCase(std::string& s); + + void ToLowerCase(std::string& s); + + void ReadFile(std::string& content, + const std::string& path); + + void Sleep(uint32_t seconds); + + void USleep(uint64_t microSeconds); + + void RemoveFile(const std::string& path); + + void SplitUriComponents(UriComponents& components, + const std::string& uri); + + bool IsChildUri(const UriComponents& baseUri, + const UriComponents& testedUri); + + std::string AutodetectMimeType(const std::string& path); + + std::string FlattenUri(const UriComponents& components, + size_t fromLevel = 0); + + uint64_t GetFileSize(const std::string& path); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Uuid.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,84 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "Uuid.h" + +// http://stackoverflow.com/a/1626302 + +extern "C" +{ +#ifdef WIN32 +#include <rpc.h> +#else +#include <uuid/uuid.h> +#endif +} + +namespace Palantir +{ + namespace Toolbox + { + 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 IsUuid(const std::string& str) + { + if (str.size() != 36) + { + return false; + } + + for (size_t i = 0; i < str.length(); i++) + { + if (i == 8 || i == 13 || i == 18 || i == 23) + { + if (str[i] != '-') + return false; + } + else + { + if (!isalnum(str[i])) + return false; + } + } + + return true; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Uuid.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,42 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> + +/** + * GUID vs. UUID + * The simple answer is: no difference, they are the same thing. Treat + * them as a 16 byte (128 bits) value that is used as a unique + * value. In Microsoft-speak they are called GUIDs, but call them + * UUIDs when not using Microsoft-speak. + * http://stackoverflow.com/questions/246930/is-there-any-difference-between-a-guid-and-a-uuid + **/ + +namespace Palantir +{ + namespace Toolbox + { + std::string GenerateUuid(); + + bool IsUuid(const std::string& str); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/INSTALL Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,68 @@ +Palantir - A Lightweight, RESTful DICOM Server +============================================== + + +Dependencies +------------ + +Palantir uses CMake (http://www.cmake.org/) to automate its building +process. You thus have to download and install CMake first. + +The other third party dependencies are automatically downloaded by the +CMake scripts. The downloaded packages are stored in the +"ThirdPartyDownloads" directory. + + + +Building Palantir at a glance +----------------------------- + +To build Palantir, you must: + +1) Download the source code (either using Mercurial, or through the + released versions). For the examples below, we assume the source + directory is "~/Palantir". + +2) Create a build directory. For the examples below, we assume the + build directory is "~/PalantirBuild". + + + +Native Linux Compilation +------------------------ + +To build binaries with debug information: + +# cd ~/PalantirBuild +# cmake -DCMAKE_BUILD_TYPE=DEBUG ~/Palantir +# make +# make doc + + +To build a release version: + +# cd ~/PalantirBuild +# cmake -DCMAKE_BUILD_TYPE=RELEASE ~/Palantir +# make +# make doc + + +Under Linux, you have the possibility to dynamically link Palantir +against the shared libraries of your system, provided their version is +recent enough. This greatly speeds up the compilation: + +# cd ~/PalantirBuild +# cmake -DSTATIC_BUILD=OFF -DCMAKE_BUILD_TYPE=DEBUG ~/Palantir +# make + + + +Cross-Compilation for Windows under Linux +----------------------------------------- + +To cross-compile Windows binaries under Linux using MinGW, please use +the following command: + +# cd ~/PalantirBuild +# cmake -DCMAKE_TOOLCHAIN_FILE=~/Palantir/Resources/MinGWToolchain.cmake -DCMAKE_BUILD_TYPE=DEBUG ~/Palantir +# make
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirCppClient/CMakeLists.txt Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,35 @@ +# Mini-project to check whether "PalantirCppClient" can compile in a +# standalone fashion + +cmake_minimum_required(VERSION 2.8) + +project(PalantirCppClientTest) + +SET(STATIC_BUILD OFF) + +include(${CMAKE_SOURCE_DIR}/../Resources/CMake/DownloadPackage.cmake) +include(${CMAKE_SOURCE_DIR}/../Resources/CMake/JsonCppConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/../Resources/CMake/LibCurlConfiguration.cmake) + +if (${CMAKE_COMPILER_IS_GNUCXX}) + set(CMAKE_C_FLAGS "-Wall -pedantic -Wno-implicit-function-declaration") # --std=c99 makes libcurl not to compile + set(CMAKE_CXX_FLAGS "-Wall -pedantic -Wno-long-long -Wno-variadic-macros") + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined") +elseif (${MSVC}) + add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) +endif() + +add_library(PalantirCppClient + SHARED + + ${THIRD_PARTY_SOURCES} + HttpException.cpp + HttpClient.cpp + ) + +add_executable(Test + main.cpp + ) + +target_link_libraries(Test PalantirCppClient)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirCppClient/HttpClient.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,195 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#include "HttpClient.h" + +#include <string.h> +#include <curl/curl.h> + + +namespace Palantir +{ + struct HttpClient::PImpl + { + CURL* curl_; + struct curl_slist *postHeaders_; + }; + + + static CURLcode CheckCode(CURLcode code) + { + if (code != CURLE_OK) + { + throw HttpException("CURL: " + std::string(curl_easy_strerror(code))); + } + + return code; + } + + + static size_t CurlCallback(void *buffer, size_t size, size_t nmemb, void *payload) + { + std::string& target = *(static_cast<std::string*>(payload)); + + size_t length = size * nmemb; + if (length == 0) + return 0; + + size_t pos = target.size(); + + target.resize(pos + length); + memcpy(&target.at(pos), buffer, length); + + return length; + } + + + HttpClient::HttpClient() : pimpl_(new PImpl) + { + pimpl_->postHeaders_ = NULL; + if ((pimpl_->postHeaders_ = curl_slist_append(pimpl_->postHeaders_, "Expect:")) == NULL) + { + throw HttpException("HttpClient: Not enough memory"); + } + + pimpl_->curl_ = curl_easy_init(); + if (!pimpl_->curl_) + { + curl_slist_free_all(pimpl_->postHeaders_); + throw HttpException("HttpClient: Not enough memory"); + } + + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEFUNCTION, &CurlCallback)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HEADER, 0)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_FOLLOWLOCATION, 1)); + + url_ = ""; + method_ = HttpMethod_Get; + lastStatus_ = HttpStatus_200_Ok; + isVerbose_ = false; + } + + + HttpClient::~HttpClient() + { + curl_easy_cleanup(pimpl_->curl_); + curl_slist_free_all(pimpl_->postHeaders_); + } + + + void HttpClient::SetVerbose(bool isVerbose) + { + isVerbose_ = isVerbose; + + if (isVerbose_) + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 1)); + } + else + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_VERBOSE, 0)); + } + } + + + bool HttpClient::Apply(std::string& answer) + { + answer.clear(); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_URL, url_.c_str())); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_WRITEDATA, &answer)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, NULL)); + + switch (method_) + { + case HttpMethod_Get: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPGET, 1L)); + break; + + case HttpMethod_Post: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POST, 1L)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_HTTPHEADER, pimpl_->postHeaders_)); + + if (postData_.size() > 0) + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, postData_.c_str())); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, postData_.size())); + } + else + { + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDS, NULL)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_POSTFIELDSIZE, 0)); + } + + break; + + case HttpMethod_Delete: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_NOBODY, 1L)); + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_CUSTOMREQUEST, "DELETE")); + break; + + case HttpMethod_Put: + CheckCode(curl_easy_setopt(pimpl_->curl_, CURLOPT_PUT, 1L)); + break; + + default: + throw HttpException("HttpClient: Internal error"); + } + + // Do the actual request + CheckCode(curl_easy_perform(pimpl_->curl_)); + + long status; + CheckCode(curl_easy_getinfo(pimpl_->curl_, CURLINFO_RESPONSE_CODE, &status)); + + if (status == 0) + { + // This corresponds to a call to an inexistent host + lastStatus_ = HttpStatus_500_InternalServerError; + } + else + { + lastStatus_ = static_cast<HttpStatus>(status); + } + + return (status >= 200 && status < 300); + } + + + bool HttpClient::Apply(Json::Value& answer) + { + std::string s; + if (Apply(s)) + { + Json::Reader reader; + return reader.parse(s, answer); + } + else + { + return false; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirCppClient/HttpClient.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,113 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#pragma once + +#include "HttpEnumerations.h" +#include "HttpException.h" + +#include <string> +#include <boost/shared_ptr.hpp> +#include <json/json.h> + +namespace Palantir +{ + class HttpClient + { + private: + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + std::string url_; + HttpMethod method_; + HttpStatus lastStatus_; + std::string postData_; + bool isVerbose_; + + public: + HttpClient(); + + ~HttpClient(); + + void SetUrl(const char* url) + { + url_ = std::string(url); + } + + void SetUrl(const std::string& url) + { + url_ = url; + } + + const std::string& GetUrl() const + { + return url_; + } + + void SetMethod(HttpMethod method) + { + method_ = method; + } + + HttpMethod GetMethod() const + { + return method_; + } + + std::string& AccessPostData() + { + return postData_; + } + + const std::string& AccessPostData() const + { + return postData_; + } + + void SetVerbose(bool isVerbose); + + bool IsVerbose() const + { + return isVerbose_; + } + + bool Apply(std::string& answer); + + bool Apply(Json::Value& answer); + + HttpStatus GetLastStatus() const + { + return lastStatus_; + } + + const char* GetLastStatusText() const + { + return HttpException::GetDescription(lastStatus_); + } + + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirCppClient/HttpEnumerations.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,109 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#pragma once + +namespace Palantir +{ + // Most common, non-joke and non-experimental HTTP status codes + // http://en.wikipedia.org/wiki/List_of_HTTP_status_codes + enum HttpStatus + { + HttpStatus_None = -1, + + // 1xx Informational + HttpStatus_100_Continue = 100, + HttpStatus_101_SwitchingProtocols = 101, + HttpStatus_102_Processing = 102, + + // 2xx Success + HttpStatus_200_Ok = 200, + HttpStatus_201_Created = 201, + HttpStatus_202_Accepted = 202, + HttpStatus_203_NonAuthoritativeInformation = 203, + HttpStatus_204_NoContent = 204, + HttpStatus_205_ResetContent = 205, + HttpStatus_206_PartialContent = 206, + HttpStatus_207_MultiStatus = 207, + HttpStatus_208_AlreadyReported = 208, + HttpStatus_226_IMUsed = 226, + + // 3xx Redirection + HttpStatus_300_MultipleChoices = 300, + HttpStatus_301_MovedPermanently = 301, + HttpStatus_302_Found = 302, + HttpStatus_303_SeeOther = 303, + HttpStatus_304_NotModified = 304, + HttpStatus_305_UseProxy = 305, + HttpStatus_307_TemporaryRedirect = 307, + + // 4xx Client Error + HttpStatus_400_BadRequest = 400, + HttpStatus_401_Unauthorized = 401, + HttpStatus_402_PaymentRequired = 402, + HttpStatus_403_Forbidden = 403, + HttpStatus_404_NotFound = 404, + HttpStatus_405_MethodNotAllowed = 405, + HttpStatus_406_NotAcceptable = 406, + HttpStatus_407_ProxyAuthenticationRequired = 407, + HttpStatus_408_RequestTimeout = 408, + HttpStatus_409_Conflict = 409, + HttpStatus_410_Gone = 410, + HttpStatus_411_LengthRequired = 411, + HttpStatus_412_PreconditionFailed = 412, + HttpStatus_413_RequestEntityTooLarge = 413, + HttpStatus_414_RequestUriTooLong = 414, + HttpStatus_415_UnsupportedMediaType = 415, + HttpStatus_416_RequestedRangeNotSatisfiable = 416, + HttpStatus_417_ExpectationFailed = 417, + HttpStatus_422_UnprocessableEntity = 422, + HttpStatus_423_Locked = 423, + HttpStatus_424_FailedDependency = 424, + HttpStatus_426_UpgradeRequired = 426, + + // 5xx Server Error + HttpStatus_500_InternalServerError = 500, + HttpStatus_501_NotImplemented = 501, + HttpStatus_502_BadGateway = 502, + HttpStatus_503_ServiceUnavailable = 503, + HttpStatus_504_GatewayTimeout = 504, + HttpStatus_505_HttpVersionNotSupported = 505, + HttpStatus_506_VariantAlsoNegotiates = 506, + HttpStatus_507_InsufficientStorage = 507, + HttpStatus_509_BandwidthLimitExceeded = 509, + HttpStatus_510_NotExtended = 510 + }; + + + enum HttpMethod + { + HttpMethod_Get, + HttpMethod_Post, + HttpMethod_Delete, + HttpMethod_Put + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirCppClient/HttpException.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,208 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#include "HttpException.h" + +namespace Palantir +{ + const char* HttpException::What() const + { + if (status_ == HttpStatus_None) + { + return custom_.c_str(); + } + else + { + return GetDescription(status_); + } + } + + const char* HttpException::GetDescription(HttpStatus status) + { + switch (status) + { + case HttpStatus_100_Continue: + return "Continue"; + + case HttpStatus_101_SwitchingProtocols: + return "Switching Protocols"; + + case HttpStatus_102_Processing: + return "Processing"; + + case HttpStatus_200_Ok: + return "OK"; + + case HttpStatus_201_Created: + return "Created"; + + case HttpStatus_202_Accepted: + return "Accepted"; + + case HttpStatus_203_NonAuthoritativeInformation: + return "Non-Authoritative Information"; + + case HttpStatus_204_NoContent: + return "No Content"; + + case HttpStatus_205_ResetContent: + return "Reset Content"; + + case HttpStatus_206_PartialContent: + return "Partial Content"; + + case HttpStatus_207_MultiStatus: + return "Multi-Status"; + + case HttpStatus_208_AlreadyReported: + return "Already Reported"; + + case HttpStatus_226_IMUsed: + return "IM Used"; + + case HttpStatus_300_MultipleChoices: + return "Multiple Choices"; + + case HttpStatus_301_MovedPermanently: + return "Moved Permanently"; + + case HttpStatus_302_Found: + return "Found"; + + case HttpStatus_303_SeeOther: + return "See Other"; + + case HttpStatus_304_NotModified: + return "Not Modified"; + + case HttpStatus_305_UseProxy: + return "Use Proxy"; + + case HttpStatus_307_TemporaryRedirect: + return "Temporary Redirect"; + + case HttpStatus_400_BadRequest: + return "Bad Request"; + + case HttpStatus_401_Unauthorized: + return "Unauthorized"; + + case HttpStatus_402_PaymentRequired: + return "Payment Required"; + + case HttpStatus_403_Forbidden: + return "Forbidden"; + + case HttpStatus_404_NotFound: + return "Not Found"; + + case HttpStatus_405_MethodNotAllowed: + return "Method Not Allowed"; + + case HttpStatus_406_NotAcceptable: + return "Not Acceptable"; + + case HttpStatus_407_ProxyAuthenticationRequired: + return "Proxy Authentication Required"; + + case HttpStatus_408_RequestTimeout: + return "Request Timeout"; + + case HttpStatus_409_Conflict: + return "Conflict"; + + case HttpStatus_410_Gone: + return "Gone"; + + case HttpStatus_411_LengthRequired: + return "Length Required"; + + case HttpStatus_412_PreconditionFailed: + return "Precondition Failed"; + + case HttpStatus_413_RequestEntityTooLarge: + return "Request Entity Too Large"; + + case HttpStatus_414_RequestUriTooLong: + return "Request-URI Too Long"; + + case HttpStatus_415_UnsupportedMediaType: + return "Unsupported Media Type"; + + case HttpStatus_416_RequestedRangeNotSatisfiable: + return "Requested Range Not Satisfiable"; + + case HttpStatus_417_ExpectationFailed: + return "Expectation Failed"; + + case HttpStatus_422_UnprocessableEntity: + return "Unprocessable Entity"; + + case HttpStatus_423_Locked: + return "Locked"; + + case HttpStatus_424_FailedDependency: + return "Failed Dependency"; + + case HttpStatus_426_UpgradeRequired: + return "Upgrade Required"; + + case HttpStatus_500_InternalServerError: + return "Internal Server Error"; + + case HttpStatus_501_NotImplemented: + return "Not Implemented"; + + case HttpStatus_502_BadGateway: + return "Bad Gateway"; + + case HttpStatus_503_ServiceUnavailable: + return "Service Unavailable"; + + case HttpStatus_504_GatewayTimeout: + return "Gateway Timeout"; + + case HttpStatus_505_HttpVersionNotSupported: + return "HTTP Version Not Supported"; + + case HttpStatus_506_VariantAlsoNegotiates: + return "Variant Also Negotiates"; + + case HttpStatus_507_InsufficientStorage: + return "Insufficient Storage"; + + case HttpStatus_509_BandwidthLimitExceeded: + return "Bandwidth Limit Exceeded"; + + case HttpStatus_510_NotExtended: + return "Not Extended"; + + default: + throw HttpException("Unknown HTTP status"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirCppClient/HttpException.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,63 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#pragma once + +#include "HttpEnumerations.h" + +#include <string> + +namespace Palantir +{ + class HttpException + { + private: + HttpStatus status_; + std::string custom_; + + public: + static const char* GetDescription(HttpStatus status); + + HttpException(const std::string& custom) + { + status_ = HttpStatus_None; + custom_ = custom; + } + + HttpException(HttpStatus status) + { + status_ = status; + } + + HttpStatus GetHttpStatus() const + { + return status_; + } + + const char* What() const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirCppClient/main.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,46 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU of Liege, + * Belgium + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + **/ + + +#include "HttpClient.h" + +#include <iostream> + +int main() +{ + // Prepare a simple call to a Web service + Palantir::HttpClient c; + c.SetUrl("http://nominatim.openstreetmap.org/search?format=json&q=chu+liege+belgium"); + + // Do the request and store the result in a JSON structure + Json::Value result; + c.Apply(result); + + // Display the JSON answer + std::cout << result << std::endl; + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/explorer.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,34 @@ +ul.tree ul { + margin-left: 36px; +} + +#progress { + position: relative; + /*height: 2em; */ + width: 100%; + background-color: grey; + height: 2.5em; +} + +#progress .label { + z-index: 10; + position: absolute; + left:0; + top: 0; + width: 100%; + font-weight: bold; + text-align: center; + text-shadow: none; + padding: .5em; + color: white; +} + +#progress .bar { + z-index: 0; + position: absolute; + left:0; + top: 0; + height: 100%; + width: 0%; + background-color: green; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/explorer.html Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,197 @@ +<!DOCTYPE html> + +<html> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>Palantir Explorer</title> + + <link rel="stylesheet" href="libs/jquery.mobile-1.1.0.min.css" /> + <link rel="stylesheet" href="libs/jqtree.css" /> + <link rel="stylesheet" href="libs/jquery.mobile.simpledialog.min.css" /> + <link rel="stylesheet" href="libs/jquery-file-upload/css/style.css" /> + <link rel="stylesheet" href="libs/jquery-file-upload/css/jquery.fileupload-ui.css" /> + <link rel="stylesheet" href="libs/slimbox2/slimbox2.css" /> + + <script src="libs/jquery-1.7.2.min.js"></script> + <script src="libs/jquery.mobile-1.1.0.min.js"></script> + <script src="libs/jqm.page.params.js"></script> + <script src="libs/tree.jquery.js"></script> + <script src="libs/date.js"></script> + <script src="libs/jquery.mobile.simpledialog2.js"></script> + <script src="libs/slimbox2.js"></script> + <script src="libs/jquery.blockUI.js"></script> + + <!-- https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin --> + <script src="libs/jquery-file-upload/js/vendor/jquery.ui.widget.js"></script> + <script src="libs/jquery-file-upload/js/jquery.iframe-transport.js"></script> + <script src="libs/jquery-file-upload/js/jquery.fileupload.js"></script> + + <link rel="stylesheet" href="explorer.css" /> + <script src="file-upload.js"></script> + <script src="explorer.js"></script> + </head> + <body> + <div data-role="page" id="find-patients" > + <div data-role="header" > + <h1>Find a patient</h1> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <ul id="all-patients" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + + <div data-role="page" id="upload" > + <div data-role="header" > + <h1>Upload DICOM files</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + </div> + <div data-role="content"> + <div style="display:none"> + <input id="fileupload" type="file" name="files[]" data-url="/instances/" multiple> + </div> + <p> + <ul data-role="listview" data-inset="true"> + <li data-icon="arrow-r" data-theme="e"><a href="#" id="upload-button">Start the upload</a></li> + <!--li data-icon="gear" data-theme="e"><a href="#" id="upload-abort" class="ui-disabled">Abort the current upload</a></li--> + <li data-icon="delete" data-theme="e"><a href="#" id="upload-clear">Clear the pending uploads</a></li> + </ul> + <div id="progress" class="ui-corner-all"> + <span class="bar ui-corner-all"></span> + <div class="label"></div> + </div> + </p> + <ul id="upload-list" data-role="listview" data-inset="true"> + <li data-role="list-divider">Drag and drop DICOM files here</li> + </ul> + </div> + </div> + + <div data-role="page" id="patient" > + <div data-role="header" > + <h1>List of the studies of one patient</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <div class="ui-grid-a"> + <div class="ui-block-a" style="width:30%"> + <div style="padding-right:10px"> + <ul data-role="listview" data-inset="true" data-theme="a" id="patient-info"> + </ul> + <p> + <a href="#find-patients" data-role="button" data-icon="search">Go to patient finder</a> + <a href="#" data-role="button" data-icon="delete" id="patient-delete">Delete this patient</a> + </p> + </div> + </div> + <div class="ui-block-b" style="width:70%"> + <div style="padding:10px"> + <ul id="list-studies" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + </div> + </div> + </div> + + <div data-role="page" id="study"> + <div data-role="header"> + <h1>List of the series of one study</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <div class="ui-grid-a"> + <div class="ui-block-a" style="width:30%"> + <div style="padding-right:10px"> + <ul data-role="listview" data-inset="true" data-theme="a" id="study-info"> + </ul> + <p> + <a href="#" data-role="button" data-icon="delete" id="study-delete">Delete this study</a> + </p> + </div> + </div> + <div class="ui-block-b" style="width:70%"> + <div style="padding:10px"> + <ul id="list-series" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + </div> + </div> + </div> + + <div data-role="page" id="series"> + <div data-role="header"> + <h1>List of the instances of one series</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <div class="ui-grid-a"> + <div class="ui-block-a" style="width:30%"> + <div style="padding-right:10px"> + <ul data-role="listview" data-inset="true" data-theme="a" id="series-info"> + </ul> + <p> + <a href="#" data-role="button" data-icon="delete" id="series-delete">Delete this series</a> + <a href="#" data-role="button" data-icon="arrow-d" id="series-preview">Preview this series</a> + <a href="#" data-role="button" data-icon="arrow-d" id="series-store">Store in another DICOM modality</a> + </p> + </div> + </div> + <div class="ui-block-b" style="width:70%"> + <div style="padding:10px"> + <ul id="list-instances" data-role="listview" data-inset="true" data-filter="true"> + </ul> + </div> + </div> + </div> + </div> + </div> + + <div data-role="page" id="instance"> + <div data-role="header"> + <h1>One DICOM instance</h1> + <a href="#find-patients" data-icon="search" class="ui-btn-left" data-direction="reverse">Find patient</a> + <a href="#upload" data-icon="gear" class="ui-btn-right">Upload DICOM</a> + </div> + <div data-role="content"> + <div class="ui-grid-a"> + <div class="ui-block-a" style="width:30%"> + <div style="padding-right:10px"> + <ul data-role="listview" data-inset="true" data-theme="a" id="instance-info"> + </ul> + <p> + <a href="#" data-role="button" data-icon="delete" id="instance-delete">Delete this instance</a> + <a href="#" data-role="button" data-icon="arrow-d" id="instance-download-dicom">Download the DICOM file</a> + <a href="#" data-role="button" data-icon="arrow-d" id="instance-download-json">Download the JSON file</a> + <a href="#" data-role="button" data-icon="arrow-d" id="instance-preview">Preview the instance</a> + <a href="#" data-role="button" data-icon="arrow-d" id="instance-store">Store in another DICOM modality</a> + </p> + </div> + </div> + <div class="ui-block-b" style="width:70%"> + <div style="padding:10px"> + <div class="ui-body ui-body-b"> + <h1>DICOM Tags</h1> + <div id="dicom-tree"></div> + </div> + </div> + </div> + </div> + </div> + </div> + + <div id="loading" style="display:none;" class="ui-body-c"> + <p align="center"><b>Sending to DICOM modality...</b></p> + <p><img src="libs/images/ajax-loader2.gif" alt="" /></p> + </div> + + <div id="dialog" style="display:none" > + </div> + </body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/explorer.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,645 @@ +// http://stackoverflow.com/questions/1663741/is-there-a-good-jquery-drag-and-drop-file-upload-plugin + + +// Forbid the access to IE +if ($.browser.msie) +{ + alert("Please use Mozilla Firefox or Google Chrome. Microsoft Internet Explorer is not supported."); +} + +// http://jquerymobile.com/demos/1.1.0/docs/api/globalconfig.html +//$.mobile.ajaxEnabled = false; +//$.mobile.page.prototype.options.addBackBtn = true; +//$.mobile.defaultPageTransition = 'slide'; + +// http://stackoverflow.com/a/4673436 +String.prototype.format = function() { + var args = arguments; + return this.replace(/{(\d+)}/g, function(match, number) { + /*return typeof args[number] != 'undefined' + ? args[number] + : match;*/ + + return args[number]; + }); +}; + + +$(document).ready(function() { + var $tree = $('#dicom-tree'); + $tree.tree({ + autoEscape: false + }); + + $('#dicom-tree').bind( + 'tree.click', + function(event) { + if (event.node.is_open) + $tree.tree('closeNode', event.node, true); + else + $tree.tree('openNode', event.node, true); + } + ); +}); + + +function SplitLongUid(s) +{ + return '<span>' + s.substr(0, s.length / 2) + '</span> <span>' + s.substr(s.length / 2, s.length - s.length / 2) + '</span>'; +} + + +function ParseDicomDate(s) +{ + y = parseInt(s.substr(0, 4), 10); + m = parseInt(s.substr(4, 2), 10) - 1; + d = parseInt(s.substr(6, 2), 10); + + if (y == null || m == null || d == null || + !isFinite(y) || !isFinite(m) || !isFinite(d)) + { + return null; + } + + if (y < 1900 || y > 2100 || + m < 0 || m >= 12 || + d <= 0 || d >= 32) + { + return null; + } + + return new Date(y, m, d); +} + + +function FormatDicomDate(s) +{ + if (s == undefined) + return "No date"; + + var d = ParseDicomDate(s); + if (d == null) + return '?'; + else + return d.toString('dddd, MMMM d, yyyy'); +} + + + +function SortOnDicomTag(arr, tag, isInteger, reverse) +{ + arr.sort(function(a, b) { + var ta = a.MainDicomTags[tag]; + var tb = b.MainDicomTags[tag]; + var order; + + if (isInteger) + { + ta = parseInt(ta, 10); + tb = parseInt(tb, 10); + order = ta - tb; + } + else + { + if (ta < tb) + order = -1; + else if (ta > tb) + order = 1; + else + order = 0; + } + + if (reverse) + return -order; + else + return order; + }); +} + + + +function GetSingleResource(type, uuid, callback) +{ + var resource = null; + $.ajax({ + url: '/' + type + '/' + uuid, + dataType: 'json', + async: false, + success: function(s) { + callback(s); + } + }); +} + + +function GetMultipleResources(type, uuids, callback) +{ + if (uuids == null) + { + $.ajax({ + url: '/' + type, + dataType: 'json', + async: false, + success: function(s) { + uuids = s; + } + }); + } + + var resources = []; + var ajaxRequests = uuids.map(function(uuid) { + return $.ajax({ + url: '/' + type + '/' + uuid, + dataType: 'json', + async: true, + success: function(s) { + resources.push(s); + } + }); + }); + + // Wait for all the AJAX requests to end + $.when.apply($, ajaxRequests).then(function() { + callback(resources); + }); +} + + + +function CompleteFormatting(s, link, isReverse) +{ + if (link != null) + { + s = 'href="' + link + '">' + s + '</a>'; + + if (isReverse) + s = 'data-direction="reverse" '+ s; + + s = '<a ' + s; + } + + if (isReverse) + return '<li data-icon="back">' + s + '</li>'; + else + return '<li>' + s + '</li>'; +} + + + +function FormatPatient(patient, link, isReverse) +{ + var s = ('<h3>{1}</h3>' + + '<p>Patient ID: <strong>{2}</strong></p>' + + '<p>Accession Number: <strong>{3}</strong></p>' + + '<p>Date of Birth: <strong>{4}</strong></p>' + + '<p>Sex: <strong>{5}</strong></p>' + + '<span class="ui-li-count">{6}</span>' + ).format + (link, + patient.MainDicomTags.PatientName, + patient.DicomPatientID, + patient.MainDicomTags.AccessionNumber, + FormatDicomDate(patient.MainDicomTags.PatientBirthDate), + patient.MainDicomTags.PatientSex, + patient.Studies.length + ); + + return CompleteFormatting(s, link, isReverse); +} + + + +function FormatStudy(study, link, isReverse) +{ + var s = ('<h3>{0}</h3>' + + '<p>Study Instance UID: <strong>{1}</strong></p>' + + '<span class="ui-li-count">{2}</span>' + ).format + (study.MainDicomTags.StudyDescription, + SplitLongUid(study.DicomStudyInstanceUID), + study.Series.length + ); + + return CompleteFormatting(s, link, isReverse); +} + + + +function FormatSeries(series, link, isReverse) +{ + var s = ('<h3>{0}</h3>' + + '<p>Modality: <strong>{1}</strong></p>' + + '<p>Protocol: <strong>{2}</strong></p>' + + '<p>Station name: <strong>{3}</strong></p>' + + '<p>Series Instance UID: <strong>{4}</strong></p>' + + '<span class="ui-li-count">{5}</span>').format + (series.MainDicomTags.SeriesDescription, + series.MainDicomTags.Modality, + series.MainDicomTags.ProtocolName, + series.MainDicomTags.StationName, + SplitLongUid(series.DicomSeriesInstanceUID), + series.Instances.length + ); + + return CompleteFormatting(s, link, isReverse); +} + + +function FormatInstance(instance, link, isReverse) +{ + var s = ('<h3>Instance {0}</h3>' + + '<p>SOP Instance UID: <strong>{1}</strong></p>' + ).format + (instance.MainDicomTags.InstanceNumber, + instance.DicomSOPInstanceUID + ); + + return CompleteFormatting(s, link, isReverse); +} + + + + +$('#find-patients').live('pagebeforeshow', function() { + GetMultipleResources('patients', null, function(patients) { + var target = $('#all-patients'); + $('li', target).remove(); + + SortOnDicomTag(patients, 'PatientName', false, false); + + for (var i = 0; i < patients.length; i++) { + var p = FormatPatient(patients[i], '#patient?uuid=' + patients[i].ID); + target.append(p); + } + + target.listview('refresh'); + }); +}); + + + +$('#patient').live('pagebeforeshow', function() { + if ($.mobile.pageData) { + GetSingleResource('patients', $.mobile.pageData.uuid, function(patient) { + GetMultipleResources('studies', patient.Studies, function(studies) { + SortOnDicomTag(studies, 'StudyDate', false, true); + + $('#patient-info li').remove(); + $('#patient-info') + .append('<li data-role="list-divider">Patient</li>') + .append(FormatPatient(patient)) + .listview('refresh'); + + var target = $('#list-studies'); + $('li', target).remove(); + + for (var i = 0; i < studies.length; i++) { + if (i == 0 || studies[i].MainDicomTags.StudyDate != studies[i - 1].MainDicomTags.StudyDate) + { + target.append('<li data-role="list-divider">{0}</li>'.format + (FormatDicomDate(studies[i].MainDicomTags.StudyDate))); + } + + target.append(FormatStudy(studies[i], '#study?uuid=' + studies[i].ID)); + } + + target.listview('refresh'); + }); + }); + } +}); + + +$('#study').live('pagebeforeshow', function() { + if ($.mobile.pageData) { + GetSingleResource('studies', $.mobile.pageData.uuid, function(study) { + GetSingleResource('patients', study.ParentPatient, function(patient) { + GetMultipleResources('series', study.Series, function(series) { + SortOnDicomTag(series, 'SeriesDate', false, true); + + $('#study-info li').remove(); + $('#study-info') + .append('<li data-role="list-divider">Patient</li>') + .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) + .append('<li data-role="list-divider">Study</li>') + .append(FormatStudy(study)) + .listview('refresh'); + + var target = $('#list-series'); + $('li', target).remove(); + for (var i = 0; i < series.length; i++) { + if (i == 0 || series[i].MainDicomTags.SeriesDate != series[i - 1].MainDicomTags.SeriesDate) + { + target.append('<li data-role="list-divider">{0}</li>'.format + (FormatDicomDate(series[i].MainDicomTags.SeriesDate))); + } + target.append(FormatSeries(series[i], '#series?uuid=' + series[i].ID)); + } + target.listview('refresh'); + }); + }); + }); + } +}); + + +$('#series').live('pagebeforeshow', function() { + if ($.mobile.pageData) { + GetSingleResource('series', $.mobile.pageData.uuid, function(series) { + GetSingleResource('studies', series.ParentStudy, function(study) { + GetSingleResource('patients', study.ParentPatient, function(patient) { + GetMultipleResources('instances', series.Instances, function(instances) { + SortOnDicomTag(instances, 'InstanceNumber', true, false); + + $('#series-info li').remove(); + $('#series-info') + .append('<li data-role="list-divider">Patient</li>') + .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) + .append('<li data-role="list-divider">Study</li>') + .append(FormatStudy(study, '#study?uuid=' + study.ID, true)) + .append('<li data-role="list-divider">Series</li>') + .append(FormatSeries(series)) + .listview('refresh'); + + var target = $('#list-instances'); + $('li', target).remove(); + for (var i = 0; i < instances.length; i++) { + target.append(FormatInstance(instances[i], '#instance?uuid=' + instances[i].ID)); + } + target.listview('refresh'); + }); + }); + }); + }); + } +}); + + + +function ConvertForTree(dicom) +{ + var result = []; + + for (var i in dicom) { + if (dicom [i] != null) { + if (typeof dicom[i] == 'string') + { + result.push({ + label: i + ': <strong>' + dicom[i] + '</strong>', + children: [] + }); + } + else if (typeof dicom[i] == 'number') + { + result.push({ + label: i + ': <i>Too long</i>', + children: [] + }); + } + else + { + var c = []; + for (var j = 0; j < dicom[i].length; j++) { + c.push({ + label: 'Item ' + j, + children: ConvertForTree(dicom[i][j]) + }); + } + + result.push({ + label: i + '[]', + children: c + }); + } + } + } + + return result; +} + + +$('#instance').live('pagebeforeshow', function() { + if ($.mobile.pageData) { + GetSingleResource('instances', $.mobile.pageData.uuid, function(instance) { + GetSingleResource('series', instance.ParentSeries, function(series) { + GetSingleResource('studies', series.ParentStudy, function(study) { + GetSingleResource('patients', study.ParentPatient, function(patient) { + + $('#instance-info li').remove(); + $('#instance-info') + .append('<li data-role="list-divider">Patient</li>') + .append(FormatPatient(patient, '#patient?uuid=' + patient.ID, true)) + .append('<li data-role="list-divider">Study</li>') + .append(FormatStudy(study, '#study?uuid=' + study.ID, true)) + .append('<li data-role="list-divider">Series</li>') + .append(FormatSeries(series, '#series?uuid=' + series.ID, true)) + .append('<li data-role="list-divider">Instance</li>') + .append(FormatInstance(instance)) + .listview('refresh'); + + $.ajax({ + url: '/instances/' + instance.ID + '/all-tags', + dataType: 'json', + success: function(s) { + $('#dicom-tree').tree('loadData', ConvertForTree(s)); + } + }); + + }); + }); + }); + }); + } +}); + + + +function DeleteResource(path) +{ + $.ajax({ + url: path, + type: 'DELETE', + dataType: 'json', + async: false, + success: function(s) { + var ancestor = s.RemainingAncestor; + if (ancestor == null) + $.mobile.changePage('#find-patients'); + else + $.mobile.changePage('#' + ancestor.Type + '?uuid=' + ancestor.ID); + } + }); +} + + + +function OpenDeleteResourceDialog(path, title) +{ + $(document).simpledialog2({ + // http://dev.jtsage.com/jQM-SimpleDialog/demos2/ + // http://dev.jtsage.com/jQM-SimpleDialog/demos2/options.html + mode: 'button', + animate: false, + headerText: title, + headerClose: true, + width: '500px', + buttons : { + 'OK': { + click: function () { + DeleteResource(path); + }, + icon: "delete", + theme: "c" + }, + 'Cancel': { + click: function () { + } + } + } + }); +} + + + +$('#instance-delete').live('click', function() { + OpenDeleteResourceDialog('/instances/' + $.mobile.pageData.uuid, + 'Delete this instance?'); +}); + +$('#study-delete').live('click', function() { + OpenDeleteResourceDialog('/studies/' + $.mobile.pageData.uuid, + 'Delete this study?'); +}); + +$('#series-delete').live('click', function() { + OpenDeleteResourceDialog('/series/' + $.mobile.pageData.uuid, + 'Delete this series?'); +}); + +$('#patient-delete').live('click', function() { + OpenDeleteResourceDialog('/patients/' + $.mobile.pageData.uuid, + 'Delete this patient?'); +}); + + +$('#instance-download-dicom').live('click', function(e) { + // http://stackoverflow.com/a/1296101 + e.preventDefault(); //stop the browser from following + window.location.href = '/instances/' + $.mobile.pageData.uuid + '/file'; +}); + +$('#instance-download-json').live('click', function(e) { + // http://stackoverflow.com/a/1296101 + e.preventDefault(); //stop the browser from following + window.location.href = '/instances/' + $.mobile.pageData.uuid + '/all-tags'; +}); + + +$('#instance-preview').live('click', function(e) { + jQuery.slimbox('/instances/' + $.mobile.pageData.uuid + '/normalized-image', '', { + overlayFadeDuration : 1, + resizeDuration : 1, + imageFadeDuration : 1 + }); +}); + +$('#series-preview').live('click', function(e) { + if ($.mobile.pageData) { + GetSingleResource('series', $.mobile.pageData.uuid, function(series) { + GetMultipleResources('instances', series.Instances, function(instances) { + SortOnDicomTag(instances, 'InstanceNumber', true, false); + + var images = []; + for (var i = 0; i < instances.length; i++) { + images.push([ '/instances/' + instances[i].ID + '/normalized-image', + '{0}/{1}'.format(i + 1, instances.length) ]) + } + + jQuery.slimbox(images, 0, { + overlayFadeDuration : 1, + resizeDuration : 1, + imageFadeDuration : 1, + loop : true + }); + }) + }); + } +}); + + + + + + +function ChooseDicomModality(callback) +{ + $.ajax({ + url: '/modalities', + type: 'GET', + dataType: 'json', + async: false, + success: function(modalities) { + var clickedModality = ''; + var items = $('<ul>') + .attr('data-role', 'listview'); + + for (var i = 0; i < modalities.length; i++) { + var modality = modalities[i]; + var item = $('<li>') + .html('<a href="#" rel="close">' + modality + '</a>') + .attr('modality', modality) + .click(function() { + clickedModality = $(this).attr('modality'); + }); + items.append(item); + } + + $('#dialog').simpledialog2({ + mode: 'blank', + animate: false, + headerText: 'DICOM modality', + headerClose: true, + width: '100%', + blankContent: items, + callbackClose: function() { + var timer; + function WaitForDialogToClose() { + if (!$('#dialog').is(':visible')) { + clearInterval(timer); + callback(clickedModality); + } + } + timer = setInterval(WaitForDialogToClose, 100); + } + }); + } + }); +} + + +$('#instance-store,#series-store').live('click', function(e) { + ChooseDicomModality(function(modality) { + if (modality != '') { + $.ajax({ + url: '/modalities/' + modality + '/store', + type: 'POST', + dataType: 'text', + data: $.mobile.pageData.uuid, + async: true, // Necessary to block UI + beforeSend: function() { + $.blockUI({ message: $('#loading') }); + }, + complete: function(s) { + $.unblockUI(); + }, + success: function(s) { + console.log('done !'); + }, + error: function() { + alert('Error during C-Store'); + } + }); + + } + }); +});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/file-upload.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,88 @@ +var pendingUploads = []; +var currentUpload = 0; +var totalUpload = 0; + +$(document).ready(function() { + // Initialize the jQuery File Upload widget: + $('#fileupload').fileupload({ + //dataType: 'json', + //maxChunkSize: 500, + //sequentialUploads: true, + limitConcurrentUploads: 3, + add: function (e, data) { + pendingUploads.push(data); + } + }) + .bind('fileuploadstop', function(e, data) { + $('#upload-button').removeClass('ui-disabled'); + //$('#upload-abort').addClass('ui-disabled'); + $('#progress .bar').css('width', '100%'); + if ($('#progress .label').text() != 'Failure') + $('#progress .label').text('Done'); + }) + .bind('fileuploadfail', function(e, data) { + $('#progress .bar') + .css('width', '100%') + .css('background-color', 'red'); + $('#progress .label').text('Failure'); + }) + .bind('fileuploaddrop', function (e, data) { + var target = $('#upload-list'); + $.each(data.files, function (index, file) { + target.append('<li class="pending-file">' + file.name + '</li>'); + }); + target.listview('refresh'); + }) + .bind('fileuploadsend', function (e, data) { + // Update the progress bar. Note: for some weird reason, the + // "fileuploadprogressall" does not work under Firefox. + var progress = parseInt(currentUpload / totalUploads * 100, 10); + currentUpload += 1; + $('#progress .label').text('Uploading: ' + progress + '%'); + $('#progress .bar') + .css('width', progress + '%') + .css('background-color', 'green'); + }); +}); + + + +$('#upload').live('pageshow', function() { + $('#fileupload').fileupload('enable'); +}); + +$('#upload').live('pagehide', function() { + $('#fileupload').fileupload('disable'); +}); + + +$('#upload-button').live('click', function() { + var pu = pendingUploads; + pendingUploads = []; + + $('.pending-file').remove(); + $('#upload-list').listview('refresh'); + $('#progress .bar').css('width', '0%'); + $('#progress .label').text(''); + + currentUpload = 1; + totalUploads = pu.length + 1; + if (pu.length > 0) { + $('#upload-button').addClass('ui-disabled'); + //$('#upload-abort').removeClass('ui-disabled'); + } + + for (var i = 0; i < pu.length; i++) { + pu[i].submit(); + } +}); + +$('#upload-clear').live('click', function() { + pendingUploads = []; + $('.pending-file').remove(); + $('#upload-list').listview('refresh'); +}); + +/*$('#upload-abort').live('click', function() { + $('#fileupload').fileupload().abort(); + });*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/date.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,104 @@ +/** + * Version: 1.0 Alpha-1 + * Build Date: 13-Nov-2007 + * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved. + * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. + * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/ + */ +Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}}; +Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}} +return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}} +return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}} +return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);} +if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;} +var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);} +if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);} +if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);} +if(x.hour||x.hours){this.addHours(x.hour||x.hours);} +if(x.month||x.months){this.addMonths(x.month||x.months);} +if(x.year||x.years){this.addYears(x.year||x.years);} +if(x.day||x.days){this.addDays(x.day||x.days);} +return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");} +return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;} +if(!x.second&&x.second!==0){x.second=-1;} +if(!x.minute&&x.minute!==0){x.minute=-1;} +if(!x.hour&&x.hour!==0){x.hour=-1;} +if(!x.day&&x.day!==0){x.day=-1;} +if(!x.month&&x.month!==0){x.month=-1;} +if(!x.year&&x.year!==0){x.year=-1;} +if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());} +if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());} +if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());} +if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());} +if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());} +if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());} +if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());} +if(x.timezone){this.setTimezone(x.timezone);} +if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);} +return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;} +var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}} +return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();}; +Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;} +return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);} +var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;} +return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);} +var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";} +return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}}; +(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;} +break;} +return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];} +rx.push(r[0]);s=r[1];} +return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];} +return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];} +throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));} +return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;} +if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;} +try{r=(px[i].call(this,s));}catch(e){r=null;} +if(r){return r;}} +throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;} +try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);} +rx.push(r[0]);s=r[1];} +return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];} +return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;} +rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;} +s=q[1];} +if(!r){throw new $P.Exception(s);} +if(q){throw new $P.Exception(q[1]);} +if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}} +return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;} +rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;} +if(!last&&q[1].length===0){last=true;} +if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}} +p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}} +if(rx[1].length<best[1].length){best=rx;} +if(best[1].length===0){break;}} +if(best[0].length===0){return best;} +if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);} +best[1]=q[1];} +return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);} +return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];} +if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);} +var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}} +return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}} +this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");} +var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});} +return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;} +for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}} +if(this.now){return new Date();} +var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);} +if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;} +if(!this.unit){this.unit="day";} +if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;} +if(this.unit=="week"){this.unit="day";this.value=this.value*7;} +this[this.unit+"s"]=this.value*orient;} +return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;} +if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();} +if(this.month&&!this.day){this.day=1;} +return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));} +fn=_C[keys]=_.any.apply(null,px);} +return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));} +return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){} +return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;} +try{r=Date.Grammar.start.call({},s);}catch(e){return null;} +return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;} +return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jqm.page.params.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,111 @@ +// jqm.page.params.js - version 0.1 +// Copyright (c) 2011, Kin Blas +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of the <organization> nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 <COPYRIGHT HOLDER> 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. + +(function( $, window, undefined ) { + +// Given a query string, convert all the name/value pairs +// into a property/value object. If a name appears more than +// once in a query string, the value is automatically turned +// into an array. +function queryStringToObject( qstr ) +{ + var result = {}, + nvPairs = ( ( qstr || "" ).replace( /^\?/, "" ).split( /&/ ) ), + i, pair, n, v; + + for ( i = 0; i < nvPairs.length; i++ ) { + var pstr = nvPairs[ i ]; + if ( pstr ) { + pair = pstr.split( /=/ ); + n = pair[ 0 ]; + v = pair[ 1 ]; + if ( result[ n ] === undefined ) { + result[ n ] = v; + } else { + if ( typeof result[ n ] !== "object" ) { + result[ n ] = [ result[ n ] ]; + } + result[ n ].push( v ); + } + } + } + + return result; +} + +// The idea here is to listen for any pagebeforechange notifications from +// jQuery Mobile, and then muck with the toPage and options so that query +// params can be passed to embedded/internal pages. So for example, if a +// changePage() request for a URL like: +// +// http://mycompany.com/myapp/#page-1?foo=1&bar=2 +// +// is made, the page that will actually get shown is: +// +// http://mycompany.com/myapp/#page-1 +// +// The browser's location will still be updated to show the original URL. +// The query params for the embedded page are also added as a property/value +// object on the options object. You can access it from your page notifications +// via data.options.pageData. +$( document ).bind( "pagebeforechange", function( e, data ) { + + // We only want to handle the case where we are being asked + // to go to a page by URL, and only if that URL is referring + // to an internal page by id. + + if ( typeof data.toPage === "string" ) { + var u = $.mobile.path.parseUrl( data.toPage ); + if ( $.mobile.path.isEmbeddedPage( u ) ) { + // The request is for an internal page, if the hash + // contains query (search) params, strip them off the + // toPage URL and then set options.dataUrl appropriately + // so the location.hash shows the originally requested URL + // that hash the query params in the hash. + + var u2 = $.mobile.path.parseUrl( u.hash.replace( /^#/, "" ) ); + if ( u2.search ) { + if ( !data.options.dataUrl ) { + data.options.dataUrl = data.toPage; + } + data.options.pageData = queryStringToObject( u2.search ); + data.toPage = u.hrefNoHash + "#" + u2.pathname; + } + } + } +}); + +})( jQuery, window ); + + + + +// http://stackoverflow.com/a/8295488 +$(document).bind("pagebeforechange", function( event, data ) { + $.mobile.pageData = (data && data.options && data.options.pageData) + ? data.options.pageData + : {}; +});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jqtree.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,143 @@ +ul.tree { + margin-left: 12px; +} + +ul.tree, +ul.tree ul { + list-style: none outside; + margin-bottom: 0; + padding: 0; +} + +ul.tree ul { + display: block; + margin-left: 12px; + margin-right: 0; +} + +ul.tree li.closed > ul { + display: none; +} + +ul.tree li { + clear: both; +} + +ul.tree .toggler { + background-image: url(jqtree-icons.png); + background-repeat: no-repeat; + background-position: -8px 0; + width: 8px; + height: 8px; + display: block; + position: absolute; + left: -12px; + top: 30%; + text-indent: -9999px; + border-bottom: none; +} + +ul.tree div { + cursor: pointer; +} + +ul.tree .title { + color: #1C4257; + vertical-align: middle; +} + +ul.tree li.folder { + margin-bottom: 4px; +} + +ul.tree li.folder.closed { + margin-bottom: 1px; +} + +ul.tree li.folder .title { + margin-left: 0; +} + +ul.tree .toggler.closed { + background-position: 0 0; +} + +span.tree-dragging { + color: #fff; + background: #000; + opacity: 0.6; + cursor: pointer; + padding: 2px 8px; +} + +ul.tree li.ghost { + position: relative; + z-index: 10; + margin-right: 10px; +} + +ul.tree li.ghost span { + display: block; +} + +ul.tree li.ghost span.circle { + background-image: url(jqtree-icons.png); + background-repeat: no-repeat; + background-position: 0 -8px; + height: 8px; + width: 8px; + position: absolute; + top: -4px; + left: 2px; +} + +ul.tree li.ghost span.line { + background-color: #0000ff; + height: 2px; + padding: 0; + position: absolute; + top: -1px; + left: 10px; + width: 100%; +} + +ul.tree li.ghost.inside { + margin-left: 48px; +} + +ul.tree span.tree-hit { + position: absolute; + display: block; +} + +ul.tree span.border { + position: absolute; + display: block; + left: -2px; + top: 0; + border: solid 2px #0000ff; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + margin: 0; +} + +ul.tree div { + width: 100%; /* todo: why is this in here? */ + *width: auto; /* ie7 fix; issue 41 */ + position: relative; +} + +ul.tree li.selected > div, +ul.tree li.selected > div:hover { + background-color: #97BDD6; + background: -webkit-gradient(linear, left top, left bottom, from(#BEE0F5), to(#89AFCA)); + background: -moz-linear-gradient(top, #BEE0F5, #89AFCA); + background: -ms-linear-gradient(top, #BEE0F5, #89AFCA); + background: -o-linear-gradient(top, #BEE0F5, #89AFCA); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7); +} + +ul.tree .moving > div .title { + outline: dashed 1px #0000ff; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-1.7.2.min.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,4 @@ +/*! jQuery v1.7.2 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test("Â ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( +a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f +.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/css/jquery.fileupload-ui.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,84 @@ +@charset 'UTF-8'; +/* + * jQuery File Upload UI Plugin CSS 6.3 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +.fileinput-button { + position: relative; + overflow: hidden; + float: left; + margin-right: 4px; +} +.fileinput-button input { + position: absolute; + top: 0; + right: 0; + margin: 0; + border: solid transparent; + border-width: 0 0 100px 200px; + opacity: 0; + filter: alpha(opacity=0); + -moz-transform: translate(-300px, 0) scale(4); + direction: ltr; + cursor: pointer; +} +.fileupload-buttonbar .btn, +.fileupload-buttonbar .toggle { + margin-bottom: 5px; +} +.files .progress { + width: 200px; +} +.progress-animated .bar { + background: url(../img/progressbar.gif) !important; + filter: none; +} +.fileupload-loading { + position: absolute; + left: 50%; + width: 128px; + height: 128px; + background: url(../img/loading.gif) center no-repeat; + display: none; +} +.fileupload-processing .fileupload-loading { + display: block; +} + +/* Fix for IE 6: */ +*html .fileinput-button { + line-height: 22px; + margin: 1px -3px 0 0; +} + +/* Fix for IE 7: */ +*+html .fileinput-button { + margin: 1px 0 0 0; +} + +@media (max-width: 480px) { + .files .btn span { + display: none; + } + .files .preview * { + width: 40px; + } + .files .name * { + width: 80px; + display: inline-block; + word-wrap: break-word; + } + .files .progress { + width: 20px; + } + .files .delete { + width: 60px; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/css/style.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,15 @@ +@charset 'UTF-8'; +/* + * jQuery File Upload Plugin CSS Example 1.0 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2012, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +body{ + padding-top: 60px; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/js/cors/jquery.postmessage-transport.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,117 @@ +/* + * jQuery postMessage Transport Plugin 1.1 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint unparam: true, nomen: true */ +/*global define, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['jquery'], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + var counter = 0, + names = [ + 'accepts', + 'cache', + 'contents', + 'contentType', + 'crossDomain', + 'data', + 'dataType', + 'headers', + 'ifModified', + 'mimeType', + 'password', + 'processData', + 'timeout', + 'traditional', + 'type', + 'url', + 'username' + ], + convert = function (p) { + return p; + }; + + $.ajaxSetup({ + converters: { + 'postmessage text': convert, + 'postmessage json': convert, + 'postmessage html': convert + } + }); + + $.ajaxTransport('postmessage', function (options) { + if (options.postMessage && window.postMessage) { + var iframe, + loc = $('<a>').prop('href', options.postMessage)[0], + target = loc.protocol + '//' + loc.host, + xhrUpload = options.xhr().upload; + return { + send: function (_, completeCallback) { + var message = { + id: 'postmessage-transport-' + (counter += 1) + }, + eventName = 'message.' + message.id; + iframe = $( + '<iframe style="display:none;" src="' + + options.postMessage + '" name="' + + message.id + '"></iframe>' + ).bind('load', function () { + $.each(names, function (i, name) { + message[name] = options[name]; + }); + message.dataType = message.dataType.replace('postmessage ', ''); + $(window).bind(eventName, function (e) { + e = e.originalEvent; + var data = e.data, + ev; + if (e.origin === target && data.id === message.id) { + if (data.type === 'progress') { + ev = document.createEvent('Event'); + ev.initEvent(data.type, false, true); + $.extend(ev, data); + xhrUpload.dispatchEvent(ev); + } else { + completeCallback( + data.status, + data.statusText, + {postmessage: data.result}, + data.headers + ); + iframe.remove(); + $(window).unbind(eventName); + } + } + }); + iframe[0].contentWindow.postMessage( + message, + target + ); + }).appendTo(document.body); + }, + abort: function () { + if (iframe) { + iframe.remove(); + } + } + }; + } + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/js/cors/jquery.xdr-transport.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,85 @@ +/* + * jQuery XDomainRequest Transport Plugin 1.1.2 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + * + * Based on Julian Aubourg's ajaxHooks xdr.js: + * https://github.com/jaubourg/ajaxHooks/ + */ + +/*jslint unparam: true */ +/*global define, window, XDomainRequest */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['jquery'], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + if (window.XDomainRequest && !$.support.cors) { + $.ajaxTransport(function (s) { + if (s.crossDomain && s.async) { + if (s.timeout) { + s.xdrTimeout = s.timeout; + delete s.timeout; + } + var xdr; + return { + send: function (headers, completeCallback) { + function callback(status, statusText, responses, responseHeaders) { + xdr.onload = xdr.onerror = xdr.ontimeout = $.noop; + xdr = null; + completeCallback(status, statusText, responses, responseHeaders); + } + xdr = new XDomainRequest(); + // XDomainRequest only supports GET and POST: + if (s.type === 'DELETE') { + s.url = s.url + (/\?/.test(s.url) ? '&' : '?') + + '_method=DELETE'; + s.type = 'POST'; + } else if (s.type === 'PUT') { + s.url = s.url + (/\?/.test(s.url) ? '&' : '?') + + '_method=PUT'; + s.type = 'POST'; + } + xdr.open(s.type, s.url); + xdr.onload = function () { + callback( + 200, + 'OK', + {text: xdr.responseText}, + 'Content-Type: ' + xdr.contentType + ); + }; + xdr.onerror = function () { + callback(404, 'Not Found'); + }; + if (s.xdrTimeout) { + xdr.ontimeout = function () { + callback(0, 'timeout'); + }; + xdr.timeout = s.xdrTimeout; + } + xdr.send((s.hasContent && s.data) || null); + }, + abort: function () { + if (xdr) { + xdr.onerror = $.noop(); + xdr.abort(); + } + } + }; + } + }); + } +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/js/jquery.fileupload-fp.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,219 @@ +/* + * jQuery File Upload File Processing Plugin 1.0 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2012, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global define, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'load-image', + 'canvas-to-blob', + './jquery.fileupload' + ], factory); + } else { + // Browser globals: + factory( + window.jQuery, + window.loadImage + ); + } +}(function ($, loadImage) { + 'use strict'; + + // The File Upload IP version extends the basic fileupload widget + // with file processing functionality: + $.widget('blueimpFP.fileupload', $.blueimp.fileupload, { + + options: { + // The list of file processing actions: + process: [ + /* + { + action: 'load', + fileTypes: /^image\/(gif|jpeg|png)$/, + maxFileSize: 20000000 // 20MB + }, + { + action: 'resize', + maxWidth: 1920, + maxHeight: 1200, + minWidth: 800, + minHeight: 600 + }, + { + action: 'save' + } + */ + ], + + // The add callback is invoked as soon as files are added to the + // fileupload widget (via file input selection, drag & drop or add + // API call). See the basic file upload widget for more information: + add: function (e, data) { + $(this).fileupload('process', data).done(function () { + data.submit(); + }); + } + }, + + processActions: { + // Loads the image given via data.files and data.index + // as canvas element. + // Accepts the options fileTypes (regular expression) + // and maxFileSize (integer) to limit the files to load: + load: function (data, options) { + var that = this, + file = data.files[data.index], + dfd = $.Deferred(); + if (window.HTMLCanvasElement && + window.HTMLCanvasElement.prototype.toBlob && + ($.type(options.maxFileSize) !== 'number' || + file.size < options.maxFileSize) && + (!options.fileTypes || + options.fileTypes.test(file.type))) { + loadImage( + file, + function (canvas) { + data.canvas = canvas; + dfd.resolveWith(that, [data]); + }, + {canvas: true} + ); + } else { + dfd.rejectWith(that, [data]); + } + return dfd.promise(); + }, + // Resizes the image given as data.canvas and updates + // data.canvas with the resized image. + // Accepts the options maxWidth, maxHeight, minWidth and + // minHeight to scale the given image: + resize: function (data, options) { + if (data.canvas) { + var canvas = loadImage.scale(data.canvas, options); + if (canvas.width !== data.canvas.width || + canvas.height !== data.canvas.height) { + data.canvas = canvas; + data.processed = true; + } + } + return data; + }, + // Saves the processed image given as data.canvas + // inplace at data.index of data.files: + save: function (data, options) { + // Do nothing if no processing has happened: + if (!data.canvas || !data.processed) { + return data; + } + var that = this, + file = data.files[data.index], + name = file.name, + dfd = $.Deferred(), + callback = function (blob) { + if (!blob.name) { + if (file.type === blob.type) { + blob.name = file.name; + } else if (file.name) { + blob.name = file.name.replace( + /\..+$/, + '.' + blob.type.substr(6) + ); + } + } + // Store the created blob at the position + // of the original file in the files list: + data.files[data.index] = blob; + dfd.resolveWith(that, [data]); + }; + // Use canvas.mozGetAsFile directly, to retain the filename, as + // Gecko doesn't support the filename option for FormData.append: + if (data.canvas.mozGetAsFile) { + callback(data.canvas.mozGetAsFile( + (/^image\/(jpeg|png)$/.test(file.type) && name) || + ((name && name.replace(/\..+$/, '')) || + 'blob') + '.png', + file.type + )); + } else { + data.canvas.toBlob(callback, file.type); + } + return dfd.promise(); + } + }, + + // Resizes the file at the given index and stores the created blob at + // the original position of the files list, returns a Promise object: + _processFile: function (files, index, options) { + var that = this, + dfd = $.Deferred().resolveWith(that, [{ + files: files, + index: index + }]), + chain = dfd.promise(); + that._processing += 1; + $.each(options.process, function (i, settings) { + chain = chain.pipe(function (data) { + return that.processActions[settings.action] + .call(this, data, settings); + }); + }); + chain.always(function () { + that._processing -= 1; + if (that._processing === 0) { + that.element + .removeClass('fileupload-processing'); + } + }); + if (that._processing === 1) { + that.element.addClass('fileupload-processing'); + } + return chain; + }, + + // Processes the files given as files property of the data parameter, + // returns a Promise object that allows to bind a done handler, which + // will be invoked after processing all files (inplace) is done: + process: function (data) { + var that = this, + options = $.extend({}, this.options, data); + if (options.process && options.process.length && + this._isXHRUpload(options)) { + $.each(data.files, function (index, file) { + that._processingQueue = that._processingQueue.pipe( + function () { + var dfd = $.Deferred(); + that._processFile(data.files, index, options) + .always(function () { + dfd.resolveWith(that); + }); + return dfd.promise(); + } + ); + }); + } + return this._processingQueue; + }, + + _create: function () { + $.blueimp.fileupload.prototype._create.call(this); + this._processing = 0; + this._processingQueue = $.Deferred().resolveWith(this) + .promise(); + } + + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/js/jquery.fileupload-ui.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,702 @@ +/* + * jQuery File Upload User Interface Plugin 6.9.1 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global define, window, document, URL, webkitURL, FileReader */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'tmpl', + 'load-image', + './jquery.fileupload-fp' + ], factory); + } else { + // Browser globals: + factory( + window.jQuery, + window.tmpl, + window.loadImage + ); + } +}(function ($, tmpl, loadImage) { + 'use strict'; + + // The UI version extends the FP (file processing) version or the basic + // file upload widget and adds complete user interface interaction: + var parentWidget = ($.blueimpFP || $.blueimp).fileupload; + $.widget('blueimpUI.fileupload', parentWidget, { + + options: { + // By default, files added to the widget are uploaded as soon + // as the user clicks on the start buttons. To enable automatic + // uploads, set the following option to true: + autoUpload: false, + // The following option limits the number of files that are + // allowed to be uploaded using this widget: + maxNumberOfFiles: undefined, + // The maximum allowed file size: + maxFileSize: undefined, + // The minimum allowed file size: + minFileSize: undefined, + // The regular expression for allowed file types, matches + // against either file type or file name: + acceptFileTypes: /.+$/i, + // The regular expression to define for which files a preview + // image is shown, matched against the file type: + previewSourceFileTypes: /^image\/(gif|jpeg|png)$/, + // The maximum file size of images that are to be displayed as preview: + previewSourceMaxFileSize: 5000000, // 5MB + // The maximum width of the preview images: + previewMaxWidth: 80, + // The maximum height of the preview images: + previewMaxHeight: 80, + // By default, preview images are displayed as canvas elements + // if supported by the browser. Set the following option to false + // to always display preview images as img elements: + previewAsCanvas: true, + // The ID of the upload template: + uploadTemplateId: 'template-upload', + // The ID of the download template: + downloadTemplateId: 'template-download', + // The container for the list of files. If undefined, it is set to + // an element with class "files" inside of the widget element: + filesContainer: undefined, + // By default, files are appended to the files container. + // Set the following option to true, to prepend files instead: + prependFiles: false, + // The expected data type of the upload response, sets the dataType + // option of the $.ajax upload requests: + dataType: 'json', + + // The add callback is invoked as soon as files are added to the fileupload + // widget (via file input selection, drag & drop or add API call). + // See the basic file upload widget for more information: + add: function (e, data) { + var that = $(this).data('fileupload'), + options = that.options, + files = data.files; + $(this).fileupload('process', data).done(function () { + that._adjustMaxNumberOfFiles(-files.length); + data.isAdjusted = true; + data.files.valid = data.isValidated = that._validate(files); + data.context = that._renderUpload(files).data('data', data); + options.filesContainer[ + options.prependFiles ? 'prepend' : 'append' + ](data.context); + that._renderPreviews(files, data.context); + that._forceReflow(data.context); + that._transition(data.context).done( + function () { + if ((that._trigger('added', e, data) !== false) && + (options.autoUpload || data.autoUpload) && + data.autoUpload !== false && data.isValidated) { + data.submit(); + } + } + ); + }); + }, + // Callback for the start of each file upload request: + send: function (e, data) { + var that = $(this).data('fileupload'); + if (!data.isValidated) { + if (!data.isAdjusted) { + that._adjustMaxNumberOfFiles(-data.files.length); + } + if (!that._validate(data.files)) { + return false; + } + } + if (data.context && data.dataType && + data.dataType.substr(0, 6) === 'iframe') { + // Iframe Transport does not support progress events. + // In lack of an indeterminate progress bar, we set + // the progress to 100%, showing the full animated bar: + data.context + .find('.progress').addClass( + !$.support.transition && 'progress-animated' + ) + .attr('aria-valuenow', 100) + .find('.bar').css( + 'width', + '100%' + ); + } + return that._trigger('sent', e, data); + }, + // Callback for successful uploads: + done: function (e, data) { + var that = $(this).data('fileupload'), + template; + if (data.context) { + data.context.each(function (index) { + var file = ($.isArray(data.result) && + data.result[index]) || {error: 'emptyResult'}; + if (file.error) { + that._adjustMaxNumberOfFiles(1); + } + that._transition($(this)).done( + function () { + var node = $(this); + template = that._renderDownload([file]) + .css('height', node.height()) + .replaceAll(node); + that._forceReflow(template); + that._transition(template).done( + function () { + data.context = $(this); + that._trigger('completed', e, data); + } + ); + } + ); + }); + } else { + template = that._renderDownload(data.result) + .appendTo(that.options.filesContainer); + that._forceReflow(template); + that._transition(template).done( + function () { + data.context = $(this); + that._trigger('completed', e, data); + } + ); + } + }, + // Callback for failed (abort or error) uploads: + fail: function (e, data) { + var that = $(this).data('fileupload'), + template; + that._adjustMaxNumberOfFiles(data.files.length); + if (data.context) { + data.context.each(function (index) { + if (data.errorThrown !== 'abort') { + var file = data.files[index]; + file.error = file.error || data.errorThrown || + true; + that._transition($(this)).done( + function () { + var node = $(this); + template = that._renderDownload([file]) + .replaceAll(node); + that._forceReflow(template); + that._transition(template).done( + function () { + data.context = $(this); + that._trigger('failed', e, data); + } + ); + } + ); + } else { + that._transition($(this)).done( + function () { + $(this).remove(); + that._trigger('failed', e, data); + } + ); + } + }); + } else if (data.errorThrown !== 'abort') { + that._adjustMaxNumberOfFiles(-data.files.length); + data.context = that._renderUpload(data.files) + .appendTo(that.options.filesContainer) + .data('data', data); + that._forceReflow(data.context); + that._transition(data.context).done( + function () { + data.context = $(this); + that._trigger('failed', e, data); + } + ); + } else { + that._trigger('failed', e, data); + } + }, + // Callback for upload progress events: + progress: function (e, data) { + if (data.context) { + var progress = parseInt(data.loaded / data.total * 100, 10); + data.context.find('.progress') + .attr('aria-valuenow', progress) + .find('.bar').css( + 'width', + progress + '%' + ); + } + }, + // Callback for global upload progress events: + progressall: function (e, data) { + var $this = $(this), + progress = parseInt(data.loaded / data.total * 100, 10), + globalProgressNode = $this.find('.fileupload-progress'), + extendedProgressNode = globalProgressNode + .find('.progress-extended'); + if (extendedProgressNode.length) { + extendedProgressNode.html( + $this.data('fileupload')._renderExtendedProgress(data) + ); + } + globalProgressNode + .find('.progress') + .attr('aria-valuenow', progress) + .find('.bar').css( + 'width', + progress + '%' + ); + }, + // Callback for uploads start, equivalent to the global ajaxStart event: + start: function (e) { + var that = $(this).data('fileupload'); + that._transition($(this).find('.fileupload-progress')).done( + function () { + that._trigger('started', e); + } + ); + }, + // Callback for uploads stop, equivalent to the global ajaxStop event: + stop: function (e) { + var that = $(this).data('fileupload'); + that._transition($(this).find('.fileupload-progress')).done( + function () { + $(this).find('.progress') + .attr('aria-valuenow', '0') + .find('.bar').css('width', '0%'); + $(this).find('.progress-extended').html(' '); + that._trigger('stopped', e); + } + ); + }, + // Callback for file deletion: + destroy: function (e, data) { + var that = $(this).data('fileupload'); + if (data.url) { + $.ajax(data); + that._adjustMaxNumberOfFiles(1); + } + that._transition(data.context).done( + function () { + $(this).remove(); + that._trigger('destroyed', e, data); + } + ); + } + }, + + // Link handler, that allows to download files + // by drag & drop of the links to the desktop: + _enableDragToDesktop: function () { + var link = $(this), + url = link.prop('href'), + name = link.prop('download'), + type = 'application/octet-stream'; + link.bind('dragstart', function (e) { + try { + e.originalEvent.dataTransfer.setData( + 'DownloadURL', + [type, name, url].join(':') + ); + } catch (err) {} + }); + }, + + _adjustMaxNumberOfFiles: function (operand) { + if (typeof this.options.maxNumberOfFiles === 'number') { + this.options.maxNumberOfFiles += operand; + if (this.options.maxNumberOfFiles < 1) { + this._disableFileInputButton(); + } else { + this._enableFileInputButton(); + } + } + }, + + _formatFileSize: function (bytes) { + if (typeof bytes !== 'number') { + return ''; + } + if (bytes >= 1000000000) { + return (bytes / 1000000000).toFixed(2) + ' GB'; + } + if (bytes >= 1000000) { + return (bytes / 1000000).toFixed(2) + ' MB'; + } + return (bytes / 1000).toFixed(2) + ' KB'; + }, + + _formatBitrate: function (bits) { + if (typeof bits !== 'number') { + return ''; + } + if (bits >= 1000000000) { + return (bits / 1000000000).toFixed(2) + ' Gbit/s'; + } + if (bits >= 1000000) { + return (bits / 1000000).toFixed(2) + ' Mbit/s'; + } + if (bits >= 1000) { + return (bits / 1000).toFixed(2) + ' kbit/s'; + } + return bits + ' bit/s'; + }, + + _formatTime: function (seconds) { + var date = new Date(seconds * 1000), + days = parseInt(seconds / 86400, 10); + days = days ? days + 'd ' : ''; + return days + + ('0' + date.getUTCHours()).slice(-2) + ':' + + ('0' + date.getUTCMinutes()).slice(-2) + ':' + + ('0' + date.getUTCSeconds()).slice(-2); + }, + + _formatPercentage: function (floatValue) { + return (floatValue * 100).toFixed(2) + ' %'; + }, + + _renderExtendedProgress: function (data) { + return this._formatBitrate(data.bitrate) + ' | ' + + this._formatTime( + (data.total - data.loaded) * 8 / data.bitrate + ) + ' | ' + + this._formatPercentage( + data.loaded / data.total + ) + ' | ' + + this._formatFileSize(data.loaded) + ' / ' + + this._formatFileSize(data.total); + }, + + _hasError: function (file) { + if (file.error) { + return file.error; + } + // The number of added files is subtracted from + // maxNumberOfFiles before validation, so we check if + // maxNumberOfFiles is below 0 (instead of below 1): + if (this.options.maxNumberOfFiles < 0) { + return 'maxNumberOfFiles'; + } + // Files are accepted if either the file type or the file name + // matches against the acceptFileTypes regular expression, as + // only browsers with support for the File API report the type: + if (!(this.options.acceptFileTypes.test(file.type) || + this.options.acceptFileTypes.test(file.name))) { + return 'acceptFileTypes'; + } + if (this.options.maxFileSize && + file.size > this.options.maxFileSize) { + return 'maxFileSize'; + } + if (typeof file.size === 'number' && + file.size < this.options.minFileSize) { + return 'minFileSize'; + } + return null; + }, + + _validate: function (files) { + var that = this, + valid = !!files.length; + $.each(files, function (index, file) { + file.error = that._hasError(file); + if (file.error) { + valid = false; + } + }); + return valid; + }, + + _renderTemplate: function (func, files) { + if (!func) { + return $(); + } + var result = func({ + files: files, + formatFileSize: this._formatFileSize, + options: this.options + }); + if (result instanceof $) { + return result; + } + return $(this.options.templatesContainer).html(result).children(); + }, + + _renderPreview: function (file, node) { + var that = this, + options = this.options, + dfd = $.Deferred(); + return ((loadImage && loadImage( + file, + function (img) { + node.append(img); + that._forceReflow(node); + that._transition(node).done(function () { + dfd.resolveWith(node); + }); + if (!$.contains(document.body, node[0])) { + // If the element is not part of the DOM, + // transition events are not triggered, + // so we have to resolve manually: + dfd.resolveWith(node); + } + }, + { + maxWidth: options.previewMaxWidth, + maxHeight: options.previewMaxHeight, + canvas: options.previewAsCanvas + } + )) || dfd.resolveWith(node)) && dfd; + }, + + _renderPreviews: function (files, nodes) { + var that = this, + options = this.options; + nodes.find('.preview span').each(function (index, element) { + var file = files[index]; + if (options.previewSourceFileTypes.test(file.type) && + ($.type(options.previewSourceMaxFileSize) !== 'number' || + file.size < options.previewSourceMaxFileSize)) { + that._processingQueue = that._processingQueue.pipe(function () { + var dfd = $.Deferred(); + that._renderPreview(file, $(element)).done( + function () { + dfd.resolveWith(that); + } + ); + return dfd.promise(); + }); + } + }); + return this._processingQueue; + }, + + _renderUpload: function (files) { + return this._renderTemplate( + this.options.uploadTemplate, + files + ); + }, + + _renderDownload: function (files) { + return this._renderTemplate( + this.options.downloadTemplate, + files + ).find('a[download]').each(this._enableDragToDesktop).end(); + }, + + _startHandler: function (e) { + e.preventDefault(); + var button = $(this), + template = button.closest('.template-upload'), + data = template.data('data'); + if (data && data.submit && !data.jqXHR && data.submit()) { + button.prop('disabled', true); + } + }, + + _cancelHandler: function (e) { + e.preventDefault(); + var template = $(this).closest('.template-upload'), + data = template.data('data') || {}; + if (!data.jqXHR) { + data.errorThrown = 'abort'; + e.data.fileupload._trigger('fail', e, data); + } else { + data.jqXHR.abort(); + } + }, + + _deleteHandler: function (e) { + e.preventDefault(); + var button = $(this); + e.data.fileupload._trigger('destroy', e, { + context: button.closest('.template-download'), + url: button.attr('data-url'), + type: button.attr('data-type') || 'DELETE', + dataType: e.data.fileupload.options.dataType + }); + }, + + _forceReflow: function (node) { + return $.support.transition && node.length && + node[0].offsetWidth; + }, + + _transition: function (node) { + var dfd = $.Deferred(); + if ($.support.transition && node.hasClass('fade')) { + node.bind( + $.support.transition.end, + function (e) { + // Make sure we don't respond to other transitions events + // in the container element, e.g. from button elements: + if (e.target === node[0]) { + node.unbind($.support.transition.end); + dfd.resolveWith(node); + } + } + ).toggleClass('in'); + } else { + node.toggleClass('in'); + dfd.resolveWith(node); + } + return dfd; + }, + + _initButtonBarEventHandlers: function () { + var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'), + filesList = this.options.filesContainer, + ns = this.options.namespace; + fileUploadButtonBar.find('.start') + .bind('click.' + ns, function (e) { + e.preventDefault(); + filesList.find('.start button').click(); + }); + fileUploadButtonBar.find('.cancel') + .bind('click.' + ns, function (e) { + e.preventDefault(); + filesList.find('.cancel button').click(); + }); + fileUploadButtonBar.find('.delete') + .bind('click.' + ns, function (e) { + e.preventDefault(); + filesList.find('.delete input:checked') + .siblings('button').click(); + fileUploadButtonBar.find('.toggle') + .prop('checked', false); + }); + fileUploadButtonBar.find('.toggle') + .bind('change.' + ns, function (e) { + filesList.find('.delete input').prop( + 'checked', + $(this).is(':checked') + ); + }); + }, + + _destroyButtonBarEventHandlers: function () { + this.element.find('.fileupload-buttonbar button') + .unbind('click.' + this.options.namespace); + this.element.find('.fileupload-buttonbar .toggle') + .unbind('change.' + this.options.namespace); + }, + + _initEventHandlers: function () { + parentWidget.prototype._initEventHandlers.call(this); + var eventData = {fileupload: this}; + this.options.filesContainer + .delegate( + '.start button', + 'click.' + this.options.namespace, + eventData, + this._startHandler + ) + .delegate( + '.cancel button', + 'click.' + this.options.namespace, + eventData, + this._cancelHandler + ) + .delegate( + '.delete button', + 'click.' + this.options.namespace, + eventData, + this._deleteHandler + ); + this._initButtonBarEventHandlers(); + }, + + _destroyEventHandlers: function () { + var options = this.options; + this._destroyButtonBarEventHandlers(); + options.filesContainer + .undelegate('.start button', 'click.' + options.namespace) + .undelegate('.cancel button', 'click.' + options.namespace) + .undelegate('.delete button', 'click.' + options.namespace); + parentWidget.prototype._destroyEventHandlers.call(this); + }, + + _enableFileInputButton: function () { + this.element.find('.fileinput-button input') + .prop('disabled', false) + .parent().removeClass('disabled'); + }, + + _disableFileInputButton: function () { + this.element.find('.fileinput-button input') + .prop('disabled', true) + .parent().addClass('disabled'); + }, + + _initTemplates: function () { + var options = this.options; + options.templatesContainer = document.createElement( + options.filesContainer.prop('nodeName') + ); + if (tmpl) { + if (options.uploadTemplateId) { + options.uploadTemplate = tmpl(options.uploadTemplateId); + } + if (options.downloadTemplateId) { + options.downloadTemplate = tmpl(options.downloadTemplateId); + } + } + }, + + _initFilesContainer: function () { + var options = this.options; + if (options.filesContainer === undefined) { + options.filesContainer = this.element.find('.files'); + } else if (!(options.filesContainer instanceof $)) { + options.filesContainer = $(options.filesContainer); + } + }, + + _initSpecialOptions: function () { + parentWidget.prototype._initSpecialOptions.call(this); + this._initFilesContainer(); + this._initTemplates(); + }, + + _create: function () { + parentWidget.prototype._create.call(this); + this._refreshOptionsList.push( + 'filesContainer', + 'uploadTemplateId', + 'downloadTemplateId' + ); + if (!$.blueimpFP) { + this._processingQueue = $.Deferred().resolveWith(this).promise(); + this.process = function () { + return this._processingQueue; + }; + } + }, + + enable: function () { + parentWidget.prototype.enable.call(this); + this.element.find('input, button').prop('disabled', false); + this._enableFileInputButton(); + }, + + disable: function () { + this.element.find('input, button').prop('disabled', true); + this._disableFileInputButton(); + parentWidget.prototype.disable.call(this); + } + + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/js/jquery.fileupload.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,968 @@ +/* + * jQuery File Upload Plugin 5.12 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint nomen: true, unparam: true, regexp: true */ +/*global define, window, document, Blob, FormData, location */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define([ + 'jquery', + 'jquery.ui.widget' + ], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + // The FileReader API is not actually used, but works as feature detection, + // as e.g. Safari supports XHR file uploads via the FormData API, + // but not non-multipart XHR file uploads: + $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader); + $.support.xhrFormDataFileUpload = !!window.FormData; + + // The fileupload widget listens for change events on file input fields defined + // via fileInput setting and paste or drop events of the given dropZone. + // In addition to the default jQuery Widget methods, the fileupload widget + // exposes the "add" and "send" methods, to add or directly send files using + // the fileupload API. + // By default, files added via file input selection, paste, drag & drop or + // "add" method are uploaded immediately, but it is possible to override + // the "add" callback option to queue file uploads. + $.widget('blueimp.fileupload', { + + options: { + // The namespace used for event handler binding on the dropZone and + // fileInput collections. + // If not set, the name of the widget ("fileupload") is used. + namespace: undefined, + // The drop target collection, by the default the complete document. + // Set to null or an empty collection to disable drag & drop support: + dropZone: $(document), + // The file input field collection, that is listened for change events. + // If undefined, it is set to the file input fields inside + // of the widget element on plugin initialization. + // Set to null or an empty collection to disable the change listener. + fileInput: undefined, + // By default, the file input field is replaced with a clone after + // each input field change event. This is required for iframe transport + // queues and allows change events to be fired for the same file + // selection, but can be disabled by setting the following option to false: + replaceFileInput: true, + // The parameter name for the file form data (the request argument name). + // If undefined or empty, the name property of the file input field is + // used, or "files[]" if the file input name property is also empty, + // can be a string or an array of strings: + paramName: undefined, + // By default, each file of a selection is uploaded using an individual + // request for XHR type uploads. Set to false to upload file + // selections in one request each: + singleFileUploads: true, + // To limit the number of files uploaded with one XHR request, + // set the following option to an integer greater than 0: + limitMultiFileUploads: undefined, + // Set the following option to true to issue all file upload requests + // in a sequential order: + sequentialUploads: false, + // To limit the number of concurrent uploads, + // set the following option to an integer greater than 0: + limitConcurrentUploads: undefined, + // Set the following option to true to force iframe transport uploads: + forceIframeTransport: false, + // Set the following option to the location of a redirect url on the + // origin server, for cross-domain iframe transport uploads: + redirect: undefined, + // The parameter name for the redirect url, sent as part of the form + // data and set to 'redirect' if this option is empty: + redirectParamName: undefined, + // Set the following option to the location of a postMessage window, + // to enable postMessage transport uploads: + postMessage: undefined, + // By default, XHR file uploads are sent as multipart/form-data. + // The iframe transport is always using multipart/form-data. + // Set to false to enable non-multipart XHR uploads: + multipart: true, + // To upload large files in smaller chunks, set the following option + // to a preferred maximum chunk size. If set to 0, null or undefined, + // or the browser does not support the required Blob API, files will + // be uploaded as a whole. + maxChunkSize: undefined, + // When a non-multipart upload or a chunked multipart upload has been + // aborted, this option can be used to resume the upload by setting + // it to the size of the already uploaded bytes. This option is most + // useful when modifying the options object inside of the "add" or + // "send" callbacks, as the options are cloned for each file upload. + uploadedBytes: undefined, + // By default, failed (abort or error) file uploads are removed from the + // global progress calculation. Set the following option to false to + // prevent recalculating the global progress data: + recalculateProgress: true, + // Interval in milliseconds to calculate and trigger progress events: + progressInterval: 100, + // Interval in milliseconds to calculate progress bitrate: + bitrateInterval: 500, + + // Additional form data to be sent along with the file uploads can be set + // using this option, which accepts an array of objects with name and + // value properties, a function returning such an array, a FormData + // object (for XHR file uploads), or a simple object. + // The form of the first fileInput is given as parameter to the function: + formData: function (form) { + return form.serializeArray(); + }, + + // The add callback is invoked as soon as files are added to the fileupload + // widget (via file input selection, drag & drop, paste or add API call). + // If the singleFileUploads option is enabled, this callback will be + // called once for each file in the selection for XHR file uplaods, else + // once for each file selection. + // The upload starts when the submit method is invoked on the data parameter. + // The data object contains a files property holding the added files + // and allows to override plugin options as well as define ajax settings. + // Listeners for this callback can also be bound the following way: + // .bind('fileuploadadd', func); + // data.submit() returns a Promise object and allows to attach additional + // handlers using jQuery's Deferred callbacks: + // data.submit().done(func).fail(func).always(func); + add: function (e, data) { + data.submit(); + }, + + // Other callbacks: + // Callback for the submit event of each file upload: + // submit: function (e, data) {}, // .bind('fileuploadsubmit', func); + // Callback for the start of each file upload request: + // send: function (e, data) {}, // .bind('fileuploadsend', func); + // Callback for successful uploads: + // done: function (e, data) {}, // .bind('fileuploaddone', func); + // Callback for failed (abort or error) uploads: + // fail: function (e, data) {}, // .bind('fileuploadfail', func); + // Callback for completed (success, abort or error) requests: + // always: function (e, data) {}, // .bind('fileuploadalways', func); + // Callback for upload progress events: + // progress: function (e, data) {}, // .bind('fileuploadprogress', func); + // Callback for global upload progress events: + // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func); + // Callback for uploads start, equivalent to the global ajaxStart event: + // start: function (e) {}, // .bind('fileuploadstart', func); + // Callback for uploads stop, equivalent to the global ajaxStop event: + // stop: function (e) {}, // .bind('fileuploadstop', func); + // Callback for change events of the fileInput collection: + // change: function (e, data) {}, // .bind('fileuploadchange', func); + // Callback for paste events to the dropZone collection: + // paste: function (e, data) {}, // .bind('fileuploadpaste', func); + // Callback for drop events of the dropZone collection: + // drop: function (e, data) {}, // .bind('fileuploaddrop', func); + // Callback for dragover events of the dropZone collection: + // dragover: function (e) {}, // .bind('fileuploaddragover', func); + + // The plugin options are used as settings object for the ajax calls. + // The following are jQuery ajax settings required for the file uploads: + processData: false, + contentType: false, + cache: false + }, + + // A list of options that require a refresh after assigning a new value: + _refreshOptionsList: [ + 'namespace', + 'dropZone', + 'fileInput', + 'multipart', + 'forceIframeTransport' + ], + + _BitrateTimer: function () { + this.timestamp = +(new Date()); + this.loaded = 0; + this.bitrate = 0; + this.getBitrate = function (now, loaded, interval) { + var timeDiff = now - this.timestamp; + if (!this.bitrate || !interval || timeDiff > interval) { + this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8; + this.loaded = loaded; + this.timestamp = now; + } + return this.bitrate; + }; + }, + + _isXHRUpload: function (options) { + return !options.forceIframeTransport && + ((!options.multipart && $.support.xhrFileUpload) || + $.support.xhrFormDataFileUpload); + }, + + _getFormData: function (options) { + var formData; + if (typeof options.formData === 'function') { + return options.formData(options.form); + } + if ($.isArray(options.formData)) { + return options.formData; + } + if (options.formData) { + formData = []; + $.each(options.formData, function (name, value) { + formData.push({name: name, value: value}); + }); + return formData; + } + return []; + }, + + _getTotal: function (files) { + var total = 0; + $.each(files, function (index, file) { + total += file.size || 1; + }); + return total; + }, + + _onProgress: function (e, data) { + if (e.lengthComputable) { + var now = +(new Date()), + total, + loaded; + if (data._time && data.progressInterval && + (now - data._time < data.progressInterval) && + e.loaded !== e.total) { + return; + } + data._time = now; + total = data.total || this._getTotal(data.files); + loaded = parseInt( + e.loaded / e.total * (data.chunkSize || total), + 10 + ) + (data.uploadedBytes || 0); + this._loaded += loaded - (data.loaded || data.uploadedBytes || 0); + data.lengthComputable = true; + data.loaded = loaded; + data.total = total; + data.bitrate = data._bitrateTimer.getBitrate( + now, + loaded, + data.bitrateInterval + ); + // Trigger a custom progress event with a total data property set + // to the file size(s) of the current upload and a loaded data + // property calculated accordingly: + this._trigger('progress', e, data); + // Trigger a global progress event for all current file uploads, + // including ajax calls queued for sequential file uploads: + this._trigger('progressall', e, { + lengthComputable: true, + loaded: this._loaded, + total: this._total, + bitrate: this._bitrateTimer.getBitrate( + now, + this._loaded, + data.bitrateInterval + ) + }); + } + }, + + _initProgressListener: function (options) { + var that = this, + xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr(); + // Accesss to the native XHR object is required to add event listeners + // for the upload progress event: + if (xhr.upload) { + $(xhr.upload).bind('progress', function (e) { + var oe = e.originalEvent; + // Make sure the progress event properties get copied over: + e.lengthComputable = oe.lengthComputable; + e.loaded = oe.loaded; + e.total = oe.total; + that._onProgress(e, options); + }); + options.xhr = function () { + return xhr; + }; + } + }, + + _initXHRData: function (options) { + var formData, + file = options.files[0], + // Ignore non-multipart setting if not supported: + multipart = options.multipart || !$.support.xhrFileUpload, + paramName = options.paramName[0]; + if (!multipart || options.blob) { + // For non-multipart uploads and chunked uploads, + // file meta data is not part of the request body, + // so we transmit this data as part of the HTTP headers. + // For cross domain requests, these headers must be allowed + // via Access-Control-Allow-Headers or removed using + // the beforeSend callback: + options.headers = $.extend(options.headers, { + 'X-File-Name': file.name, + 'X-File-Type': file.type, + 'X-File-Size': file.size + }); + if (!options.blob) { + // Non-chunked non-multipart upload: + options.contentType = file.type; + options.data = file; + } else if (!multipart) { + // Chunked non-multipart upload: + options.contentType = 'application/octet-stream'; + options.data = options.blob; + } + } + if (multipart && $.support.xhrFormDataFileUpload) { + if (options.postMessage) { + // window.postMessage does not allow sending FormData + // objects, so we just add the File/Blob objects to + // the formData array and let the postMessage window + // create the FormData object out of this array: + formData = this._getFormData(options); + if (options.blob) { + formData.push({ + name: paramName, + value: options.blob + }); + } else { + $.each(options.files, function (index, file) { + formData.push({ + name: options.paramName[index] || paramName, + value: file + }); + }); + } + } else { + if (options.formData instanceof FormData) { + formData = options.formData; + } else { + formData = new FormData(); + $.each(this._getFormData(options), function (index, field) { + formData.append(field.name, field.value); + }); + } + if (options.blob) { + formData.append(paramName, options.blob, file.name); + } else { + $.each(options.files, function (index, file) { + // File objects are also Blob instances. + // This check allows the tests to run with + // dummy objects: + if (file instanceof Blob) { + formData.append( + options.paramName[index] || paramName, + file, + file.name + ); + } + }); + } + } + options.data = formData; + } + // Blob reference is not needed anymore, free memory: + options.blob = null; + }, + + _initIframeSettings: function (options) { + // Setting the dataType to iframe enables the iframe transport: + options.dataType = 'iframe ' + (options.dataType || ''); + // The iframe transport accepts a serialized array as form data: + options.formData = this._getFormData(options); + // Add redirect url to form data on cross-domain uploads: + if (options.redirect && $('<a></a>').prop('href', options.url) + .prop('host') !== location.host) { + options.formData.push({ + name: options.redirectParamName || 'redirect', + value: options.redirect + }); + } + }, + + _initDataSettings: function (options) { + if (this._isXHRUpload(options)) { + if (!this._chunkedUpload(options, true)) { + if (!options.data) { + this._initXHRData(options); + } + this._initProgressListener(options); + } + if (options.postMessage) { + // Setting the dataType to postmessage enables the + // postMessage transport: + options.dataType = 'postmessage ' + (options.dataType || ''); + } + } else { + this._initIframeSettings(options, 'iframe'); + } + }, + + _getParamName: function (options) { + var fileInput = $(options.fileInput), + paramName = options.paramName; + if (!paramName) { + paramName = []; + fileInput.each(function () { + var input = $(this), + name = input.prop('name') || 'files[]', + i = (input.prop('files') || [1]).length; + while (i) { + paramName.push(name); + i -= 1; + } + }); + if (!paramName.length) { + paramName = [fileInput.prop('name') || 'files[]']; + } + } else if (!$.isArray(paramName)) { + paramName = [paramName]; + } + return paramName; + }, + + _initFormSettings: function (options) { + // Retrieve missing options from the input field and the + // associated form, if available: + if (!options.form || !options.form.length) { + options.form = $(options.fileInput.prop('form')); + } + options.paramName = this._getParamName(options); + if (!options.url) { + options.url = options.form.prop('action') || location.href; + } + // The HTTP request method must be "POST" or "PUT": + options.type = (options.type || options.form.prop('method') || '') + .toUpperCase(); + if (options.type !== 'POST' && options.type !== 'PUT') { + options.type = 'POST'; + } + }, + + _getAJAXSettings: function (data) { + var options = $.extend({}, this.options, data); + this._initFormSettings(options); + this._initDataSettings(options); + return options; + }, + + // Maps jqXHR callbacks to the equivalent + // methods of the given Promise object: + _enhancePromise: function (promise) { + promise.success = promise.done; + promise.error = promise.fail; + promise.complete = promise.always; + return promise; + }, + + // Creates and returns a Promise object enhanced with + // the jqXHR methods abort, success, error and complete: + _getXHRPromise: function (resolveOrReject, context, args) { + var dfd = $.Deferred(), + promise = dfd.promise(); + context = context || this.options.context || promise; + if (resolveOrReject === true) { + dfd.resolveWith(context, args); + } else if (resolveOrReject === false) { + dfd.rejectWith(context, args); + } + promise.abort = dfd.promise; + return this._enhancePromise(promise); + }, + + // Uploads a file in multiple, sequential requests + // by splitting the file up in multiple blob chunks. + // If the second parameter is true, only tests if the file + // should be uploaded in chunks, but does not invoke any + // upload requests: + _chunkedUpload: function (options, testOnly) { + var that = this, + file = options.files[0], + fs = file.size, + ub = options.uploadedBytes = options.uploadedBytes || 0, + mcs = options.maxChunkSize || fs, + // Use the Blob methods with the slice implementation + // according to the W3C Blob API specification: + slice = file.webkitSlice || file.mozSlice || file.slice, + upload, + n, + jqXHR, + pipe; + if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) || + options.data) { + return false; + } + if (testOnly) { + return true; + } + if (ub >= fs) { + file.error = 'uploadedBytes'; + return this._getXHRPromise( + false, + options.context, + [null, 'error', file.error] + ); + } + // n is the number of blobs to upload, + // calculated via filesize, uploaded bytes and max chunk size: + n = Math.ceil((fs - ub) / mcs); + // The chunk upload method accepting the chunk number as parameter: + upload = function (i) { + if (!i) { + return that._getXHRPromise(true, options.context); + } + // Upload the blobs in sequential order: + return upload(i -= 1).pipe(function () { + // Clone the options object for each chunk upload: + var o = $.extend({}, options); + o.blob = slice.call( + file, + ub + i * mcs, + ub + (i + 1) * mcs + ); + // Store the current chunk size, as the blob itself + // will be dereferenced after data processing: + o.chunkSize = o.blob.size; + // Process the upload data (the blob and potential form data): + that._initXHRData(o); + // Add progress listeners for this chunk upload: + that._initProgressListener(o); + jqXHR = ($.ajax(o) || that._getXHRPromise(false, o.context)) + .done(function () { + // Create a progress event if upload is done and + // no progress event has been invoked for this chunk: + if (!o.loaded) { + that._onProgress($.Event('progress', { + lengthComputable: true, + loaded: o.chunkSize, + total: o.chunkSize + }), o); + } + options.uploadedBytes = o.uploadedBytes += + o.chunkSize; + }); + return jqXHR; + }); + }; + // Return the piped Promise object, enhanced with an abort method, + // which is delegated to the jqXHR object of the current upload, + // and jqXHR callbacks mapped to the equivalent Promise methods: + pipe = upload(n); + pipe.abort = function () { + return jqXHR.abort(); + }; + return this._enhancePromise(pipe); + }, + + _beforeSend: function (e, data) { + if (this._active === 0) { + // the start callback is triggered when an upload starts + // and no other uploads are currently running, + // equivalent to the global ajaxStart event: + this._trigger('start'); + // Set timer for global bitrate progress calculation: + this._bitrateTimer = new this._BitrateTimer(); + } + this._active += 1; + // Initialize the global progress values: + this._loaded += data.uploadedBytes || 0; + this._total += this._getTotal(data.files); + }, + + _onDone: function (result, textStatus, jqXHR, options) { + if (!this._isXHRUpload(options)) { + // Create a progress event for each iframe load: + this._onProgress($.Event('progress', { + lengthComputable: true, + loaded: 1, + total: 1 + }), options); + } + options.result = result; + options.textStatus = textStatus; + options.jqXHR = jqXHR; + this._trigger('done', null, options); + }, + + _onFail: function (jqXHR, textStatus, errorThrown, options) { + options.jqXHR = jqXHR; + options.textStatus = textStatus; + options.errorThrown = errorThrown; + this._trigger('fail', null, options); + if (options.recalculateProgress) { + // Remove the failed (error or abort) file upload from + // the global progress calculation: + this._loaded -= options.loaded || options.uploadedBytes || 0; + this._total -= options.total || this._getTotal(options.files); + } + }, + + _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) { + this._active -= 1; + options.textStatus = textStatus; + if (jqXHRorError && jqXHRorError.always) { + options.jqXHR = jqXHRorError; + options.result = jqXHRorResult; + } else { + options.jqXHR = jqXHRorResult; + options.errorThrown = jqXHRorError; + } + this._trigger('always', null, options); + if (this._active === 0) { + // The stop callback is triggered when all uploads have + // been completed, equivalent to the global ajaxStop event: + this._trigger('stop'); + // Reset the global progress values: + this._loaded = this._total = 0; + this._bitrateTimer = null; + } + }, + + _onSend: function (e, data) { + var that = this, + jqXHR, + slot, + pipe, + options = that._getAJAXSettings(data), + send = function (resolve, args) { + that._sending += 1; + // Set timer for bitrate progress calculation: + options._bitrateTimer = new that._BitrateTimer(); + jqXHR = jqXHR || ( + (resolve !== false && + that._trigger('send', e, options) !== false && + (that._chunkedUpload(options) || $.ajax(options))) || + that._getXHRPromise(false, options.context, args) + ).done(function (result, textStatus, jqXHR) { + that._onDone(result, textStatus, jqXHR, options); + }).fail(function (jqXHR, textStatus, errorThrown) { + that._onFail(jqXHR, textStatus, errorThrown, options); + }).always(function (jqXHRorResult, textStatus, jqXHRorError) { + that._sending -= 1; + that._onAlways( + jqXHRorResult, + textStatus, + jqXHRorError, + options + ); + if (options.limitConcurrentUploads && + options.limitConcurrentUploads > that._sending) { + // Start the next queued upload, + // that has not been aborted: + var nextSlot = that._slots.shift(); + while (nextSlot) { + if (!nextSlot.isRejected()) { + nextSlot.resolve(); + break; + } + nextSlot = that._slots.shift(); + } + } + }); + return jqXHR; + }; + this._beforeSend(e, options); + if (this.options.sequentialUploads || + (this.options.limitConcurrentUploads && + this.options.limitConcurrentUploads <= this._sending)) { + if (this.options.limitConcurrentUploads > 1) { + slot = $.Deferred(); + this._slots.push(slot); + pipe = slot.pipe(send); + } else { + pipe = (this._sequence = this._sequence.pipe(send, send)); + } + // Return the piped Promise object, enhanced with an abort method, + // which is delegated to the jqXHR object of the current upload, + // and jqXHR callbacks mapped to the equivalent Promise methods: + pipe.abort = function () { + var args = [undefined, 'abort', 'abort']; + if (!jqXHR) { + if (slot) { + slot.rejectWith(args); + } + return send(false, args); + } + return jqXHR.abort(); + }; + return this._enhancePromise(pipe); + } + return send(); + }, + + _onAdd: function (e, data) { + var that = this, + result = true, + options = $.extend({}, this.options, data), + limit = options.limitMultiFileUploads, + paramName = this._getParamName(options), + paramNameSet, + paramNameSlice, + fileSet, + i; + if (!(options.singleFileUploads || limit) || + !this._isXHRUpload(options)) { + fileSet = [data.files]; + paramNameSet = [paramName]; + } else if (!options.singleFileUploads && limit) { + fileSet = []; + paramNameSet = []; + for (i = 0; i < data.files.length; i += limit) { + fileSet.push(data.files.slice(i, i + limit)); + paramNameSlice = paramName.slice(i, i + limit); + if (!paramNameSlice.length) { + paramNameSlice = paramName; + } + paramNameSet.push(paramNameSlice); + } + } else { + paramNameSet = paramName; + } + data.originalFiles = data.files; + $.each(fileSet || data.files, function (index, element) { + var newData = $.extend({}, data); + newData.files = fileSet ? element : [element]; + newData.paramName = paramNameSet[index]; + newData.submit = function () { + newData.jqXHR = this.jqXHR = + (that._trigger('submit', e, this) !== false) && + that._onSend(e, this); + return this.jqXHR; + }; + return (result = that._trigger('add', e, newData)); + }); + return result; + }, + + // File Normalization for Gecko 1.9.1 (Firefox 3.5) support: + _normalizeFile: function (index, file) { + if (file.name === undefined && file.size === undefined) { + file.name = file.fileName; + file.size = file.fileSize; + } + }, + + _replaceFileInput: function (input) { + var inputClone = input.clone(true); + $('<form></form>').append(inputClone)[0].reset(); + // Detaching allows to insert the fileInput on another form + // without loosing the file input value: + input.after(inputClone).detach(); + // Avoid memory leaks with the detached file input: + $.cleanData(input.unbind('remove')); + // Replace the original file input element in the fileInput + // collection with the clone, which has been copied including + // event handlers: + this.options.fileInput = this.options.fileInput.map(function (i, el) { + if (el === input[0]) { + return inputClone[0]; + } + return el; + }); + // If the widget has been initialized on the file input itself, + // override this.element with the file input clone: + if (input[0] === this.element[0]) { + this.element = inputClone; + } + }, + + _getFileInputFiles: function (fileInput) { + fileInput = $(fileInput); + var files = $.each($.makeArray(fileInput.prop('files')), this._normalizeFile), + value; + if (!files.length) { + value = fileInput.prop('value'); + if (!value) { + return []; + } + // If the files property is not available, the browser does not + // support the File API and we add a pseudo File object with + // the input value as name with path information removed: + files = [{name: value.replace(/^.*\\/, '')}]; + } + return files; + }, + + _onChange: function (e) { + var that = e.data.fileupload, + data = { + fileInput: $(e.target), + form: $(e.target.form) + }; + data.files = that._getFileInputFiles(data.fileInput); + if (that.options.replaceFileInput) { + that._replaceFileInput(data.fileInput); + } + if (that._trigger('change', e, data) === false || + that._onAdd(e, data) === false) { + return false; + } + }, + + _onPaste: function (e) { + var that = e.data.fileupload, + cbd = e.originalEvent.clipboardData, + items = (cbd && cbd.items) || [], + data = {files: []}; + $.each(items, function (index, item) { + var file = item.getAsFile && item.getAsFile(); + if (file) { + data.files.push(file); + } + }); + if (that._trigger('paste', e, data) === false || + that._onAdd(e, data) === false) { + return false; + } + }, + + _onDrop: function (e) { + var that = e.data.fileupload, + dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer, + data = { + files: $.each( + $.makeArray(dataTransfer && dataTransfer.files), + that._normalizeFile + ) + }; + if (that._trigger('drop', e, data) === false || + that._onAdd(e, data) === false) { + return false; + } + e.preventDefault(); + }, + + _onDragOver: function (e) { + var that = e.data.fileupload, + dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer; + if (that._trigger('dragover', e) === false) { + return false; + } + if (dataTransfer) { + dataTransfer.dropEffect = 'copy'; + } + e.preventDefault(); + }, + + _initEventHandlers: function () { + var ns = this.options.namespace; + if (this._isXHRUpload(this.options)) { + this.options.dropZone + .bind('dragover.' + ns, {fileupload: this}, this._onDragOver) + .bind('drop.' + ns, {fileupload: this}, this._onDrop) + .bind('paste.' + ns, {fileupload: this}, this._onPaste); + } + this.options.fileInput + .bind('change.' + ns, {fileupload: this}, this._onChange); + }, + + _destroyEventHandlers: function () { + var ns = this.options.namespace; + this.options.dropZone + .unbind('dragover.' + ns, this._onDragOver) + .unbind('drop.' + ns, this._onDrop) + .unbind('paste.' + ns, this._onPaste); + this.options.fileInput + .unbind('change.' + ns, this._onChange); + }, + + _setOption: function (key, value) { + var refresh = $.inArray(key, this._refreshOptionsList) !== -1; + if (refresh) { + this._destroyEventHandlers(); + } + $.Widget.prototype._setOption.call(this, key, value); + if (refresh) { + this._initSpecialOptions(); + this._initEventHandlers(); + } + }, + + _initSpecialOptions: function () { + var options = this.options; + if (options.fileInput === undefined) { + options.fileInput = this.element.is('input:file') ? + this.element : this.element.find('input:file'); + } else if (!(options.fileInput instanceof $)) { + options.fileInput = $(options.fileInput); + } + if (!(options.dropZone instanceof $)) { + options.dropZone = $(options.dropZone); + } + }, + + _create: function () { + var options = this.options; + // Initialize options set via HTML5 data-attributes: + $.extend(options, $(this.element[0].cloneNode(false)).data()); + options.namespace = options.namespace || this.widgetName; + this._initSpecialOptions(); + this._slots = []; + this._sequence = this._getXHRPromise(true); + this._sending = this._active = this._loaded = this._total = 0; + this._initEventHandlers(); + }, + + destroy: function () { + this._destroyEventHandlers(); + $.Widget.prototype.destroy.call(this); + }, + + enable: function () { + $.Widget.prototype.enable.call(this); + this._initEventHandlers(); + }, + + disable: function () { + this._destroyEventHandlers(); + $.Widget.prototype.disable.call(this); + }, + + // This method is exposed to the widget API and allows adding files + // using the fileupload API. The data parameter accepts an object which + // must have a files property and can contain additional options: + // .fileupload('add', {files: filesList}); + add: function (data) { + if (!data || this.options.disabled) { + return; + } + if (data.fileInput && !data.files) { + data.files = this._getFileInputFiles(data.fileInput); + } else { + data.files = $.each($.makeArray(data.files), this._normalizeFile); + } + this._onAdd(null, data); + }, + + // This method is exposed to the widget API and allows sending files + // using the fileupload API. The data parameter accepts an object which + // must have a files property and can contain additional options: + // .fileupload('send', {files: filesList}); + // The method returns a Promise object for the file upload call. + send: function (data) { + if (data && !this.options.disabled) { + if (data.fileInput && !data.files) { + data.files = this._getFileInputFiles(data.fileInput); + } else { + data.files = $.each($.makeArray(data.files), this._normalizeFile); + } + if (data.files.length) { + return this._onSend(null, data); + } + } + return this._getXHRPromise(false, data && data.context); + } + + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/js/jquery.iframe-transport.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,171 @@ +/* + * jQuery Iframe Transport Plugin 1.4 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2011, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*jslint unparam: true, nomen: true */ +/*global define, window, document */ + +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // Register as an anonymous AMD module: + define(['jquery'], factory); + } else { + // Browser globals: + factory(window.jQuery); + } +}(function ($) { + 'use strict'; + + // Helper variable to create unique names for the transport iframes: + var counter = 0; + + // The iframe transport accepts three additional options: + // options.fileInput: a jQuery collection of file input fields + // options.paramName: the parameter name for the file form data, + // overrides the name property of the file input field(s), + // can be a string or an array of strings. + // options.formData: an array of objects with name and value properties, + // equivalent to the return data of .serializeArray(), e.g.: + // [{name: 'a', value: 1}, {name: 'b', value: 2}] + $.ajaxTransport('iframe', function (options) { + if (options.async && (options.type === 'POST' || options.type === 'GET')) { + var form, + iframe; + return { + send: function (_, completeCallback) { + form = $('<form style="display:none;"></form>'); + // javascript:false as initial iframe src + // prevents warning popups on HTTPS in IE6. + // IE versions below IE8 cannot set the name property of + // elements that have already been added to the DOM, + // so we set the name along with the iframe HTML markup: + iframe = $( + '<iframe src="javascript:false;" name="iframe-transport-' + + (counter += 1) + '"></iframe>' + ).bind('load', function () { + var fileInputClones, + paramNames = $.isArray(options.paramName) ? + options.paramName : [options.paramName]; + iframe + .unbind('load') + .bind('load', function () { + var response; + // Wrap in a try/catch block to catch exceptions thrown + // when trying to access cross-domain iframe contents: + try { + response = iframe.contents(); + // Google Chrome and Firefox do not throw an + // exception when calling iframe.contents() on + // cross-domain requests, so we unify the response: + if (!response.length || !response[0].firstChild) { + throw new Error(); + } + } catch (e) { + response = undefined; + } + // The complete callback returns the + // iframe content document as response object: + completeCallback( + 200, + 'success', + {'iframe': response} + ); + // Fix for IE endless progress bar activity bug + // (happens on form submits to iframe targets): + $('<iframe src="javascript:false;"></iframe>') + .appendTo(form); + form.remove(); + }); + form + .prop('target', iframe.prop('name')) + .prop('action', options.url) + .prop('method', options.type); + if (options.formData) { + $.each(options.formData, function (index, field) { + $('<input type="hidden"/>') + .prop('name', field.name) + .val(field.value) + .appendTo(form); + }); + } + if (options.fileInput && options.fileInput.length && + options.type === 'POST') { + fileInputClones = options.fileInput.clone(); + // Insert a clone for each file input field: + options.fileInput.after(function (index) { + return fileInputClones[index]; + }); + if (options.paramName) { + options.fileInput.each(function (index) { + $(this).prop( + 'name', + paramNames[index] || options.paramName + ); + }); + } + // Appending the file input fields to the hidden form + // removes them from their original location: + form + .append(options.fileInput) + .prop('enctype', 'multipart/form-data') + // enctype must be set as encoding for IE: + .prop('encoding', 'multipart/form-data'); + } + form.submit(); + // Insert the file input fields at their original location + // by replacing the clones with the originals: + if (fileInputClones && fileInputClones.length) { + options.fileInput.each(function (index, input) { + var clone = $(fileInputClones[index]); + $(input).prop('name', clone.prop('name')); + clone.replaceWith(input); + }); + } + }); + form.append(iframe).appendTo(document.body); + }, + abort: function () { + if (iframe) { + // javascript:false as iframe src aborts the request + // and prevents warning popups on HTTPS in IE6. + // concat is used to avoid the "Script URL" JSLint error: + iframe + .unbind('load') + .prop('src', 'javascript'.concat(':false;')); + } + if (form) { + form.remove(); + } + } + }; + } + }); + + // The iframe transport returns the iframe content document as response. + // The following adds converters from iframe to text, json, html, and script: + $.ajaxSetup({ + converters: { + 'iframe text': function (iframe) { + return $(iframe[0].body).text(); + }, + 'iframe json': function (iframe) { + return $.parseJSON($(iframe[0].body).text()); + }, + 'iframe html': function (iframe) { + return $(iframe[0].body).html(); + }, + 'iframe script': function (iframe) { + return $.globalEval($(iframe[0].body).text()); + } + } + }); + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/js/locale.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,29 @@ +/* + * jQuery File Upload Plugin Localization Example 6.5.1 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2012, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +/*global window */ + +window.locale = { + "fileupload": { + "errors": { + "maxFileSize": "File is too big", + "minFileSize": "File is too small", + "acceptFileTypes": "Filetype not allowed", + "maxNumberOfFiles": "Max number of files exceeded", + "uploadedBytes": "Uploaded bytes exceed file size", + "emptyResult": "Empty file upload result" + }, + "error": "Error", + "start": "Start", + "cancel": "Cancel", + "destroy": "Delete" + } +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery-file-upload/js/vendor/jquery.ui.widget.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,282 @@ +/* + * jQuery UI Widget 1.8.18+amd + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ + +(function (factory) { + if (typeof define === "function" && define.amd) { + // Register as an anonymous AMD module: + define(["jquery"], factory); + } else { + // Browser globals: + factory(jQuery); + } +}(function( $, undefined ) { + +// jQuery 1.4+ +if ( $.cleanData ) { + var _cleanData = $.cleanData; + $.cleanData = function( elems ) { + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + try { + $( elem ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + } + _cleanData( elems ); + }; +} else { + var _remove = $.fn.remove; + $.fn.remove = function( selector, keepData ) { + return this.each(function() { + if ( !keepData ) { + if ( !selector || $.filter( selector, [ this ] ).length ) { + $( "*", this ).add( [ this ] ).each(function() { + try { + $( this ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + }); + } + } + return _remove.call( $(this), selector, keepData ); + }); + }; +} + +$.widget = function( name, base, prototype ) { + var namespace = name.split( "." )[ 0 ], + fullName; + name = name.split( "." )[ 1 ]; + fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName ] = function( elem ) { + return !!$.data( elem, name ); + }; + + $[ namespace ] = $[ namespace ] || {}; + $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without initializing for simple inheritance + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + + var basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from +// $.each( basePrototype, function( key, val ) { +// if ( $.isPlainObject(val) ) { +// basePrototype[ key ] = $.extend( {}, val ); +// } +// }); + basePrototype.options = $.extend( true, {}, basePrototype.options ); + $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { + namespace: namespace, + widgetName: name, + widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, + widgetBaseClass: fullName + }, prototype ); + + $.widget.bridge( name, $[ namespace ][ name ] ); +}; + +$.widget.bridge = function( name, object ) { + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string", + args = Array.prototype.slice.call( arguments, 1 ), + returnValue = this; + + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? + $.extend.apply( null, [ true, options ].concat(args) ) : + options; + + // prevent calls to internal methods + if ( isMethodCall && options.charAt( 0 ) === "_" ) { + return returnValue; + } + + if ( isMethodCall ) { + this.each(function() { + var instance = $.data( this, name ), + methodValue = instance && $.isFunction( instance[options] ) ? + instance[ options ].apply( instance, args ) : + instance; + // TODO: add this back in 1.9 and use $.error() (see #5972) +// if ( !instance ) { +// throw "cannot call methods on " + name + " prior to initialization; " + +// "attempted to call method '" + options + "'"; +// } +// if ( !$.isFunction( instance[options] ) ) { +// throw "no such method '" + options + "' for " + name + " widget instance"; +// } +// var methodValue = instance[ options ].apply( instance, args ); + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue; + return false; + } + }); + } else { + this.each(function() { + var instance = $.data( this, name ); + if ( instance ) { + instance.option( options || {} )._init(); + } else { + $.data( this, name, new object( options, this ) ); + } + }); + } + + return returnValue; + }; +}; + +$.Widget = function( options, element ) { + // allow instantiation without initializing for simple inheritance + if ( arguments.length ) { + this._createWidget( options, element ); + } +}; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + options: { + disabled: false + }, + _createWidget: function( options, element ) { + // $.widget.bridge stores the plugin instance, but we do it anyway + // so that it's stored even before the _create function runs + $.data( element, this.widgetName, this ); + this.element = $( element ); + this.options = $.extend( true, {}, + this.options, + this._getCreateOptions(), + options ); + + var self = this; + this.element.bind( "remove." + this.widgetName, function() { + self.destroy(); + }); + + this._create(); + this._trigger( "create" ); + this._init(); + }, + _getCreateOptions: function() { + return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; + }, + _create: function() {}, + _init: function() {}, + + destroy: function() { + this.element + .unbind( "." + this.widgetName ) + .removeData( this.widgetName ); + this.widget() + .unbind( "." + this.widgetName ) + .removeAttr( "aria-disabled" ) + .removeClass( + this.widgetBaseClass + "-disabled " + + "ui-state-disabled" ); + }, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + + if ( arguments.length === 0 ) { + // don't return a reference to the internal hash + return $.extend( {}, this.options ); + } + + if (typeof key === "string" ) { + if ( value === undefined ) { + return this.options[ key ]; + } + options = {}; + options[ key ] = value; + } + + this._setOptions( options ); + + return this; + }, + _setOptions: function( options ) { + var self = this; + $.each( options, function( key, value ) { + self._setOption( key, value ); + }); + + return this; + }, + _setOption: function( key, value ) { + this.options[ key ] = value; + + if ( key === "disabled" ) { + this.widget() + [ value ? "addClass" : "removeClass"]( + this.widgetBaseClass + "-disabled" + " " + + "ui-state-disabled" ) + .attr( "aria-disabled", value ); + } + + return this; + }, + + enable: function() { + return this._setOption( "disabled", false ); + }, + disable: function() { + return this._setOption( "disabled", true ); + }, + + _trigger: function( type, event, data ) { + var prop, orig, + callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + + return !( $.isFunction(callback) && + callback.call( this.element[0], event, data ) === false || + event.isDefaultPrevented() ); + } +}; + +}));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery.blockUI.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,499 @@ +/*! + * jQuery blockUI plugin + * Version 2.39 (23-MAY-2011) + * @requires jQuery v1.2.3 or later + * + * Examples at: http://malsup.com/jquery/block/ + * Copyright (c) 2007-2010 M. Alsup + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Thanks to Amir-Hossein Sobhi for some excellent contributions! + */ + +;(function($) { + +if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) { + alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery); + return; +} + +$.fn._fadeIn = $.fn.fadeIn; + +var noOp = function() {}; + +// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle +// retarded userAgent strings on Vista) +var mode = document.documentMode || 0; +var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8); +var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode; + +// global $ methods for blocking/unblocking the entire page +$.blockUI = function(opts) { install(window, opts); }; +$.unblockUI = function(opts) { remove(window, opts); }; + +// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl) +$.growlUI = function(title, message, timeout, onClose) { + var $m = $('<div class="growlUI"></div>'); + if (title) $m.append('<h1>'+title+'</h1>'); + if (message) $m.append('<h2>'+message+'</h2>'); + if (timeout == undefined) timeout = 3000; + $.blockUI({ + message: $m, fadeIn: 700, fadeOut: 1000, centerY: false, + timeout: timeout, showOverlay: false, + onUnblock: onClose, + css: $.blockUI.defaults.growlCSS + }); +}; + +// plugin method for blocking element content +$.fn.block = function(opts) { + return this.unblock({ fadeOut: 0 }).each(function() { + if ($.css(this,'position') == 'static') + this.style.position = 'relative'; + if ($.browser.msie) + this.style.zoom = 1; // force 'hasLayout' + install(this, opts); + }); +}; + +// plugin method for unblocking element content +$.fn.unblock = function(opts) { + return this.each(function() { + remove(this, opts); + }); +}; + +$.blockUI.version = 2.39; // 2nd generation blocking at no extra cost! + +// override these in your code to change the default behavior and style +$.blockUI.defaults = { + // message displayed when blocking (use null for no message) + message: '<h1>Please wait...</h1>', + + title: null, // title string; only used when theme == true + draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded) + + theme: false, // set to true to use with jQuery UI themes + + // styles for the message when blocking; if you wish to disable + // these and use an external stylesheet then do this in your code: + // $.blockUI.defaults.css = {}; + css: { + padding: 0, + margin: 0, + width: '30%', + top: '40%', + left: '35%', + textAlign: 'center', + color: '#000', + border: '3px solid #aaa', + backgroundColor:'#fff', + cursor: 'wait' + }, + + // minimal style set used when themes are used + themedCSS: { + width: '30%', + top: '40%', + left: '35%' + }, + + // styles for the overlay + overlayCSS: { + backgroundColor: '#000', + opacity: 0.6, + cursor: 'wait' + }, + + // styles applied when using $.growlUI + growlCSS: { + width: '350px', + top: '10px', + left: '', + right: '10px', + border: 'none', + padding: '5px', + opacity: 0.6, + cursor: 'default', + color: '#fff', + backgroundColor: '#000', + '-webkit-border-radius': '10px', + '-moz-border-radius': '10px', + 'border-radius': '10px' + }, + + // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w + // (hat tip to Jorge H. N. de Vasconcelos) + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', + + // force usage of iframe in non-IE browsers (handy for blocking applets) + forceIframe: false, + + // z-index for the blocking overlay + baseZ: 1000, + + // set these to true to have the message automatically centered + centerX: true, // <-- only effects element blocking (page block controlled via css above) + centerY: true, + + // allow body element to be stetched in ie6; this makes blocking look better + // on "short" pages. disable if you wish to prevent changes to the body height + allowBodyStretch: true, + + // enable if you want key and mouse events to be disabled for content that is blocked + bindEvents: true, + + // be default blockUI will supress tab navigation from leaving blocking content + // (if bindEvents is true) + constrainTabKey: true, + + // fadeIn time in millis; set to 0 to disable fadeIn on block + fadeIn: 200, + + // fadeOut time in millis; set to 0 to disable fadeOut on unblock + fadeOut: 400, + + // time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock + timeout: 0, + + // disable if you don't want to show the overlay + showOverlay: true, + + // if true, focus will be placed in the first available input field when + // page blocking + focusInput: true, + + // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity) + applyPlatformOpacityRules: true, + + // callback method invoked when fadeIn has completed and blocking message is visible + onBlock: null, + + // callback method invoked when unblocking has completed; the callback is + // passed the element that has been unblocked (which is the window object for page + // blocks) and the options that were passed to the unblock call: + // onUnblock(element, options) + onUnblock: null, + + // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493 + quirksmodeOffsetHack: 4, + + // class name of the message block + blockMsgClass: 'blockMsg' +}; + +// private data and functions follow... + +var pageBlock = null; +var pageBlockEls = []; + +function install(el, opts) { + var full = (el == window); + var msg = opts && opts.message !== undefined ? opts.message : undefined; + opts = $.extend({}, $.blockUI.defaults, opts || {}); + opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); + var css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); + var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); + msg = msg === undefined ? opts.message : msg; + + // remove the current block (if there is one) + if (full && pageBlock) + remove(window, {fadeOut:0}); + + // if an existing element is being used as the blocking content then we capture + // its current place in the DOM (and current display style) so we can restore + // it when we unblock + if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { + var node = msg.jquery ? msg[0] : msg; + var data = {}; + $(el).data('blockUI.history', data); + data.el = node; + data.parent = node.parentNode; + data.display = node.style.display; + data.position = node.style.position; + if (data.parent) + data.parent.removeChild(node); + } + + $(el).data('blockUI.onUnblock', opts.onUnblock); + var z = opts.baseZ; + + // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform; + // layer1 is the iframe layer which is used to supress bleed through of underlying content + // layer2 is the overlay layer which has opacity and a wait cursor (by default) + // layer3 is the message content that is displayed while blocking + + var lyr1 = ($.browser.msie || opts.forceIframe) + ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>') + : $('<div class="blockUI" style="display:none"></div>'); + + var lyr2 = opts.theme + ? $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>') + : $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>'); + + var lyr3, s; + if (opts.theme && full) { + s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">' + + '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>' + + '<div class="ui-widget-content ui-dialog-content"></div>' + + '</div>'; + } + else if (opts.theme) { + s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">' + + '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>' + + '<div class="ui-widget-content ui-dialog-content"></div>' + + '</div>'; + } + else if (full) { + s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>'; + } + else { + s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>'; + } + lyr3 = $(s); + + // if we have a message, style it + if (msg) { + if (opts.theme) { + lyr3.css(themedCSS); + lyr3.addClass('ui-widget-content'); + } + else + lyr3.css(css); + } + + // style the overlay + if (!opts.theme && (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))) + lyr2.css(opts.overlayCSS); + lyr2.css('position', full ? 'fixed' : 'absolute'); + + // make iframe layer transparent in IE + if ($.browser.msie || opts.forceIframe) + lyr1.css('opacity',0.0); + + //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el); + var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); + $.each(layers, function() { + this.appendTo($par); + }); + + if (opts.theme && opts.draggable && $.fn.draggable) { + lyr3.draggable({ + handle: '.ui-dialog-titlebar', + cancel: 'li' + }); + } + + // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling) + var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0); + if (ie6 || expr) { + // give body 100% height + if (full && opts.allowBodyStretch && $.boxModel) + $('html,body').css('height','100%'); + + // fix ie6 issue when blocked element has a border width + if ((ie6 || !$.boxModel) && !full) { + var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); + var fixT = t ? '(0 - '+t+')' : 0; + var fixL = l ? '(0 - '+l+')' : 0; + } + + // simulate fixed position + $.each([lyr1,lyr2,lyr3], function(i,o) { + var s = o[0].style; + s.position = 'absolute'; + if (i < 2) { + full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"') + : s.setExpression('height','this.parentNode.offsetHeight + "px"'); + full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"') + : s.setExpression('width','this.parentNode.offsetWidth + "px"'); + if (fixL) s.setExpression('left', fixL); + if (fixT) s.setExpression('top', fixT); + } + else if (opts.centerY) { + if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'); + s.marginTop = 0; + } + else if (!opts.centerY && full) { + var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0; + var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; + s.setExpression('top',expression); + } + }); + } + + // show the message + if (msg) { + if (opts.theme) + lyr3.find('.ui-widget-content').append(msg); + else + lyr3.append(msg); + if (msg.jquery || msg.nodeType) + $(msg).show(); + } + + if (($.browser.msie || opts.forceIframe) && opts.showOverlay) + lyr1.show(); // opacity is zero + if (opts.fadeIn) { + var cb = opts.onBlock ? opts.onBlock : noOp; + var cb1 = (opts.showOverlay && !msg) ? cb : noOp; + var cb2 = msg ? cb : noOp; + if (opts.showOverlay) + lyr2._fadeIn(opts.fadeIn, cb1); + if (msg) + lyr3._fadeIn(opts.fadeIn, cb2); + } + else { + if (opts.showOverlay) + lyr2.show(); + if (msg) + lyr3.show(); + if (opts.onBlock) + opts.onBlock(); + } + + // bind key and mouse events + bind(1, el, opts); + + if (full) { + pageBlock = lyr3[0]; + pageBlockEls = $(':input:enabled:visible',pageBlock); + if (opts.focusInput) + setTimeout(focus, 20); + } + else + center(lyr3[0], opts.centerX, opts.centerY); + + if (opts.timeout) { + // auto-unblock + var to = setTimeout(function() { + full ? $.unblockUI(opts) : $(el).unblock(opts); + }, opts.timeout); + $(el).data('blockUI.timeout', to); + } +}; + +// remove the block +function remove(el, opts) { + var full = (el == window); + var $el = $(el); + var data = $el.data('blockUI.history'); + var to = $el.data('blockUI.timeout'); + if (to) { + clearTimeout(to); + $el.removeData('blockUI.timeout'); + } + opts = $.extend({}, $.blockUI.defaults, opts || {}); + bind(0, el, opts); // unbind events + + if (opts.onUnblock === null) { + opts.onUnblock = $el.data('blockUI.onUnblock'); + $el.removeData('blockUI.onUnblock'); + } + + var els; + if (full) // crazy selector to handle odd field errors in ie6/7 + els = $('body').children().filter('.blockUI').add('body > .blockUI'); + else + els = $('.blockUI', el); + + if (full) + pageBlock = pageBlockEls = null; + + if (opts.fadeOut) { + els.fadeOut(opts.fadeOut); + setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut); + } + else + reset(els, data, opts, el); +}; + +// move blocking element back into the DOM where it started +function reset(els,data,opts,el) { + els.each(function(i,o) { + // remove via DOM calls so we don't lose event handlers + if (this.parentNode) + this.parentNode.removeChild(this); + }); + + if (data && data.el) { + data.el.style.display = data.display; + data.el.style.position = data.position; + if (data.parent) + data.parent.appendChild(data.el); + $(el).removeData('blockUI.history'); + } + + if (typeof opts.onUnblock == 'function') + opts.onUnblock(el,opts); +}; + +// bind/unbind the handler +function bind(b, el, opts) { + var full = el == window, $el = $(el); + + // don't bother unbinding if there is nothing to unbind + if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) + return; + if (!full) + $el.data('blockUI.isBlocked', b); + + // don't bind events when overlay is not in use or if bindEvents is false + if (!opts.bindEvents || (b && !opts.showOverlay)) + return; + + // bind anchors and inputs for mouse and key events + var events = 'mousedown mouseup keydown keypress'; + b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler); + +// former impl... +// var $e = $('a,:input'); +// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler); +}; + +// event handler to suppress keyboard/mouse events when blocking +function handler(e) { + // allow tab navigation (conditionally) + if (e.keyCode && e.keyCode == 9) { + if (pageBlock && e.data.constrainTabKey) { + var els = pageBlockEls; + var fwd = !e.shiftKey && e.target === els[els.length-1]; + var back = e.shiftKey && e.target === els[0]; + if (fwd || back) { + setTimeout(function(){focus(back)},10); + return false; + } + } + } + var opts = e.data; + // allow events within the message content + if ($(e.target).parents('div.' + opts.blockMsgClass).length > 0) + return true; + + // allow events for content that is not being blocked + return $(e.target).parents().children().filter('div.blockUI').length == 0; +}; + +function focus(back) { + if (!pageBlockEls) + return; + var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; + if (e) + e.focus(); +}; + +function center(el, x, y) { + var p = el.parentNode, s = el.style; + var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); + var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); + if (x) s.left = l > 0 ? (l+'px') : '0'; + if (y) s.top = t > 0 ? (t+'px') : '0'; +}; + +function sz(el, p) { + return parseInt($.css(el,p))||0; +}; + +})(jQuery);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery.mobile-1.1.0.min.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,2 @@ +/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ +.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(#3c3c3c,#111);background-image:-moz-linear-gradient(#3c3c3c,#111);background-image:-ms-linear-gradient(#3c3c3c,#111);background-image:-o-linear-gradient(#3c3c3c,#111);background-image:linear-gradient(#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-a .ui-link:hover{color:#2489ce}.ui-bar-a .ui-link:active{color:#2489ce}.ui-bar-a .ui-link:visited{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 1px #111;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#222));background-image:-webkit-linear-gradient(#444,#222);background-image:-moz-linear-gradient(#444,#222);background-image:-ms-linear-gradient(#444,#222);background-image:-o-linear-gradient(#444,#222);background-image:linear-gradient(#444,#222)}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:bold}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-body-a .ui-link:visited{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#2d2d2d));background-image:-webkit-linear-gradient(#444,#2d2d2d);background-image:-moz-linear-gradient(#444,#2d2d2d);background-image:-ms-linear-gradient(#444,#2d2d2d);background-image:-o-linear-gradient(#444,#2d2d2d);background-image:linear-gradient(#444,#2d2d2d)}.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#383838));background-image:-webkit-linear-gradient(#555,#383838);background-image:-moz-linear-gradient(#555,#383838);background-image:-ms-linear-gradient(#555,#383838);background-image:-o-linear-gradient(#555,#383838);background-image:linear-gradient(#555,#383838)}.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#202020),to(#2c2c2c));background-image:-webkit-linear-gradient(#202020,#2c2c2c);background-image:-moz-linear-gradient(#202020,#2c2c2c);background-image:-ms-linear-gradient(#202020,#2c2c2c);background-image:-o-linear-gradient(#202020,#2c2c2c);background-image:linear-gradient(#202020,#2c2c2c)}.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:bold;text-shadow:0 1px 1px #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#497bae));background-image:-webkit-linear-gradient(#6facd5,#497bae);background-image:-moz-linear-gradient(#6facd5,#497bae);background-image:-ms-linear-gradient(#6facd5,#497bae);background-image:-o-linear-gradient(#6facd5,#497bae);background-image:linear-gradient(#6facd5,#497bae)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b .ui-link{color:#ddf0f8;font-weight:bold}.ui-bar-b .ui-link:hover{color:#ddf0f8}.ui-bar-b .ui-link:active{color:#ddf0f8}.ui-bar-b .ui-link:visited{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#ccc));background-image:-webkit-linear-gradient(#ddd,#ccc);background-image:-moz-linear-gradient(#ddd,#ccc);background-image:-ms-linear-gradient(#ddd,#ccc);background-image:-o-linear-gradient(#ddd,#ccc);background-image:linear-gradient(#ddd,#ccc)}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:bold}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-body-b .ui-link:visited{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#5f9cc5),to(#396b9e));background-image:-webkit-linear-gradient(#5f9cc5,#396b9e);background-image:-moz-linear-gradient(#5f9cc5,#396b9e);background-image:-ms-linear-gradient(#5f9cc5,#396b9e);background-image:-o-linear-gradient(#5f9cc5,#396b9e);background-image:linear-gradient(#5f9cc5,#396b9e)}.ui-btn-up-b a.ui-link-inherit{color:#fff}.ui-btn-hover-b{border:1px solid #00415e;background:#4b88b6;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#4272a4));background-image:-webkit-linear-gradient(#6facd5,#4272a4);background-image:-moz-linear-gradient(#6facd5,#4272a4);background-image:-ms-linear-gradient(#6facd5,#4272a4);background-image:-o-linear-gradient(#6facd5,#4272a4);background-image:linear-gradient(#6facd5,#4272a4)}.ui-btn-hover-b a.ui-link-inherit{color:#fff}.ui-btn-down-b{border:1px solid #225377;background:#4e89c5;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#295b8e),to(#3e79b5));background-image:-webkit-linear-gradient(#295b8e,#3e79b5);background-image:-moz-linear-gradient(#295b8e,#3e79b5);background-image:-ms-linear-gradient(#295b8e,#3e79b5);background-image:-o-linear-gradient(#295b8e,#3e79b5);background-image:linear-gradient(#295b8e,#3e79b5)}.ui-btn-down-b a.ui-link-inherit{color:#fff}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-c{border:1px solid #b3b3b3;background:#eee;color:#3e3e3e;font-weight:bold;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#ddd));background-image:-webkit-linear-gradient(#f0f0f0,#ddd);background-image:-moz-linear-gradient(#f0f0f0,#ddd);background-image:-ms-linear-gradient(#f0f0f0,#ddd);background-image:-o-linear-gradient(#f0f0f0,#ddd);background-image:linear-gradient(#f0f0f0,#ddd)}.ui-bar-c .ui-link-inherit{color:#3e3e3e}.ui-bar-c .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-c .ui-link:hover{color:#2489ce}.ui-bar-c .ui-link:active{color:#2489ce}.ui-bar-c .ui-link:visited{color:#2489ce}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c,.ui-overlay-c{border:1px solid #aaa;color:#333;text-shadow:0 1px 0 #fff;background:#f9f9f9;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#eee));background-image:-webkit-linear-gradient(#f9f9f9,#eee);background-image:-moz-linear-gradient(#f9f9f9,#eee);background-image:-ms-linear-gradient(#f9f9f9,#eee);background-image:-o-linear-gradient(#f9f9f9,#eee);background-image:linear-gradient(#f9f9f9,#eee)}.ui-overlay-c{background-image:none;border-width:0}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c .ui-link-inherit{color:#333}.ui-body-c .ui-link{color:#2489ce;font-weight:bold}.ui-body-c .ui-link:hover{color:#2489ce}.ui-body-c .ui-link:active{color:#2489ce}.ui-body-c .ui-link:visited{color:#2489ce}.ui-btn-up-c{border:1px solid #ccc;background:#eee;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f1f1f1));background-image:-webkit-linear-gradient(#fff,#f1f1f1);background-image:-moz-linear-gradient(#fff,#f1f1f1);background-image:-ms-linear-gradient(#fff,#f1f1f1);background-image:-o-linear-gradient(#fff,#f1f1f1);background-image:linear-gradient(#fff,#f1f1f1)}.ui-btn-up-c a.ui-link-inherit{color:#2f3e46}.ui-btn-hover-c{border:1px solid #bbb;background:#dfdfdf;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#e0e0e0));background-image:-webkit-linear-gradient(#f9f9f9,#e0e0e0);background-image:-moz-linear-gradient(#f6f6f6,#e0e0e0);background-image:-ms-linear-gradient(#f6f6f6,#e0e0e0);background-image:-o-linear-gradient(#f6f6f6,#e0e0e0);background-image:linear-gradient(#f6f6f6,#e0e0e0)}.ui-btn-hover-c a.ui-link-inherit{color:#2f3e46}.ui-btn-down-c{border:1px solid #bbb;background:#d6d6d6;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#d0d0d0),to(#dfdfdf));background-image:-webkit-linear-gradient(#d0d0d0,#dfdfdf);background-image:-moz-linear-gradient(#d0d0d0,#dfdfdf);background-image:-ms-linear-gradient(#d0d0d0,#dfdfdf);background-image:-o-linear-gradient(#d0d0d0,#dfdfdf);background-image:linear-gradient(#d0d0d0,#dfdfdf)}.ui-btn-down-c a.ui-link-inherit{color:#2f3e46}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-d{border:1px solid #bbb;background:#bbb;color:#333;text-shadow:0 1px 0 #eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#bbb));background-image:-webkit-linear-gradient(#ddd,#bbb);background-image:-moz-linear-gradient(#ddd,#bbb);background-image:-ms-linear-gradient(#ddd,#bbb);background-image:-o-linear-gradient(#ddd,#bbb);background-image:linear-gradient(#ddd,#bbb)}.ui-bar-d,.ui-bar-d input,.ui-bar-d select,.ui-bar-d textarea,.ui-bar-d button{font-family:Helvetica,Arial,sans-serif}.ui-bar-d .ui-link-inherit{color:#333}.ui-bar-d .ui-link{color:#2489ce;font-weight:bold}.ui-bar-d .ui-link:hover{color:#2489ce}.ui-bar-d .ui-link:active{color:#2489ce}.ui-bar-d .ui-link:visited{color:#2489ce}.ui-body-d,.ui-overlay-d{border:1px solid #bbb;color:#333;text-shadow:0 1px 0 #fff;background:#fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#fff));background-image:-webkit-linear-gradient(#fff,#fff);background-image:-moz-linear-gradient(#fff,#fff);background-image:-ms-linear-gradient(#fff,#fff);background-image:-o-linear-gradient(#fff,#fff);background-image:linear-gradient(#fff,#fff)}.ui-overlay-d{background-image:none;border-width:0}.ui-body-d,.ui-body-d input,.ui-body-d select,.ui-body-d textarea,.ui-body-d button{font-family:Helvetica,Arial,sans-serif}.ui-body-d .ui-link-inherit{color:#333}.ui-body-d .ui-link{color:#2489ce;font-weight:bold}.ui-body-d .ui-link:hover{color:#2489ce}.ui-body-d .ui-link:active{color:#2489ce}.ui-body-d .ui-link:visited{color:#2489ce}.ui-btn-up-d{border:1px solid #bbb;background:#fff;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#f6f6f6));background-image:-webkit-linear-gradient(#fafafa,#f6f6f6);background-image:-moz-linear-gradient(#fafafa,#f6f6f6);background-image:-ms-linear-gradient(#fafafa,#f6f6f6);background-image:-o-linear-gradient(#fafafa,#f6f6f6);background-image:linear-gradient(#fafafa,#f6f6f6)}.ui-btn-up-d a.ui-link-inherit{color:#333}.ui-btn-hover-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;cursor:pointer;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#fff));background-image:-webkit-linear-gradient(#eee,#fff);background-image:-moz-linear-gradient(#eee,#fff);background-image:-ms-linear-gradient(#eee,#fff);background-image:-o-linear-gradient(#eee,#fff);background-image:linear-gradient(#eee,#fff)}.ui-btn-hover-d a.ui-link-inherit{color:#333}.ui-btn-down-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#e5e5e5),to(#f2f2f2));background-image:-webkit-linear-gradient(#e5e5e5,#f2f2f2);background-image:-moz-linear-gradient(#e5e5e5,#f2f2f2);background-image:-ms-linear-gradient(#e5e5e5,#f2f2f2);background-image:-o-linear-gradient(#e5e5e5,#f2f2f2);background-image:linear-gradient(#e5e5e5,#f2f2f2)}.ui-btn-down-d a.ui-link-inherit{color:#333}.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-e{border:1px solid #f7c942;background:#fadb4e;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fceda7),to(#fbef7e));background-image:-webkit-linear-gradient(#fceda7,#fbef7e);background-image:-moz-linear-gradient(#fceda7,#fbef7e);background-image:-ms-linear-gradient(#fceda7,#fbef7e);background-image:-o-linear-gradient(#fceda7,#fbef7e);background-image:linear-gradient(#fceda7,#fbef7e)}.ui-bar-e,.ui-bar-e input,.ui-bar-e select,.ui-bar-e textarea,.ui-bar-e button{font-family:Helvetica,Arial,sans-serif}.ui-bar-e .ui-link-inherit{color:#333}.ui-bar-e .ui-link{color:#2489ce;font-weight:bold}.ui-bar-e .ui-link:hover{color:#2489ce}.ui-bar-e .ui-link:active{color:#2489ce}.ui-bar-e .ui-link:visited{color:#2489ce}.ui-body-e,.ui-overlay-e{border:1px solid #f7c942;color:#222;text-shadow:0 1px 0 #fff;background:#fff9df;background-image:-webkit-gradient(linear,left top,left bottom,from(#fffadf),to(#fff3a5));background-image:-webkit-linear-gradient(#fffadf,#fff3a5);background-image:-moz-linear-gradient(#fffadf,#fff3a5);background-image:-ms-linear-gradient(#fffadf,#fff3a5);background-image:-o-linear-gradient(#fffadf,#fff3a5);background-image:linear-gradient(#fffadf,#fff3a5)}.ui-overlay-e{background-image:none;border-width:0}.ui-body-e,.ui-body-e input,.ui-body-e select,.ui-body-e textarea,.ui-body-e button{font-family:Helvetica,Arial,sans-serif}.ui-body-e .ui-link-inherit{color:#333}.ui-body-e .ui-link{color:#2489ce;font-weight:bold}.ui-body-e .ui-link:hover{color:#2489ce}.ui-body-e .ui-link:active{color:#2489ce}.ui-body-e .ui-link:visited{color:#2489ce}.ui-btn-up-e{border:1px solid #f4c63f;background:#fadb4e;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#ffefaa),to(#ffe155));background-image:-webkit-linear-gradient(#ffefaa,#ffe155);background-image:-moz-linear-gradient(#ffefaa,#ffe155);background-image:-ms-linear-gradient(#ffefaa,#ffe155);background-image:-o-linear-gradient(#ffefaa,#ffe155);background-image:linear-gradient(#ffefaa,#ffe155)}.ui-btn-up-e a.ui-link-inherit{color:#222}.ui-btn-hover-e{border:1px solid #f2c43d;background:#fbe26f;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff5ba),to(#fbdd52));background-image:-webkit-linear-gradient(#fff5ba,#fbdd52);background-image:-moz-linear-gradient(#fff5ba,#fbdd52);background-image:-ms-linear-gradient(#fff5ba,#fbdd52);background-image:-o-linear-gradient(#fff5ba,#fbdd52);background-image:linear-gradient(#fff5ba,#fbdd52)}.ui-btn-hover-e a.ui-link-inherit{color:#333}.ui-btn-down-e{border:1px solid #f2c43d;background:#fceda7;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f8d94c),to(#fadb4e));background-image:-webkit-linear-gradient(#f8d94c,#fadb4e);background-image:-moz-linear-gradient(#f8d94c,#fadb4e);background-image:-ms-linear-gradient(#f8d94c,#fadb4e);background-image:-o-linear-gradient(#f8d94c,#fadb4e);background-image:linear-gradient(#f8d94c,#fadb4e)}.ui-btn-down-e a.ui-link-inherit{color:#333}.ui-btn-up-e,.ui-btn-hover-e,.ui-btn-down-e{font-family:Helvetica,Arial,sans-serif;text-decoration:none}a.ui-link-inherit{text-decoration:none!important}.ui-btn-active{border:1px solid #2373a5;background:#5393c5;font-weight:bold;color:#fff;cursor:pointer;text-shadow:0 1px 1px #3373a5;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from(#5393c5),to(#6facd5));background-image:-webkit-linear-gradient(#5393c5,#6facd5);background-image:-moz-linear-gradient(#5393c5,#6facd5);background-image:-ms-linear-gradient(#5393c5,#6facd5);background-image:-o-linear-gradient(#5393c5,#6facd5);background-image:linear-gradient(#5393c5,#6facd5);font-family:Helvetica,Arial,sans-serif}.ui-btn-active a.ui-link-inherit{color:#fff}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3)}.ui-corner-tl{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em}.ui-corner-tr{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bl{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-br{-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-top{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-right{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-left{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-all{-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.ui-corner-none{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.ui-br{border-bottom:#828282;border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid}.ui-disabled{opacity:.3}.ui-disabled,.ui-disabled a{cursor:default!important;pointer-events:none}.ui-disabled .ui-btn-text{-ms-filter:"alpha(opacity=30)";filter:alpha(opacity=30);zoom:1}.ui-icon,.ui-icon-searchfield:after{background:#666;background:rgba(0,0,0,.4);background-image:url(images/icons-18-white.png);background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px}.ui-icon-alt{background-image:url(images/icons-36-black.png)}}.ui-icon-plus{background-position:-0 50%}.ui-icon-minus{background-position:-36px 50%}.ui-icon-delete{background-position:-72px 50%}.ui-icon-arrow-r{background-position:-108px 50%}.ui-icon-arrow-l{background-position:-144px 50%}.ui-icon-arrow-u{background-position:-180px 50%}.ui-icon-arrow-d{background-position:-216px 50%}.ui-icon-check{background-position:-252px 50%}.ui-icon-gear{background-position:-288px 50%}.ui-icon-refresh{background-position:-324px 50%}.ui-icon-forward{background-position:-360px 50%}.ui-icon-back{background-position:-396px 50%}.ui-icon-grid{background-position:-432px 50%}.ui-icon-star{background-position:-468px 50%}.ui-icon-alert{background-position:-504px 50%}.ui-icon-info{background-position:-540px 50%}.ui-icon-home{background-position:-576px 50%}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%}.ui-icon-checkbox-off{background-position:-684px 50%}.ui-icon-checkbox-on{background-position:-648px 50%}.ui-icon-radio-off{background-position:-756px 50%}.ui-icon-radio-on{background-position:-720px 50%}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#4596ce}.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px}.ui-btn-corner-tl{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em}.ui-btn-corner-tr{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bl{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-br{-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-top{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-right{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-left{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-all{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.ui-overlay{background:#666;opacity:.5;filter:Alpha(Opacity=50);position:absolute;width:100%;height:100%}.ui-overlay-shadow{-moz-box-shadow:0 0 12px rgba(0,0,0,.6);-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-shadow{-moz-box-shadow:0 1px 4px rgba(0,0,0,.3);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3);box-shadow:0 1px 4px rgba(0,0,0,.3)}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-shadow-inset{-moz-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);box-shadow:inset 0 1px 4px rgba(0,0,0,.2)}.ui-icon-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.4);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.4);box-shadow:0 1px 0 rgba(255,255,255,.4)}.ui-btn:focus{outline:0}.ui-focus,.ui-btn:focus{-moz-box-shadow:0 0 12px #387bbe;-webkit-box-shadow:0 0 12px #387bbe;box-shadow:0 0 12px #387bbe}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}.ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus{outline-width:1px;outline-style:dotted}.ui-mobile,.ui-mobile body{height:99.9%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border-width:0}.ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-mobile .ui-page-active{display:block;overflow:visible}.ui-page{outline:0}@media screen and (orientation:portrait){.ui-mobile,.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile,.ui-mobile .ui-page{min-height:300px}}.ui-loading .ui-loader{display:block}.ui-loader{display:none;z-index:9999999;position:fixed;top:50%;box-shadow:0 1px 1px -1px #fff;left:50%;border:0}.ui-loader-default{background:0;opacity:.18;width:46px;height:46px;margin-left:-23px;margin-top:-23px}.ui-loader-verbose{width:200px;opacity:.88;height:auto;margin-left:-110px;margin-top:-43px;padding:10px}.ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden}.ui-loader-verbose h1{font-size:16px;margin:0;text-align:center}.ui-loader .ui-icon{background-color:#000;display:block;margin:0;width:44px;height:44px;padding:1px;-webkit-border-radius:36px;-moz-border-radius:36px;border-radius:36px}.ui-loader-verbose .ui-icon{margin:0 auto 10px;opacity:.75}.ui-loader-textonly{padding:15px;margin-left:-115px}.ui-loader-textonly .ui-icon{display:none}.ui-loader-fakefix{position:absolute}.ui-mobile-rendering>*{visibility:hidden}.ui-bar,.ui-body{position:relative;padding:.4em 15px;overflow:hidden;display:block;clear:both}.ui-bar{font-size:16px;margin:0}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:16px;display:inline-block}.ui-header,.ui-footer{position:relative;border-left-width:0;border-right-width:0}.ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-footer .ui-btn-left,.ui-footer .ui-btn-right{position:absolute;top:3px}.ui-header .ui-btn-left,.ui-footer .ui-btn-left{left:5px}.ui-header .ui-btn-right,.ui-footer .ui-btn-right{right:5px}.ui-footer .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext{top:6px}.ui-header .ui-title,.ui-footer .ui-title{min-height:1.1em;text-align:center;font-size:16px;display:block;margin:.6em 30% .8em;padding:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:.6em 15px .8em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:15px}.ui-icon{width:18px;height:18px}.ui-nojs{position:absolute;left:-9999px}.ui-hide-label label,.ui-hidden-accessible{position:absolute!important;left:-9999px;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden}.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout}.fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;-webkit-animation-name:popin;-moz-animation-name:popin;-webkit-animation-duration:350ms;-moz-animation-duration:350ms}.pop.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;opacity:0;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein}.pop.out.reverse{-webkit-transform:scale(.8);-moz-transform:scale(.8);-webkit-animation-name:popout;-moz-animation-name:popout}@-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(-100%)}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(100%)}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}}.slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.slide.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft}.slide.in{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft}.slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-animation-duration:225ms}.slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidedown.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slidedown.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slidedown.out.reverse{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-moz-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}}.slideup.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slideup.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slideup.out.reverse{-webkit-transform:translateY(100%);-moz-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-moz-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}}.viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms}.flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms}.flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.viewport-turn{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0 0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0 0}.turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-animation-duration:125ms}.turn.in{-webkit-animation-name:flipintoright;-moz-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.flow{-webkit-transform-origin:50% 30%;-moz-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-box-shadow:0 0 20px rgba(0,0,0,.4)}.ui-dialog.flow{-webkit-transform-origin:none;-moz-transform-origin:none;-webkit-box-shadow:none;-moz-box-shadow:none}.flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright}.flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft}@-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}}@-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}}@-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}}@-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}}@-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px}.ui-grid-solo .ui-block-a{width:100%;float:none}.ui-grid-a .ui-block-a,.ui-grid-a .ui-block-b{width:50%}.ui-grid-a .ui-block-a{clear:left}.ui-grid-b .ui-block-a,.ui-grid-b .ui-block-b,.ui-grid-b .ui-block-c{width:33.333%}.ui-grid-b .ui-block-a{clear:left}.ui-grid-c .ui-block-a,.ui-grid-c .ui-block-b,.ui-grid-c .ui-block-c,.ui-grid-c .ui-block-d{width:25%}.ui-grid-c .ui-block-a{clear:left}.ui-grid-d .ui-block-a,.ui-grid-d .ui-block-b,.ui-grid-d .ui-block-c,.ui-grid-d .ui-block-d,.ui-grid-d .ui-block-e{width:20%}.ui-grid-d .ui-block-a{clear:left}.ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000}.ui-header-fixed{top:0}.ui-footer-fixed{bottom:0}.ui-header-fullscreen,.ui-footer-fullscreen{opacity:.9}.ui-page-header-fixed{padding-top:2.5em}.ui-page-footer-fixed{padding-bottom:3em}.ui-page-header-fullscreen .ui-content,.ui-page-footer-fullscreen .ui-content{padding:0}.ui-fixed-hidden{position:absolute}.ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{left:-99999em}.ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10}.ui-navbar{overflow:hidden}.ui-navbar ul,.ui-navbar-expanded ul{list-style:none;padding:0;margin:0;position:relative;display:block;border:0}.ui-navbar-collapsed ul{float:left;width:75%;margin-right:-2px}.ui-navbar-collapsed .ui-navbar-toggle{float:left;width:25%}.ui-navbar li.ui-navbar-truncate{position:absolute;left:-9999px;top:-9999px}.ui-navbar li .ui-btn,.ui-navbar .ui-navbar-toggle .ui-btn{display:block;font-size:12px;text-align:center;margin:0;border-right-width:0;max-width:100%}.ui-navbar li .ui-btn{margin-right:-1px}.ui-navbar li .ui-btn:last-child{margin-right:0}.ui-header .ui-navbar li .ui-btn,.ui-header .ui-navbar .ui-navbar-toggle .ui-btn,.ui-footer .ui-navbar li .ui-btn,.ui-footer .ui-navbar .ui-navbar-toggle .ui-btn{border-top-width:0;border-bottom-width:0}.ui-navbar .ui-btn-inner{padding-left:2px;padding-right:2px}.ui-navbar-noicons li .ui-btn .ui-btn-inner,.ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner{padding-top:.8em;padding-bottom:.9em}.ui-navbar-expanded .ui-btn{margin:0;font-size:14px}.ui-navbar-expanded .ui-btn-inner{padding-left:5px;padding-right:5px}.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner{padding:45px 5px 15px;text-align:center}.ui-navbar-expanded .ui-btn-icon-top .ui-icon{top:15px}.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner{padding:15px 5px 45px;text-align:center}.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon{bottom:15px}.ui-navbar-expanded li .ui-btn .ui-btn-inner{min-height:2.5em}.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner{padding-top:1.8em;padding-bottom:1.9em}.ui-btn{display:block;text-align:center;cursor:pointer;position:relative;margin:.5em 5px;padding:0}.ui-mini{margin:.25em 5px}.ui-btn-inner{padding:.6em 20px;min-width:.75em;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative;zoom:1}.ui-btn input,.ui-btn button{z-index:2}.ui-btn-left,.ui-btn-right,.ui-btn-inline{display:inline-block}.ui-btn-block{display:block}.ui-header .ui-btn,.ui-footer .ui-btn{display:inline-block;margin:0}.ui-header .ui-btn-inner,.ui-footer .ui-btn-inner,.ui-mini .ui-btn-inner{font-size:12.5px;padding:.55em 11px .5em}.ui-header .ui-fullsize .ui-btn-inner,.ui-footer .ui-fullsize .ui-btn-inner{font-size:16px;padding:.6em 25px}.ui-btn-icon-notext{width:24px;height:24px}.ui-btn-icon-notext .ui-btn-inner{padding:0;height:100%}.ui-btn-icon-notext .ui-btn-inner .ui-icon{margin:2px 1px 2px 3px}.ui-btn-text{position:relative;z-index:1;width:100%}.ui-btn-icon-notext .ui-btn-text{position:absolute;left:-9999px}.ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-btn-icon-right .ui-btn-inner{padding-right:40px}.ui-btn-icon-top .ui-btn-inner{padding-top:40px}.ui-btn-icon-bottom .ui-btn-inner{padding-bottom:40px}.ui-header .ui-btn-icon-left .ui-btn-inner,.ui-footer .ui-btn-icon-left .ui-btn-inner,.ui-mini .ui-btn-icon-left .ui-btn-inner{padding-left:30px}.ui-header .ui-btn-icon-right .ui-btn-inner,.ui-footer .ui-btn-icon-right .ui-btn-inner,.ui-mini .ui-btn-icon-right .ui-btn-inner{padding-right:30px}.ui-header .ui-btn-icon-top .ui-btn-inner,.ui-footer .ui-btn-icon-top .ui-btn-inner,.ui-mini .ui-btn-icon-top .ui-btn-inner{padding:30px 3px .5em 3px}.ui-header .ui-btn-icon-bottom .ui-btn-inner,.ui-footer .ui-btn-icon-bottom .ui-btn-inner,.ui-mini .ui-btn-icon-bottom .ui-btn-inner{padding:.55em 3px 30px 3px}.ui-btn-icon-notext .ui-icon{display:block;z-index:0}.ui-btn-icon-left .ui-btn-inner .ui-icon,.ui-btn-icon-right .ui-btn-inner .ui-icon{position:absolute;top:50%;margin-top:-9px}.ui-btn-icon-top .ui-btn-inner .ui-icon,.ui-btn-icon-bottom .ui-btn-inner .ui-icon{position:absolute;left:50%;margin-left:-9px}.ui-btn-icon-left .ui-icon{left:10px}.ui-btn-icon-right .ui-icon{right:10px}.ui-btn-icon-top .ui-icon{top:10px}.ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-header .ui-btn-icon-left .ui-icon,.ui-footer .ui-btn-icon-left .ui-icon,.ui-mini.ui-btn-icon-left .ui-icon,.ui-mini .ui-btn-icon-left .ui-icon{left:5px}.ui-header .ui-btn-icon-right .ui-icon,.ui-footer .ui-btn-icon-right .ui-icon,.ui-mini.ui-btn-icon-right .ui-icon,.ui-mini .ui-btn-icon-right .ui-icon{right:5px}.ui-header .ui-btn-icon-top .ui-icon,.ui-footer .ui-btn-icon-top .ui-icon,.ui-mini.ui-btn-icon-top .ui-icon,.ui-mini .ui-btn-icon-top .ui-icon{top:5px}.ui-header .ui-btn-icon-bottom .ui-icon,.ui-footer .ui-btn-icon-bottom .ui-icon,.ui-mini.ui-btn-icon-bottom .ui-icon,.ui-mini .ui-btn-icon-bottom .ui-icon{bottom:5px}.ui-btn-hidden{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-appearance:button;opacity:.1;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=.0001);font-size:1px;border:0;text-indent:-9999px}.ui-collapsible{margin:.5em 0}.ui-collapsible-heading{font-size:16px;display:block;margin:0 -8px;padding:0;border-width:0 0 1px 0;position:relative}.ui-collapsible-heading a{text-align:left;margin:0}.ui-collapsible-heading .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner{padding-left:12px;padding-right:40px}.ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner{padding-right:40px;text-align:center}.ui-collapsible-heading a span.ui-btn{position:absolute;left:6px;top:50%;margin:-12px 0 0 0;width:20px;height:20px;padding:1px 0 1px 2px;text-indent:-9999px}.ui-collapsible-heading a span.ui-btn .ui-btn-inner{padding:10px 0}.ui-collapsible-heading a span.ui-btn .ui-icon{left:0;margin-top:-10px}.ui-collapsible-heading-status{position:absolute;top:-9999px;left:0}.ui-collapsible-content{display:block;margin:0 -8px;padding:10px 16px;border-top:0;background-image:none;font-weight:normal}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set{margin:.5em 0}.ui-collapsible-set .ui-collapsible{margin:-1px 0 0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:0 0 .5em;zoom:1}.ui-bar .ui-controlgroup{margin:0 .3em}.ui-controlgroup-label{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .4em}.ui-controlgroup-controls{display:block;width:100%}.ui-controlgroup li{list-style:none}.ui-controlgroup-vertical .ui-btn,.ui-controlgroup-vertical .ui-checkbox,.ui-controlgroup-vertical .ui-radio{margin:0;border-bottom-width:0}.ui-controlgroup-controls label.ui-select{position:absolute;left:-9999px}.ui-controlgroup-vertical .ui-controlgroup-last{border-bottom-width:1px}.ui-controlgroup-horizontal{padding:0}.ui-controlgroup-horizontal .ui-btn-inner{text-align:center}.ui-controlgroup-horizontal .ui-btn,.ui-controlgroup-horizontal .ui-select{display:inline-block;margin:0 -6px 0 0}.ui-controlgroup-horizontal .ui-checkbox,.ui-controlgroup-horizontal .ui-radio{float:left;clear:none;margin:0 -1px 0 0}.ui-controlgroup-horizontal .ui-checkbox .ui-btn,.ui-controlgroup-horizontal .ui-radio .ui-btn,.ui-controlgroup-horizontal .ui-checkbox:last-child,.ui-controlgroup-horizontal .ui-radio:last-child{margin-right:0}.ui-controlgroup-horizontal .ui-controlgroup-last{margin-right:0}.ui-controlgroup .ui-checkbox label,.ui-controlgroup .ui-radio label{font-size:16px}@media all and (min-width:450px){.ui-field-contain .ui-controlgroup-label{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-controlgroup-controls{width:60%;display:inline-block}.ui-field-contain .ui-controlgroup .ui-select{width:100%}.ui-field-contain .ui-controlgroup-horizontal .ui-select{width:auto}}.ui-dialog{background:none!important}.ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 15px auto;padding:0}.ui-dialog .ui-header{margin-top:15%;border:0;overflow:hidden}.ui-dialog .ui-header,.ui-dialog .ui-content,.ui-dialog .ui-footer{display:block;position:relative;width:auto}.ui-dialog .ui-header,.ui-dialog .ui-footer{z-index:10;padding:0}.ui-dialog .ui-footer{padding:0 15px}.ui-dialog .ui-content{padding:15px}.ui-dialog{margin-top:-15px}.ui-checkbox,.ui-radio{position:relative;clear:both;margin:.2em 0 .5em;z-index:1}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;z-index:2}.ui-checkbox .ui-btn-inner,.ui-radio .ui-btn-inner{white-space:normal}.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner{padding-left:45px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner{padding-left:36px}.ui-checkbox .ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner{padding-right:36px}.ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-btn-icon-bottom .ui-btn-inner,.ui-radio .ui-btn-icon-bottom .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-icon,.ui-radio .ui-icon{top:1.1em}.ui-checkbox .ui-btn-icon-left .ui-icon,.ui-radio .ui-btn-icon-left .ui-icon{left:15px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon,.ui-radio .ui-mini.ui-btn-icon-left .ui-icon{left:9px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox .ui-btn-icon-top .ui-icon,.ui-radio .ui-btn-icon-top .ui-icon{top:10px}.ui-checkbox .ui-btn-icon-bottom .ui-icon,.ui-radio .ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox input,.ui-radio input{position:absolute;left:20px;top:50%;width:10px;height:10px;margin:-5px 0 0 0;outline:0!important;z-index:1}.ui-field-contain,fieldset.ui-field-contain{padding:.8em 0;margin:0;border-width:0 0 1px 0;overflow:visible}.ui-field-contain:first-child{border-top-width:0}.ui-header .ui-field-contain-left,.ui-header .ui-field-contain-right{position:absolute;top:0;width:25%}.ui-header .ui-field-contain-left{left:1em}.ui-header .ui-field-contain-right{right:1em}@media all and (min-width:450px){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{border-width:0;padding:0;margin:1em 0}}.ui-select{display:block;position:relative}.ui-select select{position:absolute;left:-9999px;top:-9999px}.ui-select .ui-btn{overflow:hidden;opacity:1;margin:0}.ui-select .ui-btn select{cursor:pointer;-webkit-appearance:button;left:0;top:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;opacity:0;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);z-index:2}.ui-select .ui-disabled{opacity:.3}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-btn select.ui-select-nativeonly{opacity:1;text-indent:0}.ui-select .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-select .ui-btn-icon-right .ui-icon{right:15px}.ui-select .ui-mini.ui-btn-icon-right .ui-icon{right:7px}label.ui-select{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}.ui-select .ui-btn-text,.ui-selectmenu .ui-btn-text{display:block;min-height:1em;overflow:hidden!important}.ui-select .ui-btn-text{text-overflow:ellipsis}.ui-selectmenu{position:absolute;padding:0;z-index:1100!important;width:80%;max-width:350px;padding:6px}.ui-selectmenu .ui-listview{margin:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu-hidden{top:-9999px;left:-9999px}.ui-selectmenu-screen{position:absolute;top:0;left:0;width:100%;height:100%;z-index:99}.ui-screen-hidden,.ui-selectmenu-list .ui-li .ui-icon{display:none}.ui-selectmenu-list .ui-li .ui-icon{display:block}.ui-li.ui-selectmenu-placeholder{display:none}.ui-selectmenu .ui-header .ui-title{margin:.6em 46px .8em}@media all and (min-width:450px){.ui-field-contain label.ui-select{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-select{width:60%;display:inline-block}}.ui-selectmenu .ui-header h1:after{content:'.';visibility:hidden}label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em}input.ui-input-text,textarea.ui-input-text{background-image:none;padding:.4em;line-height:1.4;font-size:16px;display:block;width:97%;outline:0}.ui-header input.ui-input-text,.ui-footer input.ui-input-text{margin-left:1.25%;padding:.4em 1%;width:95.5%}input.ui-input-text{-webkit-appearance:none}textarea.ui-input-text{height:50px;-webkit-transition:height 200ms linear;-moz-transition:height 200ms linear;-o-transition:height 200ms linear;transition:height 200ms linear}.ui-input-search{padding:0 30px;background-image:none;position:relative}.ui-icon-searchfield:after{position:absolute;left:7px;top:50%;margin-top:-9px;content:"";width:18px;height:18px;opacity:.5}.ui-input-search input.ui-input-text{border:0;width:98%;padding:.4em 0;margin:0;display:block;background:transparent none;outline:0!important}.ui-input-search .ui-input-clear{position:absolute;right:0;top:50%;margin-top:-13px}.ui-mini .ui-input-clear{right:-3px}.ui-input-search .ui-input-clear-hidden{display:none}input.ui-mini,.ui-mini input,textarea.ui-mini{font-size:14px}textarea.ui-mini{height:45px}@media all and (min-width:450px){.ui-field-contain label.ui-input-text{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text,.ui-field-contain .ui-input-search{width:60%;display:inline-block}.ui-field-contain .ui-input-search{width:50%}.ui-hide-label input.ui-input-text,.ui-hide-label textarea.ui-input-text,.ui-hide-label .ui-input-search{padding:.4em;width:97%}.ui-input-search input.ui-input-text{width:98%}}.ui-listview{margin:0;counter-reset:listnumbering}.ui-content .ui-listview{margin:-15px}.ui-content .ui-listview-inset{margin:1em 0}.ui-listview,.ui-li{list-style:none;padding:0}.ui-li,.ui-li.ui-field-contain{display:block;margin:0;position:relative;overflow:visible;text-align:left;border-width:0;border-top-width:1px}.ui-li .ui-btn-text a.ui-link-inherit{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-divider,.ui-li-static{padding:.5em 15px;font-size:14px;font-weight:bold}.ui-li-divider{counter-reset:listnumbering}ol.ui-listview .ui-link-inherit:before,ol.ui-listview .ui-li-static:before,.ui-li-dec{font-size:.8em;display:inline-block;padding-right:.3em;font-weight:normal;counter-increment:listnumbering;content:counter(listnumbering) ". "}ol.ui-listview .ui-li-jsnumbering:before{content:""!important}.ui-listview-inset .ui-li{border-right-width:1px;border-left-width:1px}.ui-li:last-child,.ui-li.ui-field-contain:last-child{border-bottom-width:1px}.ui-li>.ui-btn-inner{display:block;position:relative;padding:0}.ui-li .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li{padding:.7em 15px .7em 15px;display:block}.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-thumb{min-height:60px;padding-left:100px}.ui-li-has-icon .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-icon{min-height:20px;padding-left:40px}.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-count{padding-right:45px}.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow{padding-right:30px}.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow.ui-li-has-count{padding-right:75px}.ui-li-has-count .ui-btn-text{padding-right:15px}.ui-li-heading{font-size:16px;font-weight:bold;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-desc{font-size:12px;font-weight:normal;display:block;margin:-.5em 0 .6em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-thumb,.ui-listview .ui-li-icon{position:absolute;left:1px;top:0;max-height:80px;max-width:80px}.ui-listview .ui-li-icon{max-height:40px;max-width:40px;left:10px;top:.9em}.ui-li-thumb,.ui-listview .ui-li-icon,.ui-li-content{float:left;margin-right:10px}.ui-li-aside{float:right;width:50%;text-align:right;margin:.3em 0}@media all and (min-width:480px){.ui-li-aside{width:45%}}.ui-li-divider{cursor:default}.ui-li-has-alt .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt{padding-right:95px}.ui-li-has-count .ui-li-count{position:absolute;font-size:11px;font-weight:bold;padding:.2em .5em;top:50%;margin-top:-.9em;right:48px}.ui-li-divider .ui-li-count,.ui-li-static .ui-li-count{right:10px}.ui-li-has-alt .ui-li-count{right:55px}.ui-li-link-alt{position:absolute;width:40px;height:100%;border-width:0;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-li-link-alt .ui-btn{overflow:hidden;position:absolute;right:8px;top:50%;margin:-11px 0 0 0;border-bottom-width:1px;z-index:-1}.ui-li-link-alt .ui-btn-inner{padding:0;height:100%;position:absolute;width:100%;top:0;left:0}.ui-li-link-alt .ui-btn .ui-icon{right:50%;margin-right:-9px}.ui-listview * .ui-btn-inner>.ui-btn>.ui-btn-inner{border-top:0}.ui-listview-filter{border-width:0;overflow:hidden;margin:-15px -15px 15px -15px}.ui-listview-filter .ui-input-search{margin:5px;width:auto;display:block}.ui-listview-filter-inset{margin:-15px -5px -15px -5px;background:transparent}.ui-li.ui-screen-hidden{display:none}@media only screen and (min-device-width:768px) and (max-device-width:1024px){.ui-li .ui-btn-text{overflow:visible}}label.ui-slider{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}input.ui-slider-input,.ui-field-contain input.ui-slider-input{display:inline-block;width:50px}select.ui-slider-switch{display:none}div.ui-slider{position:relative;display:inline-block;overflow:visible;height:15px;padding:0;margin:0 2% 0 20px;top:4px;width:65%}div.ui-slider-mini{height:12px;margin-left:10px}div.ui-slider-bg{border:0;height:100%;padding-right:8px}.ui-controlgroup a.ui-slider-handle,a.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin-top:-15px;margin-left:-15px;outline:0}a.ui-slider-handle .ui-btn-inner{padding:0;height:100%}div.ui-slider-mini a.ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -7px}div.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:-9px 0 0 -9px}@media all and (min-width:450px){.ui-field-contain label.ui-slider{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain div.ui-slider{width:43%}.ui-field-contain div.ui-slider-switch{width:5.5em}}div.ui-slider-switch{height:32px;margin-left:0;width:5.8em}a.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear}div.ui-slider-switch .ui-slider-handle{margin-top:1px}.ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1}div.ui-slider-switch.ui-slider-mini{width:5em;height:29px}div.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset{margin:0 15px 0 14px}div.ui-slider-switch.ui-slider-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px}div.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:0}span.ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;border-width:0;white-space:nowrap}.ui-slider-mini span.ui-slider-label{font-size:14px}span.ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em}span.ui-slider-label-b{z-index:0;right:0;text-indent:1.5em}.ui-slider-inline{width:120px;display:inline-block} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery.mobile-1.1.0.min.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,177 @@ +/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ +(function(D,s,k){typeof define==="function"&&define.amd?define(["jquery"],function(a){k(a,D,s);return a.mobile}):k(D.jQuery,D,s)})(this,document,function(D,s,k){(function(a,c,b,e){function f(a){for(;a&&typeof a.originalEvent!=="undefined";)a=a.originalEvent;return a}function d(b){for(var d={},f,g;b;){f=a.data(b,t);for(g in f)if(f[g])d[g]=d.hasVirtualBinding=true;b=b.parentNode}return d}function g(){y&&(clearTimeout(y),y=0);y=setTimeout(function(){F=y=0;C.length=0;z=false;G=true},a.vmouse.resetTimerDuration)} +function h(b,d,g){var c,h;if(!(h=g&&g[b])){if(g=!g)a:{for(g=d.target;g;){if((h=a.data(g,t))&&(!b||h[b]))break a;g=g.parentNode}g=null}h=g}if(h){c=d;var g=c.type,z,j;c=a.Event(c);c.type=b;h=c.originalEvent;z=a.event.props;g.search(/^(mouse|click)/)>-1&&(z=w);if(h)for(j=z.length;j;)b=z[--j],c[b]=h[b];if(g.search(/mouse(down|up)|click/)>-1&&!c.which)c.which=1;if(g.search(/^touch/)!==-1&&(b=f(h),g=b.touches,b=b.changedTouches,g=g&&g.length?g[0]:b&&b.length?b[0]:e))for(h=0,len=u.length;h<len;h++)b=u[h], +c[b]=g[b];a(d.target).trigger(c)}return c}function j(b){var d=a.data(b.target,x);if(!z&&(!F||F!==d))if(d=h("v"+b.type,b))d.isDefaultPrevented()&&b.preventDefault(),d.isPropagationStopped()&&b.stopPropagation(),d.isImmediatePropagationStopped()&&b.stopImmediatePropagation()}function o(b){var g=f(b).touches,c;if(g&&g.length===1&&(c=b.target,g=d(c),g.hasVirtualBinding))F=L++,a.data(c,x,F),y&&(clearTimeout(y),y=0),A=G=false,c=f(b).touches[0],s=c.pageX,E=c.pageY,h("vmouseover",b,g),h("vmousedown",b,g)} +function m(a){G||(A||h("vmousecancel",a,d(a.target)),A=true,g())}function p(b){if(!G){var c=f(b).touches[0],e=A,z=a.vmouse.moveDistanceThreshold;A=A||Math.abs(c.pageX-s)>z||Math.abs(c.pageY-E)>z;flags=d(b.target);A&&!e&&h("vmousecancel",b,flags);h("vmousemove",b,flags);g()}}function l(a){if(!G){G=true;var b=d(a.target),c;h("vmouseup",a,b);if(!A&&(c=h("vclick",a,b))&&c.isDefaultPrevented())c=f(a).changedTouches[0],C.push({touchID:F,x:c.clientX,y:c.clientY}),z=true;h("vmouseout",a,b);A=false;g()}}function r(b){var b= +a.data(b,t),d;if(b)for(d in b)if(b[d])return true;return false}function n(){}function k(b){var d=b.substr(1);return{setup:function(){r(this)||a.data(this,t,{});a.data(this,t)[b]=true;v[b]=(v[b]||0)+1;v[b]===1&&H.bind(d,j);a(this).bind(d,n);if(K)v.touchstart=(v.touchstart||0)+1,v.touchstart===1&&H.bind("touchstart",o).bind("touchend",l).bind("touchmove",p).bind("scroll",m)},teardown:function(){--v[b];v[b]||H.unbind(d,j);K&&(--v.touchstart,v.touchstart||H.unbind("touchstart",o).unbind("touchmove",p).unbind("touchend", +l).unbind("scroll",m));var f=a(this),g=a.data(this,t);g&&(g[b]=false);f.unbind(d,n);r(this)||f.removeData(t)}}}var t="virtualMouseBindings",x="virtualTouchID",c="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),u="clientX clientY pageX pageY screenX screenY".split(" "),w=a.event.props.concat(a.event.mouseHooks?a.event.mouseHooks.props:[]),v={},y=0,s=0,E=0,A=false,C=[],z=false,G=false,K="addEventListener"in b,H=a(b),L=1,F=0;a.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10, +resetTimerDuration:1500};for(var I=0;I<c.length;I++)a.event.special[c[I]]=k(c[I]);K&&b.addEventListener("click",function(b){var d=C.length,f=b.target,g,c,e,h,z;if(d){g=b.clientX;c=b.clientY;threshold=a.vmouse.clickDistanceThreshold;for(e=f;e;){for(h=0;h<d;h++)if(z=C[h],e===f&&Math.abs(z.x-g)<threshold&&Math.abs(z.y-c)<threshold||a.data(e,x)===z.touchID){b.preventDefault();b.stopPropagation();return}e=e.parentNode}}},true)})(jQuery,s,k);(function(a,c,b){function e(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/, +"$1")}var f="hashchange",d=k,g,h=a.event.special,j=d.documentMode,o="on"+f in c&&(j===b||j>7);a.fn[f]=function(a){return a?this.bind(f,a):this.trigger(f)};a.fn[f].delay=50;h[f]=a.extend(h[f],{setup:function(){if(o)return false;a(g.start)},teardown:function(){if(o)return false;a(g.stop)}});g=function(){function g(){var b=e(),d=t(r);if(b!==r)k(r=b,d),a(c).trigger(f);else if(d!==r)location.href=location.href.replace(/#.*/,"")+d;j=setTimeout(g,a.fn[f].delay)}var h={},j,r=e(),n=function(a){return a},k= +n,t=n;h.start=function(){j||g()};h.stop=function(){j&&clearTimeout(j);j=b};a.browser.msie&&!o&&function(){var b,c;h.start=function(){if(!b)c=(c=a.fn[f].src)&&c+e(),b=a('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){c||k(e());g()}).attr("src",c||"javascript:0").insertAfter("body")[0].contentWindow,d.onpropertychange=function(){try{if(event.propertyName==="title")b.document.title=d.title}catch(a){}}};h.stop=n;t=function(){return e(b.location.href)};k=function(g,c){var e=b.document, +h=a.fn[f].domain;if(g!==c)e.title=d.title,e.open(),h&&e.write('<script>document.domain="'+h+'"<\/script>'),e.close(),b.location.hash=g}}();return h}()})(jQuery,this);(function(a,c){if(a.cleanData){var b=a.cleanData;a.cleanData=function(f){for(var d=0,g;(g=f[d])!=null;d++)a(g).triggerHandler("remove");b(f)}}else{var e=a.fn.remove;a.fn.remove=function(b,d){return this.each(function(){d||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){a(this).triggerHandler("remove")});return e.call(a(this), +b,d)})}}a.widget=function(b,d,g){var c=b.split(".")[0],e,b=b.split(".")[1];e=c+"-"+b;if(!g)g=d,d=a.Widget;a.expr[":"][e]=function(d){return!!a.data(d,b)};a[c]=a[c]||{};a[c][b]=function(a,b){arguments.length&&this._createWidget(a,b)};d=new d;d.options=a.extend(true,{},d.options);a[c][b].prototype=a.extend(true,d,{namespace:c,widgetName:b,widgetEventPrefix:a[c][b].prototype.widgetEventPrefix||b,widgetBaseClass:e},g);a.widget.bridge(b,a[c][b])};a.widget.bridge=function(b,d){a.fn[b]=function(g){var e= +typeof g==="string",j=Array.prototype.slice.call(arguments,1),o=this,g=!e&&j.length?a.extend.apply(null,[true,g].concat(j)):g;if(e&&g.charAt(0)==="_")return o;e?this.each(function(){var d=a.data(this,b);if(!d)throw"cannot call methods on "+b+" prior to initialization; attempted to call method '"+g+"'";if(!a.isFunction(d[g]))throw"no such method '"+g+"' for "+b+" widget instance";var e=d[g].apply(d,j);if(e!==d&&e!==c)return o=e,false}):this.each(function(){var c=a.data(this,b);c?c.option(g||{})._init(): +a.data(this,b,new d(g,this))});return o}};a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)};a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(b,d){a.data(d,this.widgetName,this);this.element=a(d);this.options=a.extend(true,{},this.options,this._getCreateOptions(),b);var g=this;this.element.bind("remove."+this.widgetName,function(){g.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){var b= +{};a.metadata&&(b=a.metadata.get(element)[this.widgetName]);return b},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(b,d){var g=b;if(arguments.length===0)return a.extend({},this.options);if(typeof b==="string"){if(d===c)return this.options[b]; +g={};g[b]=d}this._setOptions(g);return this},_setOptions:function(b){var d=this;a.each(b,function(a,b){d._setOption(a,b)});return this},_setOption:function(a,b){this.options[a]=b;a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",b);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(b,d,g){var c=this.options[b],d=a.Event(d); +d.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase();g=g||{};if(d.originalEvent)for(var b=a.event.props.length,e;b;)e=a.event.props[--b],d[e]=d.originalEvent[e];this.element.trigger(d,g);return!(a.isFunction(c)&&c.call(this.element[0],d,g)===false||d.isDefaultPrevented())}}})(jQuery);(function(a,c){a.widget("mobile.widget",{_createWidget:function(){a.Widget.prototype._createWidget.apply(this,arguments);this._trigger("init")},_getCreateOptions:function(){var b=this.element, +e={};a.each(this.options,function(a){var d=b.jqmData(a.replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()}));d!==c&&(e[a]=d)});return e},enhanceWithin:function(b,c){this.enhance(a(this.options.initSelector,a(b)),c)},enhance:function(b,c){var f,d=a(b),d=a.mobile.enhanceable(d);c&&d.length&&(f=(f=a.mobile.closestPageData(d))&&f.keepNativeSelector()||"",d=d.not(f));d[this.widgetName]()},raise:function(a){throw"Widget ["+this.widgetName+"]: "+a;}})})(jQuery);(function(a,c){var b={};a.mobile=a.extend({}, +{version:"1.1.0",ns:"",subPageUrlKey:"ui-page",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",focusClass:"ui-focus",ajaxEnabled:true,hashListeningEnabled:true,linkBindingEnabled:true,defaultPageTransition:"fade",maxTransitionWidth:false,minScrollBack:250,touchOverflowEnabled:false,defaultDialogTransition:"pop",loadingMessage:"loading",pageLoadErrorMessage:"Error Loading Page",loadingMessageTextVisible:false,loadingMessageTheme:"a",pageLoadErrorMessageTheme:"e",autoInitializePage:true, +pushStateEnabled:true,ignoreContentEnabled:false,orientationChangeEnabled:true,buttonMarkup:{hoverDelay:200},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91},silentScroll:function(b){if(a.type(b)!== +"number")b=a.mobile.defaultHomeScroll;a.event.special.scrollstart.enabled=false;setTimeout(function(){c.scrollTo(0,b);a(k).trigger("silentscroll",{x:0,y:b})},20);setTimeout(function(){a.event.special.scrollstart.enabled=true},150)},nsNormalizeDict:b,nsNormalize:function(d){return!d?void 0:b[d]||(b[d]=a.camelCase(a.mobile.ns+d))},getInheritedTheme:function(a,b){for(var c=a[0],e="",f=/ui-(bar|body|overlay)-([a-z])\b/,m,p;c;){m=c.className||"";if((p=f.exec(m))&&(e=p[2]))break;c=c.parentNode}return e|| +b||"a"},closestPageData:function(a){return a.closest(':jqmData(role="page"), :jqmData(role="dialog")').data("page")},enhanceable:function(a){return this.haveParents(a,"enhance")},hijackable:function(a){return this.haveParents(a,"ajax")},haveParents:function(b,c){if(!a.mobile.ignoreContentEnabled)return b;for(var e=b.length,f=a(),o,m,p,l=0;l<e;l++){m=b.eq(l);p=false;for(o=b[l];o;){if((o.getAttribute?o.getAttribute("data-"+a.mobile.ns+c):"")==="false"){p=true;break}o=o.parentNode}p||(f=f.add(m))}return f}}, +a.mobile);a.fn.jqmData=function(b,c){var f;typeof b!="undefined"&&(b&&(b=a.mobile.nsNormalize(b)),f=this.data.apply(this,arguments.length<2?[b]:[b,c]));return f};a.jqmData=function(b,c,f){var e;typeof c!="undefined"&&(e=a.data(b,c?a.mobile.nsNormalize(c):c,f));return e};a.fn.jqmRemoveData=function(b){return this.removeData(a.mobile.nsNormalize(b))};a.jqmRemoveData=function(b,c){return a.removeData(b,a.mobile.nsNormalize(c))};a.fn.removeWithDependents=function(){a.removeWithDependents(this)};a.removeWithDependents= +function(b){b=a(b);(b.jqmData("dependents")||a()).remove();b.remove()};a.fn.addDependents=function(b){a.addDependents(a(this),b)};a.addDependents=function(b,c){var f=a(b).jqmData("dependents")||a();a(b).jqmData("dependents",a.merge(f,c))};a.fn.getEncodedText=function(){return a("<div/>").text(a(this).text()).html()};a.fn.jqmEnhanceable=function(){return a.mobile.enhanceable(this)};a.fn.jqmHijackable=function(){return a.mobile.hijackable(this)};var e=a.find,f=/:jqmData\(([^)]*)\)/g;a.find=function(b, +c,h,j){b=b.replace(f,"[data-"+(a.mobile.ns||"")+"$1]");return e.call(this,b,c,h,j)};a.extend(a.find,e);a.find.matches=function(b,c){return a.find(b,null,null,c)};a.find.matchesSelector=function(b,c){return a.find(c,null,null,[b]).length>0}})(jQuery,this);(function(a){a(s);var c=a("html");a.mobile.media=function(){var b={},e=a("<div id='jquery-mediatest'>"),f=a("<body>").append(e);return function(a){if(!(a in b)){var g=k.createElement("style"),h="@media "+a+" { #jquery-mediatest { position:absolute; } }"; +g.type="text/css";g.styleSheet?g.styleSheet.cssText=h:g.appendChild(k.createTextNode(h));c.prepend(f).prepend(g);b[a]=e.css("position")==="absolute";f.add(g).remove()}return b[a]}}()})(jQuery);(function(a,c){function b(a){var b=a.charAt(0).toUpperCase()+a.substr(1),a=(a+" "+g.join(b+" ")+b).split(" "),f;for(f in a)if(d[a[f]]!==c)return true}function e(a,b,c){var d=k.createElement("div"),c=c?[c]:g,f;for(i=0;i<c.length;i++){var e=c[i],h="-"+e.charAt(0).toLowerCase()+e.substr(1)+"-"+a+": "+b+";",e=e.charAt(0).toUpperCase()+ +e.substr(1)+(a.charAt(0).toUpperCase()+a.substr(1));d.setAttribute("style",h);d.style[e]&&(f=true)}return!!f}var f=a("<body>").prependTo("html"),d=f[0].style,g=["Webkit","Moz","O"],h="palmGetResource"in s,j=s.operamini&&{}.toString.call(s.operamini)==="[object OperaMini]",o=s.blackberry;a.extend(a.mobile,{browser:{}});a.mobile.browser.ie=function(){for(var a=3,b=k.createElement("div"),c=b.all||[];b.innerHTML="<\!--[if gt IE "+ ++a+"]><br><![endif]--\>",c[0];);return a>4?a:!a}();a.extend(a.support, +{orientation:"orientation"in s&&"onorientationchange"in s,touch:"ontouchend"in k,cssTransitions:"WebKitTransitionEvent"in s||e("transition","height 100ms linear"),pushState:"pushState"in history&&"replaceState"in history,mediaquery:a.mobile.media("only all"),cssPseudoElement:!!b("content"),touchOverflow:!!b("overflowScrolling"),cssTransform3d:e("perspective","10px","moz")||a.mobile.media("(-"+g.join("-transform-3d),(-")+"-transform-3d),(transform-3d)"),boxShadow:!!b("boxShadow")&&!o,scrollTop:("pageXOffset"in +s||"scrollTop"in k.documentElement||"scrollTop"in f[0])&&!h&&!j,dynamicBaseTag:function(){var b=location.protocol+"//"+location.host+location.pathname+"ui-dir/",c=a("head base"),d=null,e="",g;c.length?e=c.attr("href"):c=d=a("<base>",{href:b}).appendTo("head");g=a("<a href='testurl' />").prependTo(f)[0].href;c[0].href=e||location.pathname;d&&d.remove();return g.indexOf(b)===0}()});f.remove();h=function(){var a=s.navigator.userAgent;return a.indexOf("Nokia")>-1&&(a.indexOf("Symbian/3")>-1||a.indexOf("Series60/5")> +-1)&&a.indexOf("AppleWebKit")>-1&&a.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/)}();a.mobile.gradeA=function(){return a.support.mediaquery||a.mobile.browser.ie&&a.mobile.browser.ie>=7};a.mobile.ajaxBlacklist=s.blackberry&&!s.WebKitPoint||j||h;h&&a(function(){a("head link[rel='stylesheet']").attr("rel","alternate stylesheet").attr("rel","stylesheet")});a.support.boxShadow||a("html").addClass("ui-mobile-nosupport-boxshadow")})(jQuery);(function(a,c,b){function e(b,c,d){var f=d.type;d.type=c;a.event.handle.call(b, +d);d.type=f}a.each("touchstart touchmove touchend orientationchange throttledresize tap taphold swipe swipeleft swiperight scrollstart scrollstop".split(" "),function(b,c){a.fn[c]=function(a){return a?this.bind(c,a):this.trigger(c)};a.attrFn[c]=true});var f=a.support.touch,d=f?"touchstart":"mousedown",g=f?"touchend":"mouseup",h=f?"touchmove":"mousemove";a.event.special.scrollstart={enabled:true,setup:function(){function b(a,f){d=f;e(c,d?"scrollstart":"scrollstop",a)}var c=this,d,f;a(c).bind("touchmove scroll", +function(c){a.event.special.scrollstart.enabled&&(d||b(c,true),clearTimeout(f),f=setTimeout(function(){b(c,false)},50))})}};a.event.special.tap={setup:function(){var b=this,c=a(b);c.bind("vmousedown",function(d){function f(){clearTimeout(q)}function g(){f();c.unbind("vclick",h).unbind("vmouseup",f);a(k).unbind("vmousecancel",g)}function h(a){g();n==a.target&&e(b,"tap",a)}if(d.which&&d.which!==1)return false;var n=d.target,q;c.bind("vmouseup",f).bind("vclick",h);a(k).bind("vmousecancel",g);q=setTimeout(function(){e(b, +"taphold",a.Event("taphold",{target:n}))},750)})}};a.event.special.swipe={scrollSupressionThreshold:10,durationThreshold:1E3,horizontalDistanceThreshold:30,verticalDistanceThreshold:75,setup:function(){var c=a(this);c.bind(d,function(d){function f(b){if(l){var c=b.originalEvent.touches?b.originalEvent.touches[0]:b;k={time:(new Date).getTime(),coords:[c.pageX,c.pageY]};Math.abs(l.coords[0]-k.coords[0])>a.event.special.swipe.scrollSupressionThreshold&&b.preventDefault()}}var e=d.originalEvent.touches? +d.originalEvent.touches[0]:d,l={time:(new Date).getTime(),coords:[e.pageX,e.pageY],origin:a(d.target)},k;c.bind(h,f).one(g,function(){c.unbind(h,f);l&&k&&k.time-l.time<a.event.special.swipe.durationThreshold&&Math.abs(l.coords[0]-k.coords[0])>a.event.special.swipe.horizontalDistanceThreshold&&Math.abs(l.coords[1]-k.coords[1])<a.event.special.swipe.verticalDistanceThreshold&&l.origin.trigger("swipe").trigger(l.coords[0]>k.coords[0]?"swipeleft":"swiperight");l=k=b})})}};(function(a,b){function c(){var a= +f();a!==e&&(e=a,d.trigger("orientationchange"))}var d=a(b),f,e,g,h,t={0:true,180:true};if(a.support.orientation&&(g=b.innerWidth||a(b).width(),h=b.innerHeight||a(b).height(),g=g>h&&g-h>50,h=t[b.orientation],g&&h||!g&&!h))t={"-90":true,90:true};a.event.special.orientationchange={setup:function(){if(a.support.orientation&&a.mobile.orientationChangeEnabled)return false;e=f();d.bind("throttledresize",c)},teardown:function(){if(a.support.orientation&&a.mobile.orientationChangeEnabled)return false;d.unbind("throttledresize", +c)},add:function(a){var b=a.handler;a.handler=function(a){a.orientation=f();return b.apply(this,arguments)}}};a.event.special.orientationchange.orientation=f=function(){var c=true,c=k.documentElement;return(c=a.support.orientation?t[b.orientation]:c&&c.clientWidth/c.clientHeight<1.1)?"portrait":"landscape"}})(jQuery,c);(function(){a.event.special.throttledresize={setup:function(){a(this).bind("resize",b)},teardown:function(){a(this).unbind("resize",b)}};var b=function(){f=(new Date).getTime();g=f- +c;g>=250?(c=f,a(this).trigger("throttledresize")):(d&&clearTimeout(d),d=setTimeout(b,250-g))},c=0,d,f,g})();a.each({scrollstop:"scrollstart",taphold:"tap",swipeleft:"swipe",swiperight:"swipe"},function(b,c){a.event.special[b]={setup:function(){a(this).bind(c,a.noop)}}})})(jQuery,this);(function(a){a.widget("mobile.page",a.mobile.widget,{options:{theme:"c",domCache:false,keepNativeDefault:":jqmData(role='none'), :jqmData(role='nojs')"},_create:function(){var a=this;if(a._trigger("beforecreate")=== +false)return false;a.element.attr("tabindex","0").addClass("ui-page ui-body-"+a.options.theme).bind("pagebeforehide",function(){a.removeContainerBackground()}).bind("pagebeforeshow",function(){a.setContainerBackground()})},removeContainerBackground:function(){a.mobile.pageContainer.removeClass("ui-overlay-"+a.mobile.getInheritedTheme(this.element.parent()))},setContainerBackground:function(c){this.options.theme&&a.mobile.pageContainer.addClass("ui-overlay-"+(c||this.options.theme))},keepNativeSelector:function(){var c= +this.options;return c.keepNative&&a.trim(c.keepNative)&&c.keepNative!==c.keepNativeDefault?[c.keepNative,c.keepNativeDefault].join(", "):c.keepNativeDefault}})})(jQuery);(function(a,c,b){var e=function(d){d===b&&(d=true);return function(b,f,e,o){var k=new a.Deferred,p=f?" reverse":"",l=a.mobile.urlHistory.getActive().lastScroll||a.mobile.defaultHomeScroll,r=a.mobile.getScreenHeight(),n=a.mobile.maxTransitionWidth!==false&&a(c).width()>a.mobile.maxTransitionWidth,q=!a.support.cssTransitions||n||!b|| +b==="none",t=function(){a.mobile.pageContainer.toggleClass("ui-mobile-viewport-transitioning viewport-"+b)},x=function(){a.event.special.scrollstart.enabled=false;c.scrollTo(0,l);setTimeout(function(){a.event.special.scrollstart.enabled=true},150)},u=function(){o.removeClass(a.mobile.activePageClass+" out in reverse "+b).height("")},n=function(){o&&d&&u();e.addClass(a.mobile.activePageClass);a.mobile.focusPage(e);e.height(r+l);x();q||e.animationComplete(w);e.addClass(b+" in"+p);q&&w()},w=function(){d|| +o&&u();e.removeClass("out in reverse "+b).height("");t();a(c).scrollTop()!==l&&x();k.resolve(b,f,e,o,true)};t();o&&!q?(d?o.animationComplete(n):n(),o.height(r+a(c).scrollTop()).addClass(b+" out"+p)):n();return k.promise()}},f=e(),e=e(false);a.mobile.defaultTransitionHandler=f;a.mobile.transitionHandlers={"default":a.mobile.defaultTransitionHandler,sequential:f,simultaneous:e};a.mobile.transitionFallbacks={}})(jQuery,this);(function(a,c){function b(b){r&&(!r.closest(".ui-page-active").length||b)&& +r.removeClass(a.mobile.activeBtnClass);r=null}function e(){t=false;q.length>0&&a.mobile.changePage.apply(null,q.pop())}function f(b,c,d,f){c&&c.data("page")._trigger("beforehide",null,{nextPage:b});b.data("page")._trigger("beforeshow",null,{prevPage:c||a("")});a.mobile.hidePageLoadingMsg();d&&!a.support.cssTransform3d&&a.mobile.transitionFallbacks[d]&&(d=a.mobile.transitionFallbacks[d]);d=(a.mobile.transitionHandlers[d||"default"]||a.mobile.defaultTransitionHandler)(d,f,b,c);d.done(function(){c&& +c.data("page")._trigger("hide",null,{nextPage:b});b.data("page")._trigger("show",null,{prevPage:c||a("")})});return d}function d(){return s.innerHeight||a(s).height()}function g(){var b=a("."+a.mobile.activePageClass),c=parseFloat(b.css("padding-top")),f=parseFloat(b.css("padding-bottom"));b.css("min-height",d()-c-f)}function h(b,c){c&&b.attr("data-"+a.mobile.ns+"role",c);b.page()}function j(a){for(;a;){if(typeof a.nodeName==="string"&&a.nodeName.toLowerCase()=="a")break;a=a.parentNode}return a}function o(b){var b= +a(b).closest(".ui-page").jqmData("url"),c=v.hrefNoHash;if(!b||!l.isPath(b))b=c;return l.makeUrlAbsolute(b,c)}var m=a(s);a("html");var p=a("head"),l={urlParseRE:/^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,parseUrl:function(b){if(a.type(b)==="object")return b;b=l.urlParseRE.exec(b||"")||[];return{href:b[0]||"",hrefNoHash:b[1]||"",hrefNoSearch:b[2]||"",domain:b[3]||"", +protocol:b[4]||"",doubleSlash:b[5]||"",authority:b[6]||"",username:b[8]||"",password:b[9]||"",host:b[10]||"",hostname:b[11]||"",port:b[12]||"",pathname:b[13]||"",directory:b[14]||"",filename:b[15]||"",search:b[16]||"",hash:b[17]||""}},makePathAbsolute:function(a,b){if(a&&a.charAt(0)==="/")return a;for(var a=a||"",c=(b=b?b.replace(/^\/|(\/[^\/]*|[^\/]+)$/g,""):"")?b.split("/"):[],d=a.split("/"),f=0;f<d.length;f++){var e=d[f];switch(e){case ".":break;case "..":c.length&&c.pop();break;default:c.push(e)}}return"/"+ +c.join("/")},isSameDomain:function(a,b){return l.parseUrl(a).domain===l.parseUrl(b).domain},isRelativeUrl:function(a){return l.parseUrl(a).protocol===""},isAbsoluteUrl:function(a){return l.parseUrl(a).protocol!==""},makeUrlAbsolute:function(a,b){if(!l.isRelativeUrl(a))return a;var c=l.parseUrl(a),d=l.parseUrl(b),f=c.protocol||d.protocol,e=c.protocol?c.doubleSlash:c.doubleSlash||d.doubleSlash,g=c.authority||d.authority,h=c.pathname!=="",j=l.makePathAbsolute(c.pathname||d.filename,d.pathname);return f+ +e+g+j+(c.search||!h&&d.search||"")+c.hash},addSearchParams:function(b,c){var d=l.parseUrl(b),f=typeof c==="object"?a.param(c):c,e=d.search||"?";return d.hrefNoSearch+e+(e.charAt(e.length-1)!=="?"?"&":"")+f+(d.hash||"")},convertUrlToDataUrl:function(a){var b=l.parseUrl(a);if(l.isEmbeddedPage(b))return b.hash.split(x)[0].replace(/^#/,"");else if(l.isSameDomain(b,v))return b.hrefNoHash.replace(v.domain,"");return a},get:function(a){if(a===c)a=location.hash;return l.stripHash(a).replace(/[^\/]*\.[^\/*]+$/, +"")},getFilePath:function(b){var c="&"+a.mobile.subPageUrlKey;return b&&b.split(c)[0].split(x)[0]},set:function(a){location.hash=a},isPath:function(a){return/\//.test(a)},clean:function(a){return a.replace(v.domain,"")},stripHash:function(a){return a.replace(/^#/,"")},cleanHash:function(a){return l.stripHash(a.replace(/\?.*$/,"").replace(x,""))},isExternal:function(a){a=l.parseUrl(a);return a.protocol&&a.domain!==w.domain?true:false},hasProtocol:function(a){return/^(:?\w+:)/.test(a)},isFirstPageUrl:function(b){var b= +l.parseUrl(l.makeUrlAbsolute(b,v)),d=a.mobile.firstPage,d=d&&d[0]?d[0].id:c;return(b.hrefNoHash===w.hrefNoHash||y&&b.hrefNoHash===v.hrefNoHash)&&(!b.hash||b.hash==="#"||d&&b.hash.replace(/^#/,"")===d)},isEmbeddedPage:function(a){a=l.parseUrl(a);return a.protocol!==""?a.hash&&(a.hrefNoHash===w.hrefNoHash||y&&a.hrefNoHash===v.hrefNoHash):/^#/.test(a.href)}},r=null,n={stack:[],activeIndex:0,getActive:function(){return n.stack[n.activeIndex]},getPrev:function(){return n.stack[n.activeIndex-1]},getNext:function(){return n.stack[n.activeIndex+ +1]},addNew:function(a,b,c,d,f){n.getNext()&&n.clearForward();n.stack.push({url:a,transition:b,title:c,pageUrl:d,role:f});n.activeIndex=n.stack.length-1},clearForward:function(){n.stack=n.stack.slice(0,n.activeIndex+1)},directHashChange:function(b){var d,f,e;this.getActive();a.each(n.stack,function(a,c){b.currentUrl===c.url&&(d=a<n.activeIndex,f=!d,e=a)});this.activeIndex=e!==c?e:this.activeIndex;d?(b.either||b.isBack)(true):f&&(b.either||b.isForward)(false)},ignoreNextHashChange:false},q=[],t=false, +x="&ui-state=dialog",u=p.children("base"),w=l.parseUrl(location.href),v=u.length?l.parseUrl(l.makeUrlAbsolute(u.attr("href"),w.href)):w,y=w.hrefNoHash!==v.hrefNoHash,B=a.support.dynamicBaseTag?{element:u.length?u:a("<base>",{href:v.hrefNoHash}).prependTo(p),set:function(a){B.element.attr("href",l.makeUrlAbsolute(a,v))},reset:function(){B.element.attr("href",v.hrefNoHash)}}:c;a.mobile.focusPage=function(a){var b=a.find("[autofocus]"),c=a.find(".ui-title:eq(0)");b.length?b.focus():c.length?c.focus(): +a.focus()};var E=true,A,C;A=function(){if(E){var b=a.mobile.urlHistory.getActive();if(b){var c=m.scrollTop();b.lastScroll=c<a.mobile.minScrollBack?a.mobile.defaultHomeScroll:c}}};C=function(){setTimeout(A,100)};m.bind(a.support.pushState?"popstate":"hashchange",function(){E=false});m.one(a.support.pushState?"popstate":"hashchange",function(){E=true});m.one("pagecontainercreate",function(){a.mobile.pageContainer.bind("pagechange",function(){E=true;m.unbind("scrollstop",C);m.bind("scrollstop",C)})}); +m.bind("scrollstop",C);a.mobile.getScreenHeight=d;a.fn.animationComplete=function(b){return a.support.cssTransitions?a(this).one("webkitAnimationEnd animationend",b):(setTimeout(b,0),a(this))};a.mobile.path=l;a.mobile.base=B;a.mobile.urlHistory=n;a.mobile.dialogHashKey=x;a.mobile.allowCrossDomainPages=false;a.mobile.getDocumentUrl=function(b){return b?a.extend({},w):w.href};a.mobile.getDocumentBase=function(b){return b?a.extend({},v):v.href};a.mobile._bindPageRemove=function(){var b=a(this);!b.data("page").options.domCache&& +b.is(":jqmData(external-page='true')")&&b.bind("pagehide.remove",function(){var b=a(this),c=new a.Event("pageremove");b.trigger(c);c.isDefaultPrevented()||b.removeWithDependents()})};a.mobile.loadPage=function(b,d){var f=a.Deferred(),e=a.extend({},a.mobile.loadPage.defaults,d),g=null,j=null,k=l.makeUrlAbsolute(b,a.mobile.activePage&&o(a.mobile.activePage)||v.hrefNoHash);if(e.data&&e.type==="get")k=l.addSearchParams(k,e.data),e.data=c;if(e.data&&e.type==="post")e.reloadPage=true;var u=l.getFilePath(k), +n=l.convertUrlToDataUrl(k);e.pageContainer=e.pageContainer||a.mobile.pageContainer;g=e.pageContainer.children(":jqmData(url='"+n+"')");g.length===0&&n&&!l.isPath(n)&&(g=e.pageContainer.children("#"+n).attr("data-"+a.mobile.ns+"url",n));if(g.length===0)if(a.mobile.firstPage&&l.isFirstPageUrl(u))a.mobile.firstPage.parent().length&&(g=a(a.mobile.firstPage));else if(l.isEmbeddedPage(u))return f.reject(k,d),f.promise();B&&B.reset();if(g.length){if(!e.reloadPage)return h(g,e.role),f.resolve(k,d,g),f.promise(); +j=g}var m=e.pageContainer,x=new a.Event("pagebeforeload"),p={url:b,absUrl:k,dataUrl:n,deferred:f,options:e};m.trigger(x,p);if(x.isDefaultPrevented())return f.promise();if(e.showLoadMsg)var r=setTimeout(function(){a.mobile.showPageLoadingMsg()},e.loadMsgDelay);!a.mobile.allowCrossDomainPages&&!l.isSameDomain(w,k)?f.reject(k,d):a.ajax({url:u,type:e.type,data:e.data,dataType:"html",success:function(c,o,m){var x=a("<div></div>"),v=c.match(/<title[^>]*>([^<]*)/)&&RegExp.$1,w=RegExp("\\bdata-"+a.mobile.ns+ +"url=[\"']?([^\"'>]*)[\"']?");RegExp("(<[^>]+\\bdata-"+a.mobile.ns+"role=[\"']?page[\"']?[^>]*>)").test(c)&&RegExp.$1&&w.test(RegExp.$1)&&RegExp.$1&&(b=u=l.getFilePath(RegExp.$1));B&&B.set(u);x.get(0).innerHTML=c;g=x.find(":jqmData(role='page'), :jqmData(role='dialog')").first();g.length||(g=a("<div data-"+a.mobile.ns+"role='page'>"+c.split(/<\/?body[^>]*>/gmi)[1]+"</div>"));v&&!g.jqmData("title")&&(~v.indexOf("&")&&(v=a("<div>"+v+"</div>").text()),g.jqmData("title",v));if(!a.support.dynamicBaseTag){var q= +l.get(u);g.find("[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]").each(function(){var b=a(this).is("[href]")?"href":a(this).is("[src]")?"src":"action",c=a(this).attr(b),c=c.replace(location.protocol+"//"+location.host+location.pathname,"");/^(\w+:|#|\/)/.test(c)||a(this).attr(b,q+c)})}g.attr("data-"+a.mobile.ns+"url",l.convertUrlToDataUrl(u)).attr("data-"+a.mobile.ns+"external-page",true).appendTo(e.pageContainer);g.one("pagecreate",a.mobile._bindPageRemove);h(g,e.role);k.indexOf("&"+ +a.mobile.subPageUrlKey)>-1&&(g=e.pageContainer.children(":jqmData(url='"+n+"')"));e.showLoadMsg&&(clearTimeout(r),a.mobile.hidePageLoadingMsg());p.xhr=m;p.textStatus=o;p.page=g;e.pageContainer.trigger("pageload",p);f.resolve(k,d,g,j)},error:function(b,c,g){B&&B.set(l.get());p.xhr=b;p.textStatus=c;p.errorThrown=g;b=new a.Event("pageloadfailed");e.pageContainer.trigger(b,p);b.isDefaultPrevented()||(e.showLoadMsg&&(clearTimeout(r),a.mobile.hidePageLoadingMsg(),a.mobile.showPageLoadingMsg(a.mobile.pageLoadErrorMessageTheme, +a.mobile.pageLoadErrorMessage,true),setTimeout(a.mobile.hidePageLoadingMsg,1500)),f.reject(k,d))}});return f.promise()};a.mobile.loadPage.defaults={type:"get",data:c,reloadPage:false,role:c,showLoadMsg:false,pageContainer:c,loadMsgDelay:50};a.mobile.changePage=function(d,g){if(t)q.unshift(arguments);else{var j=a.extend({},a.mobile.changePage.defaults,g);j.pageContainer=j.pageContainer||a.mobile.pageContainer;j.fromPage=j.fromPage||a.mobile.activePage;var u=j.pageContainer,o=new a.Event("pagebeforechange"), +m={toPage:d,options:j};u.trigger(o,m);if(!o.isDefaultPrevented())if(d=m.toPage,t=true,typeof d=="string")a.mobile.loadPage(d,j).done(function(b,c,d,e){t=false;c.duplicateCachedPage=e;a.mobile.changePage(d,c)}).fail(function(){t=false;b(true);e();j.pageContainer.trigger("pagechangefailed",m)});else{if(d[0]===a.mobile.firstPage[0]&&!j.dataUrl)j.dataUrl=w.hrefNoHash;var o=j.fromPage,p=j.dataUrl&&l.convertUrlToDataUrl(j.dataUrl)||d.jqmData("url"),v=p;l.getFilePath(p);var r=n.getActive(),s=n.activeIndex=== +0,y=0,B=k.title,A=j.role==="dialog"||d.jqmData("role")==="dialog";if(o&&o[0]===d[0]&&!j.allowSamePageTransition)t=false,u.trigger("pagechange",m);else{h(d,j.role);j.fromHashChange&&n.directHashChange({currentUrl:p,isBack:function(){y=-1},isForward:function(){y=1}});try{k.activeElement&&k.activeElement.nodeName.toLowerCase()!="body"?a(k.activeElement).blur():a("input:focus, textarea:focus, select:focus").blur()}catch(E){}A&&r&&(p=(r.url||"")+x);if(j.changeHash!==false&&p)n.ignoreNextHashChange=true, +l.set(p);var C=!r?B:d.jqmData("title")||d.children(":jqmData(role='header')").find(".ui-title").getEncodedText();C&&B==k.title&&(B=C);d.jqmData("title")||d.jqmData("title",B);j.transition=j.transition||(y&&!s?r.transition:c)||(A?a.mobile.defaultDialogTransition:a.mobile.defaultPageTransition);y||n.addNew(p,j.transition,B,v,j.role);k.title=n.getActive().title;a.mobile.activePage=d;j.reverse=j.reverse||y<0;f(d,o,j.transition,j.reverse).done(function(c,f,g,h,l){b();j.duplicateCachedPage&&j.duplicateCachedPage.remove(); +l||a.mobile.focusPage(d);e();u.trigger("pagechange",m)})}}}};a.mobile.changePage.defaults={transition:c,reverse:false,changeHash:true,fromHashChange:false,role:c,duplicateCachedPage:c,pageContainer:c,showLoadMsg:true,dataUrl:c,fromPage:c,allowSamePageTransition:false};a.mobile._registerInternalEvents=function(){a(k).delegate("form","submit",function(b){var c=a(this);if(a.mobile.ajaxEnabled&&!c.is(":jqmData(ajax='false')")&&c.jqmHijackable().length){var d=c.attr("method"),e=c.attr("target"),f=c.attr("action"); +if(!f&&(f=o(c),f===v.hrefNoHash))f=w.hrefNoSearch;f=l.makeUrlAbsolute(f,o(c));!l.isExternal(f)&&!e&&(a.mobile.changePage(f,{type:d&&d.length&&d.toLowerCase()||"get",data:c.serialize(),transition:c.jqmData("transition"),direction:c.jqmData("direction"),reloadPage:true}),b.preventDefault())}});a(k).bind("vclick",function(c){if(!(c.which>1)&&a.mobile.linkBindingEnabled&&(c=j(c.target),a(c).jqmHijackable().length&&c&&l.parseUrl(c.getAttribute("href")||"#").hash!=="#"))b(true),r=a(c).closest(".ui-btn").not(".ui-disabled"), +r.addClass(a.mobile.activeBtnClass),a("."+a.mobile.activePageClass+" .ui-btn").not(c).blur(),a(c).jqmData("href",a(c).attr("href")).attr("href","#")});a(k).bind("click",function(d){if(a.mobile.linkBindingEnabled){var f=j(d.target),e=a(f),g;if(f&&!(d.which>1)&&e.jqmHijackable().length){g=function(){s.setTimeout(function(){b(true)},200)};e.jqmData("href")&&e.attr("href",e.jqmData("href"));if(e.is(":jqmData(rel='back')"))return s.history.back(),false;var h=o(e),f=l.makeUrlAbsolute(e.attr("href")||"#", +h);if(!a.mobile.ajaxEnabled&&!l.isEmbeddedPage(f))g();else{if(f.search("#")!=-1)if(f=f.replace(/[^#]*#/,""))f=l.isPath(f)?l.makeUrlAbsolute(f,h):l.makeUrlAbsolute("#"+f,w.hrefNoHash);else{d.preventDefault();return}var h=e.is("[rel='external']")||e.is(":jqmData(ajax='false')")||e.is("[target]"),k=a.mobile.allowCrossDomainPages&&w.protocol==="file:"&&f.search(/^https?:/)!=-1;h||l.isExternal(f)&&!k?g():(g=e.jqmData("transition"),h=(h=e.jqmData("direction"))&&h==="reverse"||e.jqmData("back"),e=e.attr("data-"+ +a.mobile.ns+"rel")||c,a.mobile.changePage(f,{transition:g,reverse:h,role:e}),d.preventDefault())}}}});a(k).delegate(".ui-page","pageshow.prefetch",function(){var b=[];a(this).find("a:jqmData(prefetch)").each(function(){var c=a(this),d=c.attr("href");d&&a.inArray(d,b)===-1&&(b.push(d),a.mobile.loadPage(d,{role:c.attr("data-"+a.mobile.ns+"rel")}))})});a.mobile._handleHashChange=function(b){var d=l.stripHash(b),f={transition:a.mobile.urlHistory.stack.length===0?"none":c,changeHash:false,fromHashChange:true}; +if(!a.mobile.hashListeningEnabled||n.ignoreNextHashChange)n.ignoreNextHashChange=false;else{if(n.stack.length>1&&d.indexOf(x)>-1)if(a.mobile.activePage.is(".ui-dialog"))n.directHashChange({currentUrl:d,either:function(b){var c=a.mobile.urlHistory.getActive();d=c.pageUrl;a.extend(f,{role:c.role,transition:c.transition,reverse:b})}});else{n.directHashChange({currentUrl:d,isBack:function(){s.history.back()},isForward:function(){s.history.forward()}});return}d?(d=typeof d==="string"&&!l.isPath(d)?l.makeUrlAbsolute("#"+ +d,v):d,a.mobile.changePage(d,f)):a.mobile.changePage(a.mobile.firstPage,f)}};m.bind("hashchange",function(){a.mobile._handleHashChange(location.hash)});a(k).bind("pageshow",g);a(s).bind("throttledresize",g)}})(jQuery);(function(a,c){var b={},e=a(c),f=a.mobile.path.parseUrl(location.href);a.extend(b,{initialFilePath:f.pathname+f.search,initialHref:f.hrefNoHash,state:function(){return{hash:location.hash||"#"+b.initialFilePath,title:k.title,initialHref:b.initialHref}},resetUIKeys:function(b){var c="&"+ +a.mobile.subPageUrlKey,f=b.indexOf(a.mobile.dialogHashKey);f>-1?b=b.slice(0,f)+"#"+b.slice(f):b.indexOf(c)>-1&&(b=b.split(c).join("#"+c));return b},hashValueAfterReset:function(c){c=b.resetUIKeys(c);return a.mobile.path.parseUrl(c).hash},nextHashChangePrevented:function(c){a.mobile.urlHistory.ignoreNextHashChange=c;b.onHashChangeDisabled=c},onHashChange:function(){if(!b.onHashChangeDisabled){var c,f;c=location.hash;var e=a.mobile.path.isPath(c),j=e?location.href:a.mobile.getDocumentUrl();c=e?c.replace("#", +""):c;f=b.state();c=a.mobile.path.makeUrlAbsolute(c,j);e&&(c=b.resetUIKeys(c));history.replaceState(f,k.title,c)}},onPopState:function(c){var c=c.originalEvent.state,f,h;if(c){f=b.hashValueAfterReset(a.mobile.urlHistory.getActive().url);h=b.hashValueAfterReset(c.hash.replace("#",""));if(f=f!==h)e.one("hashchange.pushstate",function(){b.nextHashChangePrevented(false)});b.nextHashChangePrevented(false);a.mobile._handleHashChange(c.hash);f&&b.nextHashChangePrevented(true)}},init:function(){e.bind("hashchange", +b.onHashChange);e.bind("popstate",b.onPopState);location.hash===""&&history.replaceState(b.state(),k.title,location.href)}});a(function(){a.mobile.pushStateEnabled&&a.support.pushState&&b.init()})})(jQuery,this);jQuery.mobile.transitionFallbacks.pop="fade";(function(a){a.mobile.transitionHandlers.slide=a.mobile.transitionHandlers.simultaneous;a.mobile.transitionFallbacks.slide="fade"})(jQuery,this);jQuery.mobile.transitionFallbacks.slidedown="fade";jQuery.mobile.transitionFallbacks.slideup="fade"; +jQuery.mobile.transitionFallbacks.flip="fade";jQuery.mobile.transitionFallbacks.flow="fade";jQuery.mobile.transitionFallbacks.turn="fade";(function(a){a.mobile.page.prototype.options.degradeInputs={color:false,date:false,datetime:false,"datetime-local":false,email:false,month:false,number:false,range:"number",search:"text",tel:false,time:false,url:false,week:false};a(k).bind("pagecreate create",function(c){var b=a.mobile.closestPageData(a(c.target)),e;if(b)e=b.options,a(c.target).find("input").not(b.keepNativeSelector()).each(function(){var b= +a(this),c=this.getAttribute("type"),g=e.degradeInputs[c]||"text";if(e.degradeInputs[c]){var h=a("<div>").html(b.clone()).html(),j=h.indexOf(" type=")>-1;b.replaceWith(h.replace(j?/\s+type=["']?\w+['"]?/:/\/?>/,' type="'+g+'" data-'+a.mobile.ns+'type="'+c+'"'+(j?"":">")))}})})})(jQuery);(function(a,c){a.widget("mobile.dialog",a.mobile.widget,{options:{closeBtnText:"Close",overlayTheme:"a",initSelector:":jqmData(role='dialog')"},_create:function(){var b=this,c=this.element,f=a("<a href='#' data-"+a.mobile.ns+ +"icon='delete' data-"+a.mobile.ns+"iconpos='notext'>"+this.options.closeBtnText+"</a>"),d=a("<div/>",{role:"dialog","class":"ui-dialog-contain ui-corner-all ui-overlay-shadow"});c.addClass("ui-dialog ui-overlay-"+this.options.overlayTheme);c.wrapInner(d).children().find(":jqmData(role='header')").prepend(f).end().children(":first-child").addClass("ui-corner-top").end().children(":last-child").addClass("ui-corner-bottom");f.bind("click",function(){b.close()});c.bind("vclick submit",function(b){var b= +a(b.target).closest(b.type==="vclick"?"a":"form"),c;b.length&&!b.jqmData("transition")&&(c=a.mobile.urlHistory.getActive()||{},b.attr("data-"+a.mobile.ns+"transition",c.transition||a.mobile.defaultDialogTransition).attr("data-"+a.mobile.ns+"direction","reverse"))}).bind("pagehide",function(){a(this).find("."+a.mobile.activeBtnClass).removeClass(a.mobile.activeBtnClass)}).bind("pagebeforeshow",function(){b.options.overlayTheme&&b.element.page("removeContainerBackground").page("setContainerBackground", +b.options.overlayTheme)})},close:function(){c.history.back()}});a(k).delegate(a.mobile.dialog.prototype.options.initSelector,"pagecreate",function(){a.mobile.dialog.prototype.enhance(this)})})(jQuery,this);(function(a){a.fn.fieldcontain=function(){return this.addClass("ui-field-contain ui-body ui-br")};a(k).bind("pagecreate create",function(c){a(":jqmData(role='fieldcontain')",c.target).jqmEnhanceable().fieldcontain()})})(jQuery);(function(a){a.fn.grid=function(c){return this.each(function(){var b= +a(this),e=a.extend({grid:null},c),f=b.children(),d={solo:1,a:2,b:3,c:4,d:5},e=e.grid;if(!e)if(f.length<=5)for(var g in d)d[g]===f.length&&(e=g);else e="a";d=d[e];b.addClass("ui-grid-"+e);f.filter(":nth-child("+d+"n+1)").addClass("ui-block-a");d>1&&f.filter(":nth-child("+d+"n+2)").addClass("ui-block-b");d>2&&f.filter(":nth-child(3n+3)").addClass("ui-block-c");d>3&&f.filter(":nth-child(4n+4)").addClass("ui-block-d");d>4&&f.filter(":nth-child(5n+5)").addClass("ui-block-e")})}})(jQuery);(function(a){a(k).bind("pagecreate create", +function(c){a(":jqmData(role='nojs')",c.target).addClass("ui-nojs")})})(jQuery);(function(a,c){function b(a){for(var b;a;){if((b=typeof a.className==="string"&&a.className+" ")&&b.indexOf("ui-btn ")>-1&&b.indexOf("ui-disabled ")<0)break;a=a.parentNode}return a}a.fn.buttonMarkup=function(b){for(var b=b&&a.type(b)=="object"?b:{},d=0;d<this.length;d++){var g=this.eq(d),h=g[0],j=a.extend({},a.fn.buttonMarkup.defaults,{icon:b.icon!==c?b.icon:g.jqmData("icon"),iconpos:b.iconpos!==c?b.iconpos:g.jqmData("iconpos"), +theme:b.theme!==c?b.theme:g.jqmData("theme")||a.mobile.getInheritedTheme(g,"c"),inline:b.inline!==c?b.inline:g.jqmData("inline"),shadow:b.shadow!==c?b.shadow:g.jqmData("shadow"),corners:b.corners!==c?b.corners:g.jqmData("corners"),iconshadow:b.iconshadow!==c?b.iconshadow:g.jqmData("iconshadow"),mini:b.mini!==c?b.mini:g.jqmData("mini")},b),o="ui-btn-inner",m,p,l,r,n,q;a.each(j,function(b,c){h.setAttribute("data-"+a.mobile.ns+b,c);g.jqmData(b,c)});(q=a.data(h.tagName==="INPUT"||h.tagName==="BUTTON"? +h.parentNode:h,"buttonElements"))?(h=q.outer,g=a(h),l=q.inner,r=q.text,a(q.icon).remove(),q.icon=null):(l=k.createElement(j.wrapperEls),r=k.createElement(j.wrapperEls));n=j.icon?k.createElement("span"):null;e&&!q&&e();if(!j.theme)j.theme=a.mobile.getInheritedTheme(g,"c");m="ui-btn ui-btn-up-"+j.theme;m+=j.inline?" ui-btn-inline":"";m+=j.shadow?" ui-shadow":"";m+=j.corners?" ui-btn-corner-all":"";j.mini!==c&&(m+=j.mini?" ui-mini":" ui-fullsize");j.inline!==c&&(m+=j.inline===false?" ui-btn-block":" ui-btn-inline"); +if(j.icon)j.icon="ui-icon-"+j.icon,j.iconpos=j.iconpos||"left",p="ui-icon "+j.icon,j.iconshadow&&(p+=" ui-icon-shadow");j.iconpos&&(m+=" ui-btn-icon-"+j.iconpos,j.iconpos=="notext"&&!g.attr("title")&&g.attr("title",g.getEncodedText()));o+=j.corners?" ui-btn-corner-all":"";j.iconpos&&j.iconpos==="notext"&&!g.attr("title")&&g.attr("title",g.getEncodedText());q&&g.removeClass(q.bcls||"");g.removeClass("ui-link").addClass(m);l.className=o;r.className="ui-btn-text";q||l.appendChild(r);if(n&&(n.className= +p,!q||!q.icon))n.appendChild(k.createTextNode("\u00a0")),l.appendChild(n);for(;h.firstChild&&!q;)r.appendChild(h.firstChild);q||h.appendChild(l);q={bcls:m,outer:h,inner:l,text:r,icon:n};a.data(h,"buttonElements",q);a.data(l,"buttonElements",q);a.data(r,"buttonElements",q);n&&a.data(n,"buttonElements",q)}return this};a.fn.buttonMarkup.defaults={corners:true,shadow:true,iconshadow:true,wrapperEls:"span"};var e=function(){var c=a.mobile.buttonMarkup.hoverDelay,d,g;a(k).bind({"vmousedown vmousecancel vmouseup vmouseover vmouseout focus blur scrollstart":function(e){var j, +k=a(b(e.target)),e=e.type;if(k.length)if(j=k.attr("data-"+a.mobile.ns+"theme"),e==="vmousedown")a.support.touch?d=setTimeout(function(){k.removeClass("ui-btn-up-"+j).addClass("ui-btn-down-"+j)},c):k.removeClass("ui-btn-up-"+j).addClass("ui-btn-down-"+j);else if(e==="vmousecancel"||e==="vmouseup")k.removeClass("ui-btn-down-"+j).addClass("ui-btn-up-"+j);else if(e==="vmouseover"||e==="focus")a.support.touch?g=setTimeout(function(){k.removeClass("ui-btn-up-"+j).addClass("ui-btn-hover-"+j)},c):k.removeClass("ui-btn-up-"+ +j).addClass("ui-btn-hover-"+j);else if(e==="vmouseout"||e==="blur"||e==="scrollstart")k.removeClass("ui-btn-hover-"+j+" ui-btn-down-"+j).addClass("ui-btn-up-"+j),d&&clearTimeout(d),g&&clearTimeout(g)},"focusin focus":function(c){a(b(c.target)).addClass(a.mobile.focusClass)},"focusout blur":function(c){a(b(c.target)).removeClass(a.mobile.focusClass)}});e=null};a(k).bind("pagecreate create",function(b){a(":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a", +b.target).not(".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')").buttonMarkup()})})(jQuery);(function(a){a.mobile.page.prototype.options.backBtnText="Back";a.mobile.page.prototype.options.addBackBtn=false;a.mobile.page.prototype.options.backBtnTheme=null;a.mobile.page.prototype.options.headerTheme="a";a.mobile.page.prototype.options.footerTheme="a";a.mobile.page.prototype.options.contentTheme=null;a(k).delegate(":jqmData(role='page'), :jqmData(role='dialog')","pagecreate",function(){var c=a(this), +b=c.data("page").options,e=c.jqmData("role"),f=b.theme;a(":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')",this).jqmEnhanceable().each(function(){var d=a(this),g=d.jqmData("role"),h=d.jqmData("theme"),j=h||b.contentTheme||e==="dialog"&&f,k;d.addClass("ui-"+g);if(g==="header"||g==="footer"){var m=h||(g==="header"?b.headerTheme:b.footerTheme)||f;d.addClass("ui-bar-"+m).attr("role",g==="header"?"banner":"contentinfo");g==="header"&&(h=d.children("a"),k=h.hasClass("ui-btn-left"), +j=h.hasClass("ui-btn-right"),k=k||h.eq(0).not(".ui-btn-right").addClass("ui-btn-left").length,j||h.eq(1).addClass("ui-btn-right"));b.addBackBtn&&g==="header"&&a(".ui-page").length>1&&c.jqmData("url")!==a.mobile.path.stripHash(location.hash)&&!k&&a("<a href='#' class='ui-btn-left' data-"+a.mobile.ns+"rel='back' data-"+a.mobile.ns+"icon='arrow-l'>"+b.backBtnText+"</a>").attr("data-"+a.mobile.ns+"theme",b.backBtnTheme||m).prependTo(d);d.children("h1, h2, h3, h4, h5, h6").addClass("ui-title").attr({role:"heading", +"aria-level":"1"})}else g==="content"&&(j&&d.addClass("ui-body-"+j),d.attr("role","main"))})})})(jQuery);(function(a){a.widget("mobile.collapsible",a.mobile.widget,{options:{expandCueText:" click to expand contents",collapseCueText:" click to collapse contents",collapsed:true,heading:"h1,h2,h3,h4,h5,h6,legend",theme:null,contentTheme:null,iconTheme:"d",mini:false,initSelector:":jqmData(role='collapsible')"},_create:function(){var c=this.element,b=this.options,e=c.addClass("ui-collapsible"),f=c.children(b.heading).first(), +d=e.wrapInner("<div class='ui-collapsible-content'></div>").find(".ui-collapsible-content"),g=c.closest(":jqmData(role='collapsible-set')").addClass("ui-collapsible-set");f.is("legend")&&(f=a("<div role='heading'>"+f.html()+"</div>").insertBefore(f),f.next().remove());if(g.length){if(!b.theme)b.theme=g.jqmData("theme")||a.mobile.getInheritedTheme(g,"c");if(!b.contentTheme)b.contentTheme=g.jqmData("content-theme");if(!b.iconPos)b.iconPos=g.jqmData("iconpos");if(!b.mini)b.mini=g.jqmData("mini")}d.addClass(b.contentTheme? +"ui-body-"+b.contentTheme:"");f.insertBefore(d).addClass("ui-collapsible-heading").append("<span class='ui-collapsible-heading-status'></span>").wrapInner("<a href='#' class='ui-collapsible-heading-toggle'></a>").find("a").first().buttonMarkup({shadow:false,corners:false,iconpos:c.jqmData("iconpos")||b.iconPos||"left",icon:"plus",mini:b.mini,theme:b.theme}).add(".ui-btn-inner",c).addClass("ui-corner-top ui-corner-bottom");e.bind("expand collapse",function(c){if(!c.isDefaultPrevented()){c.preventDefault(); +var j=a(this),c=c.type==="collapse",k=b.contentTheme;f.toggleClass("ui-collapsible-heading-collapsed",c).find(".ui-collapsible-heading-status").text(c?b.expandCueText:b.collapseCueText).end().find(".ui-icon").toggleClass("ui-icon-minus",!c).toggleClass("ui-icon-plus",c);j.toggleClass("ui-collapsible-collapsed",c);d.toggleClass("ui-collapsible-content-collapsed",c).attr("aria-hidden",c);if(k&&(!g.length||e.jqmData("collapsible-last")))f.find("a").first().add(f.find(".ui-btn-inner")).toggleClass("ui-corner-bottom", +c),d.toggleClass("ui-corner-bottom",!c);d.trigger("updatelayout")}}).trigger(b.collapsed?"collapse":"expand");f.bind("click",function(a){var b=f.is(".ui-collapsible-heading-collapsed")?"expand":"collapse";e.trigger(b);a.preventDefault()})}});a(k).bind("pagecreate create",function(c){a.mobile.collapsible.prototype.enhanceWithin(c.target)})})(jQuery);(function(a,c){a.widget("mobile.collapsibleset",a.mobile.widget,{options:{initSelector:":jqmData(role='collapsible-set')"},_create:function(){var b=this.element.addClass("ui-collapsible-set"), +e=this.options;if(!e.theme)e.theme=a.mobile.getInheritedTheme(b,"c");if(!e.contentTheme)e.contentTheme=b.jqmData("content-theme");if(!e.corners)e.corners=b.jqmData("corners")===c?true:false;b.jqmData("collapsiblebound")||b.jqmData("collapsiblebound",true).bind("expand collapse",function(b){var c=b.type==="collapse",b=a(b.target).closest(".ui-collapsible"),e=b.data("collapsible");e.options.contentTheme&&b.jqmData("collapsible-last")&&(b.find(e.options.heading).first().find("a").first().add(".ui-btn-inner").toggleClass("ui-corner-bottom", +c),b.find(".ui-collapsible-content").toggleClass("ui-corner-bottom",!c))}).bind("expand",function(b){a(b.target).closest(".ui-collapsible").siblings(".ui-collapsible").trigger("collapse")})},_init:function(){this.refresh()},refresh:function(){var b=this.options,c=this.element.children(":jqmData(role='collapsible')");a.mobile.collapsible.prototype.enhance(c.not(".ui-collapsible"));c.each(function(){a(this).find(a.mobile.collapsible.prototype.options.heading).find("a").first().add(".ui-btn-inner").removeClass("ui-corner-top ui-corner-bottom")}); +c.first().find("a").first().addClass(b.corners?"ui-corner-top":"").find(".ui-btn-inner").addClass("ui-corner-top");c.last().jqmData("collapsible-last",true).find("a").first().addClass(b.corners?"ui-corner-bottom":"").find(".ui-btn-inner").addClass("ui-corner-bottom")}});a(k).bind("pagecreate create",function(b){a.mobile.collapsibleset.prototype.enhanceWithin(b.target)})})(jQuery);(function(a,c){a.widget("mobile.navbar",a.mobile.widget,{options:{iconpos:"top",grid:null,initSelector:":jqmData(role='navbar')"}, +_create:function(){var b=this.element,e=b.find("a"),f=e.filter(":jqmData(icon)").length?this.options.iconpos:c;b.addClass("ui-navbar").attr("role","navigation").find("ul").jqmEnhanceable().grid({grid:this.options.grid});f||b.addClass("ui-navbar-noicons");e.buttonMarkup({corners:false,shadow:false,inline:true,iconpos:f});b.delegate("a","vclick",function(b){a(b.target).hasClass("ui-disabled")||(e.removeClass(a.mobile.activeBtnClass),a(this).addClass(a.mobile.activeBtnClass))});b.closest(".ui-page").bind("pagebeforeshow", +function(){e.filter(".ui-state-persist").addClass(a.mobile.activeBtnClass)})}});a(k).bind("pagecreate create",function(b){a.mobile.navbar.prototype.enhanceWithin(b.target)})})(jQuery);(function(a){var c={};a.widget("mobile.listview",a.mobile.widget,{options:{theme:null,countTheme:"c",headerTheme:"b",dividerTheme:"b",splitIcon:"arrow-r",splitTheme:"b",mini:false,inset:false,initSelector:":jqmData(role='listview')"},_create:function(){var a="";a+=this.options.inset?" ui-listview-inset ui-corner-all ui-shadow ": +"";a+=this.element.jqmData("mini")||this.options.mini===true?" ui-mini":"";this.element.addClass(function(c,f){return f+" ui-listview "+a});this.refresh(true)},_removeCorners:function(a,c){a=a.add(a.find(".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb"));c==="top"?a.removeClass("ui-corner-top ui-corner-tr ui-corner-tl"):c==="bottom"?a.removeClass("ui-corner-bottom ui-corner-br ui-corner-bl"):a.removeClass("ui-corner-top ui-corner-tr ui-corner-tl ui-corner-bottom ui-corner-br ui-corner-bl")},_refreshCorners:function(a){var c, +f;this.options.inset&&(c=this.element.children("li"),f=a?c.not(".ui-screen-hidden"):c.filter(":visible"),this._removeCorners(c),c=f.first().addClass("ui-corner-top"),c.add(c.find(".ui-btn-inner").not(".ui-li-link-alt span:first-child")).addClass("ui-corner-top").end().find(".ui-li-link-alt, .ui-li-link-alt span:first-child").addClass("ui-corner-tr").end().find(".ui-li-thumb").not(".ui-li-icon").addClass("ui-corner-tl"),f=f.last().addClass("ui-corner-bottom"),f.add(f.find(".ui-btn-inner")).find(".ui-li-link-alt").addClass("ui-corner-br").end().find(".ui-li-thumb").not(".ui-li-icon").addClass("ui-corner-bl")); +a||this.element.trigger("updatelayout")},_findFirstElementByTagName:function(a,c,f,d){var g={};for(g[f]=g[d]=true;a;){if(g[a.nodeName])return a;a=a[c]}return null},_getChildrenByTagName:function(b,c,f){var d=[],g={};g[c]=g[f]=true;for(b=b.firstChild;b;)g[b.nodeName]&&d.push(b),b=b.nextSibling;return a(d)},_addThumbClasses:function(b){var c,f,d=b.length;for(c=0;c<d;c++)f=a(this._findFirstElementByTagName(b[c].firstChild,"nextSibling","img","IMG")),f.length&&(f.addClass("ui-li-thumb"),a(this._findFirstElementByTagName(f[0].parentNode, +"parentNode","li","LI")).addClass(f.is(".ui-li-icon")?"ui-li-has-icon":"ui-li-has-thumb"))},refresh:function(b){this.parentPage=this.element.closest(".ui-page");this._createSubPages();var c=this.options,f=this.element,d=f.jqmData("dividertheme")||c.dividerTheme,g=f.jqmData("splittheme"),h=f.jqmData("spliticon"),j=this._getChildrenByTagName(f[0],"li","LI"),o=a.support.cssPseudoElement||!a.nodeName(f[0],"ol")?0:1,m={},p,l,r,n,q,t,x;o&&f.find(".ui-li-dec").remove();if(!c.theme)c.theme=a.mobile.getInheritedTheme(this.element, +"c");for(var u=0,w=j.length;u<w;u++){p=j.eq(u);l="ui-li";if(b||!p.hasClass("ui-li"))r=p.jqmData("theme")||c.theme,n=this._getChildrenByTagName(p[0],"a","A"),n.length?(t=p.jqmData("icon"),p.buttonMarkup({wrapperEls:"div",shadow:false,corners:false,iconpos:"right",icon:n.length>1||t===false?false:t||"arrow-r",theme:r}),t!=false&&n.length==1&&p.addClass("ui-li-has-arrow"),n.first().removeClass("ui-link").addClass("ui-link-inherit"),n.length>1&&(l+=" ui-li-has-alt",n=n.last(),q=g||n.jqmData("theme")|| +c.splitTheme,x=n.jqmData("icon"),n.appendTo(p).attr("title",n.getEncodedText()).addClass("ui-li-link-alt").empty().buttonMarkup({shadow:false,corners:false,theme:r,icon:false,iconpos:false}).find(".ui-btn-inner").append(a(k.createElement("span")).buttonMarkup({shadow:true,corners:true,theme:q,iconpos:"notext",icon:x||t||h||c.splitIcon})))):p.jqmData("role")==="list-divider"?(l+=" ui-li-divider ui-bar-"+d,p.attr("role","heading"),o&&(o=1)):l+=" ui-li-static ui-body-"+r;o&&l.indexOf("ui-li-divider")< +0&&(r=p.is(".ui-li-static:first")?p:p.find(".ui-link-inherit"),r.addClass("ui-li-jsnumbering").prepend("<span class='ui-li-dec'>"+o++ +". </span>"));m[l]||(m[l]=[]);m[l].push(p[0])}for(l in m)a(m[l]).addClass(l).children(".ui-btn-inner").addClass(l);f.find("h1, h2, h3, h4, h5, h6").addClass("ui-li-heading").end().find("p, dl").addClass("ui-li-desc").end().find(".ui-li-aside").each(function(){var b=a(this);b.prependTo(b.parent())}).end().find(".ui-li-count").each(function(){a(this).closest("li").addClass("ui-li-has-count")}).addClass("ui-btn-up-"+ +(f.jqmData("counttheme")||this.options.countTheme)+" ui-btn-corner-all");this._addThumbClasses(j);this._addThumbClasses(f.find(".ui-link-inherit"));this._refreshCorners(b)},_idStringEscape:function(a){return a.replace(/[^a-zA-Z0-9]/g,"-")},_createSubPages:function(){var b=this.element,e=b.closest(".ui-page"),f=e.jqmData("url"),d=f||e[0][a.expando],g=b.attr("id"),h=this.options,j="data-"+a.mobile.ns,k=this,m=e.find(":jqmData(role='footer')").jqmData("id"),p;typeof c[d]==="undefined"&&(c[d]=-1);g=g|| +++c[d];a(b.find("li>ul, li>ol").toArray().reverse()).each(function(c){var d=a(this),e=d.attr("id")||g+"-"+c,c=d.parent(),k=a(d.prevAll().toArray().reverse()),k=k.length?k:a("<span>"+a.trim(c.contents()[0].nodeValue)+"</span>"),o=k.first().getEncodedText(),e=(f||"")+"&"+a.mobile.subPageUrlKey+"="+e,x=d.jqmData("theme")||h.theme,u=d.jqmData("counttheme")||b.jqmData("counttheme")||h.countTheme;p=true;d.detach().wrap("<div "+j+"role='page' "+j+"url='"+e+"' "+j+"theme='"+x+"' "+j+"count-theme='"+u+"'><div "+ +j+"role='content'></div></div>").parent().before("<div "+j+"role='header' "+j+"theme='"+h.headerTheme+"'><div class='ui-title'>"+o+"</div></div>").after(m?a("<div "+j+"role='footer' "+j+"id='"+m+"'>"):"").parent().appendTo(a.mobile.pageContainer).page();d=c.find("a:first");d.length||(d=a("<a/>").html(k||o).prependTo(c.empty()));d.attr("href","#"+e)}).listview();p&&e.is(":jqmData(external-page='true')")&&e.data("page").options.domCache===false&&e.unbind("pagehide.remove").bind("pagehide.remove",function(b, +c){var d=c.nextPage;c.nextPage&&(d=d.jqmData("url"),d.indexOf(f+"&"+a.mobile.subPageUrlKey)!==0&&(k.childPages().remove(),e.remove()))})},childPages:function(){var b=this.parentPage.jqmData("url");return a(":jqmData(url^='"+b+"&"+a.mobile.subPageUrlKey+"')")}});a(k).bind("pagecreate create",function(b){a.mobile.listview.prototype.enhanceWithin(b.target)})})(jQuery);(function(a,c){a.widget("mobile.checkboxradio",a.mobile.widget,{options:{theme:null,initSelector:"input[type='checkbox'],input[type='radio']"}, +_create:function(){var b=this,e=this.element,f=a(e).closest("label"),d=f.length?f:a(e).closest("form,fieldset,:jqmData(role='page'),:jqmData(role='dialog')").find("label").filter("[for='"+e[0].id+"']"),g=e[0].type,f=e.jqmData("mini")||e.closest("form,fieldset").jqmData("mini"),h=g+"-on",j=g+"-off",o=e.parents(":jqmData(type='horizontal')").length?c:j,m=e.jqmData("iconpos")||e.closest("form,fieldset").jqmData("iconpos");if(!(g!=="checkbox"&&g!=="radio")){a.extend(this,{label:d,inputtype:g,checkedClass:"ui-"+ +h+(o?"":" "+a.mobile.activeBtnClass),uncheckedClass:"ui-"+j,checkedicon:"ui-icon-"+h,uncheckedicon:"ui-icon-"+j});if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.element,"c");d.buttonMarkup({theme:this.options.theme,icon:o,shadow:false,mini:f,iconpos:m});f=k.createElement("div");f.className="ui-"+g;e.add(d).wrapAll(f);d.bind({vmouseover:function(b){a(this).parent().is(".ui-disabled")&&b.stopPropagation()},vclick:function(a){if(e.is(":disabled"))a.preventDefault();else return b._cacheVals(), +e.prop("checked",g==="radio"&&true||!e.prop("checked")),e.triggerHandler("click"),b._getInputSet().not(e).prop("checked",false),b._updateAll(),false}});e.bind({vmousedown:function(){b._cacheVals()},vclick:function(){var c=a(this);c.is(":checked")?(c.prop("checked",true),b._getInputSet().not(c).prop("checked",false)):c.prop("checked",false);b._updateAll()},focus:function(){d.addClass(a.mobile.focusClass)},blur:function(){d.removeClass(a.mobile.focusClass)}});this.refresh()}},_cacheVals:function(){this._getInputSet().each(function(){a(this).jqmData("cacheVal", +this.checked)})},_getInputSet:function(){return this.inputtype==="checkbox"?this.element:this.element.closest("form,fieldset,:jqmData(role='page')").find("input[name='"+this.element[0].name+"'][type='"+this.inputtype+"']")},_updateAll:function(){var b=this;this._getInputSet().each(function(){var c=a(this);(this.checked||b.inputtype==="checkbox")&&c.trigger("change")}).checkboxradio("refresh")},refresh:function(){var a=this.element[0],c=this.label,f=c.find(".ui-icon");a.checked?(c.addClass(this.checkedClass).removeClass(this.uncheckedClass), +f.addClass(this.checkedicon).removeClass(this.uncheckedicon)):(c.removeClass(this.checkedClass).addClass(this.uncheckedClass),f.removeClass(this.checkedicon).addClass(this.uncheckedicon));a.disabled?this.disable():this.enable()},disable:function(){this.element.prop("disabled",true).parent().addClass("ui-disabled")},enable:function(){this.element.prop("disabled",false).parent().removeClass("ui-disabled")}});a(k).bind("pagecreate create",function(b){a.mobile.checkboxradio.prototype.enhanceWithin(b.target, +true)})})(jQuery);(function(a,c){a.widget("mobile.button",a.mobile.widget,{options:{theme:null,icon:null,iconpos:null,inline:false,corners:true,shadow:true,iconshadow:true,initSelector:"button, [type='button'], [type='submit'], [type='reset'], [type='image']",mini:false},_create:function(){var b=this.element,e,f=this.options,d;d="";var g;if(b[0].tagName==="A")!b.hasClass("ui-btn")&&b.buttonMarkup();else{if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.element,"c");~b[0].className.indexOf("ui-btn-left")&& +(d="ui-btn-left");~b[0].className.indexOf("ui-btn-right")&&(d="ui-btn-right");e=this.button=a("<div></div>").text(b.text()||b.val()).insertBefore(b).buttonMarkup({theme:f.theme,icon:f.icon,iconpos:f.iconpos,inline:f.inline,corners:f.corners,shadow:f.shadow,iconshadow:f.iconshadow,mini:f.mini}).addClass(d).append(b.addClass("ui-btn-hidden"));f=b.attr("type");d=b.attr("name");f!=="button"&&f!=="reset"&&d&&b.bind("vclick",function(){g===c&&(g=a("<input>",{type:"hidden",name:b.attr("name"),value:b.attr("value")}).insertBefore(b), +a(k).one("submit",function(){g.remove();g=c}))});b.bind({focus:function(){e.addClass(a.mobile.focusClass)},blur:function(){e.removeClass(a.mobile.focusClass)}});this.refresh()}},enable:function(){this.element.attr("disabled",false);this.button.removeClass("ui-disabled").attr("aria-disabled",false);return this._setOption("disabled",false)},disable:function(){this.element.attr("disabled",true);this.button.addClass("ui-disabled").attr("aria-disabled",true);return this._setOption("disabled",true)},refresh:function(){var b= +this.element;b.prop("disabled")?this.disable():this.enable();a(this.button.data("buttonElements").text).text(b.text()||b.val())}});a(k).bind("pagecreate create",function(b){a.mobile.button.prototype.enhanceWithin(b.target,true)})})(jQuery);(function(a){a.fn.controlgroup=function(c){function b(a,b){a.removeClass("ui-btn-corner-all ui-shadow").eq(0).addClass(b[0]).end().last().addClass(b[1]).addClass("ui-controlgroup-last")}return this.each(function(){var e=a(this),f=a.extend({direction:e.jqmData("type")|| +"vertical",shadow:false,excludeInvisible:true,mini:e.jqmData("mini")},c),d=e.children("legend"),g=f.direction=="horizontal"?["ui-corner-left","ui-corner-right"]:["ui-corner-top","ui-corner-bottom"];e.find("input").first().attr("type");d.length&&(e.wrapInner("<div class='ui-controlgroup-controls'></div>"),a("<div role='heading' class='ui-controlgroup-label'>"+d.html()+"</div>").insertBefore(e.children(0)),d.remove());e.addClass("ui-corner-all ui-controlgroup ui-controlgroup-"+f.direction);b(e.find(".ui-btn"+ +(f.excludeInvisible?":visible":"")).not(".ui-slider-handle"),g);b(e.find(".ui-btn-inner"),g);f.shadow&&e.addClass("ui-shadow");f.mini&&e.addClass("ui-mini")})}})(jQuery);(function(a){a(k).bind("pagecreate create",function(c){a(c.target).find("a").jqmEnhanceable().not(".ui-btn, .ui-link-inherit, :jqmData(role='none'), :jqmData(role='nojs')").addClass("ui-link")})})(jQuery);(function(a){var c=a("meta[name=viewport]"),b=c.attr("content"),e=b+",maximum-scale=1, user-scalable=no",f=b+",maximum-scale=10, user-scalable=yes", +d=/(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test(b);a.mobile.zoom=a.extend({},{enabled:!d,locked:false,disable:function(b){if(!d&&!a.mobile.zoom.locked)c.attr("content",e),a.mobile.zoom.enabled=false,a.mobile.zoom.locked=b||false},enable:function(b){if(!d&&(!a.mobile.zoom.locked||b===true))c.attr("content",f),a.mobile.zoom.enabled=true,a.mobile.zoom.locked=false},restore:function(){if(!d)c.attr("content",b),a.mobile.zoom.enabled=true}})})(jQuery);(function(a){a.widget("mobile.textinput", +a.mobile.widget,{options:{theme:null,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1,initSelector:"input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input[type='time'], input[type='date'], input[type='month'], input[type='week'], input[type='datetime'], input[type='datetime-local'], input[type='color'], input:not([type])", +clearSearchButtonText:"clear text"},_create:function(){var c=this.element,b=this.options,e=b.theme||a.mobile.getInheritedTheme(this.element,"c"),f=" ui-body-"+e,d=c.jqmData("mini")==true,g=d?" ui-mini":"",h,j;a("label[for='"+c.attr("id")+"']").addClass("ui-input-text");h=c.addClass("ui-input-text ui-body-"+e);typeof c[0].autocorrect!=="undefined"&&!a.support.touchOverflow&&(c[0].setAttribute("autocorrect","off"),c[0].setAttribute("autocomplete","off"));c.is("[type='search'],:jqmData(type='search')")? +(h=c.wrap("<div class='ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield"+f+g+"'></div>").parent(),j=a("<a href='#' class='ui-input-clear' title='"+b.clearSearchButtonText+"'>"+b.clearSearchButtonText+"</a>").bind("click",function(a){c.val("").focus().trigger("change");j.addClass("ui-input-clear-hidden");a.preventDefault()}).appendTo(h).buttonMarkup({icon:"delete",iconpos:"notext",corners:true,shadow:true,mini:d}),e=function(){setTimeout(function(){j.toggleClass("ui-input-clear-hidden", +!c.val())},0)},e(),c.bind("paste cut keyup focus change blur",e)):c.addClass("ui-corner-all ui-shadow-inset"+f+g);c.focus(function(){h.addClass(a.mobile.focusClass)}).blur(function(){h.removeClass(a.mobile.focusClass)}).bind("focus",function(){b.preventFocusZoom&&a.mobile.zoom.disable(true)}).bind("blur",function(){b.preventFocusZoom&&a.mobile.zoom.enable(true)});if(c.is("textarea")){var o=function(){var a=c[0].scrollHeight;c[0].clientHeight<a&&c.height(a+15)},m;c.keyup(function(){clearTimeout(m); +m=setTimeout(o,100)});a(k).one("pagechange",o);a.trim(c.val())&&a(s).load(o)}},disable:function(){(this.element.attr("disabled",true).is("[type='search'],:jqmData(type='search')")?this.element.parent():this.element).addClass("ui-disabled")},enable:function(){(this.element.attr("disabled",false).is("[type='search'],:jqmData(type='search')")?this.element.parent():this.element).removeClass("ui-disabled")}});a(k).bind("pagecreate create",function(c){a.mobile.textinput.prototype.enhanceWithin(c.target, +true)})})(jQuery);(function(a){a.mobile.listview.prototype.options.filter=false;a.mobile.listview.prototype.options.filterPlaceholder="Filter items...";a.mobile.listview.prototype.options.filterTheme="c";a.mobile.listview.prototype.options.filterCallback=function(a,b){return a.toLowerCase().indexOf(b)===-1};a(k).delegate(":jqmData(role='listview')","listviewcreate",function(){var c=a(this),b=c.data("listview");if(b.options.filter){var e=a("<form>",{"class":"ui-listview-filter ui-bar-"+b.options.filterTheme, +role:"search"});a("<input>",{placeholder:b.options.filterPlaceholder}).attr("data-"+a.mobile.ns+"type","search").jqmData("lastval","").bind("keyup change",function(){var e=a(this),d=this.value.toLowerCase(),g=null,g=e.jqmData("lastval")+"",h=false,j="";e.jqmData("lastval",d);g=d.length<g.length||d.indexOf(g)!==0?c.children():c.children(":not(.ui-screen-hidden)");if(d){for(var k=g.length-1;k>=0;k--)e=a(g[k]),j=e.jqmData("filtertext")||e.text(),e.is("li:jqmData(role=list-divider)")?(e.toggleClass("ui-filter-hidequeue", +!h),h=false):b.options.filterCallback(j,d)?e.toggleClass("ui-filter-hidequeue",true):h=true;g.filter(":not(.ui-filter-hidequeue)").toggleClass("ui-screen-hidden",false);g.filter(".ui-filter-hidequeue").toggleClass("ui-screen-hidden",true).toggleClass("ui-filter-hidequeue",false)}else g.toggleClass("ui-screen-hidden",false);b._refreshCorners()}).appendTo(e).textinput();b.options.inset&&e.addClass("ui-listview-filter-inset");e.bind("submit",function(){return false}).insertBefore(c)}})})(jQuery);(function(a, +c){a.widget("mobile.slider",a.mobile.widget,{options:{theme:null,trackTheme:null,disabled:false,initSelector:"input[type='range'], :jqmData(type='range'), :jqmData(role='slider')",mini:false},_create:function(){var b=this,e=this.element,f=a.mobile.getInheritedTheme(e,"c"),d=this.options.theme||f,f=this.options.trackTheme||f,g=e[0].nodeName.toLowerCase(),h=g=="select"?"ui-slider-switch":"",j=e.attr("id"),o=j+"-label",j=a("[for='"+j+"']").attr("id",o),m=function(){return g=="input"?parseFloat(e.val()): +e[0].selectedIndex},p=g=="input"?parseFloat(e.attr("min")):0,l=g=="input"?parseFloat(e.attr("max")):e.find("option").length-1,r=s.parseFloat(e.attr("step")||1),n=this.options.inline||e.jqmData("inline")==true?" ui-slider-inline":"",q=this.options.mini||e.jqmData("mini")?" ui-slider-mini":"",t=k.createElement("a"),x=a(t),u=k.createElement("div"),w=a(u),v=e.jqmData("highlight")&&g!="select"?function(){var b=k.createElement("div");b.className="ui-slider-bg ui-btn-active ui-btn-corner-all";return a(b).prependTo(w)}(): +false;t.setAttribute("href","#");u.setAttribute("role","application");u.className=["ui-slider ",h," ui-btn-down-",f," ui-btn-corner-all",n,q].join("");t.className="ui-slider-handle";u.appendChild(t);x.buttonMarkup({corners:true,theme:d,shadow:true}).attr({role:"slider","aria-valuemin":p,"aria-valuemax":l,"aria-valuenow":m(),"aria-valuetext":m(),title:m(),"aria-labelledby":o});a.extend(this,{slider:w,handle:x,valuebg:v,dragging:false,beforeStart:null,userModified:false,mouseMoved:false});if(g=="select"){d= +k.createElement("div");d.className="ui-slider-inneroffset";h=0;for(o=u.childNodes.length;h<o;h++)d.appendChild(u.childNodes[h]);u.appendChild(d);x.addClass("ui-slider-handle-snapping");u=e.find("option");d=0;for(h=u.length;d<h;d++)o=!d?"b":"a",n=!d?" ui-btn-down-"+f:" "+a.mobile.activeBtnClass,k.createElement("div"),q=k.createElement("span"),q.className=["ui-slider-label ui-slider-label-",o,n," ui-btn-corner-all"].join(""),q.setAttribute("role","img"),q.appendChild(k.createTextNode(u[d].innerHTML)), +a(q).prependTo(w);b._labels=a(".ui-slider-label",w)}j.addClass("ui-slider");e.addClass(g==="input"?"ui-slider-input":"ui-slider-switch").change(function(){b.mouseMoved||b.refresh(m(),true)}).keyup(function(){b.refresh(m(),true,true)}).blur(function(){b.refresh(m(),true)});a(k).bind("vmousemove",function(a){if(b.dragging)return b.mouseMoved=true,g==="select"&&x.removeClass("ui-slider-handle-snapping"),b.refresh(a),b.userModified=b.beforeStart!==e[0].selectedIndex,false});w.bind("vmousedown",function(a){b.dragging= +true;b.userModified=false;b.mouseMoved=false;if(g==="select")b.beforeStart=e[0].selectedIndex;b.refresh(a);return false}).bind("vclick",false);w.add(k).bind("vmouseup",function(){if(b.dragging)return b.dragging=false,g==="select"&&(x.addClass("ui-slider-handle-snapping"),b.mouseMoved?b.userModified?b.refresh(b.beforeStart==0?1:0):b.refresh(b.beforeStart):b.refresh(b.beforeStart==0?1:0)),b.mouseMoved=false});w.insertAfter(e);g=="select"&&this.handle.bind({focus:function(){w.addClass(a.mobile.focusClass)}, +blur:function(){w.removeClass(a.mobile.focusClass)}});this.handle.bind({vmousedown:function(){a(this).focus()},vclick:false,keydown:function(c){var d=m();if(!b.options.disabled){switch(c.keyCode){case a.mobile.keyCode.HOME:case a.mobile.keyCode.END:case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:if(c.preventDefault(),!b._keySliding)b._keySliding=true,a(this).addClass("ui-state-active")}switch(c.keyCode){case a.mobile.keyCode.HOME:b.refresh(p); +break;case a.mobile.keyCode.END:b.refresh(l);break;case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:b.refresh(d+r);break;case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:b.refresh(d-r)}}},keyup:function(){if(b._keySliding)b._keySliding=false,a(this).removeClass("ui-state-active")}});this.refresh(c,c,true)},refresh:function(b,c,f){(this.options.disabled||this.element.attr("disabled"))&&this.disable();var d=this.element,g=d[0].nodeName.toLowerCase(), +h=g==="input"?parseFloat(d.attr("min")):0,j=g==="input"?parseFloat(d.attr("max")):d.find("option").length-1,k=g==="input"&&parseFloat(d.attr("step"))>0?parseFloat(d.attr("step")):1;if(typeof b==="object"){if(!this.dragging||b.pageX<this.slider.offset().left-8||b.pageX>this.slider.offset().left+this.slider.width()+8)return;b=Math.round((b.pageX-this.slider.offset().left)/this.slider.width()*100)}else b==null&&(b=g==="input"?parseFloat(d.val()||0):d[0].selectedIndex),b=(parseFloat(b)-h)/(j-h)*100;if(!isNaN(b)){b< +0&&(b=0);b>100&&(b=100);var m=b/100*(j-h)+h,p=(m-h)%k;m-=p;Math.abs(p)*2>=k&&(m+=p>0?k:-k);m=parseFloat(m.toFixed(5));m<h&&(m=h);m>j&&(m=j);this.handle.css("left",b+"%");this.handle.attr({"aria-valuenow":g==="input"?m:d.find("option").eq(m).attr("value"),"aria-valuetext":g==="input"?m:d.find("option").eq(m).getEncodedText(),title:g==="input"?m:d.find("option").eq(m).getEncodedText()});this.valuebg&&this.valuebg.css("width",b+"%");if(this._labels){var h=this.handle.width()/this.slider.width()*100, +l=b&&h+(100-h)*b/100,r=b===100?0:Math.min(h+100-l,100);this._labels.each(function(){var b=a(this).is(".ui-slider-label-a");a(this).width((b?l:r)+"%")})}if(!f)f=false,g==="input"?(f=d.val()!==m,d.val(m)):(f=d[0].selectedIndex!==m,d[0].selectedIndex=m),!c&&f&&d.trigger("change")}},enable:function(){this.element.attr("disabled",false);this.slider.removeClass("ui-disabled").attr("aria-disabled",false);return this._setOption("disabled",false)},disable:function(){this.element.attr("disabled",true);this.slider.addClass("ui-disabled").attr("aria-disabled", +true);return this._setOption("disabled",true)}});a(k).bind("pagecreate create",function(b){a.mobile.slider.prototype.enhanceWithin(b.target,true)})})(jQuery);(function(a){a.widget("mobile.selectmenu",a.mobile.widget,{options:{theme:null,disabled:false,icon:"arrow-d",iconpos:"right",inline:false,corners:true,shadow:true,iconshadow:true,overlayTheme:"a",hidePlaceholderMenuItems:true,closeText:"Close",nativeMenu:true,preventFocusZoom:/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")> +-1,initSelector:"select:not(:jqmData(role='slider'))",mini:false},_button:function(){return a("<div/>")},_setDisabled:function(a){this.element.attr("disabled",a);this.button.attr("aria-disabled",a);return this._setOption("disabled",a)},_focusButton:function(){var a=this;setTimeout(function(){a.button.focus()},40)},_selectOptions:function(){return this.select.find("option")},_preExtension:function(){var c="";~this.element[0].className.indexOf("ui-btn-left")&&(c=" ui-btn-left");~this.element[0].className.indexOf("ui-btn-right")&& +(c=" ui-btn-right");this.select=this.element.wrap("<div class='ui-select"+c+"'>");this.selectID=this.select.attr("id");this.label=a("label[for='"+this.selectID+"']").addClass("ui-select");this.isMultiple=this.select[0].multiple;if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.select,"c")},_create:function(){this._preExtension();this._trigger("beforeCreate");this.button=this._button();var c=this,b=this.options,e=this.button.text(a(this.select[0].options.item(this.select[0].selectedIndex== +-1?0:this.select[0].selectedIndex)).text()).insertBefore(this.select).buttonMarkup({theme:b.theme,icon:b.icon,iconpos:b.iconpos,inline:b.inline,corners:b.corners,shadow:b.shadow,iconshadow:b.iconshadow,mini:b.mini});b.nativeMenu&&s.opera&&s.opera.version&&this.select.addClass("ui-select-nativeonly");if(this.isMultiple)this.buttonCount=a("<span>").addClass("ui-li-count ui-btn-up-c ui-btn-corner-all").hide().appendTo(e.addClass("ui-li-has-count"));(b.disabled||this.element.attr("disabled"))&&this.disable(); +this.select.change(function(){c.refresh()});this.build()},build:function(){var c=this;this.select.appendTo(c.button).bind("vmousedown",function(){c.button.addClass(a.mobile.activeBtnClass)}).bind("focus",function(){c.button.addClass(a.mobile.focusClass)}).bind("blur",function(){c.button.removeClass(a.mobile.focusClass)}).bind("focus vmouseover",function(){c.button.trigger("vmouseover")}).bind("vmousemove",function(){c.button.removeClass(a.mobile.activeBtnClass)}).bind("change blur vmouseout",function(){c.button.trigger("vmouseout").removeClass(a.mobile.activeBtnClass)}).bind("change blur", +function(){c.button.removeClass("ui-btn-down-"+c.options.theme)});c.button.bind("vmousedown",function(){c.options.preventFocusZoom&&a.mobile.zoom.disable(true)}).bind("mouseup",function(){c.options.preventFocusZoom&&a.mobile.zoom.enable(true)})},selected:function(){return this._selectOptions().filter(":selected")},selectedIndices:function(){var a=this;return this.selected().map(function(){return a._selectOptions().index(this)}).get()},setButtonText:function(){var c=this,b=this.selected();this.button.find(".ui-btn-text").text(function(){return!c.isMultiple? +b.text():b.length?b.map(function(){return a(this).text()}).get().join(", "):c.placeholder})},setButtonCount:function(){var a=this.selected();this.isMultiple&&this.buttonCount[a.length>1?"show":"hide"]().text(a.length)},refresh:function(){this.setButtonText();this.setButtonCount()},open:a.noop,close:a.noop,disable:function(){this._setDisabled(true);this.button.addClass("ui-disabled")},enable:function(){this._setDisabled(false);this.button.removeClass("ui-disabled")}});a(k).bind("pagecreate create", +function(c){a.mobile.selectmenu.prototype.enhanceWithin(c.target,true)})})(jQuery);(function(a){var c=function(b){var c=b.selectID,f=b.label,d=b.select.closest(".ui-page"),g=a("<div>",{"class":"ui-selectmenu-screen ui-screen-hidden"}).appendTo(d),h=b._selectOptions(),j=b.isMultiple=b.select[0].multiple,o=c+"-button",m=c+"-menu",p=a("<div data-"+a.mobile.ns+"role='dialog' data-"+a.mobile.ns+"theme='"+b.options.theme+"' data-"+a.mobile.ns+"overlay-theme='"+b.options.overlayTheme+"'><div data-"+a.mobile.ns+ +"role='header'><div class='ui-title'>"+f.getEncodedText()+"</div></div><div data-"+a.mobile.ns+"role='content'></div></div>"),l=a("<div>",{"class":"ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-"+b.options.overlayTheme+" "+a.mobile.defaultDialogTransition}).insertAfter(g),r=a("<ul>",{"class":"ui-selectmenu-list",id:m,role:"listbox","aria-labelledby":o}).attr("data-"+a.mobile.ns+"theme",b.options.theme).appendTo(l),n=a("<div>",{"class":"ui-header ui-bar-"+b.options.theme}).prependTo(l), +q=a("<h1>",{"class":"ui-title"}).appendTo(n),t;b.isMultiple&&(t=a("<a>",{text:b.options.closeText,href:"#","class":"ui-btn-left"}).attr("data-"+a.mobile.ns+"iconpos","notext").attr("data-"+a.mobile.ns+"icon","delete").appendTo(n).buttonMarkup());a.extend(b,{select:b.select,selectID:c,buttonId:o,menuId:m,thisPage:d,menuPage:p,label:f,screen:g,selectOptions:h,isMultiple:j,theme:b.options.theme,listbox:l,list:r,header:n,headerTitle:q,headerClose:t,menuPageContent:void 0,menuPageClose:void 0,placeholder:"", +build:function(){var c=this;c.refresh();c.select.attr("tabindex","-1").focus(function(){a(this).blur();c.button.focus()});c.button.bind("vclick keydown",function(b){if(b.type=="vclick"||b.keyCode&&(b.keyCode===a.mobile.keyCode.ENTER||b.keyCode===a.mobile.keyCode.SPACE))c.open(),b.preventDefault()});c.list.attr("role","listbox").bind("focusin",function(b){a(b.target).attr("tabindex","0").trigger("vmouseover")}).bind("focusout",function(b){a(b.target).attr("tabindex","-1").trigger("vmouseout")}).delegate("li:not(.ui-disabled, .ui-li-divider)", +"click",function(b){var d=c.select[0].selectedIndex,e=c.list.find("li:not(.ui-li-divider)").index(this),f=c._selectOptions().eq(e)[0];f.selected=c.isMultiple?!f.selected:true;c.isMultiple&&a(this).find(".ui-icon").toggleClass("ui-icon-checkbox-on",f.selected).toggleClass("ui-icon-checkbox-off",!f.selected);(c.isMultiple||d!==e)&&c.select.trigger("change");c.isMultiple||c.close();b.preventDefault()}).keydown(function(c){var d=a(c.target),e=d.closest("li");switch(c.keyCode){case 38:return c=e.prev().not(".ui-selectmenu-placeholder"), +c.is(".ui-li-divider")&&(c=c.prev()),c.length&&(d.blur().attr("tabindex","-1"),c.addClass("ui-btn-down-"+b.options.theme).find("a").first().focus()),false;case 40:return c=e.next(),c.is(".ui-li-divider")&&(c=c.next()),c.length&&(d.blur().attr("tabindex","-1"),c.addClass("ui-btn-down-"+b.options.theme).find("a").first().focus()),false;case 13:case 32:return d.trigger("click"),false}});c.menuPage.bind("pagehide",function(){c.list.appendTo(c.listbox);c._focusButton();a.mobile._bindPageRemove.call(c.thisPage)}); +c.screen.bind("vclick",function(){c.close()});c.isMultiple&&c.headerClose.click(function(){if(c.menuType=="overlay")return c.close(),false});c.thisPage.addDependents(this.menuPage)},_isRebuildRequired:function(){var a=this.list.find("li");return this._selectOptions().text()!==a.text()},refresh:function(b){var c=this;this._selectOptions();this.selected();var d=this.selectedIndices();(b||this._isRebuildRequired())&&c._buildList();c.setButtonText();c.setButtonCount();c.list.find("li:not(.ui-li-divider)").removeClass(a.mobile.activeBtnClass).attr("aria-selected", +false).each(function(b){a.inArray(b,d)>-1&&(b=a(this),b.attr("aria-selected",true),c.isMultiple?b.find(".ui-icon").removeClass("ui-icon-checkbox-off").addClass("ui-icon-checkbox-on"):b.is(".ui-selectmenu-placeholder")?b.next().addClass(a.mobile.activeBtnClass):b.addClass(a.mobile.activeBtnClass))})},close:function(){if(!this.options.disabled&&this.isOpen)this.menuType=="page"?s.history.back():(this.screen.addClass("ui-screen-hidden"),this.listbox.addClass("ui-selectmenu-hidden").removeAttr("style").removeClass("in"), +this.list.appendTo(this.listbox),this._focusButton()),this.isOpen=false},open:function(){function b(){c.list.find("."+a.mobile.activeBtnClass+" a").focus()}if(!this.options.disabled){var c=this,d=a(s),e=c.list.parent(),f=e.outerHeight(),e=e.outerWidth();a(".ui-page-active");var g=d.scrollTop(),j=c.button.offset().top,h=d.height(),d=d.width();c.button.addClass(a.mobile.activeBtnClass);setTimeout(function(){c.button.removeClass(a.mobile.activeBtnClass)},300);if(f>h-80||!a.support.scrollTop){c.menuPage.appendTo(a.mobile.pageContainer).page(); +c.menuPageContent=p.find(".ui-content");c.menuPageClose=p.find(".ui-header a");c.thisPage.unbind("pagehide.remove");if(g==0&&j>h)c.thisPage.one("pagehide",function(){a(this).jqmData("lastScroll",j)});c.menuPage.one("pageshow",function(){b();c.isOpen=true});c.menuType="page";c.menuPageContent.append(c.list);c.menuPage.find("div .ui-title").text(c.label.text());a.mobile.changePage(c.menuPage,{transition:a.mobile.defaultDialogTransition})}else{c.menuType="overlay";c.screen.height(a(k).height()).removeClass("ui-screen-hidden"); +var l=j-g,m=g+h-j,n=f/2,o=parseFloat(c.list.parent().css("max-width")),f=l>f/2&&m>f/2?j+c.button.outerHeight()/2-n:l>m?g+h-f-30:g+30;e<o?g=(d-e)/2:(g=c.button.offset().left+c.button.outerWidth()/2-e/2,g<30?g=30:g+e>d&&(g=d-e-30));c.listbox.append(c.list).removeClass("ui-selectmenu-hidden").css({top:f,left:g}).addClass("in");b();c.isOpen=true}}},_buildList:function(){var b=this.options,c=this.placeholder,d=true,e=this.isMultiple?"checkbox-off":"false";this.list.empty().filter(".ui-listview").listview("destroy"); +var f=this.select.find("option"),g=f.length,j=this.select[0],h="data-"+a.mobile.ns,l=h+"option-index",m=h+"icon";h+="role";for(var n=k.createDocumentFragment(),o,p=0;p<g;p++){var r=f[p],q=a(r),s=r.parentNode,t=q.text(),D=k.createElement("a"),J=[];D.setAttribute("href","#");D.appendChild(k.createTextNode(t));s!==j&&s.nodeName.toLowerCase()==="optgroup"&&(s=s.getAttribute("label"),s!=o&&(o=k.createElement("li"),o.setAttribute(h,"list-divider"),o.setAttribute("role","option"),o.setAttribute("tabindex", +"-1"),o.appendChild(k.createTextNode(s)),n.appendChild(o),o=s));if(d&&(!r.getAttribute("value")||t.length==0||q.jqmData("placeholder")))if(d=false,b.hidePlaceholderMenuItems&&J.push("ui-selectmenu-placeholder"),!c)c=this.placeholder=t;q=k.createElement("li");r.disabled&&(J.push("ui-disabled"),q.setAttribute("aria-disabled",true));q.setAttribute(l,p);q.setAttribute(m,e);q.className=J.join(" ");q.setAttribute("role","option");D.setAttribute("tabindex","-1");q.appendChild(D);n.appendChild(q)}this.list[0].appendChild(n); +!this.isMultiple&&!c.length?this.header.hide():this.headerTitle.text(this.placeholder);this.list.listview()},_button:function(){return a("<a>",{href:"#",role:"button",id:this.buttonId,"aria-haspopup":"true","aria-owns":this.menuId})}})};a(k).bind("selectmenubeforecreate",function(b){b=a(b.target).data("selectmenu");b.options.nativeMenu||c(b)})})(jQuery);(function(a){a.widget("mobile.fixedtoolbar",a.mobile.widget,{options:{visibleOnPageShow:true,disablePageZoom:true,transition:"slide",fullscreen:false, +tapToggle:true,tapToggleBlacklist:"a, input, select, textarea, .ui-header-fixed, .ui-footer-fixed",hideDuringFocus:"input, textarea, select",updatePagePadding:true,trackPersistentToolbars:true,supportBlacklist:function(){var a=s,b=navigator.userAgent,e=navigator.platform,f=b.match(/AppleWebKit\/([0-9]+)/),f=!!f&&f[1],d=b.match(/Fennec\/([0-9]+)/),d=!!d&&d[1],g=b.match(/Opera Mobi\/([0-9]+)/),h=!!g&&g[1];return(e.indexOf("iPhone")>-1||e.indexOf("iPad")>-1||e.indexOf("iPod")>-1)&&f&&f<534||a.operamini&& +{}.toString.call(a.operamini)==="[object OperaMini]"||g&&h<7458||b.indexOf("Android")>-1&&f&&f<533||d&&d<6||"palmGetResource"in s&&f&&f<534||b.indexOf("MeeGo")>-1&&b.indexOf("NokiaBrowser/8.5.0")>-1?true:false},initSelector:":jqmData(position='fixed')"},_create:function(){var a=this.options,b=this.element,e=b.is(":jqmData(role='header')")?"header":"footer",f=b.closest(".ui-page");a.supportBlacklist()?this.destroy():(b.addClass("ui-"+e+"-fixed"),a.fullscreen?(b.addClass("ui-"+e+"-fullscreen"),f.addClass("ui-page-"+ +e+"-fullscreen")):f.addClass("ui-page-"+e+"-fixed"),this._addTransitionClass(),this._bindPageEvents(),this._bindToggleHandlers())},_addTransitionClass:function(){var a=this.options.transition;a&&a!=="none"&&(a==="slide"&&(a=this.element.is(".ui-header")?"slidedown":"slideup"),this.element.addClass(a))},_bindPageEvents:function(){var c=this,b=c.options;c.element.closest(".ui-page").bind("pagebeforeshow",function(){b.disablePageZoom&&a.mobile.zoom.disable(true);b.visibleOnPageShow||c.hide(true)}).bind("webkitAnimationStart animationstart updatelayout", +function(){b.updatePagePadding&&c.updatePagePadding()}).bind("pageshow",function(){c.updatePagePadding();b.updatePagePadding&&a(s).bind("throttledresize."+c.widgetName,function(){c.updatePagePadding()})}).bind("pagebeforehide",function(e,f){b.disablePageZoom&&a.mobile.zoom.enable(true);b.updatePagePadding&&a(s).unbind("throttledresize."+c.widgetName);if(b.trackPersistentToolbars){var d=a(".ui-footer-fixed:jqmData(id)",this),g=a(".ui-header-fixed:jqmData(id)",this),h=d.length&&f.nextPage&&a(".ui-footer-fixed:jqmData(id='"+ +d.jqmData("id")+"')",f.nextPage),j=g.length&&f.nextPage&&a(".ui-header-fixed:jqmData(id='"+g.jqmData("id")+"')",f.nextPage),h=h||a();if(h.length||j.length)h.add(j).appendTo(a.mobile.pageContainer),f.nextPage.one("pageshow",function(){h.add(j).appendTo(this)})}})},_visible:true,updatePagePadding:function(){var a=this.element,b=a.is(".ui-header");this.options.fullscreen||a.closest(".ui-page").css("padding-"+(b?"top":"bottom"),a.outerHeight())},_useTransition:function(c){var b=this.element,e=a(s).scrollTop(), +f=b.height(),d=b.closest(".ui-page").height(),g=a.mobile.getScreenHeight(),b=b.is(":jqmData(role='header')")?"header":"footer";return!c&&(this.options.transition&&this.options.transition!=="none"&&(b==="header"&&!this.options.fullscreen&&e>f||b==="footer"&&!this.options.fullscreen&&e+g<d-f)||this.options.fullscreen)},show:function(a){var b=this.element;this._useTransition(a)?b.removeClass("out ui-fixed-hidden").addClass("in"):b.removeClass("ui-fixed-hidden");this._visible=true},hide:function(a){var b= +this.element,e="out"+(this.options.transition==="slide"?" reverse":"");this._useTransition(a)?b.addClass(e).removeClass("in").animationComplete(function(){b.addClass("ui-fixed-hidden").removeClass(e)}):b.addClass("ui-fixed-hidden").removeClass(e);this._visible=false},toggle:function(){this[this._visible?"hide":"show"]()},_bindToggleHandlers:function(){var c=this,b=c.options;c.element.closest(".ui-page").bind("vclick",function(e){b.tapToggle&&!a(e.target).closest(b.tapToggleBlacklist).length&&c.toggle()}).bind("focusin focusout", +function(e){if(screen.width<500&&a(e.target).is(b.hideDuringFocus)&&!a(e.target).closest(".ui-header-fixed, .ui-footer-fixed").length)c[e.type==="focusin"&&c._visible?"hide":"show"]()})},destroy:function(){this.element.removeClass("ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden");this.element.closest(".ui-page").removeClass("ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen")}});a(k).bind("pagecreate create", +function(c){a(c.target).jqmData("fullscreen")&&a(a.mobile.fixedtoolbar.prototype.options.initSelector,c.target).not(":jqmData(fullscreen)").jqmData("fullscreen",true);a.mobile.fixedtoolbar.prototype.enhanceWithin(c.target)})})(jQuery);(function(a,c){if(/iPhone|iPad|iPod/.test(navigator.platform)&&navigator.userAgent.indexOf("AppleWebKit")>-1){var b=a.mobile.zoom,e,f,d,g,h;a(c).bind("orientationchange.iosorientationfix",b.enable).bind("devicemotion.iosorientationfix",function(a){e=a.originalEvent; +h=e.accelerationIncludingGravity;f=Math.abs(h.x);d=Math.abs(h.y);g=Math.abs(h.z);!c.orientation&&(f>7||(g>6&&d<8||g<8&&d>6)&&f>5)?b.enabled&&b.disable():b.enabled||b.enable()})}})(jQuery,this);(function(a,c){function b(){var b=a("."+a.mobile.activeBtnClass).first();h.css({top:a.support.scrollTop&&g.scrollTop()+g.height()/2||b.length&&b.offset().top||100})}function e(){var c=h.offset(),d=g.scrollTop(),f=a.mobile.getScreenHeight();if(c.top<d||c.top-d>f)h.addClass("ui-loader-fakefix"),b(),g.unbind("scroll", +e).bind("scroll",b)}function f(){d.removeClass("ui-mobile-rendering")}var d=a("html");a("head");var g=a(c);a(c.document).trigger("mobileinit");if(a.mobile.gradeA()){if(a.mobile.ajaxBlacklist)a.mobile.ajaxEnabled=false;d.addClass("ui-mobile ui-mobile-rendering");setTimeout(f,5E3);var h=a("<div class='ui-loader'><span class='ui-icon ui-icon-loading'></span><h1></h1></div>");a.extend(a.mobile,{showPageLoadingMsg:function(b,c,f){d.addClass("ui-loading");if(a.mobile.loadingMessage){var k=f||a.mobile.loadingMessageTextVisible; +b=b||a.mobile.loadingMessageTheme;h.attr("class","ui-loader ui-corner-all ui-body-"+(b||"a")+" ui-loader-"+(k?"verbose":"default")+(f?" ui-loader-textonly":"")).find("h1").text(c||a.mobile.loadingMessage).end().appendTo(a.mobile.pageContainer);e();g.bind("scroll",e)}},hidePageLoadingMsg:function(){d.removeClass("ui-loading");a.mobile.loadingMessage&&h.removeClass("ui-loader-fakefix");a(c).unbind("scroll",b);a(c).unbind("scroll",e)},initializePage:function(){var b=a(":jqmData(role='page'), :jqmData(role='dialog')"); +b.length||(b=a("body").wrapInner("<div data-"+a.mobile.ns+"role='page'></div>").children(0));b.each(function(){var b=a(this);b.jqmData("url")||b.attr("data-"+a.mobile.ns+"url",b.attr("id")||location.pathname+location.search)});a.mobile.firstPage=b.first();a.mobile.pageContainer=b.first().parent().addClass("ui-mobile-viewport");g.trigger("pagecontainercreate");a.mobile.showPageLoadingMsg();f();!a.mobile.hashListeningEnabled||!a.mobile.path.stripHash(location.hash)?a.mobile.changePage(a.mobile.firstPage, +{transition:"none",reverse:true,changeHash:false,fromHashChange:true}):g.trigger("hashchange",[true])}});a.mobile._registerInternalEvents();a(function(){c.scrollTo(0,1);a.mobile.defaultHomeScroll=!a.support.scrollTop||a(c).scrollTop()===1?0:1;a.fn.controlgroup&&a(k).bind("pagecreate create",function(b){a(":jqmData(role='controlgroup')",b.target).jqmEnhanceable().controlgroup({excludeInvisible:false})});a.mobile.autoInitializePage&&a.mobile.initializePage();g.load(a.mobile.silentScroll)})}})(jQuery, +this)});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery.mobile.simpledialog.min.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,8 @@ +/* + * jQuery Mobile Framework : plugin to provide a simple Dialog widget. + * Copyright (c) JTSage + * CC 3.0 Attribution. May be relicensed without permission/notifcation. + * https://github.com/jtsage/jquery-mobile-simpledialog + */ + +.ui-simpledialog-header h4{margin-top:5px;margin-bottom:5px;text-align:center}.ui-simpledialog-container{border:5px solid #111!important;width:85%;max-width:500px}.ui-simpledialog-screen{position:absolute;top:0;left:0;width:100%;height:100%}.ui-simpledialog-hidden{display:none}.ui-simpledialog-input{width:85%!important;display:block!important;margin-left:auto;margin-right:auto}.ui-simpledialog-screen-modal{background-color:black;-moz-opacity:.8;opacity:.80;filter:alpha(opacity=80)}.ui-simpledialog-subtitle{text-align:center}.ui-simpledialog-controls .buttons-separator{min-height:.6em}.ui-simpledialog-controls .button-hidden{display:none}.ui-dialog .ui-simpledialog-container{border:none!important}.ui-dialog-simpledialog .ui-content{padding:5px!important} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery.mobile.simpledialog2.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,382 @@ +/* + * jQuery Mobile Framework : plugin to provide a dialogs Widget. ver2 + * Copyright (c) JTSage + * CC 3.0 Attribution. May be relicensed without permission/notifcation. + * https://github.com/jtsage/jquery-mobile-simpledialog + * + * Modifications by Sebastien Jodogne + */ + +(function($, undefined ) { + $.widget( "mobile.simpledialog2", $.mobile.widget, { + options: { + version: '1.0.1-2012061300', // jQueryMobile-YrMoDaySerial + mode: 'blank', // or 'button' + themeDialog: 'b', + themeInput: false, + themeButtonDefault: false, + themeHeader: 'a', + + fullScreen: false, + fullScreenForce: false, + dialogAllow: false, + dialogForce: false, + + headerText: false, + headerClose: false, + buttonPrompt: false, + buttonInput: false, + buttonInputDefault: false, + buttonPassword: false, + blankContent: false, + blankContentAdopt: false, + + resizeListener: true, + safeNuke: true, + forceInput: true, + showModal: true, + animate: true, + transition: 'pop', + clickEvent: 'click', + zindex: '500', + width: '280px', + left: false, + top: false, + + callbackOpen: false, + callbackOpenArgs: [], + callbackClose: false, + callbackCloseArgs: [] + }, + _eventHandler: function(e,p) { + // Handle the triggers + var self = e.data.widget, + o = e.data.widget.options; + + if ( ! e.isPropagationStopped() ) { + switch (p.method) { + case 'close': + self.close(); + break; + case 'html': + self.updateBlank(p.source); + break; + } + } + }, + _create: function () { + var self = this, + o = $.extend(this.options, this.element.jqmData('options')), + initDate = new Date(), + content = $("<div class='ui-simpledialog-container ui-overlay-shadow ui-corner-all ui-simpledialog-hidden " + + ((o.animate === true) ? o.transition : '') + " ui-body-" + o.themeDialog + "'></div>"); + + if ( o.themeButtonDefault === false ) { o.themeButtonDefault = o.themeDialog; } + if ( o.themeInput === false ) { o.themeInput = o.themeDialog; } + $.mobile.sdCurrentDialog = self; + if ( typeof $.mobile.sdLastInput !== 'undefined' ) { delete $.mobile.sdLastInput; } + self.internalID = initDate.getTime(); + self.displayAnchor = $.mobile.activePage.children('.ui-content').first(); + if ( self.displayAnchor.length === 0 ) { self.displayAnchor = $.mobile.activePage; } + + self.dialogPage = $("<div data-role='dialog' data-theme='" + o.themeDialog + "'><div data-role='header'></div><div data-role='content'></div></div>"); + self.sdAllContent = self.dialogPage.find('[data-role=content]'); + + content.appendTo(self.sdAllContent); + + self.sdIntContent = self.sdAllContent.find('.ui-simpledialog-container'); + self.sdIntContent.css('width', o.width); + + if ( o.headerText !== false || o.headerClose !== false ) { + self.sdHeader = $('<div style="margin-bottom: 4px;" class="ui-header ui-bar-'+o.themeHeader+'"></div>'); + if ( o.headerClose === true ) { + $("<a class='ui-btn-left' rel='close' href='#'>Close</a>").appendTo(self.sdHeader).buttonMarkup({ theme : o.themeHeader, icon : 'delete', iconpos: 'notext', corners: true, shadow : true }); + } + $('<h1 class="ui-title">'+((o.headerText !== false)?o.headerText:'')+'</h1>').appendTo(self.sdHeader); + self.sdHeader.appendTo(self.sdIntContent); + } + + if ( o.mode === 'blank' ) { + if ( o.blankContent === true ) { + if ( o.blankContentAdopt === true ) { + o.blankContent = self.element.children(); + } else { + o.blankContent = self.element.html(); + } + } + $(o.blankContent).appendTo(self.sdIntContent); + } else if ( o.mode === 'button' ) { + self._makeButtons().appendTo(self.sdIntContent); + } + + self.sdIntContent.appendTo(self.displayAnchor.parent()); + + self.dialogPage.appendTo( $.mobile.pageContainer ) + .page().css('minHeight', '0px').css('zIndex', o.zindex); + + if ( o.animate === true ) { self.dialogPage.addClass(o.transition); } + + self.screen = $("<div>", {'class':'ui-simpledialog-screen ui-simpledialog-hidden'}) + .css('z-index', (o.zindex-1)) + .appendTo(self.displayAnchor.parent()) + .bind(o.clickEvent, function(event){ + if ( !o.forceInput ) { + self.close(); + } + event.preventDefault(); + }); + + if ( o.showModal ) { self.screen.addClass('ui-simpledialog-screen-modal'); } + + $(document).bind('simpledialog.'+self.internalID, {widget:self}, function(e,p) { self._eventHandler(e,p); }); + }, + _makeButtons: function () { + var self = this, + o = self.options, + buttonHTML = $('<div></div>'), + pickerInput = $("<div class='ui-simpledialog-controls'><input class='ui-simpledialog-input ui-input-text ui-shadow-inset ui-corner-all ui-body-"+o.themeInput+"' type='"+((o.buttonPassword===true)?"password":"text")+"' value='"+((o.buttonInputDefault!==false)?o.buttonInputDefault.replace( '"', """ ).replace( "'", "'" ):"")+"' name='pickin' /></div>"), + pickerChoice = $("<div>", { "class":'ui-simpledialog-controls' }); + + + if ( o.buttonPrompt !== false ) { + self.buttonPromptText = $("<p class='ui-simpledialog-subtitle'>"+o.buttonPrompt+"</p>").appendTo(buttonHTML); + } + + if ( o.buttonInput !== false ) { + $.mobile.sdLastInput = ""; + pickerInput.appendTo(buttonHTML); + pickerInput.find('input').bind('change', function () { + $.mobile.sdLastInput = pickerInput.find('input').first().val(); + self.thisInput = pickerInput.find('input').first().val(); + }); + } + + pickerChoice.appendTo(buttonHTML); + + self.butObj = []; + + $.each(o.buttons, function(name, props) { + props = $.isFunction( props ) ? { click: props } : props; + props = $.extend({ + text : name, + id : name + self.internalID, + theme : o.themeButtonDefault, + icon : 'check', + iconpos: 'left', + corners: 'true', + shadow : 'true', + args : [], + close : true + }, props); + + self.butObj.push($("<a href='#'>"+name+"</a>") + .appendTo(pickerChoice) + .attr('id', props.id) + .buttonMarkup({ + theme : props.theme, + icon : props.icon, + iconpos: props.iconpos, + corners: props.corners, + shadow : props.shadow + }).unbind("vclick click") + .bind(o.clickEvent, function() { + if ( o.buttonInput ) { self.sdIntContent.find('input [name=pickin]').trigger('change'); } + var returnValue = props.click.apply(self, $.merge(arguments, props.args)); + if ( returnValue !== false && props.close === true ) { + self.close(); + } + }) + ); + }); + + return buttonHTML; + }, + _getCoords: function(widget) { + var self = widget, + docWinWidth = $.mobile.activePage.width(), + docWinHighOff = $(window).scrollTop(), + docWinHigh = $(window).height(), + diaWinWidth = widget.sdIntContent.innerWidth(), + diaWinHigh = widget.sdIntContent.outerHeight(), + + coords = { + 'high' : $(window).height(), + 'width' : $.mobile.activePage.width(), + 'fullTop' : $(window).scrollTop(), + 'fullLeft': $(window).scrollLeft(), + 'winTop' : docWinHighOff + ((widget.options.top !== false) ? widget.options.top : (( docWinHigh / 2 ) - ( diaWinHigh / 2 ) )), + 'winLeft' : ((widget.options.left !== false) ? widget.options.left : (( docWinWidth / 2 ) - ( diaWinWidth / 2 ) )) + }; + + if ( coords.winTop < 45 ) { coords.winTop = 45; } + + return coords; + }, + _orientChange: function(e) { + var self = e.data.widget, + o = e.data.widget.options, + coords = e.data.widget._getCoords(e.data.widget); + + e.stopPropagation(); + + if ( self.isDialog === true ) { + return true; + } else { + if ( o.fullScreen === true && ( coords.width < 400 || o.fullScreenForce === true ) ) { + self.sdIntContent.css({'border': 'none', 'position': 'absolute', 'top': coords.fullTop, 'left': coords.fullLeft, 'height': coords.high, 'width': coords.width, 'maxWidth': coords.width }).removeClass('ui-simpledialog-hidden'); + } else { + self.sdIntContent.css({'position': 'absolute', 'top': coords.winTop, 'left': coords.winLeft}).removeClass('ui-simpledialog-hidden'); + } + } + }, + repos: function() { + var bsEvent = { data: {widget:this}, stopPropagation: function () { return true; }}; + this._orientChange(bsEvent); + }, + open: function() { + var self = this, + o = this.options, + coords = this._getCoords(this); + + self.sdAllContent.find('.ui-btn-active').removeClass('ui-btn-active'); + self.sdIntContent.delegate('[rel=close]', o.clickEvent, function (e) { e.preventDefault(); self.close(); }); + + if ( ( o.dialogAllow === true && coords.width < 400 ) || o.dialogForce ) { + self.isDialog = true; + + if ( o.mode === 'blank' ) { // Custom selects do not play well with dialog mode - so, we turn them off. + self.sdIntContent.find('select').each(function () { + $(this).jqmData('nativeMenu', true); + }); + } + + self.displayAnchor.parent().unbind("pagehide.remove"); + self.sdAllContent.append(self.sdIntContent); + self.sdAllContent.trigger('create'); + if ( o.headerText !== false ) { + self.sdHeader.find('h1').appendTo(self.dialogPage.find('[data-role=header]')); + self.sdIntContent.find('.ui-header').empty().removeClass(); + } + if ( o.headerClose === true ) { + self.dialogPage.find('.ui-header a').bind('click', function () { + setTimeout("$.mobile.sdCurrentDialog.destroy();", 1000); + }); + } else { + self.dialogPage.find('.ui-header a').remove(); + } + + self.sdIntContent.removeClass().css({'top': 'auto', 'width': 'auto', 'left': 'auto', 'marginLeft': 'auto', 'marginRight': 'auto', 'zIndex': o.zindex}); + $.mobile.changePage(self.dialogPage, {'transition': (o.animate === true) ? o.transition : 'none'}); + } else { + self.isDialog = false; + self.selects = []; + + if ( o.fullScreen === false ) { + if ( o.showModal === true && o.animate === true ) { self.screen.fadeIn('slow'); } + else { self.screen.removeClass('ui-simpledialog-hidden'); } + } + + self.sdIntContent.addClass('ui-overlay-shadow in').css('zIndex', o.zindex).trigger('create'); + + if ( o.fullScreen === true && ( coords.width < 400 || o.fullScreenForce === true ) ) { + self.sdIntContent.removeClass('ui-simpledialog-container').css({'border': 'none', 'position': 'absolute', 'top': coords.fullTop, 'left': coords.fullLeft, 'height': coords.high, 'width': coords.width, 'maxWidth': coords.width }).removeClass('ui-simpledialog-hidden'); + } else { + self.sdIntContent.css({'position': 'absolute', 'top': coords.winTop, 'left': coords.winLeft}).removeClass('ui-simpledialog-hidden'); + } + + $(document).bind('orientationchange.simpledialog', {widget:self}, function(e) { self._orientChange(e); }); + if ( o.resizeListener === true ) { + $(window).bind('resize.simpledialog', {widget:self}, function (e) { self._orientChange(e); }); + } + } + if ( $.isFunction(o.callbackOpen) ) { + o.callbackOpen.apply(self, o.callbackOpenArgs); + } + }, + close: function() { + var self = this, o = this.options, retty; + + if ( $.isFunction(self.options.callbackClose) ) { + retty = self.options.callbackClose.apply(self, self.options.callbackCloseArgs); + if ( retty === false ) { return false; } + } + + if ( self.isDialog ) { + $(self.dialogPage).dialog('close'); + self.sdIntContent.addClass('ui-simpledialog-hidden'); + self.sdIntContent.appendTo(self.displayAnchor.parent()); + if ( $.mobile.activePage.jqmData("page").options.domCache != true && $.mobile.activePage.is(":jqmData(external-page='true')") ) { + $.mobile.activePage.bind("pagehide.remove", function () { + $(this).remove(); + }); + } + } else { + if ( self.options.showModal === true && self.options.animate === true ) { + self.screen.fadeOut('slow'); + } else { + self.screen.addClass('ui-simpledialog-hidden'); + } + self.sdIntContent.addClass('ui-simpledialog-hidden').removeClass('in'); + $(document).unbind('orientationchange.simpledialog'); + if ( self.options.resizeListener === true ) { $(window).unbind('resize.simpledialog'); } + } + + if ( o.mode === 'blank' && o.blankContent !== false && o.blankContentAdopt === true ) { + self.element.append(o.blankContent); + o.blankContent = true; + } + + if ( self.isDialog === true || self.options.animate === true ) { + setTimeout(function(that) { return function () { that.destroy(); };}(self), 1000); + } else { + self.destroy(); + } + }, + destroy: function() { + var self = this, + ele = self.element; + + if ( self.options.mode === 'blank' ) { + $.mobile.sdCurrentDialog.sdIntContent.find('select').each(function() { + if ( $(this).data('nativeMenu') == false ) { + $(this).data('selectmenu').menuPage.remove(); + $(this).data('selectmenu').screen.remove(); + $(this).data('selectmenu').listbox.remove(); + } + }); + } + + $(self.sdIntContent).remove(); + $(self.dialogPage).remove(); + $(self.screen).remove(); + $(document).unbind('simpledialog.'+self.internalID); + delete $.mobile.sdCurrentDialog; + $.Widget.prototype.destroy.call(self); + if ( self.options.safeNuke === true && $(ele).parents().length === 0 && $(ele).contents().length === 0 ) { + ele.remove(); + } + }, + updateBlank: function (newHTML) { + var self = this, + o = this.options; + + self.sdIntContent.empty(); + + if ( o.headerText !== false || o.headerClose !== false ) { + self.sdHeader = $('<div class="ui-header ui-bar-'+o.themeHeader+'"></div>'); + if ( o.headerClose === true ) { + $("<a class='ui-btn-left' rel='close' href='#'>Close</a>").appendTo(self.sdHeader).buttonMarkup({ theme : o.themeHeader, icon : 'delete', iconpos: 'notext', corners: true, shadow : true }); + } + $('<h1 class="ui-title">'+((o.headerText !== false)?o.headerText:'')+'</h1>').appendTo(self.sdHeader); + self.sdHeader.appendTo(self.sdIntContent); + } + + $(newHTML).appendTo(self.sdIntContent); + self.sdIntContent.trigger('create'); + $(document).trigger('orientationchange.simpledialog'); + }, + _init: function() { + this.open(); + } + }); +})( jQuery );
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery.mobile.structure-1.1.0.min.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,2 @@ +/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ +.ui-mobile,.ui-mobile body{height:99.9%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border-width:0}.ui-mobile-viewport{margin:0;overflow-x:visible;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}body.ui-mobile-viewport,div.ui-mobile-viewport{overflow-x:hidden}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-mobile .ui-page-active{display:block;overflow:visible}.ui-page{outline:0}@media screen and (orientation:portrait){.ui-mobile,.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile,.ui-mobile .ui-page{min-height:300px}}.ui-loading .ui-loader{display:block}.ui-loader{display:none;z-index:9999999;position:fixed;top:50%;box-shadow:0 1px 1px -1px #fff;left:50%;border:0}.ui-loader-default{background:0;opacity:.18;width:46px;height:46px;margin-left:-23px;margin-top:-23px}.ui-loader-verbose{width:200px;opacity:.88;height:auto;margin-left:-110px;margin-top:-43px;padding:10px}.ui-loader-default h1{font-size:0;width:0;height:0;overflow:hidden}.ui-loader-verbose h1{font-size:16px;margin:0;text-align:center}.ui-loader .ui-icon{background-color:#000;display:block;margin:0;width:44px;height:44px;padding:1px;-webkit-border-radius:36px;-moz-border-radius:36px;border-radius:36px}.ui-loader-verbose .ui-icon{margin:0 auto 10px;opacity:.75}.ui-loader-textonly{padding:15px;margin-left:-115px}.ui-loader-textonly .ui-icon{display:none}.ui-loader-fakefix{position:absolute}.ui-mobile-rendering>*{visibility:hidden}.ui-bar,.ui-body{position:relative;padding:.4em 15px;overflow:hidden;display:block;clear:both}.ui-bar{font-size:16px;margin:0}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:16px;display:inline-block}.ui-header,.ui-footer{position:relative;border-left-width:0;border-right-width:0}.ui-header .ui-btn-left,.ui-header .ui-btn-right,.ui-footer .ui-btn-left,.ui-footer .ui-btn-right{position:absolute;top:3px}.ui-header .ui-btn-left,.ui-footer .ui-btn-left{left:5px}.ui-header .ui-btn-right,.ui-footer .ui-btn-right{right:5px}.ui-footer .ui-btn-icon-notext,.ui-header .ui-btn-icon-notext{top:6px}.ui-header .ui-title,.ui-footer .ui-title{min-height:1.1em;text-align:center;font-size:16px;display:block;margin:.6em 30% .8em;padding:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:.6em 15px .8em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:15px}.ui-icon{width:18px;height:18px}.ui-nojs{position:absolute;left:-9999px}.ui-hide-label label,.ui-hidden-accessible{position:absolute!important;left:-9999px;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden}.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.out{-webkit-animation-timing-function:ease-in;-webkit-animation-duration:225ms;-moz-animation-timing-function:ease-in;-moz-animation-duration:225}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}@-moz-keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{opacity:0;-webkit-animation-duration:125ms;-webkit-animation-name:fadeout;-moz-animation-duration:125ms;-moz-animation-name:fadeout}.fade.in{opacity:1;-webkit-animation-duration:225ms;-webkit-animation-name:fadein;-moz-animation-duration:225ms;-moz-animation-name:fadein}.pop{-webkit-transform-origin:50% 50%;-moz-transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);-moz-transform:scale(1);opacity:1;-webkit-animation-name:popin;-moz-animation-name:popin;-webkit-animation-duration:350ms;-moz-animation-duration:350ms}.pop.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;opacity:0;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.pop.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein}.pop.out.reverse{-webkit-transform:scale(.8);-moz-transform:scale(.8);-webkit-animation-name:popout;-moz-animation-name:popout}@-webkit-keyframes popin{from{-webkit-transform:scale(.8);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-moz-keyframes popin{from{-moz-transform:scale(.8);opacity:0}to{-moz-transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.8);opacity:0}}@-moz-keyframes popout{from{-moz-transform:scale(1);opacity:1}to{-moz-transform:scale(.8);opacity:0}}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromright{from{-moz-transform:translateX(100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%)}to{-webkit-transform:translateX(0)}}@-moz-keyframes slideinfromleft{from{-moz-transform:translateX(-100%)}to{-moz-transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(-100%)}}@-moz-keyframes slideouttoleft{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(100%)}}@-moz-keyframes slideouttoright{from{-moz-transform:translateX(0)}to{-moz-transform:translateX(100%)}}.slide.out,.slide.in{-webkit-animation-timing-function:ease-out;-webkit-animation-duration:350ms;-moz-animation-timing-function:ease-out;-moz-animation-duration:350ms}.slide.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft}.slide.in{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromright;-moz-transform:translateX(0);-moz-animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromleft;-moz-transform:translateX(0);-moz-animation-name:slideinfromleft}.slidefade.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft;-moz-transform:translateX(-100%);-moz-animation-name:slideouttoleft;-webkit-animation-duration:225ms;-moz-animation-duration:225ms}.slidefade.in{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright;-moz-transform:translateX(100%);-moz-animation-name:slideouttoright;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidefade.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:fadein;-moz-transform:translateX(0);-moz-animation-name:fadein;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}.slidedown.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;-moz-transform:translateY(0);-moz-animation-name:slideinfromtop;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slidedown.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slidedown.out.reverse{-webkit-transform:translateY(-100%);-moz-transform:translateY(-100%);-webkit-animation-name:slideouttotop;-moz-animation-name:slideouttotop;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfromtop{from{-moz-transform:translateY(-100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-moz-keyframes slideouttotop{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(-100%)}}.slideup.out{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-webkit-animation-duration:100ms;-moz-animation-duration:100ms}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;-moz-transform:translateY(0);-moz-animation-name:slideinfrombottom;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.slideup.in.reverse{-webkit-animation-name:fadein;-moz-animation-name:fadein;-webkit-animation-duration:150ms;-moz-animation-duration:150ms}.slideup.out.reverse{-webkit-transform:translateY(100%);-moz-transform:translateY(100%);-webkit-animation-name:slideouttobottom;-moz-animation-name:slideouttobottom;-webkit-animation-duration:200ms;-moz-animation-duration:200ms}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-moz-keyframes slideinfrombottom{from{-moz-transform:translateY(100%)}to{-moz-transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-moz-keyframes slideouttobottom{from{-moz-transform:translateY(0)}to{-moz-transform:translateY(100%)}}.viewport-flip{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.flip{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-moz-backface-visibility:hidden;-moz-transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-webkit-animation-duration:175ms;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-moz-animation-duration:175ms}.flip.in{-webkit-animation-name:flipintoright;-webkit-animation-duration:225ms;-moz-animation-name:flipintoright;-moz-animation-duration:225ms}.flip.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.flip.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.viewport-turn{-webkit-perspective:1000;-moz-perspective:1000;position:absolute}.turn{-webkit-backface-visibility:hidden;-webkit-transform:translateX(0);-webkit-transform-origin:0 0;-moz-backface-visibility:hidden;-moz-transform:translateX(0);-moz-transform-origin:0 0}.turn.out{-webkit-transform:rotateY(-90deg) scale(.9);-webkit-animation-name:flipouttoleft;-moz-transform:rotateY(-90deg) scale(.9);-moz-animation-name:flipouttoleft;-webkit-animation-duration:125ms;-moz-animation-duration:125ms}.turn.in{-webkit-animation-name:flipintoright;-moz-animation-name:flipintoright;-webkit-animation-duration:250ms;-moz-animation-duration:250ms}.turn.out.reverse{-webkit-transform:rotateY(90deg) scale(.9);-webkit-animation-name:flipouttoright;-moz-transform:rotateY(90deg) scale(.9);-moz-animation-name:flipouttoright}.turn.in.reverse{-webkit-animation-name:flipintoleft;-moz-animation-name:flipintoleft}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(-90deg) scale(.9)}}@-moz-keyframes flipouttoleft{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(-90deg) scale(.9)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0)}to{-webkit-transform:rotateY(90deg) scale(.9)}}@-moz-keyframes flipouttoright{from{-moz-transform:rotateY(0)}to{-moz-transform:rotateY(90deg) scale(.9)}}@-webkit-keyframes flipintoleft{from{-webkit-transform:rotateY(-90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoleft{from{-moz-transform:rotateY(-90deg) scale(.9)}to{-moz-transform:rotateY(0)}}@-webkit-keyframes flipintoright{from{-webkit-transform:rotateY(90deg) scale(.9)}to{-webkit-transform:rotateY(0)}}@-moz-keyframes flipintoright{from{-moz-transform:rotateY(90deg) scale(.9)}to{-moz-transform:rotateY(0)}}.flow{-webkit-transform-origin:50% 30%;-moz-transform-origin:50% 30%;-webkit-box-shadow:0 0 20px rgba(0,0,0,.4);-moz-box-shadow:0 0 20px rgba(0,0,0,.4)}.ui-dialog.flow{-webkit-transform-origin:none;-moz-transform-origin:none;-webkit-box-shadow:none;-moz-box-shadow:none}.flow.out{-webkit-transform:translateX(-100%) scale(.7);-webkit-animation-name:flowouttoleft;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(-100%) scale(.7);-moz-animation-name:flowouttoleft;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.in{-webkit-transform:translateX(0) scale(1);-webkit-animation-name:flowinfromright;-webkit-animation-timing-function:ease;-webkit-animation-duration:350ms;-moz-transform:translateX(0) scale(1);-moz-animation-name:flowinfromright;-moz-animation-timing-function:ease;-moz-animation-duration:350ms}.flow.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:flowouttoright;-moz-transform:translateX(100%);-moz-animation-name:flowouttoright}.flow.in.reverse{-webkit-animation-name:flowinfromleft;-moz-animation-name:flowinfromleft}@-webkit-keyframes flowouttoleft{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(-100%) scale(.7)}}@-moz-keyframes flowouttoleft{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(-100%) scale(.7)}}@-webkit-keyframes flowouttoright{0%{-webkit-transform:translateX(0) scale(1)}60%,70%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(100%) scale(.7)}}@-moz-keyframes flowouttoright{0%{-moz-transform:translateX(0) scale(1)}60%,70%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(100%) scale(.7)}}@-webkit-keyframes flowinfromleft{0%{-webkit-transform:translateX(-100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromleft{0%{-moz-transform:translateX(-100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}@-webkit-keyframes flowinfromright{0%{-webkit-transform:translateX(100%) scale(.7)}30%,40%{-webkit-transform:translateX(0) scale(.7)}100%{-webkit-transform:translateX(0) scale(1)}}@-moz-keyframes flowinfromright{0%{-moz-transform:translateX(100%) scale(.7)}30%,40%{-moz-transform:translateX(0) scale(.7)}100%{-moz-transform:translateX(0) scale(1)}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px}.ui-grid-solo .ui-block-a{width:100%;float:none}.ui-grid-a .ui-block-a,.ui-grid-a .ui-block-b{width:50%}.ui-grid-a .ui-block-a{clear:left}.ui-grid-b .ui-block-a,.ui-grid-b .ui-block-b,.ui-grid-b .ui-block-c{width:33.333%}.ui-grid-b .ui-block-a{clear:left}.ui-grid-c .ui-block-a,.ui-grid-c .ui-block-b,.ui-grid-c .ui-block-c,.ui-grid-c .ui-block-d{width:25%}.ui-grid-c .ui-block-a{clear:left}.ui-grid-d .ui-block-a,.ui-grid-d .ui-block-b,.ui-grid-d .ui-block-c,.ui-grid-d .ui-block-d,.ui-grid-d .ui-block-e{width:20%}.ui-grid-d .ui-block-a{clear:left}.ui-header-fixed,.ui-footer-fixed{left:0;right:0;width:100%;position:fixed;z-index:1000}.ui-header-fixed{top:0}.ui-footer-fixed{bottom:0}.ui-header-fullscreen,.ui-footer-fullscreen{opacity:.9}.ui-page-header-fixed{padding-top:2.5em}.ui-page-footer-fixed{padding-bottom:3em}.ui-page-header-fullscreen .ui-content,.ui-page-footer-fullscreen .ui-content{padding:0}.ui-fixed-hidden{position:absolute}.ui-page-header-fullscreen .ui-fixed-hidden,.ui-page-footer-fullscreen .ui-fixed-hidden{left:-99999em}.ui-header-fixed .ui-btn,.ui-footer-fixed .ui-btn{z-index:10}.ui-navbar{overflow:hidden}.ui-navbar ul,.ui-navbar-expanded ul{list-style:none;padding:0;margin:0;position:relative;display:block;border:0}.ui-navbar-collapsed ul{float:left;width:75%;margin-right:-2px}.ui-navbar-collapsed .ui-navbar-toggle{float:left;width:25%}.ui-navbar li.ui-navbar-truncate{position:absolute;left:-9999px;top:-9999px}.ui-navbar li .ui-btn,.ui-navbar .ui-navbar-toggle .ui-btn{display:block;font-size:12px;text-align:center;margin:0;border-right-width:0;max-width:100%}.ui-navbar li .ui-btn{margin-right:-1px}.ui-navbar li .ui-btn:last-child{margin-right:0}.ui-header .ui-navbar li .ui-btn,.ui-header .ui-navbar .ui-navbar-toggle .ui-btn,.ui-footer .ui-navbar li .ui-btn,.ui-footer .ui-navbar .ui-navbar-toggle .ui-btn{border-top-width:0;border-bottom-width:0}.ui-navbar .ui-btn-inner{padding-left:2px;padding-right:2px}.ui-navbar-noicons li .ui-btn .ui-btn-inner,.ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner{padding-top:.8em;padding-bottom:.9em}.ui-navbar-expanded .ui-btn{margin:0;font-size:14px}.ui-navbar-expanded .ui-btn-inner{padding-left:5px;padding-right:5px}.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner{padding:45px 5px 15px;text-align:center}.ui-navbar-expanded .ui-btn-icon-top .ui-icon{top:15px}.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner{padding:15px 5px 45px;text-align:center}.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon{bottom:15px}.ui-navbar-expanded li .ui-btn .ui-btn-inner{min-height:2.5em}.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner{padding-top:1.8em;padding-bottom:1.9em}.ui-btn{display:block;text-align:center;cursor:pointer;position:relative;margin:.5em 5px;padding:0}.ui-mini{margin:.25em 5px}.ui-btn-inner{padding:.6em 20px;min-width:.75em;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative;zoom:1}.ui-btn input,.ui-btn button{z-index:2}.ui-btn-left,.ui-btn-right,.ui-btn-inline{display:inline-block}.ui-btn-block{display:block}.ui-header .ui-btn,.ui-footer .ui-btn{display:inline-block;margin:0}.ui-header .ui-btn-inner,.ui-footer .ui-btn-inner,.ui-mini .ui-btn-inner{font-size:12.5px;padding:.55em 11px .5em}.ui-header .ui-fullsize .ui-btn-inner,.ui-footer .ui-fullsize .ui-btn-inner{font-size:16px;padding:.6em 25px}.ui-btn-icon-notext{width:24px;height:24px}.ui-btn-icon-notext .ui-btn-inner{padding:0;height:100%}.ui-btn-icon-notext .ui-btn-inner .ui-icon{margin:2px 1px 2px 3px}.ui-btn-text{position:relative;z-index:1;width:100%}.ui-btn-icon-notext .ui-btn-text{position:absolute;left:-9999px}.ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-btn-icon-right .ui-btn-inner{padding-right:40px}.ui-btn-icon-top .ui-btn-inner{padding-top:40px}.ui-btn-icon-bottom .ui-btn-inner{padding-bottom:40px}.ui-header .ui-btn-icon-left .ui-btn-inner,.ui-footer .ui-btn-icon-left .ui-btn-inner,.ui-mini .ui-btn-icon-left .ui-btn-inner{padding-left:30px}.ui-header .ui-btn-icon-right .ui-btn-inner,.ui-footer .ui-btn-icon-right .ui-btn-inner,.ui-mini .ui-btn-icon-right .ui-btn-inner{padding-right:30px}.ui-header .ui-btn-icon-top .ui-btn-inner,.ui-footer .ui-btn-icon-top .ui-btn-inner,.ui-mini .ui-btn-icon-top .ui-btn-inner{padding:30px 3px .5em 3px}.ui-header .ui-btn-icon-bottom .ui-btn-inner,.ui-footer .ui-btn-icon-bottom .ui-btn-inner,.ui-mini .ui-btn-icon-bottom .ui-btn-inner{padding:.55em 3px 30px 3px}.ui-btn-icon-notext .ui-icon{display:block;z-index:0}.ui-btn-icon-left .ui-btn-inner .ui-icon,.ui-btn-icon-right .ui-btn-inner .ui-icon{position:absolute;top:50%;margin-top:-9px}.ui-btn-icon-top .ui-btn-inner .ui-icon,.ui-btn-icon-bottom .ui-btn-inner .ui-icon{position:absolute;left:50%;margin-left:-9px}.ui-btn-icon-left .ui-icon{left:10px}.ui-btn-icon-right .ui-icon{right:10px}.ui-btn-icon-top .ui-icon{top:10px}.ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-header .ui-btn-icon-left .ui-icon,.ui-footer .ui-btn-icon-left .ui-icon,.ui-mini.ui-btn-icon-left .ui-icon,.ui-mini .ui-btn-icon-left .ui-icon{left:5px}.ui-header .ui-btn-icon-right .ui-icon,.ui-footer .ui-btn-icon-right .ui-icon,.ui-mini.ui-btn-icon-right .ui-icon,.ui-mini .ui-btn-icon-right .ui-icon{right:5px}.ui-header .ui-btn-icon-top .ui-icon,.ui-footer .ui-btn-icon-top .ui-icon,.ui-mini.ui-btn-icon-top .ui-icon,.ui-mini .ui-btn-icon-top .ui-icon{top:5px}.ui-header .ui-btn-icon-bottom .ui-icon,.ui-footer .ui-btn-icon-bottom .ui-icon,.ui-mini.ui-btn-icon-bottom .ui-icon,.ui-mini .ui-btn-icon-bottom .ui-icon{bottom:5px}.ui-btn-hidden{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-appearance:button;opacity:.1;cursor:pointer;background:#fff;background:rgba(255,255,255,0);filter:Alpha(Opacity=.0001);font-size:1px;border:0;text-indent:-9999px}.ui-collapsible{margin:.5em 0}.ui-collapsible-heading{font-size:16px;display:block;margin:0 -8px;padding:0;border-width:0 0 1px 0;position:relative}.ui-collapsible-heading a{text-align:left;margin:0}.ui-collapsible-heading .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner{padding-left:40px}.ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner{padding-left:12px;padding-right:40px}.ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner,.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner{padding-right:40px;text-align:center}.ui-collapsible-heading a span.ui-btn{position:absolute;left:6px;top:50%;margin:-12px 0 0 0;width:20px;height:20px;padding:1px 0 1px 2px;text-indent:-9999px}.ui-collapsible-heading a span.ui-btn .ui-btn-inner{padding:10px 0}.ui-collapsible-heading a span.ui-btn .ui-icon{left:0;margin-top:-10px}.ui-collapsible-heading-status{position:absolute;top:-9999px;left:0}.ui-collapsible-content{display:block;margin:0 -8px;padding:10px 16px;border-top:0;background-image:none;font-weight:normal}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set{margin:.5em 0}.ui-collapsible-set .ui-collapsible{margin:-1px 0 0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:0 0 .5em;zoom:1}.ui-bar .ui-controlgroup{margin:0 .3em}.ui-controlgroup-label{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .4em}.ui-controlgroup-controls{display:block;width:100%}.ui-controlgroup li{list-style:none}.ui-controlgroup-vertical .ui-btn,.ui-controlgroup-vertical .ui-checkbox,.ui-controlgroup-vertical .ui-radio{margin:0;border-bottom-width:0}.ui-controlgroup-controls label.ui-select{position:absolute;left:-9999px}.ui-controlgroup-vertical .ui-controlgroup-last{border-bottom-width:1px}.ui-controlgroup-horizontal{padding:0}.ui-controlgroup-horizontal .ui-btn-inner{text-align:center}.ui-controlgroup-horizontal .ui-btn,.ui-controlgroup-horizontal .ui-select{display:inline-block;margin:0 -6px 0 0}.ui-controlgroup-horizontal .ui-checkbox,.ui-controlgroup-horizontal .ui-radio{float:left;clear:none;margin:0 -1px 0 0}.ui-controlgroup-horizontal .ui-checkbox .ui-btn,.ui-controlgroup-horizontal .ui-radio .ui-btn,.ui-controlgroup-horizontal .ui-checkbox:last-child,.ui-controlgroup-horizontal .ui-radio:last-child{margin-right:0}.ui-controlgroup-horizontal .ui-controlgroup-last{margin-right:0}.ui-controlgroup .ui-checkbox label,.ui-controlgroup .ui-radio label{font-size:16px}@media all and (min-width:450px){.ui-field-contain .ui-controlgroup-label{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-controlgroup-controls{width:60%;display:inline-block}.ui-field-contain .ui-controlgroup .ui-select{width:100%}.ui-field-contain .ui-controlgroup-horizontal .ui-select{width:auto}}.ui-dialog{background:none!important}.ui-dialog-contain{width:92.5%;max-width:500px;margin:10% auto 15px auto;padding:0}.ui-dialog .ui-header{margin-top:15%;border:0;overflow:hidden}.ui-dialog .ui-header,.ui-dialog .ui-content,.ui-dialog .ui-footer{display:block;position:relative;width:auto}.ui-dialog .ui-header,.ui-dialog .ui-footer{z-index:10;padding:0}.ui-dialog .ui-footer{padding:0 15px}.ui-dialog .ui-content{padding:15px}.ui-dialog{margin-top:-15px}.ui-checkbox,.ui-radio{position:relative;clear:both;margin:.2em 0 .5em;z-index:1}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;z-index:2}.ui-checkbox .ui-btn-inner,.ui-radio .ui-btn-inner{white-space:normal}.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner{padding-left:45px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner{padding-left:36px}.ui-checkbox .ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner{padding-right:36px}.ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-btn-icon-bottom .ui-btn-inner,.ui-radio .ui-btn-icon-bottom .ui-btn-inner{padding-right:0;padding-left:0;text-align:center}.ui-checkbox .ui-icon,.ui-radio .ui-icon{top:1.1em}.ui-checkbox .ui-btn-icon-left .ui-icon,.ui-radio .ui-btn-icon-left .ui-icon{left:15px}.ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon,.ui-radio .ui-mini.ui-btn-icon-left .ui-icon{left:9px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox .ui-btn-icon-top .ui-icon,.ui-radio .ui-btn-icon-top .ui-icon{top:10px}.ui-checkbox .ui-btn-icon-bottom .ui-icon,.ui-radio .ui-btn-icon-bottom .ui-icon{top:auto;bottom:10px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon,.ui-radio .ui-mini.ui-btn-icon-right .ui-icon{right:9px}.ui-checkbox input,.ui-radio input{position:absolute;left:20px;top:50%;width:10px;height:10px;margin:-5px 0 0 0;outline:0!important;z-index:1}.ui-field-contain,fieldset.ui-field-contain{padding:.8em 0;margin:0;border-width:0 0 1px 0;overflow:visible}.ui-field-contain:first-child{border-top-width:0}.ui-header .ui-field-contain-left,.ui-header .ui-field-contain-right{position:absolute;top:0;width:25%}.ui-header .ui-field-contain-left{left:1em}.ui-header .ui-field-contain-right{right:1em}@media all and (min-width:450px){.ui-field-contain,.ui-mobile fieldset.ui-field-contain{border-width:0;padding:0;margin:1em 0}}.ui-select{display:block;position:relative}.ui-select select{position:absolute;left:-9999px;top:-9999px}.ui-select .ui-btn{overflow:hidden;opacity:1;margin:0}.ui-select .ui-btn select{cursor:pointer;-webkit-appearance:button;left:0;top:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;opacity:0;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);z-index:2}.ui-select .ui-disabled{opacity:.3}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-btn select.ui-select-nativeonly{opacity:1;text-indent:0}.ui-select .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-select .ui-btn-icon-right .ui-icon{right:15px}.ui-select .ui-mini.ui-btn-icon-right .ui-icon{right:7px}label.ui-select{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}.ui-select .ui-btn-text,.ui-selectmenu .ui-btn-text{display:block;min-height:1em;overflow:hidden!important}.ui-select .ui-btn-text{text-overflow:ellipsis}.ui-selectmenu{position:absolute;padding:0;z-index:1100!important;width:80%;max-width:350px;padding:6px}.ui-selectmenu .ui-listview{margin:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu-hidden{top:-9999px;left:-9999px}.ui-selectmenu-screen{position:absolute;top:0;left:0;width:100%;height:100%;z-index:99}.ui-screen-hidden,.ui-selectmenu-list .ui-li .ui-icon{display:none}.ui-selectmenu-list .ui-li .ui-icon{display:block}.ui-li.ui-selectmenu-placeholder{display:none}.ui-selectmenu .ui-header .ui-title{margin:.6em 46px .8em}@media all and (min-width:450px){.ui-field-contain label.ui-select{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-select{width:60%;display:inline-block}}.ui-selectmenu .ui-header h1:after{content:'.';visibility:hidden}label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em}input.ui-input-text,textarea.ui-input-text{background-image:none;padding:.4em;line-height:1.4;font-size:16px;display:block;width:97%;outline:0}.ui-header input.ui-input-text,.ui-footer input.ui-input-text{margin-left:1.25%;padding:.4em 1%;width:95.5%}input.ui-input-text{-webkit-appearance:none}textarea.ui-input-text{height:50px;-webkit-transition:height 200ms linear;-moz-transition:height 200ms linear;-o-transition:height 200ms linear;transition:height 200ms linear}.ui-input-search{padding:0 30px;background-image:none;position:relative}.ui-icon-searchfield:after{position:absolute;left:7px;top:50%;margin-top:-9px;content:"";width:18px;height:18px;opacity:.5}.ui-input-search input.ui-input-text{border:0;width:98%;padding:.4em 0;margin:0;display:block;background:transparent none;outline:0!important}.ui-input-search .ui-input-clear{position:absolute;right:0;top:50%;margin-top:-13px}.ui-mini .ui-input-clear{right:-3px}.ui-input-search .ui-input-clear-hidden{display:none}input.ui-mini,.ui-mini input,textarea.ui-mini{font-size:14px}textarea.ui-mini{height:45px}@media all and (min-width:450px){.ui-field-contain label.ui-input-text{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text,.ui-field-contain .ui-input-search{width:60%;display:inline-block}.ui-field-contain .ui-input-search{width:50%}.ui-hide-label input.ui-input-text,.ui-hide-label textarea.ui-input-text,.ui-hide-label .ui-input-search{padding:.4em;width:97%}.ui-input-search input.ui-input-text{width:98%}}.ui-listview{margin:0;counter-reset:listnumbering}.ui-content .ui-listview{margin:-15px}.ui-content .ui-listview-inset{margin:1em 0}.ui-listview,.ui-li{list-style:none;padding:0}.ui-li,.ui-li.ui-field-contain{display:block;margin:0;position:relative;overflow:visible;text-align:left;border-width:0;border-top-width:1px}.ui-li .ui-btn-text a.ui-link-inherit{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-divider,.ui-li-static{padding:.5em 15px;font-size:14px;font-weight:bold}.ui-li-divider{counter-reset:listnumbering}ol.ui-listview .ui-link-inherit:before,ol.ui-listview .ui-li-static:before,.ui-li-dec{font-size:.8em;display:inline-block;padding-right:.3em;font-weight:normal;counter-increment:listnumbering;content:counter(listnumbering) ". "}ol.ui-listview .ui-li-jsnumbering:before{content:""!important}.ui-listview-inset .ui-li{border-right-width:1px;border-left-width:1px}.ui-li:last-child,.ui-li.ui-field-contain:last-child{border-bottom-width:1px}.ui-li>.ui-btn-inner{display:block;position:relative;padding:0}.ui-li .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li{padding:.7em 15px .7em 15px;display:block}.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-thumb{min-height:60px;padding-left:100px}.ui-li-has-icon .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-icon{min-height:20px;padding-left:40px}.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-count{padding-right:45px}.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow{padding-right:30px}.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow.ui-li-has-count{padding-right:75px}.ui-li-has-count .ui-btn-text{padding-right:15px}.ui-li-heading{font-size:16px;font-weight:bold;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-desc{font-size:12px;font-weight:normal;display:block;margin:-.5em 0 .6em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-thumb,.ui-listview .ui-li-icon{position:absolute;left:1px;top:0;max-height:80px;max-width:80px}.ui-listview .ui-li-icon{max-height:40px;max-width:40px;left:10px;top:.9em}.ui-li-thumb,.ui-listview .ui-li-icon,.ui-li-content{float:left;margin-right:10px}.ui-li-aside{float:right;width:50%;text-align:right;margin:.3em 0}@media all and (min-width:480px){.ui-li-aside{width:45%}}.ui-li-divider{cursor:default}.ui-li-has-alt .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt{padding-right:95px}.ui-li-has-count .ui-li-count{position:absolute;font-size:11px;font-weight:bold;padding:.2em .5em;top:50%;margin-top:-.9em;right:48px}.ui-li-divider .ui-li-count,.ui-li-static .ui-li-count{right:10px}.ui-li-has-alt .ui-li-count{right:55px}.ui-li-link-alt{position:absolute;width:40px;height:100%;border-width:0;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-li-link-alt .ui-btn{overflow:hidden;position:absolute;right:8px;top:50%;margin:-11px 0 0 0;border-bottom-width:1px;z-index:-1}.ui-li-link-alt .ui-btn-inner{padding:0;height:100%;position:absolute;width:100%;top:0;left:0}.ui-li-link-alt .ui-btn .ui-icon{right:50%;margin-right:-9px}.ui-listview * .ui-btn-inner>.ui-btn>.ui-btn-inner{border-top:0}.ui-listview-filter{border-width:0;overflow:hidden;margin:-15px -15px 15px -15px}.ui-listview-filter .ui-input-search{margin:5px;width:auto;display:block}.ui-listview-filter-inset{margin:-15px -5px -15px -5px;background:transparent}.ui-li.ui-screen-hidden{display:none}@media only screen and (min-device-width:768px) and (max-device-width:1024px){.ui-li .ui-btn-text{overflow:visible}}label.ui-slider{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}input.ui-slider-input,.ui-field-contain input.ui-slider-input{display:inline-block;width:50px}select.ui-slider-switch{display:none}div.ui-slider{position:relative;display:inline-block;overflow:visible;height:15px;padding:0;margin:0 2% 0 20px;top:4px;width:65%}div.ui-slider-mini{height:12px;margin-left:10px}div.ui-slider-bg{border:0;height:100%;padding-right:8px}.ui-controlgroup a.ui-slider-handle,a.ui-slider-handle{position:absolute;z-index:1;top:50%;width:28px;height:28px;margin-top:-15px;margin-left:-15px;outline:0}a.ui-slider-handle .ui-btn-inner{padding:0;height:100%}div.ui-slider-mini a.ui-slider-handle{height:14px;width:14px;margin:-8px 0 0 -7px}div.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:-9px 0 0 -9px}@media all and (min-width:450px){.ui-field-contain label.ui-slider{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain div.ui-slider{width:43%}.ui-field-contain div.ui-slider-switch{width:5.5em}}div.ui-slider-switch{height:32px;margin-left:0;width:5.8em}a.ui-slider-handle-snapping{-webkit-transition:left 70ms linear;-moz-transition:left 70ms linear}div.ui-slider-switch .ui-slider-handle{margin-top:1px}.ui-slider-inneroffset{margin:0 16px;position:relative;z-index:1}div.ui-slider-switch.ui-slider-mini{width:5em;height:29px}div.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset{margin:0 15px 0 14px}div.ui-slider-switch.ui-slider-mini .ui-slider-handle{width:25px;height:25px;margin:1px 0 0 -13px}div.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner{height:30px;width:30px;padding:0;margin:0}span.ui-slider-label{position:absolute;text-align:center;width:100%;overflow:hidden;font-size:16px;top:0;line-height:2;min-height:100%;border-width:0;white-space:nowrap}.ui-slider-mini span.ui-slider-label{font-size:14px}span.ui-slider-label-a{z-index:1;left:0;text-indent:-1.5em}span.ui-slider-label-b{z-index:0;right:0;text-indent:1.5em}.ui-slider-inline{width:120px;display:inline-block} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/jquery.mobile.theme-1.1.0.min.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,2 @@ +/*! jQuery Mobile v1.1.0 db342b1f315c282692791aa870455901fdb46a55 jquerymobile.com | jquery.org/license */ +.ui-bar-a{border:1px solid #333;background:#111;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(#3c3c3c,#111);background-image:-moz-linear-gradient(#3c3c3c,#111);background-image:-ms-linear-gradient(#3c3c3c,#111);background-image:-o-linear-gradient(#3c3c3c,#111);background-image:linear-gradient(#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-a .ui-link:hover{color:#2489ce}.ui-bar-a .ui-link:active{color:#2489ce}.ui-bar-a .ui-link:visited{color:#2489ce}.ui-body-a,.ui-overlay-a{border:1px solid #444;background:#222;color:#fff;text-shadow:0 1px 1px #111;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#222));background-image:-webkit-linear-gradient(#444,#222);background-image:-moz-linear-gradient(#444,#222);background-image:-ms-linear-gradient(#444,#222);background-image:-o-linear-gradient(#444,#222);background-image:linear-gradient(#444,#222)}.ui-overlay-a{background-image:none;border-width:0}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:bold}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-body-a .ui-link:visited{color:#2489ce}.ui-btn-up-a{border:1px solid #111;background:#333;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#444),to(#2d2d2d));background-image:-webkit-linear-gradient(#444,#2d2d2d);background-image:-moz-linear-gradient(#444,#2d2d2d);background-image:-ms-linear-gradient(#444,#2d2d2d);background-image:-o-linear-gradient(#444,#2d2d2d);background-image:linear-gradient(#444,#2d2d2d)}.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#383838));background-image:-webkit-linear-gradient(#555,#383838);background-image:-moz-linear-gradient(#555,#383838);background-image:-ms-linear-gradient(#555,#383838);background-image:-o-linear-gradient(#555,#383838);background-image:linear-gradient(#555,#383838)}.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#222;font-weight:bold;color:#fff;text-shadow:0 1px 1px #111;background-image:-webkit-gradient(linear,left top,left bottom,from(#202020),to(#2c2c2c));background-image:-webkit-linear-gradient(#202020,#2c2c2c);background-image:-moz-linear-gradient(#202020,#2c2c2c);background-image:-ms-linear-gradient(#202020,#2c2c2c);background-image:-o-linear-gradient(#202020,#2c2c2c);background-image:linear-gradient(#202020,#2c2c2c)}.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:bold;text-shadow:0 1px 1px #3e6790;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#497bae));background-image:-webkit-linear-gradient(#6facd5,#497bae);background-image:-moz-linear-gradient(#6facd5,#497bae);background-image:-ms-linear-gradient(#6facd5,#497bae);background-image:-o-linear-gradient(#6facd5,#497bae);background-image:linear-gradient(#6facd5,#497bae)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b .ui-link{color:#ddf0f8;font-weight:bold}.ui-bar-b .ui-link:hover{color:#ddf0f8}.ui-bar-b .ui-link:active{color:#ddf0f8}.ui-bar-b .ui-link:visited{color:#ddf0f8}.ui-body-b,.ui-overlay-b{border:1px solid #999;background:#f3f3f3;color:#222;text-shadow:0 1px 0 #fff;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#ccc));background-image:-webkit-linear-gradient(#ddd,#ccc);background-image:-moz-linear-gradient(#ddd,#ccc);background-image:-ms-linear-gradient(#ddd,#ccc);background-image:-o-linear-gradient(#ddd,#ccc);background-image:linear-gradient(#ddd,#ccc)}.ui-overlay-b{background-image:none;border-width:0}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:bold}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-body-b .ui-link:visited{color:#2489ce}.ui-btn-up-b{border:1px solid #044062;background:#396b9e;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#5f9cc5),to(#396b9e));background-image:-webkit-linear-gradient(#5f9cc5,#396b9e);background-image:-moz-linear-gradient(#5f9cc5,#396b9e);background-image:-ms-linear-gradient(#5f9cc5,#396b9e);background-image:-o-linear-gradient(#5f9cc5,#396b9e);background-image:linear-gradient(#5f9cc5,#396b9e)}.ui-btn-up-b a.ui-link-inherit{color:#fff}.ui-btn-hover-b{border:1px solid #00415e;background:#4b88b6;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#6facd5),to(#4272a4));background-image:-webkit-linear-gradient(#6facd5,#4272a4);background-image:-moz-linear-gradient(#6facd5,#4272a4);background-image:-ms-linear-gradient(#6facd5,#4272a4);background-image:-o-linear-gradient(#6facd5,#4272a4);background-image:linear-gradient(#6facd5,#4272a4)}.ui-btn-hover-b a.ui-link-inherit{color:#fff}.ui-btn-down-b{border:1px solid #225377;background:#4e89c5;font-weight:bold;color:#fff;text-shadow:0 1px 1px #194b7e;background-image:-webkit-gradient(linear,left top,left bottom,from(#295b8e),to(#3e79b5));background-image:-webkit-linear-gradient(#295b8e,#3e79b5);background-image:-moz-linear-gradient(#295b8e,#3e79b5);background-image:-ms-linear-gradient(#295b8e,#3e79b5);background-image:-o-linear-gradient(#295b8e,#3e79b5);background-image:linear-gradient(#295b8e,#3e79b5)}.ui-btn-down-b a.ui-link-inherit{color:#fff}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-c{border:1px solid #b3b3b3;background:#eee;color:#3e3e3e;font-weight:bold;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#ddd));background-image:-webkit-linear-gradient(#f0f0f0,#ddd);background-image:-moz-linear-gradient(#f0f0f0,#ddd);background-image:-ms-linear-gradient(#f0f0f0,#ddd);background-image:-o-linear-gradient(#f0f0f0,#ddd);background-image:linear-gradient(#f0f0f0,#ddd)}.ui-bar-c .ui-link-inherit{color:#3e3e3e}.ui-bar-c .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-c .ui-link:hover{color:#2489ce}.ui-bar-c .ui-link:active{color:#2489ce}.ui-bar-c .ui-link:visited{color:#2489ce}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c,.ui-overlay-c{border:1px solid #aaa;color:#333;text-shadow:0 1px 0 #fff;background:#f9f9f9;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#eee));background-image:-webkit-linear-gradient(#f9f9f9,#eee);background-image:-moz-linear-gradient(#f9f9f9,#eee);background-image:-ms-linear-gradient(#f9f9f9,#eee);background-image:-o-linear-gradient(#f9f9f9,#eee);background-image:linear-gradient(#f9f9f9,#eee)}.ui-overlay-c{background-image:none;border-width:0}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c .ui-link-inherit{color:#333}.ui-body-c .ui-link{color:#2489ce;font-weight:bold}.ui-body-c .ui-link:hover{color:#2489ce}.ui-body-c .ui-link:active{color:#2489ce}.ui-body-c .ui-link:visited{color:#2489ce}.ui-btn-up-c{border:1px solid #ccc;background:#eee;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f1f1f1));background-image:-webkit-linear-gradient(#fff,#f1f1f1);background-image:-moz-linear-gradient(#fff,#f1f1f1);background-image:-ms-linear-gradient(#fff,#f1f1f1);background-image:-o-linear-gradient(#fff,#f1f1f1);background-image:linear-gradient(#fff,#f1f1f1)}.ui-btn-up-c a.ui-link-inherit{color:#2f3e46}.ui-btn-hover-c{border:1px solid #bbb;background:#dfdfdf;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#e0e0e0));background-image:-webkit-linear-gradient(#f9f9f9,#e0e0e0);background-image:-moz-linear-gradient(#f6f6f6,#e0e0e0);background-image:-ms-linear-gradient(#f6f6f6,#e0e0e0);background-image:-o-linear-gradient(#f6f6f6,#e0e0e0);background-image:linear-gradient(#f6f6f6,#e0e0e0)}.ui-btn-hover-c a.ui-link-inherit{color:#2f3e46}.ui-btn-down-c{border:1px solid #bbb;background:#d6d6d6;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#d0d0d0),to(#dfdfdf));background-image:-webkit-linear-gradient(#d0d0d0,#dfdfdf);background-image:-moz-linear-gradient(#d0d0d0,#dfdfdf);background-image:-ms-linear-gradient(#d0d0d0,#dfdfdf);background-image:-o-linear-gradient(#d0d0d0,#dfdfdf);background-image:linear-gradient(#d0d0d0,#dfdfdf)}.ui-btn-down-c a.ui-link-inherit{color:#2f3e46}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-d{border:1px solid #bbb;background:#bbb;color:#333;text-shadow:0 1px 0 #eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#bbb));background-image:-webkit-linear-gradient(#ddd,#bbb);background-image:-moz-linear-gradient(#ddd,#bbb);background-image:-ms-linear-gradient(#ddd,#bbb);background-image:-o-linear-gradient(#ddd,#bbb);background-image:linear-gradient(#ddd,#bbb)}.ui-bar-d,.ui-bar-d input,.ui-bar-d select,.ui-bar-d textarea,.ui-bar-d button{font-family:Helvetica,Arial,sans-serif}.ui-bar-d .ui-link-inherit{color:#333}.ui-bar-d .ui-link{color:#2489ce;font-weight:bold}.ui-bar-d .ui-link:hover{color:#2489ce}.ui-bar-d .ui-link:active{color:#2489ce}.ui-bar-d .ui-link:visited{color:#2489ce}.ui-body-d,.ui-overlay-d{border:1px solid #bbb;color:#333;text-shadow:0 1px 0 #fff;background:#fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#fff));background-image:-webkit-linear-gradient(#fff,#fff);background-image:-moz-linear-gradient(#fff,#fff);background-image:-ms-linear-gradient(#fff,#fff);background-image:-o-linear-gradient(#fff,#fff);background-image:linear-gradient(#fff,#fff)}.ui-overlay-d{background-image:none;border-width:0}.ui-body-d,.ui-body-d input,.ui-body-d select,.ui-body-d textarea,.ui-body-d button{font-family:Helvetica,Arial,sans-serif}.ui-body-d .ui-link-inherit{color:#333}.ui-body-d .ui-link{color:#2489ce;font-weight:bold}.ui-body-d .ui-link:hover{color:#2489ce}.ui-body-d .ui-link:active{color:#2489ce}.ui-body-d .ui-link:visited{color:#2489ce}.ui-btn-up-d{border:1px solid #bbb;background:#fff;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fafafa),to(#f6f6f6));background-image:-webkit-linear-gradient(#fafafa,#f6f6f6);background-image:-moz-linear-gradient(#fafafa,#f6f6f6);background-image:-ms-linear-gradient(#fafafa,#f6f6f6);background-image:-o-linear-gradient(#fafafa,#f6f6f6);background-image:linear-gradient(#fafafa,#f6f6f6)}.ui-btn-up-d a.ui-link-inherit{color:#333}.ui-btn-hover-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;cursor:pointer;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#fff));background-image:-webkit-linear-gradient(#eee,#fff);background-image:-moz-linear-gradient(#eee,#fff);background-image:-ms-linear-gradient(#eee,#fff);background-image:-o-linear-gradient(#eee,#fff);background-image:linear-gradient(#eee,#fff)}.ui-btn-hover-d a.ui-link-inherit{color:#333}.ui-btn-down-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#e5e5e5),to(#f2f2f2));background-image:-webkit-linear-gradient(#e5e5e5,#f2f2f2);background-image:-moz-linear-gradient(#e5e5e5,#f2f2f2);background-image:-ms-linear-gradient(#e5e5e5,#f2f2f2);background-image:-o-linear-gradient(#e5e5e5,#f2f2f2);background-image:linear-gradient(#e5e5e5,#f2f2f2)}.ui-btn-down-d a.ui-link-inherit{color:#333}.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-e{border:1px solid #f7c942;background:#fadb4e;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fceda7),to(#fbef7e));background-image:-webkit-linear-gradient(#fceda7,#fbef7e);background-image:-moz-linear-gradient(#fceda7,#fbef7e);background-image:-ms-linear-gradient(#fceda7,#fbef7e);background-image:-o-linear-gradient(#fceda7,#fbef7e);background-image:linear-gradient(#fceda7,#fbef7e)}.ui-bar-e,.ui-bar-e input,.ui-bar-e select,.ui-bar-e textarea,.ui-bar-e button{font-family:Helvetica,Arial,sans-serif}.ui-bar-e .ui-link-inherit{color:#333}.ui-bar-e .ui-link{color:#2489ce;font-weight:bold}.ui-bar-e .ui-link:hover{color:#2489ce}.ui-bar-e .ui-link:active{color:#2489ce}.ui-bar-e .ui-link:visited{color:#2489ce}.ui-body-e,.ui-overlay-e{border:1px solid #f7c942;color:#222;text-shadow:0 1px 0 #fff;background:#fff9df;background-image:-webkit-gradient(linear,left top,left bottom,from(#fffadf),to(#fff3a5));background-image:-webkit-linear-gradient(#fffadf,#fff3a5);background-image:-moz-linear-gradient(#fffadf,#fff3a5);background-image:-ms-linear-gradient(#fffadf,#fff3a5);background-image:-o-linear-gradient(#fffadf,#fff3a5);background-image:linear-gradient(#fffadf,#fff3a5)}.ui-overlay-e{background-image:none;border-width:0}.ui-body-e,.ui-body-e input,.ui-body-e select,.ui-body-e textarea,.ui-body-e button{font-family:Helvetica,Arial,sans-serif}.ui-body-e .ui-link-inherit{color:#333}.ui-body-e .ui-link{color:#2489ce;font-weight:bold}.ui-body-e .ui-link:hover{color:#2489ce}.ui-body-e .ui-link:active{color:#2489ce}.ui-body-e .ui-link:visited{color:#2489ce}.ui-btn-up-e{border:1px solid #f4c63f;background:#fadb4e;font-weight:bold;color:#222;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#ffefaa),to(#ffe155));background-image:-webkit-linear-gradient(#ffefaa,#ffe155);background-image:-moz-linear-gradient(#ffefaa,#ffe155);background-image:-ms-linear-gradient(#ffefaa,#ffe155);background-image:-o-linear-gradient(#ffefaa,#ffe155);background-image:linear-gradient(#ffefaa,#ffe155)}.ui-btn-up-e a.ui-link-inherit{color:#222}.ui-btn-hover-e{border:1px solid #f2c43d;background:#fbe26f;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff5ba),to(#fbdd52));background-image:-webkit-linear-gradient(#fff5ba,#fbdd52);background-image:-moz-linear-gradient(#fff5ba,#fbdd52);background-image:-ms-linear-gradient(#fff5ba,#fbdd52);background-image:-o-linear-gradient(#fff5ba,#fbdd52);background-image:linear-gradient(#fff5ba,#fbdd52)}.ui-btn-hover-e a.ui-link-inherit{color:#333}.ui-btn-down-e{border:1px solid #f2c43d;background:#fceda7;font-weight:bold;color:#111;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f8d94c),to(#fadb4e));background-image:-webkit-linear-gradient(#f8d94c,#fadb4e);background-image:-moz-linear-gradient(#f8d94c,#fadb4e);background-image:-ms-linear-gradient(#f8d94c,#fadb4e);background-image:-o-linear-gradient(#f8d94c,#fadb4e);background-image:linear-gradient(#f8d94c,#fadb4e)}.ui-btn-down-e a.ui-link-inherit{color:#333}.ui-btn-up-e,.ui-btn-hover-e,.ui-btn-down-e{font-family:Helvetica,Arial,sans-serif;text-decoration:none}a.ui-link-inherit{text-decoration:none!important}.ui-btn-active{border:1px solid #2373a5;background:#5393c5;font-weight:bold;color:#fff;cursor:pointer;text-shadow:0 1px 1px #3373a5;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from(#5393c5),to(#6facd5));background-image:-webkit-linear-gradient(#5393c5,#6facd5);background-image:-moz-linear-gradient(#5393c5,#6facd5);background-image:-ms-linear-gradient(#5393c5,#6facd5);background-image:-o-linear-gradient(#5393c5,#6facd5);background-image:linear-gradient(#5393c5,#6facd5);font-family:Helvetica,Arial,sans-serif}.ui-btn-active a.ui-link-inherit{color:#fff}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3)}.ui-corner-tl{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em}.ui-corner-tr{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bl{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-br{-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-top{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-right{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-left{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-all{-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.ui-corner-none{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.ui-br{border-bottom:#828282;border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid}.ui-disabled{opacity:.3}.ui-disabled,.ui-disabled a{cursor:default!important;pointer-events:none}.ui-disabled .ui-btn-text{-ms-filter:"alpha(opacity=30)";filter:alpha(opacity=30);zoom:1}.ui-icon,.ui-icon-searchfield:after{background:#666;background:rgba(0,0,0,.4);background-image:url(images/icons-18-white.png);background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px}.ui-icon-alt{background-image:url(images/icons-36-black.png)}}.ui-icon-plus{background-position:-0 50%}.ui-icon-minus{background-position:-36px 50%}.ui-icon-delete{background-position:-72px 50%}.ui-icon-arrow-r{background-position:-108px 50%}.ui-icon-arrow-l{background-position:-144px 50%}.ui-icon-arrow-u{background-position:-180px 50%}.ui-icon-arrow-d{background-position:-216px 50%}.ui-icon-check{background-position:-252px 50%}.ui-icon-gear{background-position:-288px 50%}.ui-icon-refresh{background-position:-324px 50%}.ui-icon-forward{background-position:-360px 50%}.ui-icon-back{background-position:-396px 50%}.ui-icon-grid{background-position:-432px 50%}.ui-icon-star{background-position:-468px 50%}.ui-icon-alert{background-position:-504px 50%}.ui-icon-info{background-position:-540px 50%}.ui-icon-home{background-position:-576px 50%}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%}.ui-icon-checkbox-off{background-position:-684px 50%}.ui-icon-checkbox-on{background-position:-648px 50%}.ui-icon-radio-off{background-position:-756px 50%}.ui-icon-radio-on{background-position:-720px 50%}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#4596ce}.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px}.ui-btn-corner-tl{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em}.ui-btn-corner-tr{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bl{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-br{-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-top{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-right{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-left{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-all{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.ui-overlay{background:#666;opacity:.5;filter:Alpha(Opacity=50);position:absolute;width:100%;height:100%}.ui-overlay-shadow{-moz-box-shadow:0 0 12px rgba(0,0,0,.6);-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-shadow{-moz-box-shadow:0 1px 4px rgba(0,0,0,.3);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3);box-shadow:0 1px 4px rgba(0,0,0,.3)}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-shadow-inset{-moz-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);box-shadow:inset 0 1px 4px rgba(0,0,0,.2)}.ui-icon-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.4);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.4);box-shadow:0 1px 0 rgba(255,255,255,.4)}.ui-btn:focus{outline:0}.ui-focus,.ui-btn:focus{-moz-box-shadow:0 0 12px #387bbe;-webkit-box-shadow:0 0 12px #387bbe;box-shadow:0 0 12px #387bbe}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}.ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus{outline-width:1px;outline-style:dotted} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/slimbox2.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,244 @@ +/*! + Slimbox v2.04 - The ultimate lightweight Lightbox clone for jQuery + (c) 2007-2010 Christophe Beyls <http://www.digitalia.be> + MIT-style license. +*/ + +(function($) { + + // Global variables, accessible to Slimbox only + var win = $(window), options, images, activeImage = -1, activeURL, prevImage, nextImage, compatibleOverlay, middle, centerWidth, centerHeight, + ie6 = !window.XMLHttpRequest, hiddenElements = [], documentElement = document.documentElement, + + // Preload images + preload = {}, preloadPrev = new Image(), preloadNext = new Image(), + + // DOM elements + overlay, center, image, sizer, prevLink, nextLink, bottomContainer, bottom, caption, number; + + /* + Initialization + */ + + $(function() { + // Append the Slimbox HTML code at the bottom of the document + $("body").append( + $([ + overlay = $('<div id="lbOverlay" />')[0], + center = $('<div id="lbCenter" />')[0], + bottomContainer = $('<div id="lbBottomContainer" />')[0] + ]).css("display", "none") + ); + + image = $('<div id="lbImage" />').appendTo(center).append( + sizer = $('<div style="position: relative;" />').append([ + prevLink = $('<a id="lbPrevLink" href="#" />').click(previous)[0], + nextLink = $('<a id="lbNextLink" href="#" />').click(next)[0] + ])[0] + )[0]; + + bottom = $('<div id="lbBottom" />').appendTo(bottomContainer).append([ + $('<a id="lbCloseLink" href="#" />').add(overlay).click(close)[0], + caption = $('<div id="lbCaption" />')[0], + number = $('<div id="lbNumber" />')[0], + $('<div style="clear: both;" />')[0] + ])[0]; + }); + + + /* + API + */ + + // Open Slimbox with the specified parameters + $.slimbox = function(_images, startImage, _options) { + options = $.extend({ + loop: false, // Allows to navigate between first and last images + overlayOpacity: 0.8, // 1 is opaque, 0 is completely transparent (change the color in the CSS file) + overlayFadeDuration: 400, // Duration of the overlay fade-in and fade-out animations (in milliseconds) + resizeDuration: 400, // Duration of each of the box resize animations (in milliseconds) + resizeEasing: "swing", // "swing" is jQuery's default easing + initialWidth: 250, // Initial width of the box (in pixels) + initialHeight: 250, // Initial height of the box (in pixels) + imageFadeDuration: 400, // Duration of the image fade-in animation (in milliseconds) + captionAnimationDuration: 400, // Duration of the caption animation (in milliseconds) + counterText: "Image {x} of {y}", // Translate or change as you wish, or set it to false to disable counter text for image groups + closeKeys: [27, 88, 67], // Array of keycodes to close Slimbox, default: Esc (27), 'x' (88), 'c' (67) + previousKeys: [37, 80], // Array of keycodes to navigate to the previous image, default: Left arrow (37), 'p' (80) + nextKeys: [39, 78] // Array of keycodes to navigate to the next image, default: Right arrow (39), 'n' (78) + }, _options); + + // The function is called for a single image, with URL and Title as first two arguments + if (typeof _images == "string") { + _images = [[_images, startImage]]; + startImage = 0; + } + + middle = win.scrollTop() + (win.height() / 2); + centerWidth = options.initialWidth; + centerHeight = options.initialHeight; + $(center).css({top: Math.max(0, middle - (centerHeight / 2)), width: centerWidth, height: centerHeight, marginLeft: -centerWidth/2}).show(); + compatibleOverlay = ie6 || (overlay.currentStyle && (overlay.currentStyle.position != "fixed")); + if (compatibleOverlay) overlay.style.position = "absolute"; + $(overlay).css("opacity", options.overlayOpacity).fadeIn(options.overlayFadeDuration); + position(); + setup(1); + + images = _images; + options.loop = options.loop && (images.length > 1); + return changeImage(startImage); + }; + + /* + options: Optional options object, see jQuery.slimbox() + linkMapper: Optional function taking a link DOM element and an index as arguments and returning an array containing 2 elements: + the image URL and the image caption (may contain HTML) + linksFilter: Optional function taking a link DOM element and an index as arguments and returning true if the element is part of + the image collection that will be shown on click, false if not. "this" refers to the element that was clicked. + This function must always return true when the DOM element argument is "this". + */ + $.fn.slimbox = function(_options, linkMapper, linksFilter) { + linkMapper = linkMapper || function(el) { + return [el.href, el.title]; + }; + + linksFilter = linksFilter || function() { + return true; + }; + + var links = this; + + return links.unbind("click").click(function() { + // Build the list of images that will be displayed + var link = this, startIndex = 0, filteredLinks, i = 0, length; + filteredLinks = $.grep(links, function(el, i) { + return linksFilter.call(link, el, i); + }); + + // We cannot use jQuery.map() because it flattens the returned array + for (length = filteredLinks.length; i < length; ++i) { + if (filteredLinks[i] == link) startIndex = i; + filteredLinks[i] = linkMapper(filteredLinks[i], i); + } + + return $.slimbox(filteredLinks, startIndex, _options); + }); + }; + + + /* + Internal functions + */ + + function position() { + var l = win.scrollLeft(), w = win.width(); + $([center, bottomContainer]).css("left", l + (w / 2)); + if (compatibleOverlay) $(overlay).css({left: l, top: win.scrollTop(), width: w, height: win.height()}); + } + + function setup(open) { + if (open) { + $("object").add(ie6 ? "select" : "embed").each(function(index, el) { + hiddenElements[index] = [el, el.style.visibility]; + el.style.visibility = "hidden"; + }); + } else { + $.each(hiddenElements, function(index, el) { + el[0].style.visibility = el[1]; + }); + hiddenElements = []; + } + var fn = open ? "bind" : "unbind"; + win[fn]("scroll resize", position); + $(document)[fn]("keydown", keyDown); + } + + function keyDown(event) { + var code = event.keyCode, fn = $.inArray; + // Prevent default keyboard action (like navigating inside the page) + return (fn(code, options.closeKeys) >= 0) ? close() + : (fn(code, options.nextKeys) >= 0) ? next() + : (fn(code, options.previousKeys) >= 0) ? previous() + : false; + } + + function previous() { + return changeImage(prevImage); + } + + function next() { + return changeImage(nextImage); + } + + function changeImage(imageIndex) { + if (imageIndex >= 0) { + activeImage = imageIndex; + activeURL = images[activeImage][0]; + prevImage = (activeImage || (options.loop ? images.length : 0)) - 1; + nextImage = ((activeImage + 1) % images.length) || (options.loop ? 0 : -1); + + stop(); + center.className = "lbLoading"; + + preload = new Image(); + preload.onload = animateBox; + preload.src = activeURL; + } + + return false; + } + + function animateBox() { + center.className = ""; + $(image).css({backgroundImage: "url(" + activeURL + ")", visibility: "hidden", display: "" }); + $(sizer).width(preload.width); + $([sizer, prevLink, nextLink]).height(preload.height); + + $(caption).html(images[activeImage][1] || ""); + $(number).html((((images.length > 1) && options.counterText) || "").replace(/{x}/, activeImage + 1).replace(/{y}/, images.length)); + + if (prevImage >= 0) preloadPrev.src = images[prevImage][0]; + if (nextImage >= 0) preloadNext.src = images[nextImage][0]; + + centerWidth = image.offsetWidth; + centerHeight = image.offsetHeight; + var top = Math.max(0, middle - (centerHeight / 2)); + if (center.offsetHeight != centerHeight) { + $(center).animate({height: centerHeight, top: top}, options.resizeDuration, options.resizeEasing); + } + if (center.offsetWidth != centerWidth) { + $(center).animate({width: centerWidth, marginLeft: -centerWidth/2}, options.resizeDuration, options.resizeEasing); + } + $(center).queue(function() { + $(bottomContainer).css({width: centerWidth, top: top + centerHeight, marginLeft: -centerWidth/2, visibility: "hidden", display: ""}); + animateCaption(); + $(image).css({display: "none", visibility: "", opacity: ""}).fadeIn(options.imageFadeDuration, animateCaption); + }); + } + + function animateCaption() { + if (prevImage >= 0) $(prevLink).show(); + if (nextImage >= 0) $(nextLink).show(); + $(bottom).css("marginTop", -bottom.offsetHeight).animate({marginTop: 0}, options.captionAnimationDuration); + bottomContainer.style.visibility = ""; + } + + function stop() { + preload.onload = null; + preload.src = preloadPrev.src = preloadNext.src = activeURL; + $([center, image, bottom]).stop(true); + $([prevLink, nextLink, image, bottomContainer]).hide(); + } + + function close() { + if (activeImage >= 0) { + stop(); + activeImage = prevImage = nextImage = -1; + $(center).hide(); + $(overlay).stop().fadeOut(options.overlayFadeDuration, setup); + } + + return false; + } + +})(jQuery); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/slimbox2/slimbox2-rtl.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,84 @@ +/* SLIMBOX */ + +#lbOverlay { + position: fixed; + z-index: 9999; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #000; + cursor: pointer; +} + +#lbCenter, #lbBottomContainer { + position: absolute; + z-index: 9999; + overflow: hidden; + background-color: #fff; +} + +.lbLoading { + background: #fff url(loading.gif) no-repeat center; +} + +#lbImage { + position: absolute; + left: 0; + top: 0; + border: 10px solid #fff; + background-repeat: no-repeat; +} + +#lbPrevLink, #lbNextLink { + display: block; + position: absolute; + top: 0; + width: 50%; + outline: none; +} + +#lbPrevLink { + right: 0; +} + +#lbPrevLink:hover { + background: transparent url(prevlabel.gif) no-repeat 100% 15%; +} + +#lbNextLink { + left: 0; +} + +#lbNextLink:hover { + background: transparent url(nextlabel.gif) no-repeat 0 15%; +} + +#lbBottom { + font-family: Verdana, Arial, Geneva, Helvetica, sans-serif; + font-size: 10px; + color: #666; + line-height: 1.4em; + text-align: right; + border: 10px solid #fff; + border-top-style: none; + direction: rtl; +} + +#lbCloseLink { + display: block; + float: left; + width: 66px; + height: 22px; + background: transparent url(closelabel.gif) no-repeat center; + margin: 5px 0; + outline: none; +} + +#lbCaption, #lbNumber { + margin-left: 71px; +} + +#lbCaption { + font-weight: bold; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/slimbox2/slimbox2.css Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,83 @@ +/* SLIMBOX */ + +#lbOverlay { + position: fixed; + z-index: 9999; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: #000; + cursor: pointer; +} + +#lbCenter, #lbBottomContainer { + position: absolute; + z-index: 9999; + overflow: hidden; + background-color: #fff; +} + +.lbLoading { + background: #fff url(loading.gif) no-repeat center; +} + +#lbImage { + position: absolute; + left: 0; + top: 0; + border: 10px solid #fff; + background-repeat: no-repeat; +} + +#lbPrevLink, #lbNextLink { + display: block; + position: absolute; + top: 0; + width: 50%; + outline: none; +} + +#lbPrevLink { + left: 0; +} + +#lbPrevLink:hover { + background: transparent url(prevlabel.gif) no-repeat 0 15%; +} + +#lbNextLink { + right: 0; +} + +#lbNextLink:hover { + background: transparent url(nextlabel.gif) no-repeat 100% 15%; +} + +#lbBottom { + font-family: Verdana, Arial, Geneva, Helvetica, sans-serif; + font-size: 10px; + color: #666; + line-height: 1.4em; + text-align: left; + border: 10px solid #fff; + border-top-style: none; +} + +#lbCloseLink { + display: block; + float: right; + width: 66px; + height: 22px; + background: transparent url(closelabel.gif) no-repeat center; + margin: 5px 0; + outline: none; +} + +#lbCaption, #lbNumber { + margin-right: 71px; +} + +#lbCaption { + font-weight: bold; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirExplorer/libs/tree.jquery.js Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,1837 @@ +// Generated by CoffeeScript 1.3.3 + +/* +Copyright 2012 Marco Braak + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +(function() { + var $, BorderDropHint, DragAndDropHandler, DragElement, FolderElement, GhostDropHint, JqTreeWidget, Json, MouseWidget, Node, NodeElement, Position, SaveStateHandler, SelectNodeHandler, SimpleWidget, Tree, html_escape, indexOf, toJson, + __slice = [].slice, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + $ = this.jQuery; + + SimpleWidget = (function() { + + SimpleWidget.prototype.defaults = {}; + + function SimpleWidget(el, options) { + this.$el = $(el); + this.options = $.extend({}, this.defaults, options); + this._init(); + } + + SimpleWidget.prototype.destroy = function() { + return this._deinit(); + }; + + SimpleWidget.prototype._init = function() { + return null; + }; + + SimpleWidget.prototype._deinit = function() { + return null; + }; + + SimpleWidget.register = function(widget_class, widget_name) { + var callFunction, createWidget, destroyWidget, getDataKey; + getDataKey = function() { + return "simple_widget_" + widget_name; + }; + createWidget = function($el, options) { + var data_key; + data_key = getDataKey(); + $el.each(function() { + var widget; + widget = new widget_class(this, options); + if (!$.data(this, data_key)) { + return $.data(this, data_key, widget); + } + }); + return $el; + }; + destroyWidget = function($el) { + var data_key; + data_key = getDataKey(); + return $el.each(function() { + var widget; + widget = $.data(this, data_key); + if (widget && (widget instanceof SimpleWidget)) { + widget.destroy(); + } + return $.removeData(this, data_key); + }); + }; + callFunction = function($el, function_name, args) { + var result; + result = null; + $el.each(function() { + var widget, widget_function; + widget = $.data(this, getDataKey()); + if (widget && (widget instanceof SimpleWidget)) { + widget_function = widget[function_name]; + if (widget_function && (typeof widget_function === 'function')) { + return result = widget_function.apply(widget, args); + } + } + }); + return result; + }; + return $.fn[widget_name] = function() { + var $el, args, argument1, function_name, options; + argument1 = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + $el = this; + if (argument1 === void 0 || typeof argument1 === 'object') { + options = argument1; + return createWidget($el, options); + } else if (typeof argument1 === 'string' && argument1[0] !== '_') { + function_name = argument1; + if (function_name === 'destroy') { + return destroyWidget($el); + } else { + return callFunction($el, function_name, args); + } + } + }; + }; + + return SimpleWidget; + + })(); + + this.SimpleWidget = SimpleWidget; + + /* + This widget does the same a the mouse widget in jqueryui. + */ + + + MouseWidget = (function(_super) { + + __extends(MouseWidget, _super); + + function MouseWidget() { + return MouseWidget.__super__.constructor.apply(this, arguments); + } + + MouseWidget.is_mouse_handled = false; + + MouseWidget.prototype._init = function() { + this.$el.bind('mousedown.mousewidget', $.proxy(this._mouseDown, this)); + return this.is_mouse_started = false; + }; + + MouseWidget.prototype._deinit = function() { + var $document; + this.$el.unbind('mousedown.mousewidget'); + $document = $(document); + $document.unbind('mousemove.mousewidget'); + return $document.unbind('mouseup.mousewidget'); + }; + + MouseWidget.prototype._mouseDown = function(e) { + var $document; + if (MouseWidget.is_mouse_handled) { + return; + } + if (!this.is_mouse_started) { + this._mouseUp(e); + } + if (e.which !== 1) { + return; + } + if (!this._mouseCapture(e)) { + return; + } + this.mouse_down_event = e; + $document = $(document); + $document.bind('mousemove.mousewidget', $.proxy(this._mouseMove, this)); + $document.bind('mouseup.mousewidget', $.proxy(this._mouseUp, this)); + e.preventDefault(); + this.is_mouse_handled = true; + return true; + }; + + MouseWidget.prototype._mouseMove = function(e) { + if (this.is_mouse_started) { + this._mouseDrag(e); + return e.preventDefault(); + } + this.is_mouse_started = this._mouseStart(this.mouse_down_event) !== false; + if (this.is_mouse_started) { + this._mouseDrag(e); + } else { + this._mouseUp(e); + } + return !this.is_mouse_started; + }; + + MouseWidget.prototype._mouseUp = function(e) { + var $document; + $document = $(document); + $document.unbind('mousemove.mousewidget'); + $document.unbind('mouseup.mousewidget'); + if (this.is_mouse_started) { + this.is_mouse_started = false; + this._mouseStop(e); + } + return false; + }; + + MouseWidget.prototype._mouseCapture = function(e) { + return true; + }; + + MouseWidget.prototype._mouseStart = function(e) { + return null; + }; + + MouseWidget.prototype._mouseDrag = function(e) { + return null; + }; + + MouseWidget.prototype._mouseStop = function(e) { + return null; + }; + + return MouseWidget; + + })(SimpleWidget); + + /* + Copyright 2012 Marco Braak + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + + + this.Tree = {}; + + $ = this.jQuery; + + indexOf = function(array, item) { + var i, value, _i, _len; + if (array.indexOf) { + return array.indexOf(item); + } else { + for (i = _i = 0, _len = array.length; _i < _len; i = ++_i) { + value = array[i]; + if (value === item) { + return i; + } + } + return -1; + } + }; + + this.Tree.indexOf = indexOf; + + Json = {}; + + Json.escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; + + Json.meta = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"': '\\"', + '\\': '\\\\' + }; + + Json.quote = function(string) { + Json.escapable.lastIndex = 0; + if (Json.escapable.test(string)) { + return '"' + string.replace(Json.escapable, function(a) { + var c; + c = Json.meta[a]; + return (typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)); + }) + '"'; + } else { + return '"' + string + '"'; + } + }; + + Json.str = function(key, holder) { + var i, k, partial, v, value, _i, _len; + value = holder[key]; + switch (typeof value) { + case 'string': + return Json.quote(value); + case 'number': + if (isFinite(value)) { + return String(value); + } else { + return 'null'; + } + case 'boolean': + case 'null': + return String(value); + case 'object': + if (!value) { + return 'null'; + } + partial = []; + if (Object.prototype.toString.apply(value) === '[object Array]') { + for (i = _i = 0, _len = value.length; _i < _len; i = ++_i) { + v = value[i]; + partial[i] = Json.str(i, value) || 'null'; + } + return (partial.length === 0 ? '[]' : '[' + partial.join(',') + ']'); + } + for (k in value) { + if (Object.prototype.hasOwnProperty.call(value, k)) { + v = Json.str(k, value); + if (v) { + partial.push(Json.quote(k) + ':' + v); + } + } + } + return (partial.length === 0 ? '{}' : '{' + partial.join(',') + '}'); + } + }; + + toJson = function(value) { + return Json.str('', { + '': value + }); + }; + + this.Tree.toJson = toJson; + + html_escape = function(string) { + return ('' + string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/'); + }; + + Position = { + getName: function(position) { + if (position === Position.BEFORE) { + return 'before'; + } else if (position === Position.AFTER) { + return 'after'; + } else if (position === Position.INSIDE) { + return 'inside'; + } else { + return 'none'; + } + } + }; + + Position.BEFORE = 1; + + Position.AFTER = 2; + + Position.INSIDE = 3; + + Position.NONE = 4; + + this.Tree.Position = Position; + + Node = (function() { + + function Node(o) { + this.setData(o); + } + + Node.prototype.setData = function(o) { + var key, value; + if (typeof o !== 'object') { + this.name = o; + } else { + for (key in o) { + value = o[key]; + if (key === 'label') { + this.name = value; + } else { + this[key] = value; + } + } + } + this.children = []; + return this.parent = null; + }; + + Node.prototype.initFromData = function(data) { + var addChildren, addNode, + _this = this; + addNode = function(node_data) { + _this.setData(node_data); + if (node_data.children) { + return addChildren(node_data.children); + } + }; + addChildren = function(children_data) { + var child, node, _i, _len; + for (_i = 0, _len = children_data.length; _i < _len; _i++) { + child = children_data[_i]; + node = new Node(''); + node.initFromData(child); + _this.addChild(node); + } + return null; + }; + addNode(data); + return null; + }; + + /* + Create tree from data. + + Structure of data is: + [ + { + label: 'node1', + children: [ + { label: 'child1' }, + { label: 'child2' } + ] + }, + { + label: 'node2' + } + ] + */ + + + Node.prototype.loadFromData = function(data) { + var node, o, _i, _len; + this.children = []; + for (_i = 0, _len = data.length; _i < _len; _i++) { + o = data[_i]; + node = new Node(o); + this.addChild(node); + if (typeof o === 'object' && o.children) { + node.loadFromData(o.children); + } + } + return null; + }; + + /* + Add child. + + tree.addChild( + new Node('child1') + ); + */ + + + Node.prototype.addChild = function(node) { + this.children.push(node); + return node._setParent(this); + }; + + /* + Add child at position. Index starts at 0. + + tree.addChildAtPosition( + new Node('abc'), + 1 + ); + */ + + + Node.prototype.addChildAtPosition = function(node, index) { + this.children.splice(index, 0, node); + return node._setParent(this); + }; + + Node.prototype._setParent = function(parent) { + this.parent = parent; + this.tree = parent.tree; + return this.tree.addNodeToIndex(this); + }; + + /* + Remove child. + + tree.removeChild(tree.children[0]); + */ + + + Node.prototype.removeChild = function(node) { + this.children.splice(this.getChildIndex(node), 1); + return this.tree.removeNodeFromIndex(node); + }; + + /* + Get child index. + + var index = getChildIndex(node); + */ + + + Node.prototype.getChildIndex = function(node) { + return $.inArray(node, this.children); + }; + + /* + Does the tree have children? + + if (tree.hasChildren()) { + // + } + */ + + + Node.prototype.hasChildren = function() { + return this.children.length !== 0; + }; + + /* + Iterate over all the nodes in the tree. + + Calls callback with (node, level). + + The callback must return true to continue the iteration on current node. + + tree.iterate( + function(node, level) { + console.log(node.name); + + // stop iteration after level 2 + return (level <= 2); + } + ); + */ + + + Node.prototype.iterate = function(callback) { + var _iterate, + _this = this; + _iterate = function(node, level) { + var child, result, _i, _len, _ref; + if (node.children) { + _ref = node.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + result = callback(child, level); + if (_this.hasChildren() && result) { + _iterate(child, level + 1); + } + } + return null; + } + }; + _iterate(this, 0); + return null; + }; + + /* + Move node relative to another node. + + Argument position: Position.BEFORE, Position.AFTER or Position.Inside + + // move node1 after node2 + tree.moveNode(node1, node2, Position.AFTER); + */ + + + Node.prototype.moveNode = function(moved_node, target_node, position) { + moved_node.parent.removeChild(moved_node); + if (position === Position.AFTER) { + return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node) + 1); + } else if (position === Position.BEFORE) { + return target_node.parent.addChildAtPosition(moved_node, target_node.parent.getChildIndex(target_node)); + } else if (position === Position.INSIDE) { + return target_node.addChildAtPosition(moved_node, 0); + } + }; + + /* + Get the tree as data. + */ + + + Node.prototype.getData = function() { + var getDataFromNodes, + _this = this; + getDataFromNodes = function(nodes) { + var data, k, node, tmp_node, v, _i, _len; + data = []; + for (_i = 0, _len = nodes.length; _i < _len; _i++) { + node = nodes[_i]; + tmp_node = {}; + for (k in node) { + v = node[k]; + if ((k !== 'parent' && k !== 'children' && k !== 'element' && k !== 'tree') && Object.prototype.hasOwnProperty.call(node, k)) { + tmp_node[k] = v; + } + } + if (node.hasChildren()) { + tmp_node.children = getDataFromNodes(node.children); + } + data.push(tmp_node); + } + return data; + }; + return getDataFromNodes(this.children); + }; + + Node.prototype.getNodeByName = function(name) { + var result; + result = null; + this.iterate(function(node) { + if (node.name === name) { + result = node; + return false; + } else { + return true; + } + }); + return result; + }; + + Node.prototype.addAfter = function(node_info) { + var child_index, node; + if (!this.parent) { + return null; + } else { + node = new Node(node_info); + child_index = this.parent.getChildIndex(this); + this.parent.addChildAtPosition(node, child_index + 1); + return node; + } + }; + + Node.prototype.addBefore = function(node_info) { + var child_index, node; + if (!this.parent) { + return null; + } else { + node = new Node(node_info); + child_index = this.parent.getChildIndex(this); + return this.parent.addChildAtPosition(node, child_index); + } + }; + + Node.prototype.addParent = function(node_info) { + var child, new_parent, original_parent, _i, _len, _ref; + if (!this.parent) { + return null; + } else { + new_parent = new Node(node_info); + new_parent._setParent(this.tree); + original_parent = this.parent; + _ref = original_parent.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + new_parent.addChild(child); + } + original_parent.children = []; + original_parent.addChild(new_parent); + return new_parent; + } + }; + + Node.prototype.remove = function() { + if (this.parent) { + this.parent.removeChild(this); + return this.parent = null; + } + }; + + Node.prototype.append = function(node_info) { + var node; + node = new Node(node_info); + this.addChild(node); + return node; + }; + + Node.prototype.prepend = function(node_info) { + var node; + node = new Node(node_info); + this.addChildAtPosition(node, 0); + return node; + }; + + return Node; + + })(); + + Tree = (function(_super) { + + __extends(Tree, _super); + + function Tree(o) { + Tree.__super__.constructor.call(this, o, null, true); + this.id_mapping = {}; + this.tree = this; + } + + Tree.prototype.getNodeById = function(node_id) { + return this.id_mapping[node_id]; + }; + + Tree.prototype.addNodeToIndex = function(node) { + if (node.id) { + return this.id_mapping[node.id] = node; + } + }; + + Tree.prototype.removeNodeFromIndex = function(node) { + if (node.id) { + return delete this.id_mapping[node.id]; + } + }; + + return Tree; + + })(Node); + + this.Tree.Tree = Tree; + + JqTreeWidget = (function(_super) { + + __extends(JqTreeWidget, _super); + + function JqTreeWidget() { + return JqTreeWidget.__super__.constructor.apply(this, arguments); + } + + JqTreeWidget.prototype.defaults = { + autoOpen: false, + saveState: false, + dragAndDrop: false, + selectable: false, + onCanSelectNode: null, + onSetStateFromStorage: null, + onGetStateFromStorage: null, + onCreateLi: null, + onIsMoveHandle: null, + onCanMove: null, + onCanMoveTo: null, + autoEscape: true, + dataUrl: null + }; + + JqTreeWidget.prototype.toggle = function(node) { + if (node.hasChildren()) { + new FolderElement(node, this.element).toggle(); + } + return this._saveState(); + }; + + JqTreeWidget.prototype.getTree = function() { + return this.tree; + }; + + JqTreeWidget.prototype.selectNode = function(node, must_open_parents) { + return this.select_node_handler.selectNode(node, must_open_parents); + }; + + JqTreeWidget.prototype.getSelectedNode = function() { + return this.selected_node || false; + }; + + JqTreeWidget.prototype.toJson = function() { + return toJson(this.tree.getData()); + }; + + JqTreeWidget.prototype.loadData = function(data, parent_node) { + var child, subtree, _i, _len, _ref; + if (!parent_node) { + this._initTree(data); + } else { + subtree = new Node(''); + subtree._setParent(parent_node.tree); + subtree.loadFromData(data); + _ref = subtree.children; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + parent_node.addChild(child); + } + this._refreshElements(parent_node.parent); + } + if (this.is_dragging) { + return this.dnd_handler.refreshHitAreas(); + } + }; + + JqTreeWidget.prototype.getNodeById = function(node_id) { + return this.tree.getNodeById(node_id); + }; + + JqTreeWidget.prototype.getNodeByName = function(name) { + return this.tree.getNodeByName(name); + }; + + JqTreeWidget.prototype.openNode = function(node, skip_slide) { + if (node.hasChildren()) { + new FolderElement(node, this.element).open(null, skip_slide); + return this._saveState(); + } + }; + + JqTreeWidget.prototype.closeNode = function(node, skip_slide) { + if (node.hasChildren()) { + new FolderElement(node, this.element).close(skip_slide); + return this._saveState(); + } + }; + + JqTreeWidget.prototype.isDragging = function() { + return this.is_dragging; + }; + + JqTreeWidget.prototype.refreshHitAreas = function() { + return this.dnd_handler.refreshHitAreas(); + }; + + JqTreeWidget.prototype.addNodeAfter = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addAfter(new_node_info); + this._refreshElements(existing_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.addNodeBefore = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addBefore(new_node_info); + this._refreshElements(existing_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.addParentNode = function(new_node_info, existing_node) { + var new_node; + new_node = existing_node.addParent(new_node_info); + this._refreshElements(new_node.parent); + return new_node; + }; + + JqTreeWidget.prototype.removeNode = function(node) { + var parent; + parent = node.parent; + if (parent) { + node.remove(); + return this._refreshElements(parent.parent); + } + }; + + JqTreeWidget.prototype.appendNode = function(new_node_info, parent_node) { + var is_already_root_node, node; + if (!parent_node) { + parent_node = this.tree; + } + is_already_root_node = parent_node.hasChildren(); + node = parent_node.append(new_node_info); + if (is_already_root_node) { + this._refreshElements(parent_node); + } else { + this._refreshElements(parent_node.parent); + } + return node; + }; + + JqTreeWidget.prototype.prependNode = function(new_node_info, parent_node) { + var node; + if (!parent_node) { + parent_node = this.tree; + } + node = parent_node.prepend(new_node_info); + this._refreshElements(parent_node); + return node; + }; + + JqTreeWidget.prototype._init = function() { + JqTreeWidget.__super__._init.call(this); + this.element = this.$el; + this._initData(); + this.element.click($.proxy(this._click, this)); + return this.element.bind('contextmenu', $.proxy(this._contextmenu, this)); + }; + + JqTreeWidget.prototype._deinit = function() { + this.element.empty(); + this.element.unbind(); + this.tree = null; + return JqTreeWidget.__super__._deinit.call(this); + }; + + JqTreeWidget.prototype._initData = function() { + var data_url, + _this = this; + if (this.options.data) { + return this._initTree(this.options.data); + } else { + data_url = this.options.dataUrl || this.element.data('url'); + if (data_url) { + return $.ajax({ + url: data_url, + cache: false, + success: function(response) { + var data; + if ($.isArray(response) || typeof response === 'object') { + data = response; + } else { + data = $.parseJSON(response); + } + return _this._initTree(data); + } + }); + } + } + }; + + JqTreeWidget.prototype._initTree = function(data) { + var event; + this.tree = new Tree(); + this.tree.loadFromData(data); + this.selected_node = null; + this.save_state_handler = new SaveStateHandler(this); + this.select_node_handler = new SelectNodeHandler(this); + this.dnd_handler = new DragAndDropHandler(this); + this._openNodes(); + this._refreshElements(); + this.select_node_handler.selectCurrentNode(); + event = $.Event('tree.init'); + return this.element.trigger(event); + }; + + JqTreeWidget.prototype._openNodes = function() { + var max_level; + if (this.options.saveState) { + if (this.save_state_handler.restoreState()) { + return; + } + } + if (this.options.autoOpen === false) { + return; + } else if (this.options.autoOpen === true) { + max_level = -1; + } else { + max_level = parseInt(this.options.autoOpen); + } + return this.tree.iterate(function(node, level) { + node.is_open = true; + return level !== max_level; + }); + }; + + JqTreeWidget.prototype._refreshElements = function(from_node) { + var $element, createFolderLi, createLi, createNodeLi, createUl, doCreateDomElements, escapeIfNecessary, is_root_node, node_element, + _this = this; + if (from_node == null) { + from_node = null; + } + escapeIfNecessary = function(value) { + if (_this.options.autoEscape) { + return html_escape(value); + } else { + return value; + } + }; + createUl = function(is_root_node) { + var class_string; + if (is_root_node) { + class_string = ' class="tree"'; + } else { + class_string = ''; + } + return $("<ul" + class_string + "></ul>"); + }; + createLi = function(node) { + var $li; + if (node.hasChildren()) { + $li = createFolderLi(node); + } else { + $li = createNodeLi(node); + } + if (_this.options.onCreateLi) { + _this.options.onCreateLi(node, $li); + } + return $li; + }; + createNodeLi = function(node) { + var escaped_name; + escaped_name = escapeIfNecessary(node.name); + return $("<li><div><span class=\"title\">" + escaped_name + "</span></div></li>"); + }; + createFolderLi = function(node) { + var button_class, escaped_name, folder_class, getButtonClass, getFolderClass; + getButtonClass = function() { + var classes; + classes = ['toggler']; + if (!node.is_open) { + classes.push('closed'); + } + return classes.join(' '); + }; + getFolderClass = function() { + var classes; + classes = ['folder']; + if (!node.is_open) { + classes.push('closed'); + } + return classes.join(' '); + }; + button_class = getButtonClass(); + folder_class = getFolderClass(); + escaped_name = escapeIfNecessary(node.name); + return $("<li class=\"" + folder_class + "\"><div><a class=\"" + button_class + "\">»</a><span class=\"title\">" + escaped_name + "</span></div></li>"); + }; + doCreateDomElements = function($element, children, is_root_node, is_open) { + var $li, $ul, child, _i, _len; + $ul = createUl(is_root_node); + $element.append($ul); + for (_i = 0, _len = children.length; _i < _len; _i++) { + child = children[_i]; + $li = createLi(child); + $ul.append($li); + child.element = $li[0]; + $li.data('node', child); + if (child.hasChildren()) { + doCreateDomElements($li, child.children, false, child.is_open); + } + } + return null; + }; + if (from_node && from_node.parent) { + is_root_node = false; + node_element = this._getNodeElementForNode(from_node); + node_element.getUl().remove(); + $element = node_element.$element; + } else { + from_node = this.tree; + $element = this.element; + $element.empty(); + is_root_node = true; + } + return doCreateDomElements($element, from_node.children, is_root_node, is_root_node); + }; + + JqTreeWidget.prototype._click = function(e) { + var $target, event, node, node_element; + if (e.ctrlKey) { + return; + } + $target = $(e.target); + if ($target.is('.toggler')) { + node_element = this._getNodeElement($target); + if (node_element && node_element.node.hasChildren()) { + node_element.toggle(); + this._saveState(); + e.preventDefault(); + return e.stopPropagation(); + } + } else if ($target.is('div') || $target.is('span')) { + node = this._getNode($target); + if (node) { + if ((!this.options.onCanSelectNode) || this.options.onCanSelectNode(node)) { + this.selectNode(node); + event = $.Event('tree.click'); + event.node = node; + return this.element.trigger(event); + } + } + } + }; + + JqTreeWidget.prototype._getNode = function($element) { + var $li; + $li = $element.closest('li'); + if ($li.length === 0) { + return null; + } else { + return $li.data('node'); + } + }; + + JqTreeWidget.prototype._getNodeElementForNode = function(node) { + if (node.hasChildren()) { + return new FolderElement(node, this.element); + } else { + return new NodeElement(node, this.element); + } + }; + + JqTreeWidget.prototype._getNodeElement = function($element) { + var node; + node = this._getNode($element); + if (node) { + return this._getNodeElementForNode(node); + } else { + return null; + } + }; + + JqTreeWidget.prototype._contextmenu = function(e) { + var $div, event, node; + $div = $(e.target).closest('ul.tree div'); + if ($div.length) { + node = this._getNode($div); + if (node) { + e.preventDefault(); + e.stopPropagation(); + event = $.Event('tree.contextmenu'); + event.node = node; + event.click_event = e; + this.element.trigger(event); + return false; + } + } + }; + + JqTreeWidget.prototype._saveState = function() { + if (this.options.saveState) { + return this.save_state_handler.saveState(); + } + }; + + JqTreeWidget.prototype._mouseCapture = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseCapture(event); + } else { + return false; + } + }; + + JqTreeWidget.prototype._mouseStart = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseStart(event); + } else { + return false; + } + }; + + JqTreeWidget.prototype._mouseDrag = function(event) { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseDrag(event); + } else { + return false; + } + }; + + JqTreeWidget.prototype._mouseStop = function() { + if (this.options.dragAndDrop) { + return this.dnd_handler.mouseStop(); + } else { + return false; + } + }; + + JqTreeWidget.prototype.testGenerateHitAreas = function(moving_node) { + this.dnd_handler.current_item = this._getNodeElementForNode(moving_node); + this.dnd_handler.generateHitAreas(); + return this.dnd_handler.hit_areas; + }; + + return JqTreeWidget; + + })(MouseWidget); + + SimpleWidget.register(JqTreeWidget, 'tree'); + + GhostDropHint = (function() { + + function GhostDropHint(node, $element, position) { + this.$element = $element; + this.node = node; + this.$ghost = $('<li class="ghost"><span class="circle"></span><span class="line"></span></li>'); + if (position === Position.AFTER) { + this.moveAfter(); + } else if (position === Position.BEFORE) { + this.moveBefore(); + } else if (position === Position.INSIDE) { + if (node.hasChildren() && node.is_open) { + this.moveInsideOpenFolder(); + } else { + this.moveInside(); + } + } + } + + GhostDropHint.prototype.remove = function() { + return this.$ghost.remove(); + }; + + GhostDropHint.prototype.moveAfter = function() { + return this.$element.after(this.$ghost); + }; + + GhostDropHint.prototype.moveBefore = function() { + return this.$element.before(this.$ghost); + }; + + GhostDropHint.prototype.moveInsideOpenFolder = function() { + return $(this.node.children[0].element).before(this.$ghost); + }; + + GhostDropHint.prototype.moveInside = function() { + this.$element.after(this.$ghost); + return this.$ghost.addClass('inside'); + }; + + return GhostDropHint; + + })(); + + BorderDropHint = (function() { + + function BorderDropHint($element) { + var $div, width; + $div = $element.children('div'); + width = $element.width() - 4; + this.$hint = $('<span class="border"></span>'); + $div.append(this.$hint); + this.$hint.css({ + width: width, + height: $div.height() - 4 + }); + } + + BorderDropHint.prototype.remove = function() { + return this.$hint.remove(); + }; + + return BorderDropHint; + + })(); + + NodeElement = (function() { + + function NodeElement(node, tree_element) { + this.init(node, tree_element); + } + + NodeElement.prototype.init = function(node, tree_element) { + this.node = node; + this.tree_element = tree_element; + return this.$element = $(node.element); + }; + + NodeElement.prototype.getUl = function() { + return this.$element.children('ul:first'); + }; + + NodeElement.prototype.getSpan = function() { + return this.$element.children('div').find('span.title'); + }; + + NodeElement.prototype.getLi = function() { + return this.$element; + }; + + NodeElement.prototype.addDropHint = function(position) { + if (position === Position.INSIDE) { + return new BorderDropHint(this.$element); + } else { + return new GhostDropHint(this.node, this.$element, position); + } + }; + + NodeElement.prototype.select = function() { + return this.getLi().addClass('selected'); + }; + + NodeElement.prototype.deselect = function() { + return this.getLi().removeClass('selected'); + }; + + return NodeElement; + + })(); + + FolderElement = (function(_super) { + + __extends(FolderElement, _super); + + function FolderElement() { + return FolderElement.__super__.constructor.apply(this, arguments); + } + + FolderElement.prototype.toggle = function() { + if (this.node.is_open) { + return this.close(); + } else { + return this.open(); + } + }; + + FolderElement.prototype.open = function(on_finished, skip_slide) { + var doOpen, + _this = this; + if (!this.node.is_open) { + this.node.is_open = true; + this.getButton().removeClass('closed'); + doOpen = function() { + var event; + _this.getLi().removeClass('closed'); + if (on_finished) { + on_finished(); + } + event = $.Event('tree.open'); + event.node = _this.node; + return _this.tree_element.trigger(event); + }; + if (skip_slide) { + return doOpen(); + } else { + return this.getUl().slideDown('fast', doOpen); + } + } + }; + + FolderElement.prototype.close = function(skip_slide) { + var doClose, + _this = this; + if (this.node.is_open) { + this.node.is_open = false; + this.getButton().addClass('closed'); + doClose = function() { + var event; + _this.getLi().addClass('closed'); + event = $.Event('tree.close'); + event.node = _this.node; + return _this.tree_element.trigger(event); + }; + if (skip_slide) { + return doClose(); + } else { + return this.getUl().slideUp('fast', doClose); + } + } + }; + + FolderElement.prototype.getButton = function() { + return this.$element.children('div').find('a.toggler'); + }; + + FolderElement.prototype.addDropHint = function(position) { + if (!this.node.is_open && position === Position.INSIDE) { + return new BorderDropHint(this.$element); + } else { + return new GhostDropHint(this.node, this.$element, position); + } + }; + + return FolderElement; + + })(NodeElement); + + DragElement = (function() { + + function DragElement(node, offset_x, offset_y, $tree) { + this.offset_x = offset_x; + this.offset_y = offset_y; + this.$element = $("<span class=\"title tree-dragging\">" + node.name + "</span>"); + this.$element.css("position", "absolute"); + $tree.append(this.$element); + } + + DragElement.prototype.move = function(page_x, page_y) { + return this.$element.offset({ + left: page_x - this.offset_x, + top: page_y - this.offset_y + }); + }; + + DragElement.prototype.remove = function() { + return this.$element.remove(); + }; + + return DragElement; + + })(); + + SaveStateHandler = (function() { + + function SaveStateHandler(tree_widget) { + this.tree_widget = tree_widget; + } + + SaveStateHandler.prototype.saveState = function() { + if (this.tree_widget.options.onSetStateFromStorage) { + return this.tree_widget.options.onSetStateFromStorage(this.getState()); + } else if (typeof localStorage !== "undefined" && localStorage !== null) { + return localStorage.setItem(this.getCookieName(), this.getState()); + } else if ($.cookie) { + return $.cookie(this.getCookieName(), this.getState(), { + path: '/' + }); + } + }; + + SaveStateHandler.prototype.restoreState = function() { + var state; + if (this.tree_widget.options.onGetStateFromStorage) { + state = this.tree_widget.options.onGetStateFromStorage(); + } else if (typeof localStorage !== "undefined" && localStorage !== null) { + state = localStorage.getItem(this.getCookieName()); + } else if ($.cookie) { + state = $.cookie(this.getCookieName(), { + path: '/' + }); + } else { + state = null; + } + if (!state) { + return false; + } else { + this.setState(state); + return true; + } + }; + + SaveStateHandler.prototype.getState = function() { + var open_nodes, selected_node, + _this = this; + open_nodes = []; + this.tree_widget.tree.iterate(function(node) { + if (node.is_open && node.id && node.hasChildren()) { + open_nodes.push(node.id); + } + return true; + }); + selected_node = ''; + if (this.tree_widget.selected_node) { + selected_node = this.tree_widget.selected_node.id; + } + return toJson({ + open_nodes: open_nodes, + selected_node: selected_node + }); + }; + + SaveStateHandler.prototype.setState = function(state) { + var data, open_nodes, selected_node_id, + _this = this; + data = $.parseJSON(state); + if (data) { + open_nodes = data.open_nodes; + selected_node_id = data.selected_node; + return this.tree_widget.tree.iterate(function(node) { + if (node.id && node.hasChildren() && (indexOf(open_nodes, node.id) >= 0)) { + node.is_open = true; + } + if (selected_node_id && (node.id === selected_node_id)) { + _this.tree_widget.selected_node = node; + } + return true; + }); + } + }; + + SaveStateHandler.prototype.getCookieName = function() { + if (typeof this.tree_widget.options.saveState === 'string') { + return this.tree_widget.options.saveState; + } else { + return 'tree'; + } + }; + + return SaveStateHandler; + + })(); + + SelectNodeHandler = (function() { + + function SelectNodeHandler(tree_widget) { + this.tree_widget = tree_widget; + } + + SelectNodeHandler.prototype.selectNode = function(node, must_open_parents) { + var parent; + if (this.tree_widget.options.selectable) { + if (this.tree_widget.selected_node) { + this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node).deselect(); + this.tree_widget.selected_node = null; + } + if (node) { + this.tree_widget._getNodeElementForNode(node).select(); + this.tree_widget.selected_node = node; + if (must_open_parents) { + parent = this.tree_widget.selected_node.parent; + while (parent) { + if (!parent.is_open) { + this.tree_widget.openNode(parent, true); + } + parent = parent.parent; + } + } + } + if (this.tree_widget.options.saveState) { + return this.tree_widget.save_state_handler.saveState(); + } + } + }; + + SelectNodeHandler.prototype.selectCurrentNode = function() { + var node_element; + if (this.tree_widget.selected_node) { + node_element = this.tree_widget._getNodeElementForNode(this.tree_widget.selected_node); + if (node_element) { + return node_element.select(); + } + } + }; + + return SelectNodeHandler; + + })(); + + DragAndDropHandler = (function() { + + function DragAndDropHandler(tree_widget) { + this.tree_widget = tree_widget; + this.hovered_area = null; + this.$ghost = null; + this.hit_areas = []; + this.is_dragging = false; + } + + DragAndDropHandler.prototype.mouseCapture = function(event) { + var $element, node_element; + $element = $(event.target); + if (this.tree_widget.options.onIsMoveHandle && !this.tree_widget.options.onIsMoveHandle($element)) { + return null; + } + node_element = this.tree_widget._getNodeElement($element); + if (node_element && this.tree_widget.options.onCanMove) { + if (!this.tree_widget.options.onCanMove(node_element.node)) { + node_element = null; + } + } + this.current_item = node_element; + return this.current_item !== null; + }; + + DragAndDropHandler.prototype.mouseStart = function(event) { + var offsetX, offsetY, _ref; + this.refreshHitAreas(); + _ref = this.getOffsetFromEvent(event), offsetX = _ref[0], offsetY = _ref[1]; + this.drag_element = new DragElement(this.current_item.node, offsetX, offsetY, this.tree_widget.element); + this.is_dragging = true; + this.current_item.$element.addClass('moving'); + return true; + }; + + DragAndDropHandler.prototype.mouseDrag = function(event) { + var area, position_name; + this.drag_element.move(event.pageX, event.pageY); + area = this.findHoveredArea(event.pageX, event.pageY); + if (area && this.tree_widget.options.onCanMoveTo) { + position_name = Position.getName(area.position); + if (!this.tree_widget.options.onCanMoveTo(this.current_item.node, area.node, position_name)) { + area = null; + } + } + if (!area) { + this.removeDropHint(); + this.removeHover(); + this.stopOpenFolderTimer(); + } else { + if (this.hovered_area !== area) { + this.hovered_area = area; + this.updateDropHint(); + } + } + return true; + }; + + DragAndDropHandler.prototype.mouseStop = function() { + this.moveItem(); + this.clear(); + this.removeHover(); + this.removeDropHint(); + this.removeHitAreas(); + this.current_item.$element.removeClass('moving'); + this.is_dragging = false; + return false; + }; + + DragAndDropHandler.prototype.getOffsetFromEvent = function(event) { + var element_offset; + element_offset = $(event.target).offset(); + return [event.pageX - element_offset.left, event.pageY - element_offset.top]; + }; + + DragAndDropHandler.prototype.refreshHitAreas = function() { + this.removeHitAreas(); + return this.generateHitAreas(); + }; + + DragAndDropHandler.prototype.removeHitAreas = function() { + return this.hit_areas = []; + }; + + DragAndDropHandler.prototype.clear = function() { + this.drag_element.remove(); + return this.drag_element = null; + }; + + DragAndDropHandler.prototype.removeDropHint = function() { + if (this.previous_ghost) { + return this.previous_ghost.remove(); + } + }; + + DragAndDropHandler.prototype.removeHover = function() { + return this.hovered_area = null; + }; + + DragAndDropHandler.prototype.generateHitAreas = function() { + var addPosition, getTop, groupPositions, handleAfterOpenFolder, handleClosedFolder, handleFirstNode, handleNode, handleOpenFolder, hit_areas, last_top, positions, + _this = this; + positions = []; + last_top = 0; + getTop = function($element) { + return $element.offset().top; + }; + addPosition = function(node, position, top) { + positions.push({ + top: top, + node: node, + position: position + }); + return last_top = top; + }; + groupPositions = function(handle_group) { + var group, position, previous_top, _i, _len; + previous_top = -1; + group = []; + for (_i = 0, _len = positions.length; _i < _len; _i++) { + position = positions[_i]; + if (position.top !== previous_top) { + if (group.length) { + handle_group(group, previous_top, position.top); + } + previous_top = position.top; + group = []; + } + group.push(position); + } + return handle_group(group, previous_top, _this.tree_widget.element.offset().top + _this.tree_widget.element.height()); + }; + handleNode = function(node, next_node, $element) { + var top; + top = getTop($element); + if (node === _this.current_item.node) { + addPosition(node, Position.NONE, top); + } else { + addPosition(node, Position.INSIDE, top); + } + if (next_node === _this.current_item.node || node === _this.current_item.node) { + return addPosition(node, Position.NONE, top); + } else { + return addPosition(node, Position.AFTER, top); + } + }; + handleOpenFolder = function(node, $element) { + if (node === _this.current_item.node) { + return false; + } + if (node.children[0] !== _this.current_item.node) { + addPosition(node, Position.INSIDE, getTop($element)); + } + return true; + }; + handleAfterOpenFolder = function(node, next_node, $element) { + if (node === _this.current_item.node || next_node === _this.current_item.node) { + return addPosition(node, Position.NONE, last_top); + } else { + return addPosition(node, Position.AFTER, last_top); + } + }; + handleClosedFolder = function(node, next_node, $element) { + var top; + top = getTop($element); + if (node === _this.current_item.node) { + return addPosition(node, Position.NONE, top); + } else { + addPosition(node, Position.INSIDE, top); + if (next_node !== _this.current_item.node) { + return addPosition(node, Position.AFTER, top); + } + } + }; + handleFirstNode = function(node, $element) { + if (node !== _this.current_item.node) { + return addPosition(node, Position.BEFORE, getTop($(node.element))); + } + }; + this.iterateVisibleNodes(handleNode, handleOpenFolder, handleClosedFolder, handleAfterOpenFolder, handleFirstNode); + hit_areas = []; + groupPositions(function(positions_in_group, top, bottom) { + var area_height, area_top, position, _i, _len; + area_height = (bottom - top) / positions_in_group.length; + area_top = top; + for (_i = 0, _len = positions_in_group.length; _i < _len; _i++) { + position = positions_in_group[_i]; + hit_areas.push({ + top: area_top, + bottom: area_top + area_height, + node: position.node, + position: position.position + }); + area_top += area_height; + } + return null; + }); + return this.hit_areas = hit_areas; + }; + + DragAndDropHandler.prototype.iterateVisibleNodes = function(handle_node, handle_open_folder, handle_closed_folder, handle_after_open_folder, handle_first_node) { + var is_first_node, iterate, + _this = this; + is_first_node = true; + iterate = function(node, next_node) { + var $element, child, children_length, i, must_iterate_inside, _i, _len, _ref; + must_iterate_inside = (node.is_open || !node.element) && node.hasChildren(); + if (node.element) { + $element = $(node.element); + if (!$element.is(':visible')) { + return; + } + if (is_first_node) { + handle_first_node(node, $element); + is_first_node = false; + } + if (!node.hasChildren()) { + handle_node(node, next_node, $element); + } else if (node.is_open) { + if (!handle_open_folder(node, $element)) { + must_iterate_inside = false; + } + } else { + handle_closed_folder(node, next_node, $element); + } + } + if (must_iterate_inside) { + children_length = node.children.length; + _ref = node.children; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + child = _ref[i]; + if (i === (children_length - 1)) { + iterate(node.children[i], null); + } else { + iterate(node.children[i], node.children[i + 1]); + } + } + if (node.is_open) { + return handle_after_open_folder(node, next_node, $element); + } + } + }; + return iterate(this.tree_widget.tree); + }; + + DragAndDropHandler.prototype.findHoveredArea = function(x, y) { + var area, high, low, mid, tree_offset; + tree_offset = this.tree_widget.element.offset(); + if (x < tree_offset.left || y < tree_offset.top || x > (tree_offset.left + this.tree_widget.element.width()) || y > (tree_offset.top + this.tree_widget.element.height())) { + return null; + } + low = 0; + high = this.hit_areas.length; + while (low < high) { + mid = (low + high) >> 1; + area = this.hit_areas[mid]; + if (y < area.top) { + high = mid; + } else if (y > area.bottom) { + low = mid + 1; + } else { + return area; + } + } + return null; + }; + + DragAndDropHandler.prototype.updateDropHint = function() { + var node, node_element; + this.stopOpenFolderTimer(); + if (!this.hovered_area) { + return; + } + node = this.hovered_area.node; + if (node.hasChildren() && !node.is_open && this.hovered_area.position === Position.INSIDE) { + this.startOpenFolderTimer(node); + } + this.removeDropHint(); + node_element = this.tree_widget._getNodeElementForNode(this.hovered_area.node); + return this.previous_ghost = node_element.addDropHint(this.hovered_area.position); + }; + + DragAndDropHandler.prototype.startOpenFolderTimer = function(folder) { + var openFolder, + _this = this; + openFolder = function() { + return _this.tree_widget._getNodeElementForNode(folder).open(function() { + _this.refreshHitAreas(); + return _this.updateDropHint(); + }); + }; + return this.open_folder_timer = setTimeout(openFolder, 500); + }; + + DragAndDropHandler.prototype.stopOpenFolderTimer = function() { + if (this.open_folder_timer) { + clearTimeout(this.open_folder_timer); + return this.open_folder_timer = null; + } + }; + + DragAndDropHandler.prototype.moveItem = function() { + var doMove, event, moved_node, position, previous_parent, target_node, + _this = this; + if (this.hovered_area && this.hovered_area.position !== Position.NONE) { + moved_node = this.current_item.node; + target_node = this.hovered_area.node; + position = this.hovered_area.position; + previous_parent = moved_node.parent; + if (position === Position.INSIDE) { + this.hovered_area.node.is_open = true; + } + doMove = function() { + _this.tree_widget.tree.moveNode(moved_node, target_node, position); + _this.tree_widget.element.empty(); + return _this.tree_widget._refreshElements(); + }; + event = $.Event('tree.move'); + event.move_info = { + moved_node: moved_node, + target_node: target_node, + position: Position.getName(position), + previous_parent: previous_parent, + do_move: doMove + }; + this.tree_widget.element.trigger(event); + if (!event.isDefaultPrevented()) { + return doMove(); + } + } + }; + + return DragAndDropHandler; + + })(); + + this.Tree.Node = Node; + +}).call(this);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomIntegerPixelAccessor.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,149 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomIntegerPixelAccessor.h" + +#include "../Core/PalantirException.h" +#include "FromDcmtkBridge.h" +#include <boost/lexical_cast.hpp> + +namespace Palantir +{ + DicomIntegerPixelAccessor::DicomIntegerPixelAccessor(const DicomMap& values, + const void* pixelData, + size_t size) : + pixelData_(pixelData), + size_(size) + { + unsigned int bitsAllocated; + unsigned int bitsStored; + unsigned int highBit; + unsigned int pixelRepresentation; + + try + { + width_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "Columns").AsString()); + height_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "Rows").AsString()); + samplesPerPixel_ = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "SamplesPerPixel").AsString()); + bitsAllocated = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "BitsAllocated").AsString()); + bitsStored = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "BitsStored").AsString()); + highBit = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "HighBit").AsString()); + pixelRepresentation = boost::lexical_cast<unsigned int>(FromDcmtkBridge::GetValue(values, "PixelRepresentation").AsString()); + } + catch (boost::bad_lexical_cast) + { + throw PalantirException(ErrorCode_NotImplemented); + } + + if (bitsAllocated != 8 && bitsAllocated != 16 && + bitsAllocated != 24 && bitsAllocated != 32) + { + throw PalantirException(ErrorCode_NotImplemented); + } + + if (bitsAllocated > 32 || + bitsStored >= 32) + { + // Not available, as the accessor internally uses int32_t values + throw PalantirException(ErrorCode_NotImplemented); + } + + if (samplesPerPixel_ != 1) + { + throw PalantirException(ErrorCode_NotImplemented); + } + + if (width_ * height_ * bitsAllocated / 8 != size) + { + throw PalantirException(ErrorCode_NotImplemented); + } + + printf("%d %d %d %d %d %d %d\n", width_, height_, samplesPerPixel_, bitsAllocated, + bitsStored, highBit, pixelRepresentation); + + bytesPerPixel_ = bitsAllocated / 8; + shift_ = highBit + 1 - bitsStored; + + if (pixelRepresentation) + { + mask_ = (1 << (bitsStored - 1)) - 1; + signMask_ = (1 << (bitsStored - 1)); + } + else + { + mask_ = (1 << bitsStored) - 1; + signMask_ = 0; + } + } + + + void DicomIntegerPixelAccessor::GetExtremeValues(int32_t& min, + int32_t& max) const + { + if (height_ == 0 || width_ == 0) + { + min = max = 0; + return; + } + + min = std::numeric_limits<int32_t>::max(); + max = std::numeric_limits<int32_t>::min(); + + for (unsigned int y = 0; y < height_; y++) + { + for (unsigned int x = 0; x < width_; x++) + { + int32_t v = GetValue(x, y); + if (v < min) + min = v; + if (v > max) + max = v; + } + } + } + + + int32_t DicomIntegerPixelAccessor::GetValue(unsigned int x, unsigned int y) const + { + assert(x < width_ && y < height_); + + const uint8_t* pixel = reinterpret_cast<const uint8_t*>(pixelData_) + (y * width_ + x) * bytesPerPixel_; + + int32_t v; + v = pixel[0]; + if (bytesPerPixel_ >= 2) + v = v + (static_cast<int32_t>(pixel[1]) << 8); + if (bytesPerPixel_ >= 3) + v = v + (static_cast<int32_t>(pixel[2]) << 16); + if (bytesPerPixel_ >= 4) + v = v + (static_cast<int32_t>(pixel[3]) << 24); + + v = (v >> shift_) & mask_; + + if (v & signMask_) + { + // Signed value: Not implemented yet + //throw PalantirException(ErrorCode_NotImplemented); + v = 0; + } + + return v; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomIntegerPixelAccessor.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,63 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/DicomFormat/DicomMap.h" + +#include <stdint.h> + +namespace Palantir +{ + class DicomIntegerPixelAccessor + { + private: + unsigned int width_; + unsigned int height_; + unsigned int samplesPerPixel_; + const void* pixelData_; + size_t size_; + + uint8_t shift_; + uint32_t signMask_; + uint32_t mask_; + size_t bytesPerPixel_; + + public: + DicomIntegerPixelAccessor(const DicomMap& values, + const void* pixelData, + size_t size); + + unsigned int GetWidth() const + { + return width_; + } + + unsigned int GetHeight() const + { + return height_; + } + + void GetExtremeValues(int32_t& min, + int32_t& max) const; + + int32_t GetValue(unsigned int x, unsigned int y) const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/DicomFindAnswers.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,54 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomFindAnswers.h" + +#include "../FromDcmtkBridge.h" + +namespace Palantir +{ + void DicomFindAnswers::Clear() + { + for (size_t i = 0; i < items_.size(); i++) + { + delete items_[i]; + } + } + + void DicomFindAnswers::Reserve(size_t size) + { + if (size > items_.size()) + { + items_.reserve(size); + } + } + + void DicomFindAnswers::ToJson(Json::Value& target) const + { + target = Json::arrayValue; + + for (size_t i = 0; i < GetSize(); i++) + { + Json::Value answer(Json::objectValue); + FromDcmtkBridge::ToJson(answer, GetAnswer(i)); + target.append(answer); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/DicomFindAnswers.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,62 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../../Core/DicomFormat/DicomMap.h" + +#include <vector> +#include <json/json.h> + +namespace Palantir +{ + class DicomFindAnswers + { + private: + std::vector<DicomMap*> items_; + + public: + ~DicomFindAnswers() + { + Clear(); + } + + void Clear(); + + void Reserve(size_t index); + + void Add(const DicomMap& map) + { + items_.push_back(map.Clone()); + } + + size_t GetSize() const + { + return items_.size(); + } + + const DicomMap& GetAnswer(size_t index) const + { + return *items_.at(index); + } + + void ToJson(Json::Value& target) const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/DicomServer.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,305 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomServer.h" + +#include "../../Core/PalantirException.h" +#include "../../Core/Toolbox.h" +#include "../Internals/CommandDispatcher.h" + +#include <boost/thread.hpp> +#include <dcmtk/dcmdata/dcdict.h> + + +namespace Palantir +{ + struct DicomServer::PImpl + { + boost::thread thread_; + + //std::set< + }; + + + namespace Internals + { + OFLogger Logger = OFLog::getLogger("dcmtk.apps.storescp"); + } + + + void DicomServer::ServerThread(DicomServer* server) + { + /* Disable "gethostbyaddr" (which results in memory leaks) and use raw IP addresses */ + dcmDisableGethostbyaddr.set(OFTrue); + + /* make sure data dictionary is loaded */ + if (!dcmDataDict.isDictionaryLoaded()) + { + OFLOG_WARN(Internals::Logger, "no data dictionary loaded, check environment variable: " + << DCM_DICT_ENVIRONMENT_VARIABLE); + } + + /* initialize network, i.e. create an instance of T_ASC_Network*. */ + T_ASC_Network *net; + OFCondition cond = ASC_initializeNetwork + (NET_ACCEPTOR, OFstatic_cast(int, server->port_), /*opt_acse_timeout*/ 30, &net); + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, "cannot create network: " << DimseCondition::dump(temp_str, cond)); + throw PalantirException("Cannot create network"); + } + + OFLOG_WARN(Internals::Logger, "DICOM server started"); + + server->started_ = true; + + while (server->continue_) + { + /* receive an association and acknowledge or reject it. If the association was */ + /* acknowledged, offer corresponding services and invoke one or more if required. */ + std::auto_ptr<Internals::CommandDispatcher> dispatcher(Internals::AcceptAssociation(*server, net)); + + if (dispatcher.get() != NULL) + { + if (server->isThreaded_) + { + server->bagOfDispatchers_.Add(dispatcher.release()); + } + else + { + IRunnableBySteps::RunUntilDone(*dispatcher); + } + } + } + + OFLOG_WARN(Internals::Logger, "DICOM server stopping"); + + /* drop the network, i.e. free memory of T_ASC_Network* structure. This call */ + /* is the counterpart of ASC_initializeNetwork(...) which was called above. */ + cond = ASC_dropNetwork(&net); + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, DimseCondition::dump(temp_str, cond)); + } + } + + + DicomServer::DicomServer() : pimpl_(new PImpl) + { + aet_ = "ANY-SCP"; + port_ = 104; + findRequestHandlerFactory_ = NULL; + moveRequestHandlerFactory_ = NULL; + storeRequestHandlerFactory_ = NULL; + applicationEntityFilter_ = NULL; + checkCalledAet_ = true; + clientTimeout_ = 30; + isThreaded_ = true; + } + + DicomServer::~DicomServer() + { + Stop(); + } + + void DicomServer::SetPort(uint16_t port) + { + Stop(); + port_ = port; + } + + uint16_t DicomServer::GetPort() const + { + return port_; + } + + void DicomServer::SetThreaded(bool isThreaded) + { + Stop(); + isThreaded_ = isThreaded; + } + + bool DicomServer::IsThreaded() const + { + return isThreaded_; + } + + void DicomServer::SetClientTimeout(uint32_t timeout) + { + Stop(); + clientTimeout_ = timeout; + } + + uint32_t DicomServer::GetClientTimeout() const + { + return clientTimeout_; + } + + + void DicomServer::SetCalledApplicationEntityTitleCheck(bool check) + { + Stop(); + checkCalledAet_ = check; + } + + bool DicomServer::HasCalledApplicationEntityTitleCheck() const + { + return checkCalledAet_; + } + + void DicomServer::SetApplicationEntityTitle(const std::string& aet) + { + if (aet.size() == 0) + { + throw PalantirException("Too short AET"); + } + + for (size_t i = 0; i < aet.size(); i++) + { + if (!isalnum(aet[i]) && aet[i] != '-') + { + throw PalantirException("Only alphanumeric characters are allowed in AET"); + } + } + + Stop(); + aet_ = aet; + } + + const std::string& DicomServer::GetApplicationEntityTitle() const + { + return aet_; + } + + void DicomServer::SetFindRequestHandlerFactory(IFindRequestHandlerFactory& factory) + { + Stop(); + findRequestHandlerFactory_ = &factory; + } + + bool DicomServer::HasFindRequestHandlerFactory() const + { + return (findRequestHandlerFactory_ != NULL); + } + + IFindRequestHandlerFactory& DicomServer::GetFindRequestHandlerFactory() const + { + if (HasFindRequestHandlerFactory()) + { + return *findRequestHandlerFactory_; + } + else + { + throw PalantirException("No C-FIND request handler factory"); + } + } + + void DicomServer::SetMoveRequestHandlerFactory(IMoveRequestHandlerFactory& factory) + { + Stop(); + moveRequestHandlerFactory_ = &factory; + } + + bool DicomServer::HasMoveRequestHandlerFactory() const + { + return (moveRequestHandlerFactory_ != NULL); + } + + IMoveRequestHandlerFactory& DicomServer::GetMoveRequestHandlerFactory() const + { + if (HasMoveRequestHandlerFactory()) + { + return *moveRequestHandlerFactory_; + } + else + { + throw PalantirException("No C-MOVE request handler factory"); + } + } + + void DicomServer::SetStoreRequestHandlerFactory(IStoreRequestHandlerFactory& factory) + { + Stop(); + storeRequestHandlerFactory_ = &factory; + } + + bool DicomServer::HasStoreRequestHandlerFactory() const + { + return (storeRequestHandlerFactory_ != NULL); + } + + IStoreRequestHandlerFactory& DicomServer::GetStoreRequestHandlerFactory() const + { + if (HasStoreRequestHandlerFactory()) + { + return *storeRequestHandlerFactory_; + } + else + { + throw PalantirException("No C-STORE request handler factory"); + } + } + + void DicomServer::SetApplicationEntityFilter(IApplicationEntityFilter& factory) + { + Stop(); + applicationEntityFilter_ = &factory; + } + + bool DicomServer::HasApplicationEntityFilter() const + { + return (applicationEntityFilter_ != NULL); + } + + IApplicationEntityFilter& DicomServer::GetApplicationEntityFilter() const + { + if (HasApplicationEntityFilter()) + { + return *applicationEntityFilter_; + } + else + { + throw PalantirException("No application entity filter"); + } + } + + void DicomServer::Start() + { + Stop(); + continue_ = true; + started_ = false; + pimpl_->thread_ = boost::thread(ServerThread, this); + + while (!started_) + { + Toolbox::USleep(50000); // Wait 50ms + } + } + + void DicomServer::Stop() + { + continue_ = false; + pimpl_->thread_.join(); + + bagOfDispatchers_.StopAll(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/DicomServer.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,97 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IFindRequestHandlerFactory.h" +#include "IMoveRequestHandlerFactory.h" +#include "IStoreRequestHandlerFactory.h" +#include "IApplicationEntityFilter.h" +#include "../../Core/MultiThreading/BagOfRunnablesBySteps.h" + +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +namespace Palantir +{ + class DicomServer : public boost::noncopyable + { + private: + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + bool checkCalledAet_; + std::string aet_; + uint16_t port_; + bool continue_; + bool started_; + uint32_t clientTimeout_; + bool isThreaded_; + IFindRequestHandlerFactory* findRequestHandlerFactory_; + IMoveRequestHandlerFactory* moveRequestHandlerFactory_; + IStoreRequestHandlerFactory* storeRequestHandlerFactory_; + IApplicationEntityFilter* applicationEntityFilter_; + + BagOfRunnablesBySteps bagOfDispatchers_; // This is used iff the server is threaded + + static void ServerThread(DicomServer* server); + + public: + DicomServer(); + + ~DicomServer(); + + void SetPort(uint16_t port); + uint16_t GetPort() const; + + void SetThreaded(bool isThreaded); + bool IsThreaded() const; + + void SetClientTimeout(uint32_t timeout); + uint32_t GetClientTimeout() const; + + void SetCalledApplicationEntityTitleCheck(bool check); + bool HasCalledApplicationEntityTitleCheck() const; + + void SetApplicationEntityTitle(const std::string& aet); + const std::string& GetApplicationEntityTitle() const; + + void SetFindRequestHandlerFactory(IFindRequestHandlerFactory& handler); + bool HasFindRequestHandlerFactory() const; + IFindRequestHandlerFactory& GetFindRequestHandlerFactory() const; + + void SetMoveRequestHandlerFactory(IMoveRequestHandlerFactory& handler); + bool HasMoveRequestHandlerFactory() const; + IMoveRequestHandlerFactory& GetMoveRequestHandlerFactory() const; + + void SetStoreRequestHandlerFactory(IStoreRequestHandlerFactory& handler); + bool HasStoreRequestHandlerFactory() const; + IStoreRequestHandlerFactory& GetStoreRequestHandlerFactory() const; + + void SetApplicationEntityFilter(IApplicationEntityFilter& handler); + bool HasApplicationEntityFilter() const; + IApplicationEntityFilter& GetApplicationEntityFilter() const; + + void Start(); + + void Stop(); + }; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/DicomUserConnection.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,633 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "DicomUserConnection.h" + +#include "../../Core/PalantirException.h" +#include "../ToDcmtkBridge.h" +#include "../FromDcmtkBridge.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> +#include <dcmtk/dcmdata/dcistrmb.h> +#include <dcmtk/dcmdata/dcistrmf.h> +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmnet/diutil.h> + +#include <set> + + + +#ifdef _WIN32 +/** + * "The maximum length, in bytes, of the string returned in the buffer + * pointed to by the name parameter is dependent on the namespace provider, + * but this string must be 256 bytes or less. + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms738527(v=vs.85).aspx + **/ +#define HOST_NAME_MAX 256 +#endif + + +namespace Palantir +{ + struct DicomUserConnection::PImpl + { + // Connection state + T_ASC_Network* net_; + T_ASC_Parameters* params_; + T_ASC_Association* assoc_; + + bool IsOpen() const + { + return assoc_ != NULL; + } + + void CheckIsOpen() const; + + void Store(DcmInputStream& is); + }; + + + static void Check(const OFCondition& cond) + { + if (cond.bad()) + { + throw PalantirException("DicomUserConnection: " + std::string(cond.text())); + } + } + + void DicomUserConnection::PImpl::CheckIsOpen() const + { + if (!IsOpen()) + { + throw PalantirException("DicomUserConnection: First open the connection"); + } + } + + + void DicomUserConnection::CheckIsOpen() const + { + pimpl_->CheckIsOpen(); + } + + + void DicomUserConnection::CopyParameters(const DicomUserConnection& other) + { + Close(); + localAet_ = other.localAet_; + distantAet_ = other.distantAet_; + distantHost_ = other.distantHost_; + distantPort_ = other.distantPort_; + } + + + void DicomUserConnection::SetupPresentationContexts() + { + // The preferred abstract syntax + std::string preferredSyntax = UID_LittleEndianImplicitTransferSyntax; + + // Fallback abstract syntaxes + std::set<std::string> abstractSyntaxes; + abstractSyntaxes.insert(UID_LittleEndianExplicitTransferSyntax); + abstractSyntaxes.insert(UID_BigEndianExplicitTransferSyntax); + abstractSyntaxes.insert(UID_LittleEndianImplicitTransferSyntax); + abstractSyntaxes.erase(preferredSyntax); + assert(abstractSyntaxes.size() == 2); + + // Transfer syntaxes for C-ECHO, C-FIND and C-MOVE + std::vector<std::string> transferSyntaxes; + transferSyntaxes.push_back(UID_VerificationSOPClass); + transferSyntaxes.push_back(UID_FINDPatientRootQueryRetrieveInformationModel); + transferSyntaxes.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); + transferSyntaxes.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel); + + // TODO: Allow the set below to be configured + std::set<std::string> uselessSyntaxes; + uselessSyntaxes.insert(UID_BlendingSoftcopyPresentationStateStorage); + uselessSyntaxes.insert(UID_GrayscaleSoftcopyPresentationStateStorage); + uselessSyntaxes.insert(UID_ColorSoftcopyPresentationStateStorage); + uselessSyntaxes.insert(UID_PseudoColorSoftcopyPresentationStateStorage); + + // Add the transfer syntaxes for C-STORE + for (int i = 0; i < numberOfDcmShortSCUStorageSOPClassUIDs - 1; i++) + { + // Test to make some room to allow the ECHO and FIND requests + if (uselessSyntaxes.find(dcmShortSCUStorageSOPClassUIDs[i]) == uselessSyntaxes.end()) + { + transferSyntaxes.push_back(dcmShortSCUStorageSOPClassUIDs[i]); + } + } + + // Flatten the fallback abstract syntaxes array + const char* asPreferred[1] = { preferredSyntax.c_str() }; + const char* asFallback[2]; + std::set<std::string>::const_iterator it = abstractSyntaxes.begin(); + asFallback[0] = it->c_str(); + it++; + asFallback[1] = it->c_str(); + + unsigned int presentationContextId = 1; + for (size_t i = 0; i < transferSyntaxes.size(); i++) + { + Check(ASC_addPresentationContext(pimpl_->params_, presentationContextId, + transferSyntaxes[i].c_str(), asPreferred, 1)); + presentationContextId += 2; + + Check(ASC_addPresentationContext(pimpl_->params_, presentationContextId, + transferSyntaxes[i].c_str(), asFallback, 2)); + presentationContextId += 2; + } + } + + + void DicomUserConnection::PImpl::Store(DcmInputStream& is) + { + CheckIsOpen(); + + DcmFileFormat dcmff; + Check(dcmff.read(is, EXS_Unknown, EGL_noChange, DCM_MaxReadLength)); + + // Figure out which SOP class and SOP instance is encapsulated in the file + DIC_UI sopClass; + DIC_UI sopInstance; + if (!DU_findSOPClassAndInstanceInDataSet(dcmff.getDataset(), sopClass, sopInstance)) + { + throw PalantirException("DicomUserConnection: Unable to find the SOP class and instance"); + } + + // Figure out which of the accepted presentation contexts should be used + int presID = ASC_findAcceptedPresentationContextID(assoc_, sopClass); + if (presID == 0) + { + const char *modalityName = dcmSOPClassUIDToModality(sopClass); + if (!modalityName) modalityName = dcmFindNameOfUID(sopClass); + if (!modalityName) modalityName = "unknown SOP class"; + throw PalantirException("DicomUserConnection: No presentation context for modality " + + std::string(modalityName)); + } + + // Prepare the transmission of data + T_DIMSE_C_StoreRQ req; + memset(&req, 0, sizeof(req)); + req.MessageID = assoc_->nextMsgID++; + strcpy(req.AffectedSOPClassUID, sopClass); + strcpy(req.AffectedSOPInstanceUID, sopInstance); + req.DataSetType = DIMSE_DATASET_PRESENT; + req.Priority = DIMSE_PRIORITY_MEDIUM; + + // Finally conduct transmission of data + T_DIMSE_C_StoreRSP rsp; + DcmDataset* statusDetail = NULL; + Check(DIMSE_storeUser(assoc_, presID, &req, + NULL, dcmff.getDataset(), /*progressCallback*/ NULL, NULL, + /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, + &rsp, &statusDetail, NULL)); + + if (statusDetail != NULL) + { + delete statusDetail; + } + } + + + static void FindCallback( + /* in */ + void *callbackData, + T_DIMSE_C_FindRQ *request, /* original find request */ + int responseCount, + T_DIMSE_C_FindRSP *response, /* pending response received */ + DcmDataset *responseIdentifiers /* pending response identifiers */ + ) + { + DicomFindAnswers& answers = *(DicomFindAnswers*) callbackData; + + if (responseIdentifiers != NULL) + { + DicomMap m; + FromDcmtkBridge::Convert(m, *responseIdentifiers); + answers.Add(m); + } + } + + void DicomUserConnection::Find(DicomFindAnswers& result, + FindRootModel model, + const DicomMap& fields) + { + CheckIsOpen(); + + const char* sopClass; + std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); + switch (model) + { + case FindRootModel_Patient: + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); + sopClass = UID_FINDPatientRootQueryRetrieveInformationModel; + + // Accession number + if (!fields.HasTag(0x0008, 0x0050)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + + // Patient ID + if (!fields.HasTag(0x0010, 0x0020)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0010, 0x0020), ""); + + break; + + case FindRootModel_Study: + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); + sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; + + // Accession number + if (!fields.HasTag(0x0008, 0x0050)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + + // Study instance UID + if (!fields.HasTag(0x0020, 0x000d)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); + + break; + + case FindRootModel_Series: + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); + sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; + + // Accession number + if (!fields.HasTag(0x0008, 0x0050)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + + // Study instance UID + if (!fields.HasTag(0x0020, 0x000d)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); + + // Series instance UID + if (!fields.HasTag(0x0020, 0x000e)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); + + break; + + case FindRootModel_Instance: + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); + sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; + + // Accession number + if (!fields.HasTag(0x0008, 0x0050)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + + // Study instance UID + if (!fields.HasTag(0x0020, 0x000d)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); + + // Series instance UID + if (!fields.HasTag(0x0020, 0x000e)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); + + // SOP Instance UID + if (!fields.HasTag(0x0008, 0x0018)) + DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0018), ""); + + break; + + default: + throw PalantirException(ErrorCode_ParameterOutOfRange); + } + + // Figure out which of the accepted presentation contexts should be used + int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); + if (presID == 0) + { + throw PalantirException("DicomUserConnection: The C-FIND command is not supported by the distant AET"); + } + + T_DIMSE_C_FindRQ request; + memset(&request, 0, sizeof(request)); + request.MessageID = pimpl_->assoc_->nextMsgID++; + strcpy(request.AffectedSOPClassUID, sopClass); + request.DataSetType = DIMSE_DATASET_PRESENT; + request.Priority = DIMSE_PRIORITY_MEDIUM; + + T_DIMSE_C_FindRSP response; + DcmDataset* statusDetail = NULL; + OFCondition cond = DIMSE_findUser(pimpl_->assoc_, presID, &request, dataset.get(), + FindCallback, &result, + /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, + &response, &statusDetail); + + if (statusDetail) + { + delete statusDetail; + } + + Check(cond); + } + + + void DicomUserConnection::FindPatient(DicomFindAnswers& result, + const DicomMap& fields) + { + // Only keep the filters from "fields" that are related to the patient + DicomMap s; + fields.ExtractPatientInformation(s); + Find(result, FindRootModel_Patient, s); + } + + void DicomUserConnection::FindStudy(DicomFindAnswers& result, + const DicomMap& fields) + { + // Only keep the filters from "fields" that are related to the study + DicomMap s; + fields.ExtractStudyInformation(s); + + s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); + s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); + + Find(result, FindRootModel_Study, s); + } + + void DicomUserConnection::FindSeries(DicomFindAnswers& result, + const DicomMap& fields) + { + // Only keep the filters from "fields" that are related to the series + DicomMap s; + fields.ExtractSeriesInformation(s); + + s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); + s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); + s.CopyTagIfExists(fields, DicomTag::STUDY_UID); + + Find(result, FindRootModel_Series, s); + } + + void DicomUserConnection::FindInstance(DicomFindAnswers& result, + const DicomMap& fields) + { + // Only keep the filters from "fields" that are related to the instance + DicomMap s; + fields.ExtractInstanceInformation(s); + + s.CopyTagIfExists(fields, DicomTag::PATIENT_ID); + s.CopyTagIfExists(fields, DicomTag::ACCESSION_NUMBER); + s.CopyTagIfExists(fields, DicomTag::STUDY_UID); + s.CopyTagIfExists(fields, DicomTag::SERIES_UID); + + Find(result, FindRootModel_Instance, s); + } + + + void DicomUserConnection::Move(const std::string& targetAet, + const DicomMap& fields) + { + CheckIsOpen(); + + const char* sopClass = UID_MOVEStudyRootQueryRetrieveInformationModel; + std::auto_ptr<DcmDataset> dataset(ToDcmtkBridge::Convert(fields)); + + // Figure out which of the accepted presentation contexts should be used + int presID = ASC_findAcceptedPresentationContextID(pimpl_->assoc_, sopClass); + if (presID == 0) + { + throw PalantirException("DicomUserConnection: The C-MOVE command is not supported by the distant AET"); + } + + T_DIMSE_C_MoveRQ request; + memset(&request, 0, sizeof(request)); + request.MessageID = pimpl_->assoc_->nextMsgID++; + strcpy(request.AffectedSOPClassUID, sopClass); + request.DataSetType = DIMSE_DATASET_PRESENT; + request.Priority = DIMSE_PRIORITY_MEDIUM; + strncpy(request.MoveDestination, targetAet.c_str(), sizeof(DIC_AE) / sizeof(char)); + + T_DIMSE_C_MoveRSP response; + DcmDataset* statusDetail = NULL; + DcmDataset* responseIdentifiers = NULL; + OFCondition cond = DIMSE_moveUser(pimpl_->assoc_, presID, &request, dataset.get(), + NULL, NULL, + /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, + pimpl_->net_, NULL, NULL, + &response, &statusDetail, &responseIdentifiers); + + if (statusDetail) + { + delete statusDetail; + } + + if (responseIdentifiers) + { + delete responseIdentifiers; + } + + Check(cond); + } + + + DicomUserConnection::DicomUserConnection() : pimpl_(new PImpl) + { + localAet_ = "STORESCU"; + distantAet_ = "ANY-SCP"; + distantPort_ = 104; + distantHost_ = "127.0.0.1"; + + pimpl_->net_ = NULL; + pimpl_->params_ = NULL; + pimpl_->assoc_ = NULL; + } + + DicomUserConnection::~DicomUserConnection() + { + Close(); + } + + void DicomUserConnection::SetLocalApplicationEntityTitle(const std::string& aet) + { + Close(); + localAet_ = aet; + } + + void DicomUserConnection::SetDistantApplicationEntityTitle(const std::string& aet) + { + Close(); + distantAet_ = aet; + } + + + void DicomUserConnection::SetDistantHost(const std::string& host) + { + if (host.size() > HOST_NAME_MAX - 10) + { + throw PalantirException("Distant host name is too long"); + } + + Close(); + distantHost_ = host; + } + + void DicomUserConnection::SetDistantPort(uint16_t port) + { + Close(); + distantPort_ = port; + } + + void DicomUserConnection::Open() + { + Close(); + + Check(ASC_initializeNetwork(NET_REQUESTOR, 0, /*opt_acse_timeout*/ 30, &pimpl_->net_)); + Check(ASC_createAssociationParameters(&pimpl_->params_, /*opt_maxReceivePDULength*/ ASC_DEFAULTMAXPDU)); + + // Set this application's title and the called application's title in the params + Check(ASC_setAPTitles(pimpl_->params_, localAet_.c_str(), distantAet_.c_str(), NULL)); + + // Set the network addresses of the local and distant entities + char localHost[HOST_NAME_MAX]; + gethostname(localHost, HOST_NAME_MAX - 1); + + char distantHostAndPort[HOST_NAME_MAX]; + snprintf(distantHostAndPort, HOST_NAME_MAX - 1, "%s:%d", distantHost_.c_str(), distantPort_); + + Check(ASC_setPresentationAddresses(pimpl_->params_, localHost, distantHostAndPort)); + + // Set various options + Check(ASC_setTransportLayerType(pimpl_->params_, /*opt_secureConnection*/ false)); + + SetupPresentationContexts(); + + // Do the association + Check(ASC_requestAssociation(pimpl_->net_, pimpl_->params_, &pimpl_->assoc_)); + + if (ASC_countAcceptedPresentationContexts(pimpl_->params_) == 0) + { + throw PalantirException("DicomUserConnection: No Acceptable Presentation Contexts"); + } + } + + void DicomUserConnection::Close() + { + if (pimpl_->assoc_ != NULL) + { + ASC_releaseAssociation(pimpl_->assoc_); + ASC_destroyAssociation(&pimpl_->assoc_); + pimpl_->assoc_ = NULL; + pimpl_->params_ = NULL; + } + else + { + if (pimpl_->params_ != NULL) + { + ASC_destroyAssociationParameters(&pimpl_->params_); + pimpl_->params_ = NULL; + } + } + + if (pimpl_->net_ != NULL) + { + ASC_dropNetwork(&pimpl_->net_); + pimpl_->net_ = NULL; + } + } + + bool DicomUserConnection::IsOpen() const + { + return pimpl_->IsOpen(); + } + + void DicomUserConnection::Store(const char* buffer, size_t size) + { + // Prepare an input stream for the memory buffer + DcmInputBufferStream is; + if (size > 0) + is.setBuffer(buffer, size); + is.setEos(); + + pimpl_->Store(is); + } + + void DicomUserConnection::Store(const std::string& buffer) + { + if (buffer.size() > 0) + Store(reinterpret_cast<const char*>(&buffer[0]), buffer.size()); + else + Store(NULL, 0); + } + + void DicomUserConnection::StoreFile(const std::string& path) + { + // Prepare an input stream for the file + DcmInputFileStream is(path.c_str()); + pimpl_->Store(is); + } + + bool DicomUserConnection::Echo() + { + CheckIsOpen(); + DIC_US status; + Check(DIMSE_echoUser(pimpl_->assoc_, pimpl_->assoc_->nextMsgID++, + /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ 0, + &status, NULL)); + return status == STATUS_Success; + } + + + void DicomUserConnection::MoveSeries(const std::string& targetAet, + const DicomMap& findResult) + { + DicomMap simplified; + simplified.SetValue(DicomTag::STUDY_UID, findResult.GetValue(DicomTag::STUDY_UID)); + simplified.SetValue(DicomTag::SERIES_UID, findResult.GetValue(DicomTag::SERIES_UID)); + Move(targetAet, simplified); + } + + void DicomUserConnection::MoveSeries(const std::string& targetAet, + const std::string& studyUid, + const std::string& seriesUid) + { + DicomMap map; + map.SetValue(DicomTag::STUDY_UID, studyUid); + map.SetValue(DicomTag::SERIES_UID, seriesUid); + Move(targetAet, map); + } + + void DicomUserConnection::MoveInstance(const std::string& targetAet, + const DicomMap& findResult) + { + DicomMap simplified; + simplified.SetValue(DicomTag::STUDY_UID, findResult.GetValue(DicomTag::STUDY_UID)); + simplified.SetValue(DicomTag::SERIES_UID, findResult.GetValue(DicomTag::SERIES_UID)); + simplified.SetValue(DicomTag::INSTANCE_UID, findResult.GetValue(DicomTag::INSTANCE_UID)); + Move(targetAet, simplified); + } + + void DicomUserConnection::MoveInstance(const std::string& targetAet, + const std::string& studyUid, + const std::string& seriesUid, + const std::string& instanceUid) + { + DicomMap map; + map.SetValue(DicomTag::STUDY_UID, studyUid); + map.SetValue(DicomTag::SERIES_UID, seriesUid); + map.SetValue(DicomTag::INSTANCE_UID, instanceUid); + Move(targetAet, map); + } + + void DicomUserConnection::SetConnectionTimeout(uint32_t seconds) + { + dcmConnectionTimeout.set(seconds); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/DicomUserConnection.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,140 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomFindAnswers.h" + +#include <stdint.h> +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +namespace Palantir +{ + class DicomUserConnection : public boost::noncopyable + { + private: + enum FindRootModel + { + FindRootModel_Patient, + FindRootModel_Study, + FindRootModel_Series, + FindRootModel_Instance + }; + + struct PImpl; + boost::shared_ptr<PImpl> pimpl_; + + // Connection parameters + std::string localAet_; + std::string distantAet_; + std::string distantHost_; + uint16_t distantPort_; + + void CheckIsOpen() const; + + void SetupPresentationContexts(); + + void Find(DicomFindAnswers& result, + FindRootModel model, + const DicomMap& fields); + + void Move(const std::string& targetAet, + const DicomMap& fields); + + public: + DicomUserConnection(); + + ~DicomUserConnection(); + + void CopyParameters(const DicomUserConnection& other); + + void SetLocalApplicationEntityTitle(const std::string& aet); + + const std::string& GetLocalApplicationEntityTitle() const + { + return localAet_; + } + + void SetDistantApplicationEntityTitle(const std::string& aet); + + const std::string& GetDistantApplicationEntityTitle() const + { + return distantAet_; + } + + void SetDistantHost(const std::string& host); + + const std::string& GetDistantHost() const + { + return distantHost_; + } + + void SetDistantPort(uint16_t port); + + uint16_t GetDistantPort() const + { + return distantPort_; + } + + void Open(); + + void Close(); + + bool IsOpen() const; + + bool Echo(); + + void Store(const char* buffer, size_t size); + + void Store(const std::string& buffer); + + void StoreFile(const std::string& path); + + void FindPatient(DicomFindAnswers& result, + const DicomMap& fields); + + void FindStudy(DicomFindAnswers& result, + const DicomMap& fields); + + void FindSeries(DicomFindAnswers& result, + const DicomMap& fields); + + void FindInstance(DicomFindAnswers& result, + const DicomMap& fields); + + void MoveSeries(const std::string& targetAet, + const DicomMap& findResult); + + void MoveSeries(const std::string& targetAet, + const std::string& studyUid, + const std::string& seriesUid); + + void MoveInstance(const std::string& targetAet, + const DicomMap& findResult); + + void MoveInstance(const std::string& targetAet, + const std::string& studyUid, + const std::string& seriesUid, + const std::string& instanceUid); + + static void SetConnectionTimeout(uint32_t seconds); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/IApplicationEntityFilter.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> + +namespace Palantir +{ + class IApplicationEntityFilter + { + public: + virtual ~IApplicationEntityFilter() + { + } + + virtual bool IsAllowed(const std::string& callingIp, + const std::string& callingAet) = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/IFindRequestHandler.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,41 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "DicomFindAnswers.h" + +#include <vector> +#include <string> + + +namespace Palantir +{ + class IFindRequestHandler + { + public: + virtual ~IFindRequestHandler() + { + } + + virtual void Handle(const DicomMap& input, + DicomFindAnswers& answers) = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/IFindRequestHandlerFactory.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,36 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IFindRequestHandler.h" + +namespace Palantir +{ + class IFindRequestHandlerFactory + { + public: + virtual ~IFindRequestHandlerFactory() + { + } + + virtual IFindRequestHandler* ConstructFindRequestHandler() = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/IMoveRequestHandler.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,62 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../../Core/DicomFormat/DicomMap.h" + +#include <vector> +#include <string> + + +namespace Palantir +{ + class IMoveRequestIterator + { + public: + enum Status + { + Status_Success, + Status_Failure, + Status_Warning + }; + + virtual ~IMoveRequestIterator() + { + } + + virtual unsigned int GetSubOperationCount() const = 0; + + virtual Status DoNext() = 0; + }; + + + class IMoveRequestHandler + { + public: + virtual ~IMoveRequestHandler() + { + } + + virtual IMoveRequestIterator* Handle(const std::string& target, + const DicomMap& input) = 0; + }; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/IMoveRequestHandlerFactory.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,36 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IMoveRequestHandler.h" + +namespace Palantir +{ + class IMoveRequestHandlerFactory + { + public: + virtual ~IMoveRequestHandlerFactory() + { + } + + virtual IMoveRequestHandler* ConstructMoveRequestHandler() = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/IStoreRequestHandler.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,43 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../../Core/DicomFormat/DicomMap.h" + +#include <vector> +#include <string> +#include <json/json.h> + +namespace Palantir +{ + class IStoreRequestHandler + { + public: + virtual ~IStoreRequestHandler() + { + } + + virtual void Handle(const std::vector<uint8_t>& dicomFile, + const DicomMap& dicomSummary, + const Json::Value& dicomJson, + const std::string& distantAet) = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/DicomProtocol/IStoreRequestHandlerFactory.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,36 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "IStoreRequestHandler.h" + +namespace Palantir +{ + class IStoreRequestHandlerFactory + { + public: + virtual ~IStoreRequestHandlerFactory() + { + } + + virtual IStoreRequestHandler* ConstructStoreRequestHandler() = 0; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/FromDcmtkBridge.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,509 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "FromDcmtkBridge.h" + +#include "ToDcmtkBridge.h" +#include "DicomIntegerPixelAccessor.h" +#include "../Core/PalantirException.h" +#include "../Core/PngWriter.h" +#include "../Core/DicomFormat/DicomString.h" +#include "../Core/DicomFormat/DicomNullValue.h" + +#include <boost/locale.hpp> +#include <boost/lexical_cast.hpp> + +#include <dcmtk/dcmdata/dcdicent.h> +#include <dcmtk/dcmdata/dcdict.h> +#include <dcmtk/dcmdata/dcelem.h> +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmdata/dcistrmb.h> +#include <dcmtk/dcmdata/dcsequen.h> +#include <dcmtk/dcmdata/dcvrfd.h> +#include <dcmtk/dcmdata/dcvrfl.h> +#include <dcmtk/dcmdata/dcvrsl.h> +#include <dcmtk/dcmdata/dcvrss.h> +#include <dcmtk/dcmdata/dcvrul.h> +#include <dcmtk/dcmdata/dcvrus.h> + + +namespace Palantir +{ + void FromDcmtkBridge::Convert(DicomMap& target, DcmDataset& dataset) + { + target.Clear(); + for (unsigned long i = 0; i < dataset.card(); i++) + { + DcmElement* element = dataset.getElement(i); + if (element && element->isLeaf()) + { + target.SetValue(element->getTag().getGTag(), + element->getTag().getETag(), + ConvertLeafElement(*element)); + } + } + } + + + DicomTag FromDcmtkBridge::GetTag(const DcmElement& element) + { + return DicomTag(element.getGTag(), element.getETag()); + } + + + DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element) + { + if (!element.isLeaf()) + { + throw PalantirException("Only applicable to leaf elements"); + } + + if (element.isaString()) + { + char *c; + if (element.getString(c).good() && + c != NULL) + { + std::string s(c); + std::string utf8; + try + { + utf8 = boost::locale::conv::to_utf<char>(s, "ISO-8859-1"); // TODO Parameter? + } + catch (std::runtime_error& e) + { + // Bad input string or bad encoding + utf8 = s; + } + + return new DicomString(utf8); + } + else + { + return new DicomNullValue; + } + } + + try + { + // http://support.dcmtk.org/docs/dcvr_8h-source.html + switch (element.getVR()) + { + + /** + * TODO. + **/ + + case EVR_DS: // decimal string + case EVR_IS: // integer string + case EVR_OB: // other byte + case EVR_OF: // other float + case EVR_OW: // other word + case EVR_AS: // age string + case EVR_AT: // attribute tag + case EVR_DA: // date string + case EVR_DT: // date time string + case EVR_TM: // time string + case EVR_UN: // unknown value representation + return new DicomNullValue(); + + + /** + * String types, should never happen at this point because of + * "element.isaString()". + **/ + + case EVR_AE: // application entity title + case EVR_CS: // code string + case EVR_SH: // short string + case EVR_LO: // long string + case EVR_ST: // short text + case EVR_LT: // long text + case EVR_UT: // unlimited text + case EVR_PN: // person name + case EVR_UI: // unique identifier + return new DicomNullValue(); + + + /** + * Numerical types + **/ + + case EVR_SL: // signed long + { + Sint32 f; + if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_SS: // signed short + { + Sint16 f; + if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_UL: // unsigned long + { + Uint32 f; + if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_US: // unsigned short + { + Uint16 f; + if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_FL: // float single-precision + { + Float32 f; + if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + case EVR_FD: // float double-precision + { + Float64 f; + if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good()) + { + return new DicomString(boost::lexical_cast<std::string>(f)); + } + else + { + return new DicomNullValue(); + } + } + + + /** + * Sequence types, should never occur at this point because of + * "element.isLeaf()". + **/ + + case EVR_SQ: // sequence of items + return new DicomNullValue; + + + /** + * Internal to DCMTK. + **/ + + case EVR_ox: // OB or OW depending on context + case EVR_xs: // SS or US depending on context + case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name) + case EVR_na: // na="not applicable", for data which has no VR + case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor + case EVR_item: // used internally for items + case EVR_metainfo: // used internally for meta info datasets + case EVR_dataset: // used internally for datasets + case EVR_fileFormat: // used internally for DICOM files + case EVR_dicomDir: // used internally for DICOMDIR objects + case EVR_dirRecord: // used internally for DICOMDIR records + case EVR_pixelSQ: // used internally for pixel sequences in a compressed image + case EVR_pixelItem: // used internally for pixel items in a compressed image + case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR) + case EVR_PixelData: // used internally for uncompressed pixeld data + case EVR_OverlayData: // used internally for overlay data + case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR + return new DicomNullValue; + + + /** + * Default case. + **/ + + default: + return new DicomNullValue; + } + } + catch (boost::bad_lexical_cast) + { + return new DicomNullValue; + } + } + + + static void StoreElement(Json::Value& target, + DcmElement& element, + unsigned int maxStringLength); + + static void StoreItem(Json::Value& target, + DcmItem& item, + unsigned int maxStringLength) + { + target = Json::Value(Json::objectValue); + + for (unsigned long i = 0; i < item.card(); i++) + { + DcmElement* element = item.getElement(i); + StoreElement(target, *element, maxStringLength); + } + } + + + static void StoreElement(Json::Value& target, + DcmElement& element, + unsigned int maxStringLength) + { + assert(target.type() == Json::objectValue); + + const std::string tagName = FromDcmtkBridge::GetName(FromDcmtkBridge::GetTag(element)); + + if (element.isLeaf()) + { + std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(element)); + if (v->IsNull()) + { + target[tagName] = Json::nullValue; + } + else + { + std::string s = v->AsString(); + if (maxStringLength == 0 || + s.size() <= maxStringLength) + { + target[tagName] = s; + } + else + { + // An integer value of 0 in JSON indicates too long field + target[tagName] = 0; + } + } + } + else + { + target[tagName] = Json::Value(Json::arrayValue); + + // "All subclasses of DcmElement except for DcmSequenceOfItems + // are leaf nodes, while DcmSequenceOfItems, DcmItem, DcmDataset + // etc. are not." The following cast is thus OK. + DcmSequenceOfItems& sequence = dynamic_cast<DcmSequenceOfItems&>(element); + + for (unsigned long i = 0; i < sequence.card(); i++) + { + DcmItem* child = sequence.getItem(i); + Json::Value& v = target[tagName].append(Json::objectValue); + StoreItem(v, *child, maxStringLength); + } + } + } + + + void FromDcmtkBridge::ToJson(Json::Value& root, + DcmDataset& dataset, + unsigned int maxStringLength) + { + StoreItem(root, dataset, maxStringLength); + } + + + + void FromDcmtkBridge::ToJson(Json::Value& target, + const std::string& path, + unsigned int maxStringLength) + { + DcmFileFormat dicom; + if (!dicom.loadFile(path.c_str()).good()) + { + throw PalantirException(ErrorCode_BadFileFormat); + } + else + { + FromDcmtkBridge::ToJson(target, *dicom.getDataset(), maxStringLength); + } + } + + + void FromDcmtkBridge::ExtractNormalizedImage(std::string& result, + DcmDataset& dataset) + { + // See also: http://support.dcmtk.org/wiki/dcmtk/howto/accessing-compressed-data + + PngWriter w; + std::auto_ptr<DicomIntegerPixelAccessor> accessor; + + DicomMap m; + FromDcmtkBridge::Convert(m, dataset); + + DcmElement* e; + if (dataset.findAndGetElement(ToDcmtkBridge::Convert(DicomTag::PIXEL_DATA), e).good() && + e != NULL) + { + Uint8* pixData = NULL; + if (e->getUint8Array(pixData) == EC_Normal) + { + accessor.reset(new DicomIntegerPixelAccessor(m, pixData, e->getLength())); + } + } + + if (accessor.get() == NULL || + accessor->GetWidth() == 0 || + accessor->GetHeight() == 0) + { + w.WriteToMemory(result, 0, 0, 0, PixelFormat_Grayscale8, NULL); + } + else + { + int32_t min, max; + accessor->GetExtremeValues(min, max); + + std::vector<uint8_t> image(accessor->GetWidth() * accessor->GetHeight(), 0); + if (min != max) + { + uint8_t* result = &image[0]; + for (unsigned int y = 0; y < accessor->GetHeight(); y++) + { + for (unsigned int x = 0; x < accessor->GetWidth(); x++, result++) + { + int32_t v = accessor->GetValue(x, y); + *result = lround(static_cast<float>(v - min) / static_cast<float>(max - min) * 255.0f); + } + } + } + + w.WriteToMemory(result, accessor->GetWidth(), accessor->GetHeight(), + accessor->GetWidth(), PixelFormat_Grayscale8, &image[0]); + } + } + + + void FromDcmtkBridge::ExtractNormalizedImage(std::string& result, + const std::string& dicomContent) + { + DcmInputBufferStream is; + if (dicomContent.size() > 0) + { + is.setBuffer(&dicomContent[0], dicomContent.size()); + } + is.setEos(); + + DcmFileFormat dicom; + if (dicom.read(is).good()) + { + ExtractNormalizedImage(result, *dicom.getDataset()); + } + else + { + throw PalantirException(ErrorCode_BadFileFormat); + } + } + + + + std::string FromDcmtkBridge::GetName(const DicomTag& t) + { + DcmTagKey tag(t.GetGroup(), t.GetElement()); + const DcmDataDictionary& dict = dcmDataDict.rdlock(); + const DcmDictEntry* entry = dict.findEntry(tag, NULL); + + std::string s("Unknown"); + if (entry != NULL) + { + s = std::string(entry->getTagName()); + } + + dcmDataDict.unlock(); + return s; + } + + + DicomTag FromDcmtkBridge::FindTag(const char* name) + { + const DcmDataDictionary& dict = dcmDataDict.rdlock(); + const DcmDictEntry* entry = dict.findEntry(name); + + if (entry == NULL) + { + dcmDataDict.unlock(); + throw PalantirException("Unknown DICOM tag"); + } + else + { + DcmTagKey key = entry->getKey(); + DicomTag tag(key.getGroup(), key.getElement()); + dcmDataDict.unlock(); + return tag; + } + } + + + void FromDcmtkBridge::Print(FILE* fp, const DicomMap& m) + { + for (DicomMap::Map::const_iterator + it = m.map_.begin(); it != m.map_.end(); it++) + { + DicomTag t = it->first; + std::string s = it->second->AsString(); + printf("0x%04x 0x%04x (%s) [%s]\n", t.GetGroup(), t.GetElement(), GetName(t).c_str(), s.c_str()); + } + } + + + void FromDcmtkBridge::ToJson(Json::Value& result, + const DicomMap& values) + { + if (result.type() != Json::objectValue) + { + throw PalantirException(ErrorCode_BadParameterType); + } + + result.clear(); + + for (DicomMap::Map::const_iterator + it = values.map_.begin(); it != values.map_.end(); it++) + { + result[GetName(it->first)] = it->second->AsString(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/FromDcmtkBridge.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,86 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/DicomFormat/DicomMap.h" +#include <dcmtk/dcmdata/dcdatset.h> +#include <json/json.h> + +namespace Palantir +{ + class FromDcmtkBridge + { + public: + static void Convert(DicomMap& target, DcmDataset& dataset); + + static DicomTag GetTag(const DcmElement& element); + + static DicomValue* ConvertLeafElement(DcmElement& element); + + static void ToJson(Json::Value& target, + DcmDataset& dataset, + unsigned int maxStringLength = 256); + + static void ToJson(Json::Value& target, + const std::string& path, + unsigned int maxStringLength = 256); + + static void ExtractNormalizedImage(std::string& result, + DcmDataset& dataset); + + static void ExtractNormalizedImage(std::string& result, + const std::string& dicomContent); + + static std::string GetName(const DicomTag& tag); + + static DicomTag FindTag(const char* name); + + static DicomTag FindTag(const std::string& name) + { + return FindTag(name.c_str()); + } + + static bool HasTag(const DicomMap& fields, + const std::string& tagName) + { + return fields.HasTag(FindTag(tagName)); + } + + static const DicomValue& GetValue(const DicomMap& fields, + const std::string& tagName) + { + return fields.GetValue(FindTag(tagName)); + } + + static void SetValue(DicomMap& target, + const std::string& tagName, + DicomValue* value) + { + target.SetValue(FindTag(tagName), value); + } + + static void Print(FILE* fp, + const DicomMap& m); + + static void ToJson(Json::Value& result, + const DicomMap& values); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/Internals/CommandDispatcher.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,403 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "CommandDispatcher.h" + +#include "FindScp.h" +#include "StoreScp.h" +#include "MoveScp.h" +#include "../../Core/Toolbox.h" + +#include <dcmtk/dcmnet/dcasccfg.h> /* for class DcmAssociationConfiguration */ + +static OFBool opt_rejectWithoutImplementationUID = OFFalse; + + +namespace Palantir +{ + namespace Internals + { + extern OFLogger Logger; + + + + OFCondition AssociationCleanup(T_ASC_Association *assoc) + { + OFString temp_str; + OFCondition cond = ASC_dropSCPAssociation(assoc); + if (cond.bad()) + { + OFLOG_FATAL(Internals::Logger, DimseCondition::dump(temp_str, cond)); + return cond; + } + + cond = ASC_destroyAssociation(&assoc); + if (cond.bad()) + { + OFLOG_FATAL(Internals::Logger, DimseCondition::dump(temp_str, cond)); + return cond; + } + + return cond; + } + + + + CommandDispatcher* AcceptAssociation(const DicomServer& server, T_ASC_Network *net) + { + DcmAssociationConfiguration asccfg; + char buf[BUFSIZ]; + T_ASC_Association *assoc; + OFCondition cond; + OFString sprofile; + OFString temp_str; + + std::vector<const char*> knownAbstractSyntaxes; + + // For C-STORE + if (server.HasStoreRequestHandlerFactory()) + { + knownAbstractSyntaxes.push_back(UID_VerificationSOPClass); + } + + // For C-FIND + if (server.HasFindRequestHandlerFactory()) + { + knownAbstractSyntaxes.push_back(UID_FINDPatientRootQueryRetrieveInformationModel); + knownAbstractSyntaxes.push_back(UID_FINDStudyRootQueryRetrieveInformationModel); + } + + // For C-MOVE + if (server.HasMoveRequestHandlerFactory()) + { + knownAbstractSyntaxes.push_back(UID_MOVEStudyRootQueryRetrieveInformationModel); + } + + const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + int numTransferSyntaxes = 0; + + cond = ASC_receiveAssociation(net, &assoc, + /*opt_maxPDU*/ ASC_DEFAULTMAXPDU, + NULL, NULL, + /*opt_secureConnection*/ OFFalse, + DUL_NOBLOCK, 1); + + if (cond == DUL_NOASSOCIATIONREQUEST) + { + // Timeout + AssociationCleanup(assoc); + return NULL; + } + + // if some kind of error occured, take care of it + if (cond.bad()) + { + OFLOG_ERROR(Internals::Logger, "Receiving Association failed: " << DimseCondition::dump(temp_str, cond)); + // no matter what kind of error occurred, we need to do a cleanup + AssociationCleanup(assoc); + return NULL; + } + + OFLOG_INFO(Internals::Logger, "Association Received"); + + transferSyntaxes[0] = UID_LittleEndianExplicitTransferSyntax; + transferSyntaxes[1] = UID_BigEndianExplicitTransferSyntax; + transferSyntaxes[2] = UID_LittleEndianImplicitTransferSyntax; + numTransferSyntaxes = 3; + + /* accept the Verification SOP Class if presented */ + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, &knownAbstractSyntaxes[0], knownAbstractSyntaxes.size(), transferSyntaxes, numTransferSyntaxes); + if (cond.bad()) + { + OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); + AssociationCleanup(assoc); + return NULL; + } + + /* the array of Storage SOP Class UIDs comes from dcuid.h */ + cond = ASC_acceptContextsWithPreferredTransferSyntaxes( assoc->params, dcmAllStorageSOPClassUIDs, numberOfAllDcmStorageSOPClassUIDs, transferSyntaxes, numTransferSyntaxes); + if (cond.bad()) + { + OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); + AssociationCleanup(assoc); + return NULL; + } + + /* set our app title */ + ASC_setAPTitles(assoc->params, NULL, NULL, server.GetApplicationEntityTitle().c_str()); + + /* acknowledge or reject this association */ + cond = ASC_getApplicationContextName(assoc->params, buf); + if ((cond.bad()) || strcmp(buf, UID_StandardApplicationContext) != 0) + { + /* reject: the application context name is not supported */ + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_APPCONTEXTNAMENOTSUPPORTED + }; + + OFLOG_INFO(Internals::Logger, "Association Rejected: Bad Application Context Name: " << buf); + cond = ASC_rejectAssociation(assoc, &rej); + if (cond.bad()) + { + OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); + } + AssociationCleanup(assoc); + return NULL; + } + + /* check the AETs */ + { + DIC_AE callingTitle_C; + DIC_AE calledTitle_C; + DIC_AE callingIP_C; + DIC_AE calledIP_C; + if (ASC_getAPTitles(assoc->params, callingTitle_C, calledTitle_C, NULL).bad() || + ASC_getPresentationAddresses(assoc->params, callingIP_C, calledIP_C).bad()) + { + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_NOREASON + }; + ASC_rejectAssociation(assoc, &rej); + AssociationCleanup(assoc); + return NULL; + } + + std::string callingIP(OFSTRING_GUARD(callingIP_C)); + std::string callingTitle(OFSTRING_GUARD(callingTitle_C)); + std::string calledTitle(OFSTRING_GUARD(calledTitle_C)); + Toolbox::ToUpperCase(callingIP); + Toolbox::ToUpperCase(callingTitle); + Toolbox::ToUpperCase(calledTitle); + + if (server.HasCalledApplicationEntityTitleCheck() && + calledTitle != server.GetApplicationEntityTitle()) + { + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_CALLEDAETITLENOTRECOGNIZED + }; + ASC_rejectAssociation(assoc, &rej); + AssociationCleanup(assoc); + return NULL; + } + + if (server.HasApplicationEntityFilter() && + !server.GetApplicationEntityFilter().IsAllowed(callingIP, callingTitle)) + { + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_CALLINGAETITLENOTRECOGNIZED + }; + ASC_rejectAssociation(assoc, &rej); + AssociationCleanup(assoc); + return NULL; + } + } + + if (opt_rejectWithoutImplementationUID && strlen(assoc->params->theirImplementationClassUID) == 0) + { + /* reject: the no implementation Class UID provided */ + T_ASC_RejectParameters rej = + { + ASC_RESULT_REJECTEDPERMANENT, + ASC_SOURCE_SERVICEUSER, + ASC_REASON_SU_NOREASON + }; + + OFLOG_INFO(Internals::Logger, "Association Rejected: No Implementation Class UID provided"); + cond = ASC_rejectAssociation(assoc, &rej); + if (cond.bad()) + { + OFLOG_DEBUG(Internals::Logger, DimseCondition::dump(temp_str, cond)); + } + AssociationCleanup(assoc); + return NULL; + } + + { + cond = ASC_acknowledgeAssociation(assoc); + if (cond.bad()) + { + OFLOG_ERROR(Internals::Logger, DimseCondition::dump(temp_str, cond)); + AssociationCleanup(assoc); + return NULL; + } + OFLOG_INFO(Internals::Logger, "Association Acknowledged (Max Send PDV: " << assoc->sendPDVLength << ")"); + if (ASC_countAcceptedPresentationContexts(assoc->params) == 0) + OFLOG_INFO(Internals::Logger, " (but no valid presentation contexts)"); + } + + return new CommandDispatcher(server, assoc); + } + + bool CommandDispatcher::Step() + /* + * This function receives DIMSE commmands over the network connection + * and handles these commands correspondingly. Note that in case of + * storscp only C-ECHO-RQ and C-STORE-RQ commands can be processed. + */ + { + bool finished = false; + + // receive a DIMSE command over the network, with a timeout of 1 second + DcmDataset *statusDetail = NULL; + T_ASC_PresentationContextID presID = 0; + T_DIMSE_Message msg; + + OFCondition cond = DIMSE_receiveCommand(assoc_, DIMSE_NONBLOCKING, 1, &presID, &msg, &statusDetail); + elapsedTimeSinceLastCommand_++; + + // if the command which was received has extra status + // detail information, dump this information + if (statusDetail != NULL) + { + OFLOG_WARN(Internals::Logger, "Status Detail:" << OFendl << DcmObject::PrintHelper(*statusDetail)); + delete statusDetail; + } + + if (cond == DIMSE_OUTOFRESOURCES) + { + finished = true; + } + else if (cond == DIMSE_NODATAAVAILABLE) + { + // Timeout due to DIMSE_NONBLOCKING + if (clientTimeout_ != 0 && + elapsedTimeSinceLastCommand_ >= clientTimeout_) + { + // This timeout is actually a client timeout + finished = true; + } + } + else if (cond == EC_Normal) + { + // Reset the client timeout counter + elapsedTimeSinceLastCommand_ = 0; + + // in case we received a valid message, process this command + // note that storescp can only process a C-ECHO-RQ and a C-STORE-RQ + switch (msg.CommandField) + { + case DIMSE_C_ECHO_RQ: + // process C-ECHO-Request + cond = EchoScp(assoc_, &msg, presID); + break; + + case DIMSE_C_STORE_RQ: + // process C-STORE-Request + if (server_.HasStoreRequestHandlerFactory()) + { + std::auto_ptr<IStoreRequestHandler> handler + (server_.GetStoreRequestHandlerFactory().ConstructStoreRequestHandler()); + cond = Internals::storeScp(assoc_, &msg, presID, *handler); + } + else + cond = DIMSE_BADCOMMANDTYPE; // Should never happen + break; + + case DIMSE_C_MOVE_RQ: + // process C-MOVE-Request + if (server_.HasMoveRequestHandlerFactory()) + { + std::auto_ptr<IMoveRequestHandler> handler + (server_.GetMoveRequestHandlerFactory().ConstructMoveRequestHandler()); + cond = Internals::moveScp(assoc_, &msg, presID, *handler); + } + else + cond = DIMSE_BADCOMMANDTYPE; // Should never happen + break; + + case DIMSE_C_FIND_RQ: + // process C-FIND-Request + if (server_.HasFindRequestHandlerFactory()) + { + std::auto_ptr<IFindRequestHandler> handler + (server_.GetFindRequestHandlerFactory().ConstructFindRequestHandler()); + cond = Internals::findScp(assoc_, &msg, presID, *handler); + } + else + cond = DIMSE_BADCOMMANDTYPE; // Should never happen + break; + + default: + // we cannot handle this kind of message + cond = DIMSE_BADCOMMANDTYPE; + OFLOG_ERROR(Internals::Logger, "cannot handle command: 0x" + << STD_NAMESPACE hex << OFstatic_cast(unsigned, msg.CommandField)); + break; + } + } + else + { + // Bad status, which indicates the closing of the connection by + // the peer or a network error + finished = true; + } + + if (finished) + { + if (cond == DUL_PEERREQUESTEDRELEASE) + { + OFLOG_INFO(Internals::Logger, "Association Release"); + ASC_acknowledgeRelease(assoc_); + } + else if (cond == DUL_PEERABORTEDASSOCIATION) + { + OFLOG_INFO(Internals::Logger, "Association Aborted"); + } + else + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, "DIMSE failure (aborting association): " << DimseCondition::dump(temp_str, cond)); + /* some kind of error so abort the association */ + ASC_abortAssociation(assoc_); + } + } + + return !finished; + } + + + OFCondition EchoScp( T_ASC_Association * assoc, T_DIMSE_Message * msg, T_ASC_PresentationContextID presID) + { + OFString temp_str; + OFLOG_INFO(Internals::Logger, "Received Echo Request"); + OFLOG_DEBUG(Internals::Logger, DIMSE_dumpMessage(temp_str, msg->msg.CEchoRQ, DIMSE_INCOMING, NULL, presID)); + + /* the echo succeeded !! */ + OFCondition cond = DIMSE_sendEchoResponse(assoc, presID, &msg->msg.CEchoRQ, STATUS_Success, NULL); + if (cond.bad()) + { + OFLOG_ERROR(Internals::Logger, "Echo SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + return cond; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/Internals/CommandDispatcher.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,68 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../DicomProtocol/DicomServer.h" +#include "../../Core/MultiThreading/IRunnableBySteps.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> + +namespace Palantir +{ + namespace Internals + { + OFCondition AssociationCleanup(T_ASC_Association *assoc); + + class CommandDispatcher : public IRunnableBySteps + { + private: + uint32_t clientTimeout_; + uint32_t elapsedTimeSinceLastCommand_; + const DicomServer& server_; + T_ASC_Association* assoc_; + + public: + CommandDispatcher(const DicomServer& server, + T_ASC_Association* assoc) : + server_(server), + assoc_(assoc) + { + clientTimeout_ = server.GetClientTimeout(); + elapsedTimeSinceLastCommand_ = 0; + } + + virtual ~CommandDispatcher() + { + AssociationCleanup(assoc_); + } + + virtual bool Step(); + }; + + OFCondition EchoScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID); + + CommandDispatcher* AcceptAssociation(const DicomServer& server, + T_ASC_Network *net); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/Internals/FindScp.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,133 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "FindScp.h" + +#include "../FromDcmtkBridge.h" +#include "../ToDcmtkBridge.h" +#include "../../Core/PalantirException.h" + +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmdata/dcmetinf.h> +#include <dcmtk/dcmdata/dcostrmb.h> +#include <dcmtk/dcmdata/dcdeftag.h> +#include <dcmtk/dcmnet/diutil.h> + + +namespace Palantir +{ + namespace Internals + { + extern OFLogger Logger; + } + + + namespace + { + struct FindScpData + { + IFindRequestHandler* handler_; + DicomMap input_; + DicomFindAnswers answers_; + DcmDataset* lastRequest_; + }; + + + void FindScpCallback( + /* in */ + void *callbackData, + OFBool cancelled, + T_DIMSE_C_FindRQ *request, + DcmDataset *requestIdentifiers, + int responseCount, + /* out */ + T_DIMSE_C_FindRSP *response, + DcmDataset **responseIdentifiers, + DcmDataset **statusDetail) + { + bzero(response, sizeof(T_DIMSE_C_FindRSP)); + *statusDetail = NULL; + + FindScpData& data = *(FindScpData*) callbackData; + if (data.lastRequest_ == NULL) + { + FromDcmtkBridge::Convert(data.input_, *requestIdentifiers); + + try + { + data.handler_->Handle(data.input_, data.answers_); + } + catch (PalantirException& e) + { + // Internal error! + OFLOG_ERROR(Internals::Logger, "IFindRequestHandler Failed: " << e.What()); + response->DimseStatus = STATUS_FIND_Failed_UnableToProcess; + *responseIdentifiers = NULL; + return; + } + + data.lastRequest_ = requestIdentifiers; + } + else if (data.lastRequest_ != requestIdentifiers) + { + // Internal error! + response->DimseStatus = STATUS_FIND_Failed_UnableToProcess; + *responseIdentifiers = NULL; + return; + } + + if (responseCount <= static_cast<int>(data.answers_.GetSize())) + { + response->DimseStatus = STATUS_Pending; + *responseIdentifiers = ToDcmtkBridge::Convert(data.answers_.GetAnswer(responseCount - 1)); + } + else + { + response->DimseStatus = STATUS_Success; + *responseIdentifiers = NULL; + } + } + } + + + OFCondition Internals::findScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IFindRequestHandler& handler) + { + FindScpData data; + data.lastRequest_ = NULL; + data.handler_ = &handler; + + OFCondition cond = DIMSE_findProvider(assoc, presID, &msg->msg.CFindRQ, + FindScpCallback, &data, + /*opt_blockMode*/ DIMSE_BLOCKING, + /*opt_dimse_timeout*/ 0); + + // if some error occured, dump corresponding information and remove the outfile if necessary + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, "Find SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + + return cond; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/Internals/FindScp.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../DicomProtocol/IFindRequestHandler.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> + +namespace Palantir +{ + namespace Internals + { + OFCondition findScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IFindRequestHandler& handler); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/Internals/MoveScp.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,175 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "MoveScp.h" + +#include <memory> + +#include "../FromDcmtkBridge.h" +#include "../ToDcmtkBridge.h" +#include "../../Core/PalantirException.h" + +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmdata/dcmetinf.h> +#include <dcmtk/dcmdata/dcostrmb.h> +#include <dcmtk/dcmdata/dcdeftag.h> +#include <dcmtk/dcmnet/diutil.h> + + +namespace Palantir +{ + namespace Internals + { + extern OFLogger Logger; + } + + + namespace + { + struct MoveScpData + { + std::string target_; + IMoveRequestHandler* handler_; + DicomMap input_; + DcmDataset* lastRequest_; + unsigned int subOperationCount_; + unsigned int failureCount_; + unsigned int warningCount_; + std::auto_ptr<IMoveRequestIterator> iterator_; + }; + + + void MoveScpCallback( + /* in */ + void *callbackData, + OFBool cancelled, + T_DIMSE_C_MoveRQ *request, + DcmDataset *requestIdentifiers, + int responseCount, + /* out */ + T_DIMSE_C_MoveRSP *response, + DcmDataset **responseIdentifiers, + DcmDataset **statusDetail) + { + bzero(response, sizeof(T_DIMSE_C_MoveRSP)); + *statusDetail = NULL; + *responseIdentifiers = NULL; + + MoveScpData& data = *(MoveScpData*) callbackData; + if (data.lastRequest_ == NULL) + { + FromDcmtkBridge::Convert(data.input_, *requestIdentifiers); + + try + { + data.iterator_.reset(data.handler_->Handle(data.target_, data.input_)); + data.subOperationCount_ = data.iterator_->GetSubOperationCount(); + data.failureCount_ = 0; + data.warningCount_ = 0; + } + catch (PalantirException& e) + { + // Internal error! + OFLOG_ERROR(Internals::Logger, "IMoveRequestHandler Failed: " << e.What()); + response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; + return; + } + + data.lastRequest_ = requestIdentifiers; + } + else if (data.lastRequest_ != requestIdentifiers) + { + // Internal error! + response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; + return; + } + + if (data.subOperationCount_ == 0) + { + response->DimseStatus = STATUS_Success; + } + else + { + IMoveRequestIterator::Status status; + + try + { + status = data.iterator_->DoNext(); + } + catch (PalantirException& e) + { + // Internal error! + OFLOG_ERROR(Internals::Logger, "IMoveRequestHandler Failed: " << e.What()); + response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess; + return; + } + + if (status == IMoveRequestIterator::Status_Failure) + { + data.failureCount_++; + } + else if (status == IMoveRequestIterator::Status_Warning) + { + data.warningCount_++; + } + + if (responseCount < static_cast<int>(data.subOperationCount_)) + { + response->DimseStatus = STATUS_Pending; + } + else + { + response->DimseStatus = STATUS_Success; + } + } + + response->NumberOfRemainingSubOperations = data.subOperationCount_ - responseCount; + response->NumberOfCompletedSubOperations = responseCount; + response->NumberOfFailedSubOperations = data.failureCount_; + response->NumberOfWarningSubOperations = data.warningCount_; + } + } + + + OFCondition Internals::moveScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IMoveRequestHandler& handler) + { + MoveScpData data; + data.target_ = std::string(msg->msg.CMoveRQ.MoveDestination); + data.lastRequest_ = NULL; + data.handler_ = &handler; + + OFCondition cond = DIMSE_moveProvider(assoc, presID, &msg->msg.CMoveRQ, + MoveScpCallback, &data, + /*opt_blockMode*/ DIMSE_BLOCKING, + /*opt_dimse_timeout*/ 0); + + // if some error occured, dump corresponding information and remove the outfile if necessary + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Internals::Logger, "Move SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + + return cond; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/Internals/MoveScp.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../DicomProtocol/IMoveRequestHandler.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> + +namespace Palantir +{ + namespace Internals + { + OFCondition moveScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IMoveRequestHandler& handler); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/Internals/StoreScp.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,266 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "StoreScp.h" + +#include "../FromDcmtkBridge.h" +#include "../ToDcmtkBridge.h" +#include "../../Core/PalantirException.h" + +#include <dcmtk/dcmdata/dcfilefo.h> +#include <dcmtk/dcmdata/dcmetinf.h> +#include <dcmtk/dcmdata/dcostrmb.h> +#include <dcmtk/dcmdata/dcdeftag.h> +#include <dcmtk/dcmnet/diutil.h> + + +namespace Palantir +{ + namespace Internals + { + extern OFLogger Logger; + } + + + namespace + { + struct StoreCallbackData + { + IStoreRequestHandler* handler; + const char* distantAET; + const char* modality; + const char* affectedSOPInstanceUID; + uint32_t messageID; + }; + + + static int SaveToMemoryBuffer(DcmDataset* dataSet, + std::vector<uint8_t>& buffer) + { + // Determine the transfer syntax which shall be used to write the + // information to the file. We always switch to the Little Endian + // syntax, with explicit length. + + // http://support.dcmtk.org/docs/dcxfer_8h-source.html + E_TransferSyntax xfer = EXS_LittleEndianExplicit; + E_EncodingType encodingType = /*opt_sequenceType*/ EET_ExplicitLength; + + uint32_t s = dataSet->getLength(xfer, encodingType); + + buffer.resize(s); + DcmOutputBufferStream ob(&buffer[0], s); + + dataSet->transferInit(); + OFCondition c = dataSet->write(ob, xfer, encodingType, NULL, + /*opt_groupLength*/ EGL_recalcGL, + /*opt_paddingType*/ EPD_withoutPadding); + dataSet->transferEnd(); + if (c.good()) + { + return 0; + } + else + { + buffer.clear(); + return -1; + } + +#if 0 + OFCondition cond = cbdata->dcmff->saveFile(fileName.c_str(), xfer, + encodingType, + /*opt_groupLength*/ EGL_recalcGL, + /*opt_paddingType*/ EPD_withoutPadding, + OFstatic_cast(Uint32, /*opt_filepad*/ 0), + OFstatic_cast(Uint32, /*opt_itempad*/ 0), + (opt_useMetaheader) ? EWM_fileformat : EWM_dataset); +#endif + } + + + static void + storeScpCallback( + void *callbackData, + T_DIMSE_StoreProgress *progress, + T_DIMSE_C_StoreRQ *req, + char * /*imageFileName*/, DcmDataset **imageDataSet, + T_DIMSE_C_StoreRSP *rsp, + DcmDataset **statusDetail) + /* + * This function.is used to indicate progress when storescp receives instance data over the + * network. On the final call to this function (identified by progress->state == DIMSE_StoreEnd) + * this function will store the data set which was received over the network to a file. + * Earlier calls to this function will simply cause some information to be dumped to stdout. + * + * Parameters: + * callbackData - [in] data for this callback function + * progress - [in] The state of progress. (identifies if this is the initial or final call + * to this function, or a call in between these two calls. + * req - [in] The original store request message. + * imageFileName - [in] The path to and name of the file the information shall be written to. + * imageDataSet - [in] The data set which shall be stored in the image file + * rsp - [inout] the C-STORE-RSP message (will be sent after the call to this function) + * statusDetail - [inout] This variable can be used to capture detailed information with regard to + * the status information which is captured in the status element (0000,0900). Note + * that this function does specify any such information, the pointer will be set to NULL. + */ + { + StoreCallbackData *cbdata = OFstatic_cast(StoreCallbackData *, callbackData); + + DIC_UI sopClass; + DIC_UI sopInstance; + + // if this is the final call of this function, save the data which was received to a file + // (note that we could also save the image somewhere else, put it in database, etc.) + if (progress->state == DIMSE_StoreEnd) + { + OFString tmpStr; + + // do not send status detail information + *statusDetail = NULL; + + // Concerning the following line: an appropriate status code is already set in the resp structure, + // it need not be success. For example, if the caller has already detected an out of resources problem + // then the status will reflect this. The callback function is still called to allow cleanup. + //rsp->DimseStatus = STATUS_Success; + + // we want to write the received information to a file only if this information + // is present and the options opt_bitPreserving and opt_ignore are not set. + if ((imageDataSet != NULL) && (*imageDataSet != NULL)) + { + DicomMap summary; + Json::Value dicomJson; + std::vector<uint8_t> buffer; + + try + { + FromDcmtkBridge::Convert(summary, **imageDataSet); + FromDcmtkBridge::ToJson(dicomJson, **imageDataSet); + + if (SaveToMemoryBuffer(*imageDataSet, buffer) < 0) + { + OFLOG_ERROR(Internals::Logger, "cannot write DICOM file to memory"); + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + } + } + catch (...) + { + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + } + + // check the image to make sure it is consistent, i.e. that its sopClass and sopInstance correspond + // to those mentioned in the request. If not, set the status in the response message variable. + if ((rsp->DimseStatus == STATUS_Success)) + { + // which SOP class and SOP instance ? + if (!DU_findSOPClassAndInstanceInDataSet(*imageDataSet, sopClass, sopInstance, /*opt_correctUIDPadding*/ OFFalse)) + { + //OFLOG_ERROR(Internals::Logger, "bad DICOM file: " << fileName); + rsp->DimseStatus = STATUS_STORE_Error_CannotUnderstand; + } + else if (strcmp(sopClass, req->AffectedSOPClassUID) != 0) + { + rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + } + else if (strcmp(sopInstance, req->AffectedSOPInstanceUID) != 0) + { + rsp->DimseStatus = STATUS_STORE_Error_DataSetDoesNotMatchSOPClass; + } + else + { + try + { + cbdata->handler->Handle(buffer, summary, dicomJson, cbdata->distantAET); + } + catch (PalantirException& e) + { + rsp->DimseStatus = STATUS_STORE_Refused_OutOfResources; + OFLOG_ERROR(Internals::Logger, "Exception while storing DICOM: " << e.What()); + } + } + } + } + } + } + } + +/* + * This function processes a DIMSE C-STORE-RQ commmand that was + * received over the network connection. + * + * Parameters: + * assoc - [in] The association (network connection to another DICOM application). + * msg - [in] The DIMSE C-STORE-RQ message that was received. + * presID - [in] The ID of the presentation context which was specified in the PDV which contained + * the DIMSE command. + */ + OFCondition Internals::storeScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IStoreRequestHandler& handler) + { + OFCondition cond = EC_Normal; + T_DIMSE_C_StoreRQ *req; + + // assign the actual information of the C-STORE-RQ command to a local variable + req = &msg->msg.CStoreRQ; + + // intialize some variables + StoreCallbackData callbackData; + callbackData.handler = &handler; + callbackData.modality = dcmSOPClassUIDToModality(req->AffectedSOPClassUID, "UNKNOWN"); + callbackData.affectedSOPInstanceUID = req->AffectedSOPInstanceUID; + callbackData.messageID = req->MessageID; + if (assoc && assoc->params) + { + callbackData.distantAET = assoc->params->DULparams.callingAPTitle; + } + else + { + callbackData.distantAET = ""; + } + + DcmFileFormat dcmff; + + // store SourceApplicationEntityTitle in metaheader + if (assoc && assoc->params) + { + const char *aet = assoc->params->DULparams.callingAPTitle; + if (aet) dcmff.getMetaInfo()->putAndInsertString(DCM_SourceApplicationEntityTitle, aet); + } + + // define an address where the information which will be received over the network will be stored + DcmDataset *dset = dcmff.getDataset(); + + cond = DIMSE_storeProvider(assoc, presID, req, NULL, /*opt_useMetaheader*/OFFalse, &dset, + storeScpCallback, &callbackData, + /*opt_blockMode*/ DIMSE_BLOCKING, + /*opt_dimse_timeout*/ 0); + + // if some error occured, dump corresponding information and remove the outfile if necessary + if (cond.bad()) + { + OFString temp_str; + OFLOG_ERROR(Logger, "Store SCP Failed: " << DimseCondition::dump(temp_str, cond)); + } + + // return return value + return cond; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/Internals/StoreScp.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,37 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../DicomProtocol/IStoreRequestHandler.h" + +#include <dcmtk/dcmnet/assoc.h> +#include <dcmtk/dcmnet/dimse.h> + +namespace Palantir +{ + namespace Internals + { + OFCondition storeScp(T_ASC_Association * assoc, + T_DIMSE_Message * msg, + T_ASC_PresentationContextID presID, + IStoreRequestHandler& handler); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/PalantirInitialization.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,184 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "PalantirInitialization.h" + +#include "../Core/PalantirException.h" +#include "../Core/Toolbox.h" + +#include <boost/lexical_cast.hpp> +#include <boost/filesystem.hpp> +#include <curl/curl.h> +#include <boost/thread.hpp> + +namespace Palantir +{ + static const char* CONFIGURATION_FILE = "Configuration.json"; + + static boost::mutex globalMutex_; + static std::auto_ptr<Json::Value> configuration_; + + + static void ReadGlobalConfiguration(const char* configurationFile) + { + configuration_.reset(new Json::Value); + + std::string content; + + if (configurationFile) + { + Toolbox::ReadFile(content, configurationFile); + } + else + { +#if PALANTIR_RELEASE == 0 + boost::filesystem::path p = PALANTIR_PATH; + p /= "Resources"; + p /= CONFIGURATION_FILE; + Toolbox::ReadFile(content, p.string()); +#else + Toolbox::ReadFile(content, CONFIGURATION_FILE); +#endif + } + + Json::Reader reader; + if (!reader.parse(content, *configuration_)) + { + throw PalantirException("Unable to read the configuration file"); + } + } + + + void PalantirInitialize(const char* configurationFile) + { + boost::mutex::scoped_lock lock(globalMutex_); + ReadGlobalConfiguration(configurationFile); + curl_global_init(CURL_GLOBAL_ALL); + } + + + + void PalantirFinalize() + { + boost::mutex::scoped_lock lock(globalMutex_); + curl_global_cleanup(); + configuration_.reset(NULL); + } + + + + std::string GetGlobalStringParameter(const std::string& parameter, + const std::string& defaultValue) + { + boost::mutex::scoped_lock lock(globalMutex_); + + if (configuration_->isMember(parameter)) + { + return (*configuration_) [parameter].asString(); + } + else + { + return defaultValue; + } + } + + + int GetGlobalIntegerParameter(const std::string& parameter, + int defaultValue) + { + boost::mutex::scoped_lock lock(globalMutex_); + + if (configuration_->isMember(parameter)) + { + return (*configuration_) [parameter].asInt(); + } + else + { + return defaultValue; + } + } + + + + void GetDicomModality(const std::string& name, + std::string& aet, + std::string& address, + int& port) + { + boost::mutex::scoped_lock lock(globalMutex_); + + if (!configuration_->isMember("DicomModalities")) + { + throw PalantirException(""); + } + + const Json::Value& modalities = (*configuration_) ["DicomModalities"]; + if (modalities.type() != Json::objectValue || + !modalities.isMember(name)) + { + throw PalantirException(""); + } + + try + { + aet = modalities[name].get(0u, "").asString(); + address = modalities[name].get(1u, "").asString(); + port = modalities[name].get(2u, "").asInt(); + } + catch (...) + { + throw PalantirException("Badly formatted DICOM modality"); + } + } + + + + void GetListOfDicomModalities(std::set<std::string>& target) + { + boost::mutex::scoped_lock lock(globalMutex_); + + target.clear(); + + if (!configuration_->isMember("DicomModalities")) + { + return; + } + + const Json::Value& modalities = (*configuration_) ["DicomModalities"]; + if (modalities.type() != Json::objectValue) + { + throw PalantirException("Badly formatted list of DICOM modalities"); + } + + Json::Value::Members members = modalities.getMemberNames(); + for (size_t i = 0; i < members.size(); i++) + { + for (size_t j = 0; j < members[i].size(); j++) + { + if (!isalnum(members[i][j]) && members[i][j] != '-') + { + throw PalantirException("Only alphanumeric and dash characters are allowed in the names of the modalities"); + } + } + + target.insert(members[i]); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/PalantirInitialization.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,45 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <string> +#include <set> +#include <json/json.h> + +namespace Palantir +{ + void PalantirInitialize(const char* configurationFile = NULL); + + void PalantirFinalize(); + + std::string GetGlobalStringParameter(const std::string& parameter, + const std::string& defaultValue); + + int GetGlobalIntegerParameter(const std::string& parameter, + int defaultValue); + + void GetDicomModality(const std::string& name, + std::string& aet, + std::string& address, + int& port); + + void GetListOfDicomModalities(std::set<std::string>& target); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/PalantirRestApi.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,655 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "PalantirRestApi.h" + +#include "PalantirInitialization.h" +#include "FromDcmtkBridge.h" +#include "../Core/Uuid.h" + +#include <dcmtk/dcmdata/dcistrmb.h> +#include <dcmtk/dcmdata/dcfilefo.h> +#include <boost/lexical_cast.hpp> + +namespace Palantir +{ + static void SendJson(HttpOutput& output, + const Json::Value& value) + { + Json::StyledWriter writer; + std::string s = writer.write(value); + output.AnswerBufferWithContentType(s, "application/json"); + } + + bool PalantirRestApi::Store(Json::Value& result, + const std::string& postData) + { + // Prepare an input stream for the memory buffer + DcmInputBufferStream is; + if (postData.size() > 0) + { + is.setBuffer(&postData[0], postData.size()); + } + is.setEos(); + + printf("[%d]\n", postData.size()); + + DcmFileFormat dicomFile; + if (dicomFile.read(is).good()) + { + DicomMap dicomSummary; + FromDcmtkBridge::Convert(dicomSummary, *dicomFile.getDataset()); + + Json::Value dicomJson; + FromDcmtkBridge::ToJson(dicomJson, *dicomFile.getDataset()); + + std::string instanceUuid; + StoreStatus status = StoreStatus_Failure; + if (postData.size() > 0) + { + status = index_.Store + (instanceUuid, storage_, reinterpret_cast<const char*>(&postData[0]), + postData.size(), dicomSummary, dicomJson, ""); + } + + switch (status) + { + case StoreStatus_Success: + result["ID"] = instanceUuid; + result["Path"] = "/instances/" + instanceUuid; + result["Status"] = "Success"; + return true; + + case StoreStatus_AlreadyStored: + result["ID"] = instanceUuid; + result["Path"] = "/instances/" + instanceUuid; + result["Status"] = "AlreadyStored"; + return true; + + default: + return false; + } + } + + return false; + } + + void PalantirRestApi::ConnectToModality(DicomUserConnection& c, + const std::string& name) + { + std::string aet, address; + int port; + GetDicomModality(name, aet, address, port); + c.SetLocalApplicationEntityTitle(GetGlobalStringParameter("DicomAet", "PALANTIR")); + c.SetDistantApplicationEntityTitle(aet); + c.SetDistantHost(address); + c.SetDistantPort(port); + c.Open(); + } + + bool PalantirRestApi::MergeQueryAndTemplate(DicomMap& result, + const std::string& postData) + { + Json::Value query; + Json::Reader reader; + + if (!reader.parse(postData, query) || + !query.type() == Json::objectValue) + { + return false; + } + + Json::Value::Members members = query.getMemberNames(); + for (size_t i = 0; i < members.size(); i++) + { + DicomTag t = FromDcmtkBridge::FindTag(members[i]); + result.SetValue(t, query[members[i]].asString()); + } + + return true; + } + + bool PalantirRestApi::DicomFindPatient(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + DicomMap m; + DicomMap::SetupFindPatientTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + + DicomFindAnswers answers; + c.FindPatient(answers, m); + answers.ToJson(result); + return true; + } + + bool PalantirRestApi::DicomFindStudy(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + DicomMap m; + DicomMap::SetupFindStudyTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + + if (m.GetValue(DicomTag::ACCESSION_NUMBER).AsString().size() <= 2 && + m.GetValue(DicomTag::PATIENT_ID).AsString().size() <= 2) + { + return false; + } + + DicomFindAnswers answers; + c.FindStudy(answers, m); + answers.ToJson(result); + return true; + } + + bool PalantirRestApi::DicomFindSeries(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + DicomMap m; + DicomMap::SetupFindSeriesTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + + if ((m.GetValue(DicomTag::ACCESSION_NUMBER).AsString().size() <= 2 && + m.GetValue(DicomTag::PATIENT_ID).AsString().size() <= 2) || + m.GetValue(DicomTag::STUDY_UID).AsString().size() <= 2) + { + return false; + } + + DicomFindAnswers answers; + c.FindSeries(answers, m); + answers.ToJson(result); + return true; + } + + bool PalantirRestApi::DicomFind(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + DicomMap m; + DicomMap::SetupFindPatientTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + + DicomFindAnswers patients; + c.FindPatient(patients, m); + + // Loop over the found patients + result = Json::arrayValue; + for (size_t i = 0; i < patients.GetSize(); i++) + { + Json::Value patient(Json::objectValue); + FromDcmtkBridge::ToJson(patient, patients.GetAnswer(i)); + + DicomMap::SetupFindStudyTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + m.CopyTagIfExists(patients.GetAnswer(i), DicomTag::PATIENT_ID); + + DicomFindAnswers studies; + c.FindStudy(studies, m); + + patient["Studies"] = Json::arrayValue; + + // Loop over the found studies + for (size_t j = 0; j < studies.GetSize(); j++) + { + Json::Value study(Json::objectValue); + FromDcmtkBridge::ToJson(study, studies.GetAnswer(j)); + + DicomMap::SetupFindSeriesTemplate(m); + if (!MergeQueryAndTemplate(m, postData)) + { + return false; + } + m.CopyTagIfExists(studies.GetAnswer(j), DicomTag::PATIENT_ID); + m.CopyTagIfExists(studies.GetAnswer(j), DicomTag::STUDY_UID); + + DicomFindAnswers series; + c.FindSeries(series, m); + + // Loop over the found series + study["Series"] = Json::arrayValue; + for (size_t k = 0; k < series.GetSize(); k++) + { + Json::Value series2(Json::objectValue); + FromDcmtkBridge::ToJson(series2, series.GetAnswer(k)); + study["Series"].append(series2); + } + + patient["Studies"].append(study); + } + + result.append(patient); + } + + return true; + } + + + + bool PalantirRestApi::DicomStore(Json::Value& result, + DicomUserConnection& c, + const std::string& postData) + { + Json::Value found(Json::objectValue); + + if (!Toolbox::IsUuid(postData)) + { + // This is not a UUID, assume this is a DICOM instance + c.Store(postData); + } + else if (index_.GetSeries(found, postData)) + { + // The UUID corresponds to a series + for (size_t i = 0; i < found["Instances"].size(); i++) + { + std::string uuid = found["Instances"][i].asString(); + Json::Value instance(Json::objectValue); + if (index_.GetInstance(instance, uuid)) + { + std::string content; + storage_.ReadFile(content, instance["FileUuid"].asString()); + c.Store(content); + } + else + { + return false; + } + } + } + else if (index_.GetInstance(found, postData)) + { + // The UUID corresponds to an instance + std::string content; + storage_.ReadFile(content, found["FileUuid"].asString()); + c.Store(content); + } + else + { + return false; + } + + return true; + } + + + PalantirRestApi::PalantirRestApi(ServerIndex& index, + const std::string& path) : + index_(index), + storage_(path) + { + GetListOfDicomModalities(modalities_); + } + + + void PalantirRestApi::Handle( + HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string& postData) + { + if (uri.size() == 0) + { + if (method == "GET") + { + output.Redirect("/app/explorer.html"); + } + else + { + output.SendMethodNotAllowedError("GET"); + } + + return; + } + + bool existingResource = false; + Json::Value result(Json::objectValue); + + + // List all the instances --------------------------------------------------- + + if (uri.size() == 1 && uri[0] == "instances") + { + if (method == "GET") + { + result = Json::Value(Json::arrayValue); + index_.GetAllUuids(result, "Instances"); + existingResource = true; + } + else if (method == "POST") + { + // Add a new instance to the storage + if (Store(result, postData)) + { + SendJson(output, result); + return; + } + else + { + output.SendHeader(HttpStatus_415_UnsupportedMediaType); + return; + } + } + else + { + output.SendMethodNotAllowedError("GET,POST"); + return; + } + } + + + // List all the patients, studies or series --------------------------------- + + if (uri.size() == 1 && + (uri[0] == "series" || + uri[0] == "studies" || + uri[0] == "patients")) + { + if (method == "GET") + { + result = Json::Value(Json::arrayValue); + + if (uri[0] == "instances") + index_.GetAllUuids(result, "Instances"); + else if (uri[0] == "series") + index_.GetAllUuids(result, "Series"); + else if (uri[0] == "studies") + index_.GetAllUuids(result, "Studies"); + else if (uri[0] == "patients") + index_.GetAllUuids(result, "Patients"); + + existingResource = true; + } + else + { + output.SendMethodNotAllowedError("GET"); + return; + } + } + + + // Information about a single object ---------------------------------------- + + else if (uri.size() == 2 && + (uri[0] == "instances" || + uri[0] == "series" || + uri[0] == "studies" || + uri[0] == "patients")) + { + if (method == "GET") + { + if (uri[0] == "patients") + { + existingResource = index_.GetPatient(result, uri[1]); + } + else if (uri[0] == "studies") + { + existingResource = index_.GetStudy(result, uri[1]); + } + else if (uri[0] == "series") + { + existingResource = index_.GetSeries(result, uri[1]); + } + else if (uri[0] == "instances") + { + existingResource = index_.GetInstance(result, uri[1]); + } + } + else if (method == "DELETE") + { + if (uri[0] == "patients") + { + existingResource = index_.DeletePatient(result, uri[1]); + } + else if (uri[0] == "studies") + { + existingResource = index_.DeleteStudy(result, uri[1]); + } + else if (uri[0] == "series") + { + existingResource = index_.DeleteSeries(result, uri[1]); + } + else if (uri[0] == "instances") + { + existingResource = index_.DeleteInstance(result, uri[1]); + } + + if (existingResource) + { + result["Status"] = "Success"; + } + } + else + { + output.SendMethodNotAllowedError("GET,DELETE"); + return; + } + } + + + // Get the DICOM or the JSON file of one instance --------------------------- + + else if (uri.size() == 3 && + uri[0] == "instances" && + (uri[2] == "file" || + uri[2] == "all-tags")) + { + std::string fileUuid, contentType; + if (uri[2] == "file") + { + existingResource = index_.GetDicomFile(fileUuid, uri[1]); + contentType = "application/dicom"; + } + else + { + existingResource = index_.GetJsonFile(fileUuid, uri[1]); + contentType = "application/json"; + } + + if (existingResource) + { + output.AnswerFile(storage_, fileUuid, contentType); + return; + } + } + + + else if (uri.size() == 3 && + uri[0] == "instances" && + uri[2] == "normalized-image") + { + std::string uuid; + existingResource = index_.GetDicomFile(uuid, uri[1]); + + if (existingResource) + { + std::string dicomContent, png; + storage_.ReadFile(dicomContent, uuid); + try + { + FromDcmtkBridge::ExtractNormalizedImage(png, dicomContent); + output.AnswerBufferWithContentType(png, "image/png"); + return; + } + catch (PalantirException&) + { + output.Redirect("/app/images/Unsupported.png"); + return; + } + } + } + + + + // Changes API -------------------------------------------------------------- + + if (uri.size() == 1 && uri[0] == "changes") + { + if (method == "GET") + { + const static unsigned int MAX_RESULTS = 100; + + std::string filter = GetArgument(arguments, "filter", ""); + int64_t since; + unsigned int limit; + try + { + since = boost::lexical_cast<int64_t>(GetArgument(arguments, "since", "0")); + limit = boost::lexical_cast<unsigned int>(GetArgument(arguments, "limit", "0")); + } + catch (boost::bad_lexical_cast) + { + output.SendHeader(HttpStatus_400_BadRequest); + return; + } + + if (limit == 0 || limit > MAX_RESULTS) + { + limit = MAX_RESULTS; + } + + if (!index_.GetChanges(result, since, filter, limit)) + { + output.SendHeader(HttpStatus_400_BadRequest); + return; + } + + existingResource = true; + } + else + { + output.SendMethodNotAllowedError("GET"); + return; + } + } + + + // DICOM bridge ------------------------------------------------------------- + + if (uri.size() == 1 && + uri[0] == "modalities") + { + if (method == "GET") + { + result = Json::Value(Json::arrayValue); + existingResource = true; + + for (Modalities::const_iterator it = modalities_.begin(); + it != modalities_.end(); it++) + { + result.append(*it); + } + } + else + { + output.SendMethodNotAllowedError("GET"); + return; + } + } + + if ((uri.size() == 2 || + uri.size() == 3) && + uri[0] == "modalities") + { + if (modalities_.find(uri[1]) == modalities_.end()) + { + // Unknown modality + } + else if (uri.size() == 2) + { + if (method != "GET") + { + output.SendMethodNotAllowedError("POST"); + return; + } + else + { + existingResource = true; + result = Json::arrayValue; + result.append("find-patient"); + result.append("find-study"); + result.append("find-series"); + result.append("find"); + result.append("store"); + } + } + else if (uri.size() == 3) + { + if (uri[2] != "find-patient" && + uri[2] != "find-study" && + uri[2] != "find-series" && + uri[2] != "find" && + uri[2] != "store") + { + // Unknown request + } + else if (method != "POST") + { + output.SendMethodNotAllowedError("POST"); + return; + } + else + { + DicomUserConnection connection; + ConnectToModality(connection, uri[1]); + existingResource = true; + + if ((uri[2] == "find-patient" && !DicomFindPatient(result, connection, postData)) || + (uri[2] == "find-study" && !DicomFindStudy(result, connection, postData)) || + (uri[2] == "find-series" && !DicomFindSeries(result, connection, postData)) || + (uri[2] == "find" && !DicomFind(result, connection, postData)) || + (uri[2] == "store" && !DicomStore(result, connection, postData))) + { + output.SendHeader(HttpStatus_400_BadRequest); + return; + } + } + } + } + + + if (existingResource) + { + SendJson(output, result); + } + else + { + output.SendHeader(HttpStatus_404_NotFound); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/PalantirRestApi.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,87 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/HttpServer/HttpHandler.h" +#include "ServerIndex.h" +#include "DicomProtocol/DicomUserConnection.h" + +#include <set> + + +namespace Palantir +{ + class PalantirRestApi : public HttpHandler + { + private: + typedef std::set<std::string> Modalities; + + ServerIndex& index_; + FileStorage storage_; + Modalities modalities_; + + bool Store(Json::Value& result, + const std::string& postData); + + void ConnectToModality(DicomUserConnection& c, + const std::string& name); + + bool MergeQueryAndTemplate(DicomMap& result, + const std::string& postData); + + bool DicomFindPatient(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + bool DicomFindStudy(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + bool DicomFindSeries(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + bool DicomFind(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + bool DicomStore(Json::Value& result, + DicomUserConnection& c, + const std::string& postData); + + public: + PalantirRestApi(ServerIndex& index, + const std::string& path); + + virtual bool IsServedUri(const UriComponents& uri) + { + return true; + } + + virtual void Handle( + HttpOutput& output, + const std::string& method, + const UriComponents& uri, + const Arguments& headers, + const Arguments& arguments, + const std::string& postData); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/PrepareDatabase.sql Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,122 @@ +CREATE TABLE GlobalProperties( + name TEXT PRIMARY KEY, + value TEXT + ); + +CREATE TABLE Patients( + uuid TEXT PRIMARY KEY, + dicomPatientId TEXT + ); + +CREATE TABLE Studies( + uuid TEXT PRIMARY KEY, + parentPatient TEXT REFERENCES Patients(uuid) ON DELETE CASCADE, + dicomStudy TEXT + ); + +CREATE TABLE Series( + uuid TEXT PRIMARY KEY, + parentStudy TEXT REFERENCES Studies(uuid) ON DELETE CASCADE, + dicomSeries TEXT + ); + +CREATE TABLE Instances( + uuid TEXT PRIMARY KEY, + parentSeries TEXT REFERENCES Series(uuid) ON DELETE CASCADE, + dicomInstance TEXT, + fileUuid TEXT, + fileSize INTEGER, + jsonUuid TEXT, + distantAet TEXT + ); + +CREATE TABLE MainDicomTags( + uuid TEXT, + tagGroup INTEGER, + tagElement INTEGER, + value TEXT, + PRIMARY KEY(uuid, tagGroup, tagElement) + ); + +CREATE TABLE Changes( + seq INTEGER PRIMARY KEY AUTOINCREMENT, + basePath TEXT, + uuid TEXT + ); + + +CREATE INDEX PatientToStudies ON Studies(parentPatient); +CREATE INDEX StudyToSeries ON Series(parentStudy); +CREATE INDEX SeriesToInstances ON Instances(parentSeries); + +CREATE INDEX DicomPatientIndex ON Patients(dicomPatientId); +CREATE INDEX DicomStudyIndex ON Studies(dicomStudy); +CREATE INDEX DicomSeriesIndex ON Series(dicomSeries); +CREATE INDEX DicomInstanceIndex ON Instances(dicomInstance); + +CREATE INDEX MainDicomTagsIndex ON MainDicomTags(uuid); +CREATE INDEX ChangesIndex ON Changes(uuid); + +CREATE TRIGGER InstanceRemoved +AFTER DELETE ON Instances +FOR EACH ROW BEGIN + DELETE FROM MainDicomTags WHERE uuid = old.uuid; + DELETE FROM Changes WHERE uuid = old.uuid; + SELECT DeleteFromFileStorage(old.fileUuid); + SELECT DeleteFromFileStorage(old.jsonUuid); + SELECT SignalDeletedLevel(3, old.parentSeries); +END; + +CREATE TRIGGER SeriesRemoved +AFTER DELETE ON Series +FOR EACH ROW BEGIN + DELETE FROM MainDicomTags WHERE uuid = old.uuid; + DELETE FROM Changes WHERE uuid = old.uuid; + SELECT SignalDeletedLevel(2, old.parentStudy); +END; + +CREATE TRIGGER StudyRemoved +AFTER DELETE ON Studies +FOR EACH ROW BEGIN + DELETE FROM MainDicomTags WHERE uuid = old.uuid; + DELETE FROM Changes WHERE uuid = old.uuid; + SELECT SignalDeletedLevel(1, old.parentPatient); +END; + +CREATE TRIGGER PatientRemoved +AFTER DELETE ON Patients +FOR EACH ROW BEGIN + DELETE FROM MainDicomTags WHERE uuid = old.uuid; + DELETE FROM Changes WHERE uuid = old.uuid; + SELECT SignalDeletedLevel(0, ""); +END; + + + + +CREATE TRIGGER InstanceRemovedUpwardCleaning +AFTER DELETE ON Instances +FOR EACH ROW + WHEN (SELECT COUNT(*) FROM Instances WHERE parentSeries = old.parentSeries) = 0 + BEGIN + SELECT DeleteFromFileStorage("deleting parent series"); -- TODO REMOVE THIS + DELETE FROM Series WHERE uuid = old.parentSeries; + END; + +CREATE TRIGGER SeriesRemovedUpwardCleaning +AFTER DELETE ON Series +FOR EACH ROW + WHEN (SELECT COUNT(*) FROM Series WHERE parentStudy = old.parentStudy) = 0 + BEGIN + SELECT DeleteFromFileStorage("deleting parent study"); -- TODO REMOVE THIS + DELETE FROM Studies WHERE uuid = old.parentStudy; + END; + +CREATE TRIGGER StudyRemovedUpwardCleaning +AFTER DELETE ON Studies +FOR EACH ROW + WHEN (SELECT COUNT(*) FROM Studies WHERE parentPatient = old.parentPatient) = 0 + BEGIN + SELECT DeleteFromFileStorage("deleting parent patient"); -- TODO REMOVE THIS + DELETE FROM Patients WHERE uuid = old.parentPatient; + END;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/ServerIndex.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,837 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "ServerIndex.h" + +using namespace Palantir; + +#include <EmbeddedResources.h> +#include "../Core/Toolbox.h" +#include "../Core/Uuid.h" +#include "../Core/DicomFormat/DicomArray.h" +#include "../Core/SQLite/Transaction.h" +#include "FromDcmtkBridge.h" + +#include <boost/lexical_cast.hpp> +#include <stdio.h> + +namespace Palantir +{ + namespace Internals + { + class DeleteFromFileStorageFunction : public SQLite::IScalarFunction + { + private: + FileStorage fileStorage_; + + public: + DeleteFromFileStorageFunction(const std::string& path) : + fileStorage_(path) + { + } + + virtual const char* GetName() const + { + return "DeleteFromFileStorage"; + } + + virtual unsigned int GetCardinality() const + { + return 1; + } + + virtual void Compute(SQLite::FunctionContext& context) + { + std::string fileUuid = context.GetStringValue(0); + printf("Removing file [%s]\n", fileUuid.c_str()); + if (Toolbox::IsUuid(fileUuid)) + { + fileStorage_.Remove(fileUuid); + } + } + }; + + + class SignalDeletedLevelFunction : public SQLite::IScalarFunction + { + private: + int remainingLevel_; + std::string remainingLevelUuid_; + + public: + void Clear() + { + remainingLevel_ = std::numeric_limits<int>::max(); + } + + bool HasRemainingLevel() const + { + return (remainingLevel_ != 0 && + remainingLevel_ != std::numeric_limits<int>::max()); + } + + const std::string& GetRemainingLevelUuid() const + { + assert(HasRemainingLevel()); + return remainingLevelUuid_; + } + + const char* GetRemainingLevelType() const + { + assert(HasRemainingLevel()); + switch (remainingLevel_) + { + case 1: + return "patient"; + case 2: + return "study"; + case 3: + return "series"; + default: + throw PalantirException(ErrorCode_InternalError); + } + } + + virtual const char* GetName() const + { + return "SignalDeletedLevel"; + } + + virtual unsigned int GetCardinality() const + { + return 2; + } + + virtual void Compute(SQLite::FunctionContext& context) + { + int level = context.GetIntValue(0); + if (level < remainingLevel_) + { + remainingLevel_ = level; + remainingLevelUuid_ = context.GetStringValue(1); + } + + //printf("deleted level [%d] [%s]\n", level, context.GetStringValue(1).c_str()); + } + }; + } + + + void ServerIndex::StoreMainDicomTags(const std::string& uuid, + const DicomMap& map) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)"); + + DicomArray flattened(map); + for (size_t i = 0; i < flattened.GetSize(); i++) + { + s.Reset(); + s.BindString(0, uuid); + s.BindInt(1, flattened.GetElement(i).GetTag().GetGroup()); + s.BindInt(2, flattened.GetElement(i).GetTag().GetElement()); + s.BindString(3, flattened.GetElement(i).GetValue().AsString()); + s.Run(); + } + } + + bool ServerIndex::GetMainDicomStringTag(std::string& result, + const std::string& uuid, + const DicomTag& tag) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, + "SELECT * FROM MainDicomTags WHERE uuid=? AND tagGroup=? AND tagElement=?"); + s.BindString(0, uuid); + s.BindInt(1, tag.GetGroup()); + s.BindInt(2, tag.GetElement()); + if (!s.Step()) + { + return false; + } + + result = s.ColumnString(0); + return true; + } + + bool ServerIndex::GetMainDicomIntTag(int& result, + const std::string& uuid, + const DicomTag& tag) + { + std::string s; + if (!GetMainDicomStringTag(s, uuid, tag)) + { + return false; + } + + try + { + result = boost::lexical_cast<int>(s); + return true; + } + catch (boost::bad_lexical_cast) + { + return false; + } + } + + bool ServerIndex::HasInstance(std::string& instanceUuid, + const std::string& dicomInstance) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE dicomInstance=?"); + s.BindString(0, dicomInstance); + if (s.Step()) + { + instanceUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + + void ServerIndex::RecordChange(const std::string& resourceType, + const std::string& uuid) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Changes VALUES(NULL, ?, ?)"); + s.BindString(0, resourceType); + s.BindString(1, uuid); + s.Run(); + } + + + std::string ServerIndex::CreateInstance(const std::string& parentSeriesUuid, + const std::string& dicomInstance, + const DicomMap& dicomSummary, + const std::string& fileUuid, + uint64_t fileSize, + const std::string& jsonUuid, + const std::string& distantAet) + { + std::string instanceUuid = Toolbox::GenerateUuid(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Instances VALUES(?, ?, ?, ?, ?, ?, ?)"); + s.BindString(0, instanceUuid); + s.BindString(1, parentSeriesUuid); + s.BindString(2, dicomInstance); + s.BindString(3, fileUuid); + s.BindInt64(4, fileSize); + s.BindString(5, jsonUuid); + s.BindString(6, distantAet); + s.Run(); + + RecordChange("instances", instanceUuid); + + DicomMap dicom; + dicomSummary.ExtractInstanceInformation(dicom); + dicom.Remove(DicomTag::INSTANCE_UID); + StoreMainDicomTags(instanceUuid, dicom); + + return instanceUuid; + } + + void ServerIndex::RemoveInstance(const std::string& uuid) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM Instances WHERE uuid=?"); + s.BindString(0, uuid); + s.Run(); + } + + bool ServerIndex::HasSeries(std::string& seriesUuid, + const std::string& dicomSeries) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Series WHERE dicomSeries=?"); + s.BindString(0, dicomSeries); + if (s.Step()) + { + seriesUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + std::string ServerIndex::CreateSeries(const std::string& parentStudyUuid, + const std::string& dicomSeries, + const DicomMap& dicomSummary) + { + std::string seriesUuid = Toolbox::GenerateUuid(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Series VALUES(?, ?, ?)"); + s.BindString(0, seriesUuid); + s.BindString(1, parentStudyUuid); + s.BindString(2, dicomSeries); + s.Run(); + + RecordChange("series", seriesUuid); + + DicomMap dicom; + dicomSummary.ExtractSeriesInformation(dicom); + dicom.Remove(DicomTag::SERIES_UID); + StoreMainDicomTags(seriesUuid, dicom); + + return seriesUuid; + } + + bool ServerIndex::HasStudy(std::string& studyUuid, + const std::string& dicomStudy) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Studies WHERE dicomStudy=?"); + s.BindString(0, dicomStudy); + if (s.Step()) + { + studyUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + std::string ServerIndex::CreateStudy(const std::string& parentPatientUuid, + const std::string& dicomStudy, + const DicomMap& dicomSummary) + { + std::string studyUuid = Toolbox::GenerateUuid(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Studies VALUES(?, ?, ?)"); + s.BindString(0, studyUuid); + s.BindString(1, parentPatientUuid); + s.BindString(2, dicomStudy); + s.Run(); + + RecordChange("studies", studyUuid); + + DicomMap dicom; + dicomSummary.ExtractStudyInformation(dicom); + dicom.Remove(DicomTag::STUDY_UID); + StoreMainDicomTags(studyUuid, dicom); + + return studyUuid; + } + + + + bool ServerIndex::HasPatient(std::string& patientUuid, + const std::string& dicomPatientId) + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Patients WHERE dicomPatientId=?"); + s.BindString(0, dicomPatientId); + if (s.Step()) + { + patientUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + std::string ServerIndex::CreatePatient(const std::string& patientId, + const DicomMap& dicomSummary) + { + std::string patientUuid = Toolbox::GenerateUuid(); + std::string dicomPatientId = dicomSummary.GetValue(DicomTag::PATIENT_ID).AsString(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Patients VALUES(?, ?)"); + s.BindString(0, patientUuid); + s.BindString(1, dicomPatientId); + s.Run(); + + RecordChange("patients", patientUuid); + + DicomMap dicom; + dicomSummary.ExtractPatientInformation(dicom); + dicom.Remove(DicomTag::PATIENT_ID); + StoreMainDicomTags(patientUuid, dicom); + + return patientUuid; + } + + + void ServerIndex::GetMainDicomTags(DicomMap& map, + const std::string& uuid) + { + map.Clear(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM MainDicomTags WHERE uuid=?"); + s.BindString(0, uuid); + while (s.Step()) + { + map.SetValue(s.ColumnInt(1), + s.ColumnInt(2), + s.ColumnString(3)); + } + } + + void ServerIndex::MainDicomTagsToJson(Json::Value& target, + const std::string& uuid) + { + DicomMap map; + GetMainDicomTags(map, uuid); + target["MainDicomTags"] = Json::objectValue; + FromDcmtkBridge::ToJson(target["MainDicomTags"], map); + } + + + bool ServerIndex::DeleteInternal(Json::Value& target, + const std::string& uuid, + const std::string& tableName) + { + boost::mutex::scoped_lock scoped_lock(mutex_); + + deletedLevels_->Clear(); + + SQLite::Statement s(db_, "DELETE FROM " + tableName + " WHERE uuid=?"); + s.BindString(0, uuid); + + if (!s.Run()) + { + return false; + } + + if (db_.GetLastChangeCount() == 0) + { + // Nothing was deleted, inexistent UUID + return false; + } + + if (deletedLevels_->HasRemainingLevel()) + { + std::string type(deletedLevels_->GetRemainingLevelType()); + const std::string& uuid = deletedLevels_->GetRemainingLevelUuid(); + + target["RemainingAncestor"] = Json::Value(Json::objectValue); + target["RemainingAncestor"]["Path"] = "/" + type + "/" + uuid; + target["RemainingAncestor"]["Type"] = type; + target["RemainingAncestor"]["ID"] = uuid; + } + else + { + target["RemainingAncestor"] = Json::nullValue; + } + + return true; + } + + + ServerIndex::ServerIndex(const std::string& storagePath) + { + boost::filesystem::path p = storagePath; + + try + { + boost::filesystem::create_directories(storagePath); + } + catch (boost::filesystem::filesystem_error) + { + } + + p /= "index"; + db_.Open(p.string()); + db_.Register(new Internals::DeleteFromFileStorageFunction(storagePath)); + deletedLevels_ = (Internals::SignalDeletedLevelFunction*) + db_.Register(new Internals::SignalDeletedLevelFunction); + + if (!db_.DoesTableExist("GlobalProperties")) + { + printf("Creating the database\n"); + std::string query; + EmbeddedResources::GetFileResource(query, EmbeddedResources::PREPARE_DATABASE); + db_.Execute(query); + } + } + + + StoreStatus ServerIndex::Store(std::string& instanceUuid, + const DicomMap& dicomSummary, + const std::string& fileUuid, + uint64_t uncompressedFileSize, + const std::string& jsonUuid, + const std::string& distantAet) + { + boost::mutex::scoped_lock scoped_lock(mutex_); + + std::string dicomPatientId = dicomSummary.GetValue(DicomTag::PATIENT_ID).AsString(); + std::string dicomInstance = dicomSummary.GetValue(DicomTag::INSTANCE_UID).AsString(); + std::string dicomSeries = dicomSummary.GetValue(DicomTag::SERIES_UID).AsString(); + std::string dicomStudy = dicomSummary.GetValue(DicomTag::STUDY_UID).AsString(); + + try + { + SQLite::Transaction t(db_); + t.Begin(); + + if (HasInstance(instanceUuid, dicomInstance)) + { + return StoreStatus_AlreadyStored; + // TODO: Check consistency? + } + + std::string patientUuid; + if (HasPatient(patientUuid, dicomPatientId)) + { + // TODO: Check consistency? + } + else + { + patientUuid = CreatePatient(dicomPatientId, dicomSummary); + } + + std::string studyUuid; + if (HasStudy(studyUuid, dicomStudy)) + { + // TODO: Check consistency? + } + else + { + studyUuid = CreateStudy(patientUuid, dicomStudy, dicomSummary); + } + + std::string seriesUuid; + if (HasSeries(seriesUuid, dicomSeries)) + { + // TODO: Check consistency? + } + else + { + seriesUuid = CreateSeries(studyUuid, dicomSeries, dicomSummary); + } + + instanceUuid = CreateInstance(seriesUuid, dicomInstance, dicomSummary, fileUuid, + uncompressedFileSize, jsonUuid, distantAet); + + t.Commit(); + return StoreStatus_Success; + //t.Rollback(); + } + catch (PalantirException& e) + { + std::cout << "EXCEPT2 [" << e.What() << "]" << " " << db_.GetErrorMessage() << std::endl; + } + + return StoreStatus_Failure; + } + + + StoreStatus ServerIndex::Store(std::string& instanceUuid, + FileStorage& storage, + const char* dicomFile, + size_t dicomSize, + const DicomMap& dicomSummary, + const Json::Value& dicomJson, + const std::string& distantAet) + { + std::string fileUuid = storage.Create(dicomFile, dicomSize); + std::string jsonUuid = storage.Create(dicomJson.toStyledString()); + StoreStatus status = Store(instanceUuid, dicomSummary, fileUuid, + dicomSize, jsonUuid, distantAet); + + if (status != StoreStatus_Success) + { + storage.Remove(fileUuid); + storage.Remove(jsonUuid); + } + + switch (status) + { + case StoreStatus_Success: + std::cout << "New instance stored: " << GetTotalSize() << std::endl; + break; + + case StoreStatus_AlreadyStored: + std::cout << "Already stored" << std::endl; + break; + + case StoreStatus_Failure: + std::cout << "Store failure" << std::endl; + break; + } + + return status; + } + + uint64_t ServerIndex::GetTotalSize() + { + boost::mutex::scoped_lock scoped_lock(mutex_); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT SUM(fileSize) FROM Instances"); + s.Run(); + return s.ColumnInt64(0); + } + + + SeriesStatus ServerIndex::GetSeriesStatus(const std::string& seriesUuid) + { + int numberOfSlices; + if (!GetMainDicomIntTag(numberOfSlices, seriesUuid, DicomTag::NUMBER_OF_SLICES) || + numberOfSlices < 0) + { + return SeriesStatus_Unknown; + } + + // Loop over the instances of the series + //std::set< + + // TODO + return SeriesStatus_Unknown; + } + + + + + + bool ServerIndex::GetInstance(Json::Value& result, + const std::string& instanceUuid) + { + assert(result.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT parentSeries, dicomInstance, fileSize, fileUuid FROM Instances WHERE uuid=?"); + s.BindString(0, instanceUuid); + if (!s.Step()) + { + return false; + } + else + { + result["ID"] = instanceUuid; + result["ParentSeries"] = s.ColumnString(0); + result["DicomSOPInstanceUID"] = s.ColumnString(1); + result["FileSize"] = s.ColumnInt(2); // TODO switch to 64bit with JsonCpp 0.6? + result["FileUuid"] = s.ColumnString(3); + MainDicomTagsToJson(result, instanceUuid); + return true; + } + } + + + bool ServerIndex::GetSeries(Json::Value& result, + const std::string& seriesUuid) + { + assert(result.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentStudy, dicomSeries FROM Series WHERE uuid=?"); + s1.BindString(0, seriesUuid); + if (!s1.Step()) + { + return false; + } + + result["ID"] = seriesUuid; + result["ParentStudy"] = s1.ColumnString(0); + result["DicomSeriesInstanceUID"] = s1.ColumnString(1); + MainDicomTagsToJson(result, seriesUuid); + + Json::Value instances(Json::arrayValue); + SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Instances WHERE parentSeries=?"); + s2.BindString(0, seriesUuid); + while (s2.Step()) + { + instances.append(s2.ColumnString(0)); + } + + result["Instances"] = instances; + + return true; + } + + + bool ServerIndex::GetStudy(Json::Value& result, + const std::string& studyUuid) + { + assert(result.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT parentPatient, dicomStudy FROM Studies WHERE uuid=?"); + s1.BindString(0, studyUuid); + if (!s1.Step()) + { + return false; + } + + result["ID"] = studyUuid; + result["ParentPatient"] = s1.ColumnString(0); + result["DicomStudyInstanceUID"] = s1.ColumnString(1); + MainDicomTagsToJson(result, studyUuid); + + Json::Value series(Json::arrayValue); + SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Series WHERE parentStudy=?"); + s2.BindString(0, studyUuid); + while (s2.Step()) + { + series.append(s2.ColumnString(0)); + } + + result["Series"] = series; + return true; + } + + + bool ServerIndex::GetPatient(Json::Value& result, + const std::string& patientUuid) + { + assert(result.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s1(db_, SQLITE_FROM_HERE, "SELECT dicomPatientId FROM Patients WHERE uuid=?"); + s1.BindString(0, patientUuid); + if (!s1.Step()) + { + return false; + } + + result["ID"] = patientUuid; + result["DicomPatientID"] = s1.ColumnString(0); + MainDicomTagsToJson(result, patientUuid); + + Json::Value studies(Json::arrayValue); + SQLite::Statement s2(db_, SQLITE_FROM_HERE, "SELECT uuid FROM Studies WHERE parentPatient=?"); + s2.BindString(0, patientUuid); + while (s2.Step()) + { + studies.append(s2.ColumnString(0)); + } + + result["Studies"] = studies; + return true; + } + + + bool ServerIndex::GetJsonFile(std::string& fileUuid, + const std::string& instanceUuid) + { + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT jsonUuid FROM Instances WHERE uuid=?"); + s.BindString(0, instanceUuid); + if (s.Step()) + { + fileUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + bool ServerIndex::GetDicomFile(std::string& fileUuid, + const std::string& instanceUuid) + { + boost::mutex::scoped_lock scoped_lock(mutex_); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT fileUuid FROM Instances WHERE uuid=?"); + s.BindString(0, instanceUuid); + if (s.Step()) + { + fileUuid = s.ColumnString(0); + return true; + } + else + { + return false; + } + } + + + void ServerIndex::GetAllUuids(Json::Value& target, + const std::string& tableName) + { + assert(target.type() == Json::arrayValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + std::string query = "SELECT uuid FROM " + tableName; + SQLite::Statement s(db_, query); + while (s.Step()) + { + target.append(s.ColumnString(0)); + } + } + + + bool ServerIndex::GetChanges(Json::Value& target, + int64_t since, + const std::string& filter, + unsigned int maxResults) + { + assert(target.type() == Json::objectValue); + boost::mutex::scoped_lock scoped_lock(mutex_); + + if (filter.size() != 0 && + filter != "instances" && + filter != "series" && + filter != "studies" && + filter != "patients") + { + return false; + } + + std::auto_ptr<SQLite::Statement> s; + if (filter.size() == 0) + { + s.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? " + "ORDER BY seq LIMIT ?")); + s->BindInt64(0, since); + s->BindInt(1, maxResults); + } + else + { + s.reset(new SQLite::Statement(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? " + "AND basePath=? ORDER BY seq LIMIT ?")); + s->BindInt64(0, since); + s->BindString(1, filter); + s->BindInt(2, maxResults); + } + + int64_t lastSeq = 0; + Json::Value results(Json::arrayValue); + while (s->Step()) + { + int64_t seq = s->ColumnInt64(0); + std::string basePath = s->ColumnString(1); + std::string uuid = s->ColumnString(2); + + if (filter.size() == 0 || + filter == basePath) + { + Json::Value change(Json::objectValue); + change["Seq"] = static_cast<int>(seq); // TODO JsonCpp in 64bit + change["BasePath"] = basePath; + change["ID"] = uuid; + results.append(change); + } + + if (seq > lastSeq) + { + lastSeq = seq; + } + } + + target["Results"] = results; + target["LastSeq"] = static_cast<int>(lastSeq); // TODO JsonCpp in 64bit + + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/ServerIndex.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,193 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <boost/thread.hpp> +#include "../Core/SQLite/Connection.h" +#include "../Core/DicomFormat/DicomMap.h" +#include "../Core/FileStorage.h" + + +namespace Palantir +{ + enum SeriesStatus + { + SeriesStatus_Complete, + SeriesStatus_Missing, + SeriesStatus_Inconsistent, + SeriesStatus_Unknown + }; + + + enum StoreStatus + { + StoreStatus_Success, + StoreStatus_AlreadyStored, + StoreStatus_Failure + }; + + + namespace Internals + { + class SignalDeletedLevelFunction; + } + + + class ServerIndex + { + private: + SQLite::Connection db_; + boost::mutex mutex_; + + // DO NOT delete the following one, SQLite::Connection will do it automatically + Internals::SignalDeletedLevelFunction* deletedLevels_; + + void StoreMainDicomTags(const std::string& uuid, + const DicomMap& map); + + bool GetMainDicomStringTag(std::string& result, + const std::string& uuid, + const DicomTag& tag); + + bool GetMainDicomIntTag(int& result, + const std::string& uuid, + const DicomTag& tag); + + bool HasInstance(std::string& instanceUuid, + const std::string& dicomInstance); + + void RecordChange(const std::string& resourceType, + const std::string& uuid); + + std::string CreateInstance(const std::string& parentSeriesUuid, + const std::string& dicomInstance, + const DicomMap& dicomSummary, + const std::string& fileUuid, + uint64_t fileSize, + const std::string& jsonUuid, + const std::string& distantAet); + + void RemoveInstance(const std::string& uuid); + + bool HasSeries(std::string& seriesUuid, + const std::string& dicomSeries); + + std::string CreateSeries(const std::string& parentStudyUuid, + const std::string& dicomSeries, + const DicomMap& dicomSummary); + + bool HasStudy(std::string& studyUuid, + const std::string& dicomStudy); + + std::string CreateStudy(const std::string& parentPatientUuid, + const std::string& dicomStudy, + const DicomMap& dicomSummary); + + bool HasPatient(std::string& patientUuid, + const std::string& dicomPatientId); + + std::string CreatePatient(const std::string& patientId, + const DicomMap& dicomSummary); + + void GetMainDicomTags(DicomMap& map, + const std::string& uuid); + + void MainDicomTagsToJson(Json::Value& target, + const std::string& uuid); + + bool DeleteInternal(Json::Value& target, + const std::string& uuid, + const std::string& tableName); + + public: + ServerIndex(const std::string& storagePath); + + StoreStatus Store(std::string& instanceUuid, + const DicomMap& dicomSummary, + const std::string& fileUuid, + uint64_t uncompressedFileSize, + const std::string& jsonUuid, + const std::string& distantAet); + + StoreStatus Store(std::string& instanceUuid, + FileStorage& storage, + const char* dicomFile, + size_t dicomSize, + const DicomMap& dicomSummary, + const Json::Value& dicomJson, + const std::string& distantAet); + + uint64_t GetTotalSize(); + + SeriesStatus GetSeriesStatus(const std::string& seriesUuid); + + + bool GetInstance(Json::Value& result, + const std::string& instanceUuid); + + bool GetSeries(Json::Value& result, + const std::string& seriesUuid); + + bool GetStudy(Json::Value& result, + const std::string& studyUuid); + + bool GetPatient(Json::Value& result, + const std::string& patientUuid); + + bool GetJsonFile(std::string& fileUuid, + const std::string& instanceUuid); + + bool GetDicomFile(std::string& fileUuid, + const std::string& instanceUuid); + + void GetAllUuids(Json::Value& target, + const std::string& tableName); + + bool DeletePatient(Json::Value& target, + const std::string& patientUuid) + { + return DeleteInternal(target, patientUuid, "Patients"); + } + + bool DeleteStudy(Json::Value& target, + const std::string& studyUuid) + { + return DeleteInternal(target, studyUuid, "Studies"); + } + + bool DeleteSeries(Json::Value& target, + const std::string& seriesUuid) + { + return DeleteInternal(target, seriesUuid, "Series"); + } + + bool DeleteInstance(Json::Value& target, + const std::string& instanceUuid) + { + return DeleteInternal(target, instanceUuid, "Instances"); + } + + bool GetChanges(Json::Value& target, + int64_t since, + const std::string& filter, + unsigned int maxResults); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/ToDcmtkBridge.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,49 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "ToDcmtkBridge.h" + +#include <memory> +#include <dcmtk/dcmdata/dcelem.h> +#include <dcmtk/dcmnet/diutil.h> + + +namespace Palantir +{ + DcmTagKey ToDcmtkBridge::Convert(const DicomTag& tag) + { + return DcmTagKey(tag.GetGroup(), tag.GetElement()); + } + + + DcmDataset* ToDcmtkBridge::Convert(const DicomMap& map) + { + std::auto_ptr<DcmDataset> result(new DcmDataset); + + for (DicomMap::Map::const_iterator + it = map.map_.begin(); it != map.map_.end(); it++) + { + std::string s = it->second->AsString(); + DU_putStringDOElement(result.get(), Convert(it->first), s.c_str()); + } + + return result.release(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/ToDcmtkBridge.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,36 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/DicomFormat/DicomMap.h" +#include <dcmtk/dcmdata/dcdatset.h> + + +namespace Palantir +{ + class ToDcmtkBridge + { + public: + static DcmTagKey Convert(const DicomTag& tag); + + static DcmDataset* Convert(const DicomMap& map); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PalantirServer/main.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,154 @@ +/** + * Palantir - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012 Medical Physics Department, CHU 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. + * + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "PalantirRestApi.h" + +#include <stdio.h> + +#include "../Core/HttpServer/EmbeddedResourceHttpHandler.h" +#include "../Core/HttpServer/FilesystemHttpHandler.h" +#include "../Core/HttpServer/MongooseServer.h" +#include "DicomProtocol/DicomServer.h" +#include "PalantirInitialization.h" + + +using namespace Palantir; + + +class MyDicomStore : public IStoreRequestHandler +{ +private: + ServerIndex& index_; + FileStorage storage_; + +public: + MyDicomStore(ServerIndex& index, + const std::string& path) : + index_(index), + storage_(path) + { + } + + virtual void Handle(const std::vector<uint8_t>& dicomFile, + const DicomMap& dicomSummary, + const Json::Value& dicomJson, + const std::string& distantAet) + { + std::string instanceUuid; + if (dicomFile.size() > 0) + { + index_.Store(instanceUuid, storage_, + reinterpret_cast<const char*>(&dicomFile[0]), dicomFile.size(), + dicomSummary, dicomJson, distantAet); + } + } +}; + + +class MyDicomStoreFactory : public IStoreRequestHandlerFactory +{ +private: + ServerIndex& index_; + std::string path_; + +public: + MyDicomStoreFactory(ServerIndex& index, + const std::string& path) : + index_(index), + path_(path) + { + } + + virtual IStoreRequestHandler* ConstructStoreRequestHandler() + { + return new MyDicomStore(index_, path_); + } + + void Done() + { + //index_.db().Execute("DELETE FROM Studies"); + } +}; + + + + + + + +int main(int argc, char* argv[]) +{ + if (argc >= 2) + { + PalantirInitialize(argv[1]); + } + else + { + PalantirInitialize(); + } + + + try + { + ServerIndex index("server"); + MyDicomStoreFactory storeScp(index, "server"); + + { + // DICOM server + DicomServer dicomServer; + dicomServer.SetCalledApplicationEntityTitleCheck(true); + dicomServer.SetStoreRequestHandlerFactory(storeScp); + dicomServer.SetPort(GetGlobalIntegerParameter("DicomPort", 4242)); + dicomServer.SetApplicationEntityTitle(GetGlobalStringParameter("DicomAet", "PALANTIR")); + + // HTTP server + MongooseServer httpServer; + httpServer.SetPort(GetGlobalIntegerParameter("HttpPort", 8000)); + +#if PALANTIR_RELEASE == 1 + httpServer.RegisterHandler(new EmbeddedResourceHttpHandler("/app", EmbeddedResources::PALANTIR_EXPLORER)); +#else + httpServer.RegisterHandler(new FilesystemHttpHandler("/app", PALANTIR_PATH "/PalantirExplorer")); +#endif + + httpServer.RegisterHandler(new PalantirRestApi(index, "server")); + + // GO !!! + httpServer.Start(); + dicomServer.Start(); + + printf("The server has started\n"); + Toolbox::ServerBarrier(); + + // Stop + printf("Finishing\n"); + } + + storeScp.Done(); + } + catch (PalantirException& e) + { + std::cout << "EXCEPT [" << e.What() << "]" << std::endl; + } + + PalantirFinalize(); + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,81 @@ +Palantir - A Lightweight, RESTful DICOM Server +============================================== + +General Information +------------------- + +General information about this software can be found on our Google +Code hosting page: +http://code.google.com/p/palantir-dicom/ + +The instructions for building Palantir can be found in the "INSTALL" +file. + + + +Licensing +--------- + +Palantir is licensed under the GPLv3 license. Because Palantir uses +the Software-as-a-Service paradigm, commercial products are allowed to +access the Palantir REST services and to bundle Palantir in an +commercial aggregate. + +We also kindly require scientific works that make use of Palantir to +cite Palantir in their associated publications. + +The files of the "PalantirCppClient" directory are licensed under the +MIT license, which allow commercial products to statically link +against the C++ client library. + + + +Supported Platforms +------------------- + +Currently, the supported platforms are: + +* Linux 32bit. +* Linux 64bit. +* Windows 32bit (through MinGW). + + + +Supported Toolchains +-------------------- + +Palantir can currently be built using the following compiling +toolchains: + +* Native Linux compilation, with gcc. +* Cross-compilation for Windows under Linux through MinGW. + +More toolchains will be supported in the future. + + + +Content +------- + +This archive contains the following directories: + +* Core/ - The core C++ classes (independent of DCMTK) +* PalantirCppClient/ - Code of the C++ client (under MIT license) +* PalantirExplorer/ - Code of the Web application (HTML5/Javascript) +* PalantirServer/ - Code of the Palantir server (depends on DCMTK) +* Resources/ - Scripts, resources for building third-party code +* UnitTests/ - Unit tests + +This archive contains the following files: + +* AUTHORS - The list of the authors +* CMakeLists.txt - The main build script +* COPYING - The GPLv3 license +* INSTALL - How to build Palantir +* README - This file +* THANKS - The list of the contributors + +We have decided not to maintain separate "NEWS" and "ChangeLog" +files. The major features of each version of Palantir ("NEWS") can be +found on our Web site. Each commit to the official Palantir Mercurial +repository should be associated with a description of the changes.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/AutoGeneratedCode.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,41 @@ +set(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_ARGUMENTS) + set(DEPENDENCIES) + set(IS_PATH_NAME false) + foreach(arg ${ARGN}) + if (${IS_PATH_NAME}) + list(APPEND SCRIPT_ARGUMENTS "${CMAKE_CURRENT_SOURCE_DIR}/${arg}") + list(APPEND DEPENDENCIES "${CMAKE_CURRENT_SOURCE_DIR}/${arg}") + set(IS_PATH_NAME false) + else() + list(APPEND SCRIPT_ARGUMENTS "${arg}") + set(IS_PATH_NAME true) + endif() + endforeach() + + set(TARGET_BASE "${AUTOGENERATED_DIR}/EmbeddedResources") + add_custom_command( + OUTPUT + "${TARGET_BASE}.h" + "${TARGET_BASE}.cpp" + COMMAND + python + "${CMAKE_CURRENT_SOURCE_DIR}/Resources/EmbedResources.py" + "${AUTOGENERATED_DIR}/EmbeddedResources" + ${SCRIPT_ARGUMENTS} + DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/Resources/EmbedResources.py" + ${DEPENDENCIES} + ) + + list(APPEND AUTOGENERATED_SOURCES + "${AUTOGENERATED_DIR}/EmbeddedResources.cpp" + ) +endmacro()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/BoostConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,75 @@ +if (${STATIC_BUILD}) + SET(BOOST_STATIC 1) +else() + find_package(Boost + COMPONENTS filesystem thread system) + + 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) + else() + SET(BOOST_STATIC 0) + + add_definitions( + -DBOOST_FILESYSTEM_VERSION=3 + ) + + include_directories(${Boost_INCLUDE_DIRS}) + link_libraries(${Boost_LIBRARIES}) + endif() +endif() + + +if (BOOST_STATIC) + SET(BOOST_NAME boost_1_49_0) + SET(BOOST_SOURCES_DIR ${CMAKE_BINARY_DIR}/${BOOST_NAME}) + DownloadPackage("http://switch.dl.sourceforge.net/project/boost/boost/1.49.0/${BOOST_NAME}.tar.gz" "${BOOST_SOURCES_DIR}" "${BOOST_PRELOADED}" "${BOOST_NAME}/boost ${BOOST_NAME}/libs/thread/src ${BOOST_NAME}/libs/system/src ${BOOST_NAME}/libs/filesystem/v3/src ${BOOST_NAME}/libs/locale/src") + + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + list(APPEND THIRD_PARTY_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 + ) + elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + list(APPEND THIRD_PARTY_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_SOURCES_DIR}/libs/filesystem/v3/src/windows_file_codecvt.cpp + ) + add_definitions( + -DBOOST_LOCALE_WITH_WCONV=1 + ) + else() + message(FATAL_ERROR "Support your platform here") + endif() + + list(APPEND THIRD_PARTY_SOURCES + ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp + ${BOOST_SOURCES_DIR}/libs/filesystem/v3/src/path.cpp + ${BOOST_SOURCES_DIR}/libs/filesystem/v3/src/path_traits.cpp + ${BOOST_SOURCES_DIR}/libs/filesystem/v3/src/operations.cpp + ${BOOST_SOURCES_DIR}/libs/filesystem/v3/src/codecvt_error_category.cpp + ${BOOST_SOURCES_DIR}/libs/locale/src/encoding/codepage.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 + ) + + include_directories( + ${BOOST_SOURCES_DIR} + ) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/DcmtkConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,58 @@ +if (${STATIC_BUILD}) + SET(DCMTK_SOURCES_DIR ${CMAKE_BINARY_DIR}/dcmtk-3.6.0) + DownloadPackage("ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/dcmtk360/dcmtk-3.6.0.zip" "${DCMTK_SOURCES_DIR}" "" "") + + IF(CMAKE_CROSSCOMPILING) + SET(C_CHAR_UNSIGNED 1 CACHE INTERNAL "Whether char is unsigned.") + ENDIF() + SET(DCMTK_SOURCE_DIR ${CMAKE_BINARY_DIR}/dcmtk-3.6.0) + include(${DCMTK_SOURCES_DIR}/CMake/CheckFunctionWithHeaderExists.cmake) + include(${DCMTK_SOURCES_DIR}/CMake/GenerateDCMTKConfigure.cmake) + CONFIGURE_FILE(${DCMTK_SOURCES_DIR}/CMake/osconfig.h.in + ${DCMTK_SOURCES_DIR}/config/include/dcmtk/config/osconfig.h) + + AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmnet/libsrc THIRD_PARTY_SOURCES) + AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmdata/libsrc THIRD_PARTY_SOURCES) + AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/ofstd/libsrc THIRD_PARTY_SOURCES) + AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/oflog/libsrc THIRD_PARTY_SOURCES) + + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + list(REMOVE_ITEM THIRD_PARTY_SOURCES + ${DCMTK_SOURCES_DIR}/oflog/libsrc/windebap.cc + ${DCMTK_SOURCES_DIR}/oflog/libsrc/winsock.cc + ) + elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + list(REMOVE_ITEM THIRD_PARTY_SOURCES + ${DCMTK_SOURCES_DIR}/oflog/libsrc/unixsock.cc + ) + endif() + + list(REMOVE_ITEM THIRD_PARTY_SOURCES + ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/mkdictbi.cc + ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/mkdeftag.cc + ${DCMTK_SOURCES_DIR}/dcmdata/libsrc/dcdictbi.cc + ) + + # This fixes crashes related to the destruction of the DCMTK OFLogger + # http://support.dcmtk.org/docs-snapshot/file_macros.html + add_definitions(-DLOG4CPLUS_DISABLE_FATAL=1) + + include_directories( + #${DCMTK_SOURCES_DIR} + ${DCMTK_SOURCES_DIR}/config/include + ${DCMTK_SOURCES_DIR}/dcmnet/include + ${DCMTK_SOURCES_DIR}/ofstd/include + ${DCMTK_SOURCES_DIR}/oflog/include + ${DCMTK_SOURCES_DIR}/dcmdata/include + ) + +else() + include(FindDCMTK) + + include_directories(${DCMTK_INCLUDE_DIR}) + link_libraries(${DCMTK_LIBRARIES} oflog ofstd wrap) + + add_definitions( + -DHAVE_CONFIG_H=1 + ) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/DownloadPackage.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,61 @@ +macro(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() + + +macro(DownloadPackage Url TargetDirectory PreloadedVariable UncompressArguments) + if (NOT IS_DIRECTORY "${TargetDirectory}") + GetUrlFilename(TMP_FILENAME "${Url}") + if ("${PreloadedVariable}" STREQUAL "") + set(TMP_PATH "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${TMP_FILENAME}") + if (NOT EXISTS "${TMP_PATH}") + message("Downloading ${Url}") + file(DOWNLOAD "${Url}" "${TMP_PATH}" SHOW_PROGRESS) + else() + message("Already downloaded ${Url}") + endif() + else() + message("Using preloaded archive ${PreloadedVariable} for ${Url}") + set(TMP_PATH "${PreloadedVariable}") + endif() + + GetUrlExtension(TMP_EXTENSION "${Url}") + #message(${TMP_EXTENSION}) + + if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux") + if ("${TMP_EXTENSION}" STREQUAL "zip") + execute_process( + COMMAND sh -c "unzip ${TMP_PATH} ${UncompressArguments}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + elseif (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz")) + #message("tar xvfz ${TMP_PATH} ${UncompressArguments}") + execute_process( + COMMAND sh -c "tar xvfz ${TMP_PATH} ${UncompressArguments}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + elseif ("${TMP_EXTENSION}" STREQUAL "bz2") + execute_process( + COMMAND sh -c "tar xvfj ${TMP_PATH} ${UncompressArguments}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + else() + message(FATAL_ERROR "Unknown package format.") + endif() + else() + message(FATAL_ERROR "Support your platform here") + 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() +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/GoogleTestConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,18 @@ +if (${STATIC_BUILD}) + SET(GTEST_SOURCES_DIR ${CMAKE_BINARY_DIR}/gtest-1.6.0) + DownloadPackage("http://googletest.googlecode.com/files/gtest-1.6.0.zip" "${GTEST_SOURCES_DIR}" "" "") + + include_directories( + ${GTEST_SOURCES_DIR}/include + ${GTEST_SOURCES_DIR} + ) + + set(GTEST_SOURCES + ${GTEST_SOURCES_DIR}/src/gtest-all.cc + ) + +else() + include(FindGTest) + include_directories(${GTEST_INCLUDE_DIRS}) + link_libraries(${GTEST_LIBRARIES}) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/JsonCppConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,12 @@ +SET(JSONCPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/jsoncpp-src-0.5.0) +DownloadPackage("http://downloads.sourceforge.net/project/jsoncpp/jsoncpp/0.5.0/jsoncpp-src-0.5.0.tar.gz" "${JSONCPP_SOURCES_DIR}" "" "") + +list(APPEND THIRD_PARTY_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 + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/LibCurlConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,48 @@ +if (${STATIC_BUILD}) + SET(CURL_SOURCES_DIR ${CMAKE_BINARY_DIR}/curl-7.26.0) + DownloadPackage("http://curl.haxx.se/download/curl-7.26.0.tar.gz" "${CURL_SOURCES_DIR}" "" "") + + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + SET(SOURCE_CONFIG ${CMAKE_SOURCE_DIR}/Resources/libcurl/x86_64-linux) + elseif ("${CMAKE_SIZEOF_VOID_P}" EQUAL "4") + SET(SOURCE_CONFIG ${CMAKE_SOURCE_DIR}/Resources/libcurl/i686-pc-linux-gnu) + else() + message(FATAL_ERROR "Support your platform here") + endif() + elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + SET(SOURCE_CONFIG ${CMAKE_SOURCE_DIR}/Resources/libcurl/i586-mingw32msvc) + else() + message(FATAL_ERROR "Support your platform here") + endif() + + configure_file("${SOURCE_CONFIG}/curl_config.h" "${CURL_SOURCES_DIR}/lib/curl_config.h" COPYONLY) + configure_file("${SOURCE_CONFIG}/curlbuild.h" "${CURL_SOURCES_DIR}/include/curl/curlbuild.h" COPYONLY) + + include_directories(${CURL_SOURCES_DIR}/include) + + AUX_SOURCE_DIRECTORY(${CURL_SOURCES_DIR}/lib CURL_SOURCES) + + set_property( + SOURCE ${CURL_SOURCES} + PROPERTY COMPILE_DEFINITIONS HAVE_CONFIG_H) + + list(APPEND THIRD_PARTY_SOURCES ${CURL_SOURCES}) + + add_definitions( + -DCURL_STATICLIB=1 + -DBUILDING_LIBCURL=1 + ) + + #add_library(libcurl STATIC ${CURL_SOURCES}) + #link_libraries(libcurl) + +else() + include(FindCURL) + include_directories(${CURL_INCLUDE_DIRS}) + link_libraries(${CURL_LIBRARIES}) + + if (NOT ${CURL_FOUND}) + message(FATAL_ERROR "Unable to find LibCurl") + endif() +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/LibPngConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,55 @@ +if (${STATIC_BUILD}) + SET(LIBPNG_SOURCES_DIR ${CMAKE_BINARY_DIR}/libpng-1.5.12) + DownloadPackage("http://download.sourceforge.net/libpng/libpng-1.5.12.tar.gz" "${LIBPNG_SOURCES_DIR}" "${LIBPNG_PRELOADED}" "") + + include_directories( + ${LIBPNG_SOURCES_DIR} + ) + + configure_file( + ${LIBPNG_SOURCES_DIR}/scripts/pnglibconf.h.prebuilt + ${LIBPNG_SOURCES_DIR}/pnglibconf.h + COPY_ONLY) + + set(LIBPNG_SOURCES + #${LIBPNG_SOURCES_DIR}/example.c + ${LIBPNG_SOURCES_DIR}/png.c + ${LIBPNG_SOURCES_DIR}/pngerror.c + ${LIBPNG_SOURCES_DIR}/pngget.c + ${LIBPNG_SOURCES_DIR}/pngmem.c + ${LIBPNG_SOURCES_DIR}/pngpread.c + ${LIBPNG_SOURCES_DIR}/pngread.c + ${LIBPNG_SOURCES_DIR}/pngrio.c + ${LIBPNG_SOURCES_DIR}/pngrtran.c + ${LIBPNG_SOURCES_DIR}/pngrutil.c + ${LIBPNG_SOURCES_DIR}/pngset.c + #${LIBPNG_SOURCES_DIR}/pngtest.c + ${LIBPNG_SOURCES_DIR}/pngtrans.c + ${LIBPNG_SOURCES_DIR}/pngwio.c + ${LIBPNG_SOURCES_DIR}/pngwrite.c + ${LIBPNG_SOURCES_DIR}/pngwtran.c + ${LIBPNG_SOURCES_DIR}/pngwutil.c + ) + + #set_property( + # SOURCE ${LIBPNG_SOURCES} + # PROPERTY COMPILE_FLAGS -UHAVE_CONFIG_H) + + list(APPEND THIRD_PARTY_SOURCES ${LIBPNG_SOURCES}) + + add_definitions( + -DPNG_NO_CONSOLE_IO=1 + -DPNG_NO_STDIO=1 + ) + +else() + include(FindPNG) + + if (NOT ${PNG_FOUND}) + message(FATAL_ERROR "Unable to find LibPNG") + endif() + + include_directories(${PNG_INCLUDE_DIRS}) + link_libraries(${PNG_LIBRARIES}) + add_definitions(${PNG_DEFINITIONS}) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/MongooseConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,21 @@ +SET(MONGOOSE_SOURCES_DIR ${CMAKE_BINARY_DIR}/mongoose) +DownloadPackage("http://mongoose.googlecode.com/files/mongoose-3.1.tgz" "${MONGOOSE_SOURCES_DIR}" "" "") + +# Patch mongoose +execute_process( + COMMAND patch mongoose.c ${CMAKE_SOURCE_DIR}/Resources/mongoose-patch.diff + WORKING_DIRECTORY ${MONGOOSE_SOURCES_DIR} + ) + +include_directories( + ${MONGOOSE_SOURCES_DIR} + ) + +list(APPEND THIRD_PARTY_SOURCES + ${MONGOOSE_SOURCES_DIR}/mongoose.c + ) + +add_definitions( + # Remove SSL support from mongoose + -DNO_SSL=1 + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/SQLiteConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,17 @@ +SET(SQLITE_SOURCES_DIR ${CMAKE_BINARY_DIR}/sqlite-amalgamation-3071300) +DownloadPackage("http://www.sqlite.org/sqlite-amalgamation-3071300.zip" "${SQLITE_SOURCES_DIR}" "" "") + +list(APPEND THIRD_PARTY_SOURCES + ${SQLITE_SOURCES_DIR}/sqlite3.c + ) + +add_definitions( + # For SQLite to run in the "Serialized" thread-safe mode + # http://www.sqlite.org/threadsafe.html + -DSQLITE_THREADSAFE=1 + -DSQLITE_OMIT_LOAD_EXTENSION # Disable SQLite plugins + ) + +include_directories( + ${SQLITE_SOURCES_DIR} + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/ZlibConfiguration.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,31 @@ +if (${STATIC_BUILD}) + SET(ZLIB_SOURCES_DIR ${CMAKE_BINARY_DIR}/zlib-1.2.7) + DownloadPackage("http://zlib.net/zlib-1.2.7.tar.gz" "${ZLIB_SOURCES_DIR}" "${ZLIB_PRELOADED}" "") + + include_directories( + ${ZLIB_SOURCES_DIR} + ) + + list(APPEND THIRD_PARTY_SOURCES + ${ZLIB_SOURCES_DIR}/adler32.c + ${ZLIB_SOURCES_DIR}/compress.c + ${ZLIB_SOURCES_DIR}/crc32.c + ${ZLIB_SOURCES_DIR}/deflate.c + ${ZLIB_SOURCES_DIR}/gzclose.c + ${ZLIB_SOURCES_DIR}/gzlib.c + ${ZLIB_SOURCES_DIR}/gzread.c + ${ZLIB_SOURCES_DIR}/gzwrite.c + ${ZLIB_SOURCES_DIR}/infback.c + ${ZLIB_SOURCES_DIR}/inffast.c + ${ZLIB_SOURCES_DIR}/inflate.c + ${ZLIB_SOURCES_DIR}/inftrees.c + ${ZLIB_SOURCES_DIR}/trees.c + ${ZLIB_SOURCES_DIR}/uncompr.c + ${ZLIB_SOURCES_DIR}/zutil.c + ) + +else() + include(FindZLIB) + include_directories(${ZLIB_INCLUDE_DIRS}) + link_libraries(${ZLIB_LIBRARIES}) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Configuration.json Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,11 @@ +{ + "HttpPort" : 8000, + + "DicomAet" : "ANY-SCP", + "DicomPort" : 4242, + "DicomModalities" : { + }, + + "PalantirPeers" : { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/EmbedResources.py Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,310 @@ +import sys +import os +import os.path +import pprint + +if len(sys.argv) < 2 or len(sys.argv) % 2 != 0: + print ('Usage:') + print ('python %s <TargetBaseFilename> [ <Name> <Source> ]*' % sys.argv[0]) + exit(-1) + + +try: + # Make sure the destination directory exists + os.makedirs(os.path.normpath(os.path.join(sys.argv[1], '..'))) +except: + pass + + +##################################################################### +## Read each resource file +##################################################################### + +resources = {} + +counter = 0 +i = 2 +while i < len(sys.argv): + resourceName = sys.argv[i].upper() + pathName = sys.argv[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) + for f in files: + if f.find('~') == -1: # Ignore Emacs backup files + if base == '.': + r = f.lower() + else: + r = os.path.join(base, f).lower() + + r = '/' + r + 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(sys.argv[1] + '.h', 'w') + +header.write(""" +#pragma once + +#include <string> + +namespace Palantir +{ + namespace EmbeddedResources + { + enum FileResourceId + { +""") + +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); + } +} +""") +header.close() + + + +##################################################################### +## Write the resource content in the .cpp source +##################################################################### + +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 pos > 0: + cpp.write(', ') + + if (pos % 16) == 0: + cpp.write('\n ') + + if ord(b[0]) < 0: + raise Exception("Internal error") + + cpp.write("0x%02x" % ord(b[0])) + pos += 1 + + cpp.write(' };\n') + cpp.write(' static const size_t resource%dSize = %d;\n' % (item['Index'], pos)) + + +cpp = open(sys.argv[1] + '.cpp', 'w') + +cpp.write(""" +#include "%s.h" +#include "%s/Core/PalantirException.h" + +#include <stdint.h> +#include <string.h> + +namespace Palantir +{ + namespace EmbeddedResources + { +""" % (os.path.basename(sys.argv[1]), + os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))) + + +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 PalantirException(ErrorCode_ParameterOutOfRange); + } + } + + size_t GetFileResourceSize(FileResourceId id) + { + switch (id) + { +""") + +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 PalantirException(ErrorCode_ParameterOutOfRange); + } + } +""") + + + +##################################################################### +## 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 PalantirException("Unknown path in a directory resource");\n\n') + +cpp.write(""" default: + throw PalantirException(ErrorCode_ParameterOutOfRange); + } + } + + size_t GetDirectoryResourceSize(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%dSize;\n' % resources[name]['Files'][path]['Index']) + cpp.write(' throw PalantirException("Unknown path in a directory resource");\n\n') + +cpp.write(""" default: + throw PalantirException(ErrorCode_ParameterOutOfRange); + } + } +""") + + + + +##################################################################### +## 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()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/MinGWToolchain.cmake Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,19 @@ +# http://www.vtk.org/Wiki/CmakeMingw + +# 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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Palantir.doxygen Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,1716 @@ +# Doxyfile 1.7.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Palantir + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @CMAKE_SOURCE_DIR@/Core @CMAKE_SOURCE_DIR@/PalantirServer @CMAKE_SOURCE_DIR@/PalantirCppClient + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = Palantir::Internals + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = doc + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is adviced to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/libcurl/NOTES Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,29 @@ +1- GENERATE THE CONFIGURATION FILES +=================================== + +Download and uncompress curl 7.26.0. + + +For Linux +--------- + +# ./configure --without-ssl --without-zlib --without-libidn --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-ipv6 + + +For MinGW +--------- + +# ./configure --host=i586-mingw32msvc --without-ssl --without-zlib --without-libidn --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-proxy --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-ipv6 + + + +2- COPY THE CONFIGURATION FILES +=============================== + + +For MinGW +--------- + +# mkdir i586-mingw32msvc +# cp lib/curl_config.h [...]/Resources/libcurl/i586-mingw32msvc/ +# cp include/curl/curlbuild.h [...]/Resources/libcurl/i586-mingw32msvc/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/libcurl/i586-mingw32msvc/curl_config.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,1056 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +#define CURL_CA_BUNDLE "/etc/ssl/certs/ca-certificates.crt" + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +#define CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#define CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable Gopher */ +#define CURL_DISABLE_GOPHER 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +#define CURL_DISABLE_IMAP 1 + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +/* #undef CURL_DISABLE_LIBCURL_OPTION */ + +/* to disable POP3 */ +#define CURL_DISABLE_POP3 1 + +/* to disable proxies */ +#define CURL_DISABLE_PROXY 1 + +/* to disable RTSP */ +#define CURL_DISABLE_RTSP 1 + +/* to disable SMTP */ +#define CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable TLS-SRP authentication */ +/* #undef CURL_DISABLE_TLS_SRP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +/* #undef CURL_EXTERN_SYMBOL */ + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_QUAL_ARG1 */ + +/* Define to the type of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG1 */ + +/* Define to the type of arg 2 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG2 */ + +/* Define to the type of args 4 and 6 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG46 */ + +/* Define to the type of arg 7 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG7 */ + +/* Specifies the number of arguments to getservbyport_r */ +/* #undef GETSERVBYPORT_R_ARGS */ + +/* Specifies the size of the buffer to pass to getservbyport_r */ +/* #undef GETSERVBYPORT_R_BUFSIZE */ + +/* Define to 1 if you have the alarm function. */ +/* #undef HAVE_ALARM */ + +/* Define to 1 if you have the <alloca.h> header file. */ +/* #undef HAVE_ALLOCA_H */ + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +/* #undef HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the <arpa/tftp.h> header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the <assert.h> header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */ + +/* Define to 1 if you have the closesocket function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the <crypto.h> header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the <des.h> header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the <err.h> header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +/* #undef HAVE_FCNTL */ + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +/* #undef HAVE_FCNTL_O_NONBLOCK */ + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +/* #undef HAVE_FORK */ + +/* Define to 1 if you have the freeaddrinfo function. */ +/* #undef HAVE_FREEADDRINFO */ + +/* Define to 1 if you have the freeifaddrs function. */ +/* #undef HAVE_FREEIFADDRS */ + +/* Define to 1 if you have the fsetxattr function. */ +/* #undef HAVE_FSETXATTR */ + +/* fsetxattr() takes 5 args */ +/* #undef HAVE_FSETXATTR_5 */ + +/* fsetxattr() takes 6 args */ +/* #undef HAVE_FSETXATTR_6 */ + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +/* #undef HAVE_GAI_STRERROR */ + +/* Define to 1 if you have a working getaddrinfo function. */ +/* #undef HAVE_GETADDRINFO */ + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +/* #undef HAVE_GETADDRINFO_THREADSAFE */ + +/* Define to 1 if you have the `geteuid' function. */ +/* #undef HAVE_GETEUID */ + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +/* #undef HAVE_GETHOSTBYADDR_R */ + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +/* #undef HAVE_GETHOSTBYADDR_R_8 */ + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +/* #undef HAVE_GETIFADDRS */ + +/* Define to 1 if you have the getnameinfo function. */ +/* #undef HAVE_GETNAMEINFO */ + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +/* #undef HAVE_GETPPID */ + +/* Define to 1 if you have the `getprotobyname' function. */ +/* #undef HAVE_GETPROTOBYNAME */ + +/* Define to 1 if you have the `getpwuid' function. */ +/* #undef HAVE_GETPWUID */ + +/* Define to 1 if you have the `getrlimit' function. */ +/* #undef HAVE_GETRLIMIT */ + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +/* #undef HAVE_GMTIME_R */ + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the <gssapi/gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the <idn-free.h> header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +/* #undef HAVE_IFADDRS_H */ + +/* Define to 1 if you have the `inet_addr' function. */ +/* #undef HAVE_INET_ADDR */ + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/* #undef HAVE_INET_NTOP */ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/* #undef HAVE_INET_PTON */ + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +/* #undef HAVE_IOCTL */ + +/* Define to 1 if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +/* #undef HAVE_IOCTL_FIONBIO */ + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +/* #undef HAVE_IOCTL_SIOCGIFADDR */ + +/* Define to 1 if you have the <io.h> header file. */ +#define HAVE_IO_H 1 + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the <krb.h> header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the <libgen.h> header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the <librtmp/rtmp.h> header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the `libssh2_exit' function. */ +/* #undef HAVE_LIBSSH2_EXIT */ + +/* Define to 1 if you have the <libssh2.h> header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `libssh2_init' function. */ +/* #undef HAVE_LIBSSH2_INIT */ + +/* Define to 1 if you have the `libssh2_scp_send64' function. */ +/* #undef HAVE_LIBSSH2_SCP_SEND64 */ + +/* Define to 1 if you have the `libssh2_session_handshake' function. */ +/* #undef HAVE_LIBSSH2_SESSION_HANDSHAKE */ + +/* Define to 1 if you have the `libssh2_version' function. */ +/* #undef HAVE_LIBSSH2_VERSION */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the <locale.h> header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +/* #undef HAVE_LOCALTIME_R */ + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +/* #undef HAVE_MEMRCHR */ + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/* #undef HAVE_MSG_NOSIGNAL */ + +/* Define to 1 if you have the <netdb.h> header file. */ +/* #undef HAVE_NETDB_H */ + +/* Define to 1 if you have the <netinet/in.h> header file. */ +/* #undef HAVE_NETINET_IN_H */ + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the <net/if.h> header file. */ +/* #undef HAVE_NET_IF_H */ + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have the NSS_InitContext function */ +/* #undef HAVE_NSS_INITCONTEXT */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the <openssl/crypto.h> header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the <openssl/engine.h> header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the <openssl/err.h> header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the <openssl/pem.h> header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the <openssl/pkcs12.h> header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the <openssl/rsa.h> header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the <openssl/ssl.h> header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the <openssl/x509.h> header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the <pem.h> header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +/* #undef HAVE_PIPE */ + +/* Define to 1 if you have a working poll function. */ +/* #undef HAVE_POLL */ + +/* If you have a fine poll */ +/* #undef HAVE_POLL_FINE */ + +/* Define to 1 if you have the <poll.h> header file. */ +/* #undef HAVE_POLL_H */ + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +/* #undef HAVE_POSIX_STRERROR_R */ + +/* if you have <pthread.h> */ +/* #undef HAVE_PTHREAD_H */ + +/* Define to 1 if you have the <pwd.h> header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the <rsa.h> header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the <setjmp.h> header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +/* #undef HAVE_SETRLIMIT */ + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the <sgtty.h> header file. */ +/* #undef HAVE_SGTTY_H */ + +/* Define to 1 if you have the sigaction function. */ +/* #undef HAVE_SIGACTION */ + +/* Define to 1 if you have the siginterrupt function. */ +/* #undef HAVE_SIGINTERRUPT */ + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the <signal.h> header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +/* #undef HAVE_SOCKETPAIR */ + +/* Define to 1 if you have the <socket.h> header file. */ +/* #undef HAVE_SOCKET_H */ + +/* Define this if you have the SPNEGO library fbopenssl */ +/* #undef HAVE_SPNEGO */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the <ssl.h> header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the <stdbool.h> header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdio.h> header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcasestr function. */ +/* #undef HAVE_STRCASESTR */ + +/* Define to 1 if you have the strcmpi function. */ +#define HAVE_STRCMPI 1 + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +/* #undef HAVE_STRERROR_R */ + +/* Define to 1 if you have the stricmp function. */ +#define HAVE_STRICMP 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> 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 strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the <stropts.h> header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +/* #undef HAVE_STRTOK_R */ + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the <sys/filio.h> header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +/* #undef HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/poll.h> header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the <sys/resource.h> header file. */ +/* #undef HAVE_SYS_RESOURCE_H */ + +/* Define to 1 if you have the <sys/select.h> header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the <sys/socket.h> header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the <sys/sockio.h> header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/uio.h> header file. */ +/* #undef HAVE_SYS_UIO_H */ + +/* Define to 1 if you have the <sys/un.h> header file. */ +/* #undef HAVE_SYS_UN_H */ + +/* Define to 1 if you have the <sys/utime.h> header file. */ +#define HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the <sys/wait.h> header file. */ +/* #undef HAVE_SYS_WAIT_H */ + +/* Define to 1 if you have the <sys/xattr.h> header file. */ +/* #undef HAVE_SYS_XATTR_H */ + +/* Define to 1 if you have the <termios.h> header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* Define to 1 if you have the <termio.h> header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define to 1 if you have the <time.h> header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the <tld.h> header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +/* #undef HAVE_UNAME */ + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the <utime.h> header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +#define HAVE_WINBER_H 1 + +/* Define to 1 if you have the windows.h header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define to 1 if you have the winldap.h header file. */ +#define HAVE_WINLDAP_H 1 + +/* Define to 1 if you have the winsock2.h header file. */ +#define HAVE_WINSOCK2_H 1 + +/* Define to 1 if you have the winsock.h header file. */ +#define HAVE_WINSOCK_H 1 + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +/* #undef HAVE_WRITEV */ + +/* Define to 1 if you have the ws2tcpip.h header file. */ +#define HAVE_WS2TCPIP_H 1 + +/* Define to 1 if you have the <x509.h> header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "i586-pc-mingw32msvc" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type qualifier pointed by arg 5 for recvfrom. */ +#define RECVFROM_QUAL_ARG5 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG2_IS_VOID */ + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG5_IS_VOID */ + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG6_IS_VOID */ + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 const + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* 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 `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +/* #undef STRERROR_R_TYPE_ARG3 */ + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* Define to disable non-blocking sockets. */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +/* #undef USE_THREADS_POSIX */ + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +#define USE_WIN32_LARGE_FILES 1 + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to avoid automatic inclusion of winsock.h */ +#define WIN32_LEAN_AND_MEAN 1 + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +#define in_addr_t unsigned long + +/* 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 `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/libcurl/i586-mingw32msvc/curlbuild.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,191 @@ +/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */ +#ifndef __CURL_CURLBUILD_H +#define __CURL_CURLBUILD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * If you think that something actually needs to be changed, adjusted + * or fixed in this file, then, report it on the libcurl development + * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * This header file shall only export symbols which are 'curl' or 'CURL' + * prefixed, otherwise public name space would be polluted. + * + * NOTE 2: + * ------- + * + * Right now you might be staring at file include/curl/curlbuild.h.in or + * at file include/curl/curlbuild.h, this is due to the following reason: + * + * On systems capable of running the configure script, the configure process + * will overwrite the distributed include/curl/curlbuild.h file with one that + * is suitable and specific to the library being configured and built, which + * is generated from the include/curl/curlbuild.h.in template file. + * + */ + +/* ================================================================ */ +/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ +/* ================================================================ */ + +#ifdef CURL_SIZEOF_LONG +#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T +#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_SOCKLEN_T +#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_OFF_T +#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_T +#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_TU +#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined +#endif + +#ifdef CURL_FORMAT_OFF_T +#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_OFF_T +#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_T +#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_TU +#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined +#endif + +/* ================================================================ */ +/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ +/* ================================================================ */ + +/* Configure process defines this to 1 when it finds out that system */ +/* header file ws2tcpip.h must be included by the external interface. */ +#define CURL_PULL_WS2TCPIP_H 1 +#ifdef CURL_PULL_WS2TCPIP_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# include <windows.h> +# include <winsock2.h> +# include <ws2tcpip.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/types.h must be included by the external interface. */ +#define CURL_PULL_SYS_TYPES_H 1 +#ifdef CURL_PULL_SYS_TYPES_H +# include <sys/types.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file stdint.h must be included by the external interface. */ +#define CURL_PULL_STDINT_H 1 +#ifdef CURL_PULL_STDINT_H +# include <stdint.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file inttypes.h must be included by the external interface. */ +#define CURL_PULL_INTTYPES_H 1 +#ifdef CURL_PULL_INTTYPES_H +# include <inttypes.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/socket.h must be included by the external interface. */ +/* #undef CURL_PULL_SYS_SOCKET_H */ +#ifdef CURL_PULL_SYS_SOCKET_H +# include <sys/socket.h> +#endif + +/* The size of `long', as computed by sizeof. */ +#define CURL_SIZEOF_LONG 4 + +/* Integral data type used for curl_socklen_t. */ +#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t + +/* The size of `curl_socklen_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +/* Data type definition of curl_socklen_t. */ +typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; + +/* Signed integral data type used for curl_off_t. */ +#define CURL_TYPEOF_CURL_OFF_T int64_t + +/* Data type definition of curl_off_t. */ +typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; + +/* curl_off_t formatting string directive without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_T "I64d" + +/* unsigned curl_off_t formatting string without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_TU "I64u" + +/* curl_off_t formatting string directive with "%" conversion specifier. */ +#define CURL_FORMAT_OFF_T "%I64d" + +/* The size of `curl_off_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_OFF_T 8 + +/* curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_T LL + +/* unsigned curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_TU ULL + +#endif /* __CURL_CURLBUILD_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/libcurl/i686-pc-linux-gnu/curl_config.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,1056 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +#define CURL_CA_BUNDLE "/etc/ssl/certs/ca-certificates.crt" + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +#define CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#define CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable Gopher */ +#define CURL_DISABLE_GOPHER 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +#define CURL_DISABLE_IMAP 1 + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +/* #undef CURL_DISABLE_LIBCURL_OPTION */ + +/* to disable POP3 */ +#define CURL_DISABLE_POP3 1 + +/* to disable proxies */ +#define CURL_DISABLE_PROXY 1 + +/* to disable RTSP */ +#define CURL_DISABLE_RTSP 1 + +/* to disable SMTP */ +#define CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable TLS-SRP authentication */ +/* #undef CURL_DISABLE_TLS_SRP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 unsigned int + +/* Specifies the number of arguments to getservbyport_r */ +#define GETSERVBYPORT_R_ARGS 6 + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#define GETSERVBYPORT_R_BUFSIZE 4096 + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the <alloca.h> header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the <arpa/tftp.h> header file. */ +#define HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the <assert.h> header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#define HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the <crypto.h> header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the <des.h> header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the <err.h> header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the fsetxattr function. */ +#define HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +#define HAVE_FSETXATTR_5 1 + +/* fsetxattr() takes 6 args */ +/* #undef HAVE_FSETXATTR_6 */ + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#define HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +#define HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +#define HAVE_GETHOSTBYNAME_R_6 1 + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#define HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +#define HAVE_GETSERVBYPORT_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the <gssapi/gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the <idn-free.h> header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the <io.h> header file. */ +/* #undef HAVE_IO_H */ + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the <krb.h> header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the <libgen.h> header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the <librtmp/rtmp.h> header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the `libssh2_exit' function. */ +/* #undef HAVE_LIBSSH2_EXIT */ + +/* Define to 1 if you have the <libssh2.h> header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `libssh2_init' function. */ +/* #undef HAVE_LIBSSH2_INIT */ + +/* Define to 1 if you have the `libssh2_scp_send64' function. */ +/* #undef HAVE_LIBSSH2_SCP_SEND64 */ + +/* Define to 1 if you have the `libssh2_session_handshake' function. */ +/* #undef HAVE_LIBSSH2_SESSION_HANDSHAKE */ + +/* Define to 1 if you have the `libssh2_version' function. */ +/* #undef HAVE_LIBSSH2_VERSION */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the <locale.h> header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +/* #undef HAVE_MEMRCHR */ + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#define HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the <netdb.h> header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the <net/if.h> header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have the NSS_InitContext function */ +/* #undef HAVE_NSS_INITCONTEXT */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the <openssl/crypto.h> header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the <openssl/engine.h> header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the <openssl/err.h> header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the <openssl/pem.h> header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the <openssl/pkcs12.h> header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the <openssl/rsa.h> header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the <openssl/ssl.h> header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the <openssl/x509.h> header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the <pem.h> header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#define HAVE_POLL 1 + +/* If you have a fine poll */ +#define HAVE_POLL_FINE 1 + +/* Define to 1 if you have the <poll.h> header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#define HAVE_POSIX_STRERROR_R 1 + +/* if you have <pthread.h> */ +/* #undef HAVE_PTHREAD_H */ + +/* Define to 1 if you have the <pwd.h> header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the <rsa.h> header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the <setjmp.h> header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +/* #undef HAVE_SETMODE */ + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the <sgtty.h> header file. */ +#define HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the <signal.h> header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the <socket.h> header file. */ +/* #undef HAVE_SOCKET_H */ + +/* Define this if you have the SPNEGO library fbopenssl */ +/* #undef HAVE_SPNEGO */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the <ssl.h> header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the <stdbool.h> header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdio.h> header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcasestr function. */ +/* #undef HAVE_STRCASESTR */ + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> 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 strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the <stropts.h> header file. */ +#define HAVE_STROPTS_H 1 + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the <sys/filio.h> header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/poll.h> header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the <sys/resource.h> header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the <sys/select.h> header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the <sys/sockio.h> header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/uio.h> header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the <sys/un.h> header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the <sys/utime.h> header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the <sys/wait.h> header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the <sys/xattr.h> header file. */ +#define HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the <termios.h> header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the <termio.h> header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the <time.h> header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the <tld.h> header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the <utime.h> header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the <x509.h> header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "i686-pc-linux-gnu" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type qualifier pointed by arg 5 for recvfrom. */ +#define RECVFROM_QUAL_ARG5 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG5_IS_VOID */ + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 socklen_t + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG6_IS_VOID */ + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* 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 `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#define STRERROR_R_TYPE_ARG3 size_t + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* Define to disable non-blocking sockets. */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +/* #undef USE_THREADS_POSIX */ + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* 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 `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/libcurl/i686-pc-linux-gnu/curlbuild.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,191 @@ +/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */ +#ifndef __CURL_CURLBUILD_H +#define __CURL_CURLBUILD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * If you think that something actually needs to be changed, adjusted + * or fixed in this file, then, report it on the libcurl development + * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * This header file shall only export symbols which are 'curl' or 'CURL' + * prefixed, otherwise public name space would be polluted. + * + * NOTE 2: + * ------- + * + * Right now you might be staring at file include/curl/curlbuild.h.in or + * at file include/curl/curlbuild.h, this is due to the following reason: + * + * On systems capable of running the configure script, the configure process + * will overwrite the distributed include/curl/curlbuild.h file with one that + * is suitable and specific to the library being configured and built, which + * is generated from the include/curl/curlbuild.h.in template file. + * + */ + +/* ================================================================ */ +/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ +/* ================================================================ */ + +#ifdef CURL_SIZEOF_LONG +#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T +#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_SOCKLEN_T +#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_OFF_T +#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_T +#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_TU +#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined +#endif + +#ifdef CURL_FORMAT_OFF_T +#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_OFF_T +#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_T +#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_TU +#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined +#endif + +/* ================================================================ */ +/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ +/* ================================================================ */ + +/* Configure process defines this to 1 when it finds out that system */ +/* header file ws2tcpip.h must be included by the external interface. */ +/* #undef CURL_PULL_WS2TCPIP_H */ +#ifdef CURL_PULL_WS2TCPIP_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include <windows.h> +# include <winsock2.h> +# include <ws2tcpip.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/types.h must be included by the external interface. */ +#define CURL_PULL_SYS_TYPES_H 1 +#ifdef CURL_PULL_SYS_TYPES_H +# include <sys/types.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file stdint.h must be included by the external interface. */ +#define CURL_PULL_STDINT_H 1 +#ifdef CURL_PULL_STDINT_H +# include <stdint.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file inttypes.h must be included by the external interface. */ +#define CURL_PULL_INTTYPES_H 1 +#ifdef CURL_PULL_INTTYPES_H +# include <inttypes.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/socket.h must be included by the external interface. */ +#define CURL_PULL_SYS_SOCKET_H 1 +#ifdef CURL_PULL_SYS_SOCKET_H +# include <sys/socket.h> +#endif + +/* The size of `long', as computed by sizeof. */ +#define CURL_SIZEOF_LONG 4 + +/* Integral data type used for curl_socklen_t. */ +#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t + +/* The size of `curl_socklen_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +/* Data type definition of curl_socklen_t. */ +typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; + +/* Signed integral data type used for curl_off_t. */ +#define CURL_TYPEOF_CURL_OFF_T int64_t + +/* Data type definition of curl_off_t. */ +typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; + +/* curl_off_t formatting string directive without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_T "lld" + +/* unsigned curl_off_t formatting string without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_TU "llu" + +/* curl_off_t formatting string directive with "%" conversion specifier. */ +#define CURL_FORMAT_OFF_T "%lld" + +/* The size of `curl_off_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_OFF_T 8 + +/* curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_T LL + +/* unsigned curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_TU ULL + +#endif /* __CURL_CURLBUILD_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/libcurl/x86_64-linux/curl_config.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,1056 @@ +/* lib/curl_config.h. Generated from curl_config.h.in by configure. */ +/* lib/curl_config.h.in. Generated from configure.ac by autoheader. */ + +/* Location of default ca bundle */ +#define CURL_CA_BUNDLE "/etc/ssl/certs/ca-certificates.crt" + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +#define CURL_DISABLE_DICT 1 + +/* to disable FILE */ +#define CURL_DISABLE_FILE 1 + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable Gopher */ +#define CURL_DISABLE_GOPHER 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable IMAP */ +#define CURL_DISABLE_IMAP 1 + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable --libcurl C code generation option */ +/* #undef CURL_DISABLE_LIBCURL_OPTION */ + +/* to disable POP3 */ +#define CURL_DISABLE_POP3 1 + +/* to disable proxies */ +#define CURL_DISABLE_PROXY 1 + +/* to disable RTSP */ +#define CURL_DISABLE_RTSP 1 + +/* to disable SMTP */ +#define CURL_DISABLE_SMTP 1 + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable TLS-SRP authentication */ +/* #undef CURL_DISABLE_TLS_SRP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL __attribute__ ((__visibility__ ("default"))) + +/* Use Windows LDAP implementation */ +/* #undef CURL_LDAP_WIN */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 socklen_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 unsigned int + +/* Specifies the number of arguments to getservbyport_r */ +#define GETSERVBYPORT_R_ARGS 6 + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#define GETSERVBYPORT_R_BUFSIZE 4096 + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the <alloca.h> header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the <arpa/tftp.h> header file. */ +#define HAVE_ARPA_TFTP_H 1 + +/* Define to 1 if you have the <assert.h> header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the basename function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#define HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ + +/* Define to 1 if you have the <crypto.h> header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the <des.h> header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* #undef HAVE_ENGINE_CLEANUP */ + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ + +/* Define to 1 if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the <err.h> header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the fdopen function. */ +#define HAVE_FDOPEN 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the fsetxattr function. */ +#define HAVE_FSETXATTR 1 + +/* fsetxattr() takes 5 args */ +#define HAVE_FSETXATTR_5 1 + +/* fsetxattr() takes 6 args */ +/* #undef HAVE_FSETXATTR_6 */ + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the gai_strerror function. */ +#define HAVE_GAI_STRERROR 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#define HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +#define HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +#define HAVE_GETHOSTBYNAME_R_6 1 + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +#define HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +#define HAVE_GETSERVBYPORT_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the function gnutls_srp_verifier */ +/* #undef HAVE_GNUTLS_SRP */ + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the <gssapi/gssapi_generic.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the <gssapi/gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the <idn-free.h> header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the <io.h> header file. */ +/* #undef HAVE_IO_H */ + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the <krb.h> header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `ldap_init_fd' function. */ +/* #undef HAVE_LDAP_INIT_FD */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the <libgen.h> header file. */ +#define HAVE_LIBGEN_H 1 + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the <librtmp/rtmp.h> header file. */ +/* #undef HAVE_LIBRTMP_RTMP_H */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the `libssh2_exit' function. */ +/* #undef HAVE_LIBSSH2_EXIT */ + +/* Define to 1 if you have the <libssh2.h> header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `libssh2_init' function. */ +/* #undef HAVE_LIBSSH2_INIT */ + +/* Define to 1 if you have the `libssh2_scp_send64' function. */ +/* #undef HAVE_LIBSSH2_SCP_SEND64 */ + +/* Define to 1 if you have the `libssh2_session_handshake' function. */ +/* #undef HAVE_LIBSSH2_SESSION_HANDSHAKE */ + +/* Define to 1 if you have the `libssh2_version' function. */ +/* #undef HAVE_LIBSSH2_VERSION */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the <locale.h> header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the memrchr function or macro. */ +/* #undef HAVE_MEMRCHR */ + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#define HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the <netdb.h> header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the <net/if.h> header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have the NSS_InitContext function */ +/* #undef HAVE_NSS_INITCONTEXT */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the <openssl/crypto.h> header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ + +/* Define to 1 if you have the <openssl/engine.h> header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ + +/* Define to 1 if you have the <openssl/err.h> header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ + +/* Define to 1 if you have the <openssl/pem.h> header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ + +/* Define to 1 if you have the <openssl/pkcs12.h> header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ + +/* Define to 1 if you have the <openssl/rsa.h> header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ + +/* Define to 1 if you have the <openssl/ssl.h> header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ + +/* Define to 1 if you have the <openssl/x509.h> header file. */ +/* #undef HAVE_OPENSSL_X509_H */ + +/* Define to 1 if you have the <pem.h> header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +#define HAVE_POLL 1 + +/* If you have a fine poll */ +#define HAVE_POLL_FINE 1 + +/* Define to 1 if you have the <poll.h> header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +#define HAVE_POSIX_STRERROR_R 1 + +/* if you have <pthread.h> */ +/* #undef HAVE_PTHREAD_H */ + +/* Define to 1 if you have the <pwd.h> header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the <rsa.h> header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the <setjmp.h> header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +/* #undef HAVE_SETMODE */ + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the <sgtty.h> header file. */ +#define HAVE_SGTTY_H 1 + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the <signal.h> header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the socketpair function. */ +#define HAVE_SOCKETPAIR 1 + +/* Define to 1 if you have the <socket.h> header file. */ +/* #undef HAVE_SOCKET_H */ + +/* Define this if you have the SPNEGO library fbopenssl */ +/* #undef HAVE_SPNEGO */ + +/* if you have the function SRP_Calc_client_key */ +/* #undef HAVE_SSLEAY_SRP */ + +/* Define to 1 if you have the `SSLv2_client_method' function. */ +/* #undef HAVE_SSLV2_CLIENT_METHOD */ + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/* #undef HAVE_SSL_GET_SHUTDOWN */ + +/* Define to 1 if you have the <ssl.h> header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the <stdbool.h> header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdio.h> header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcasestr function. */ +/* #undef HAVE_STRCASESTR */ + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> 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 strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the <stropts.h> header file. */ +#define HAVE_STROPTS_H 1 + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the <sys/filio.h> header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/poll.h> header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the <sys/resource.h> header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the <sys/select.h> header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the <sys/sockio.h> header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/uio.h> header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the <sys/un.h> header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the <sys/utime.h> header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the <sys/wait.h> header file. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the <sys/xattr.h> header file. */ +#define HAVE_SYS_XATTR_H 1 + +/* Define to 1 if you have the <termios.h> header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the <termio.h> header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the <time.h> header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the <tld.h> header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the <utime.h> header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the <x509.h> header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to enable NTLM delegation to winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_ENABLED */ + +/* Define absolute filename for winbind's ntlm_auth helper. */ +/* #undef NTLM_WB_FILE */ + +/* cpu-machine-OS */ +#define OS "x86_64-unknown-linux-gnu" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "a suitable curl mailing list: http://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define to the type qualifier pointed by arg 5 for recvfrom. */ +#define RECVFROM_QUAL_ARG5 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG5_IS_VOID */ + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 socklen_t + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG6_IS_VOID */ + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV ssize_t + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV ssize_t + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV ssize_t + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* 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 `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* The size of `void*', as computed by sizeof. */ +#define SIZEOF_VOIDP 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +#define STRERROR_R_TYPE_ARG3 size_t + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to enable c-ares support */ +/* #undef USE_ARES */ + +/* if axTLS is enabled */ +/* #undef USE_AXTLS */ + +/* Define to disable non-blocking sockets. */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if CyaSSL is enabled */ +/* #undef USE_CYASSL */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if GnuTLS uses nettle as crypto backend */ +/* #undef USE_GNUTLS_NETTLE */ + +/* if librtmp is in use */ +/* #undef USE_LIBRTMP */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* Use OpenLDAP-specific code */ +/* #undef USE_OPENLDAP */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if PolarSSL is enabled */ +/* #undef USE_POLARSSL */ + +/* if SSL is enabled */ +/* #undef USE_SSLEAY */ + +/* if you want POSIX threaded DNS lookup */ +/* #undef USE_THREADS_POSIX */ + +/* Use TLS-SRP authentication */ +/* #undef USE_TLS_SRP */ + +/* Define to 1 if you are building a Windows target with large file support. + */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_SMALL_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +#define VERSION "-" + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* 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 `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/libcurl/x86_64-linux/curlbuild.h Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,191 @@ +/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */ +#ifndef __CURL_CURLBUILD_H +#define __CURL_CURLBUILD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * Nothing in this file is intended to be modified or adjusted by the + * curl library user nor by the curl library builder. + * + * If you think that something actually needs to be changed, adjusted + * or fixed in this file, then, report it on the libcurl development + * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ + * + * This header file shall only export symbols which are 'curl' or 'CURL' + * prefixed, otherwise public name space would be polluted. + * + * NOTE 2: + * ------- + * + * Right now you might be staring at file include/curl/curlbuild.h.in or + * at file include/curl/curlbuild.h, this is due to the following reason: + * + * On systems capable of running the configure script, the configure process + * will overwrite the distributed include/curl/curlbuild.h file with one that + * is suitable and specific to the library being configured and built, which + * is generated from the include/curl/curlbuild.h.in template file. + * + */ + +/* ================================================================ */ +/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ +/* ================================================================ */ + +#ifdef CURL_SIZEOF_LONG +#error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_SOCKLEN_T +#error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_SOCKLEN_T +#error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined +#endif + +#ifdef CURL_TYPEOF_CURL_OFF_T +#error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_T +#error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_FORMAT_CURL_OFF_TU +#error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined +#endif + +#ifdef CURL_FORMAT_OFF_T +#error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined +#endif + +#ifdef CURL_SIZEOF_CURL_OFF_T +#error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_T +#error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined +#endif + +#ifdef CURL_SUFFIX_CURL_OFF_TU +#error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" + Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined +#endif + +/* ================================================================ */ +/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ +/* ================================================================ */ + +/* Configure process defines this to 1 when it finds out that system */ +/* header file ws2tcpip.h must be included by the external interface. */ +/* #undef CURL_PULL_WS2TCPIP_H */ +#ifdef CURL_PULL_WS2TCPIP_H +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include <windows.h> +# include <winsock2.h> +# include <ws2tcpip.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/types.h must be included by the external interface. */ +#define CURL_PULL_SYS_TYPES_H 1 +#ifdef CURL_PULL_SYS_TYPES_H +# include <sys/types.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file stdint.h must be included by the external interface. */ +/* #undef CURL_PULL_STDINT_H */ +#ifdef CURL_PULL_STDINT_H +# include <stdint.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file inttypes.h must be included by the external interface. */ +/* #undef CURL_PULL_INTTYPES_H */ +#ifdef CURL_PULL_INTTYPES_H +# include <inttypes.h> +#endif + +/* Configure process defines this to 1 when it finds out that system */ +/* header file sys/socket.h must be included by the external interface. */ +#define CURL_PULL_SYS_SOCKET_H 1 +#ifdef CURL_PULL_SYS_SOCKET_H +# include <sys/socket.h> +#endif + +/* The size of `long', as computed by sizeof. */ +#define CURL_SIZEOF_LONG 8 + +/* Integral data type used for curl_socklen_t. */ +#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t + +/* The size of `curl_socklen_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_SOCKLEN_T 4 + +/* Data type definition of curl_socklen_t. */ +typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; + +/* Signed integral data type used for curl_off_t. */ +#define CURL_TYPEOF_CURL_OFF_T long + +/* Data type definition of curl_off_t. */ +typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; + +/* curl_off_t formatting string directive without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_T "ld" + +/* unsigned curl_off_t formatting string without "%" conversion specifier. */ +#define CURL_FORMAT_CURL_OFF_TU "lu" + +/* curl_off_t formatting string directive with "%" conversion specifier. */ +#define CURL_FORMAT_OFF_T "%ld" + +/* The size of `curl_off_t', as computed by sizeof. */ +#define CURL_SIZEOF_CURL_OFF_T 8 + +/* curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_T L + +/* unsigned curl_off_t constant suffix. */ +#define CURL_SUFFIX_CURL_OFF_TU UL + +#endif /* __CURL_CURLBUILD_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/mongoose-patch.diff Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,28 @@ +--- mongoose/mongoose.c 2012-03-11 23:41:35.000000000 +0100 ++++ mongoose.c 2012-06-22 13:44:40.093202063 +0200 +@@ -3844,10 +3844,8 @@ + } + + static void discard_current_request_from_buffer(struct mg_connection *conn) { +- char *buffered; + int buffered_len, body_len; + +- buffered = conn->buf + conn->request_len; + buffered_len = conn->data_len - conn->request_len; + assert(buffered_len >= 0); + +@@ -4148,7 +4146,13 @@ + + // Wait until mg_fini() stops + while (ctx->stop_flag != 2) { +- (void) sleep(0); ++#if defined(__linux) ++ usleep(100000); ++#elif defined(_WIN32) ++ Sleep(100); ++#else ++#error Support your platform here ++#endif + } + free_context(ctx); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/THANKS Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,14 @@ +Palantir - A Lightweight, RESTful DICOM Server +============================================== + +Palantir has originally been written by Sebastien Jodogne +(cf. "AUTHORS" file). This file contains the list of the people that +have further contributed to Palantir by reporting problems, suggesting +various improvements, or submitting actual actual. Please help keep it +complete and exempt or errors. + + +Contributors +------------ + +* None at this time :)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTests/SQLite.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,204 @@ +#include "gtest/gtest.h" + +#include "../Core/Toolbox.h" +#include "../Core/SQLite/Connection.h" +#include "../Core/SQLite/Statement.h" + +#include <sqlite3.h> + +using namespace Palantir; + + +TEST(SQLite, Configuration) +{ + ASSERT_EQ(1, sqlite3_threadsafe()); +} + + +TEST(SQLite, Connection) +{ + Toolbox::RemoveFile("coucou"); + SQLite::Connection c; + c.Open("coucou"); + c.Execute("CREATE TABLE c(k INTEGER PRIMARY KEY AUTOINCREMENT, v INTEGER)"); + c.Execute("INSERT INTO c VALUES(NULL, 42);"); +} + + +TEST(SQLite, StatementReferenceBasic) +{ + sqlite3* db; + sqlite3_open(":memory:", &db); + + { + SQLite::StatementReference r(db, "SELECT * FROM sqlite_master"); + ASSERT_EQ(0u, r.GetReferenceCount()); + + { + SQLite::StatementReference r1(r); + ASSERT_EQ(1u, r.GetReferenceCount()); + ASSERT_EQ(0u, r1.GetReferenceCount()); + + { + SQLite::StatementReference r2(r); + ASSERT_EQ(2u, r.GetReferenceCount()); + ASSERT_EQ(0u, r1.GetReferenceCount()); + ASSERT_EQ(0u, r2.GetReferenceCount()); + + SQLite::StatementReference r3(r2); + ASSERT_EQ(3u, r.GetReferenceCount()); + ASSERT_EQ(0u, r1.GetReferenceCount()); + ASSERT_EQ(0u, r2.GetReferenceCount()); + ASSERT_EQ(0u, r3.GetReferenceCount()); + } + + ASSERT_EQ(1u, r.GetReferenceCount()); + ASSERT_EQ(0u, r1.GetReferenceCount()); + + { + SQLite::StatementReference r2(r); + ASSERT_EQ(2u, r.GetReferenceCount()); + ASSERT_EQ(0u, r1.GetReferenceCount()); + ASSERT_EQ(0u, r2.GetReferenceCount()); + } + + ASSERT_EQ(1u, r.GetReferenceCount()); + ASSERT_EQ(0u, r1.GetReferenceCount()); + } + + ASSERT_EQ(0u, r.GetReferenceCount()); + } + + sqlite3_close(db); +} + +TEST(SQLite, StatementBasic) +{ + SQLite::Connection c; + c.OpenInMemory(); + + SQLite::Statement s(c, "SELECT * from sqlite_master"); + s.Run(); + + for (unsigned int i = 0; i < 5; i++) + { + SQLite::Statement cs(c, SQLITE_FROM_HERE, "SELECT * from sqlite_master"); + cs.Step(); + } +} + + +namespace +{ + static bool destroyed; + + class MyFunc : public SQLite::IScalarFunction + { + public: + MyFunc() + { + destroyed = false; + } + + virtual ~MyFunc() + { + destroyed = true; + } + + virtual const char* GetName() const + { + return "MYFUNC"; + } + + virtual unsigned int GetCardinality() const + { + return 2; + } + + virtual void Compute(SQLite::FunctionContext& context) + { + context.SetIntResult(1000 + context.GetIntValue(0) * context.GetIntValue(1)); + } + }; + + class MyDelete : public SQLite::IScalarFunction + { + public: + std::set<int> deleted_; + + virtual const char* GetName() const + { + return "MYDELETE"; + } + + virtual unsigned int GetCardinality() const + { + return 1; + } + + virtual void Compute(SQLite::FunctionContext& context) + { + deleted_.insert(context.GetIntValue(0)); + context.SetNullResult(); + } + }; +} + +TEST(SQLite, ScalarFunction) +{ + { + SQLite::Connection c; + c.OpenInMemory(); + c.Register(new MyFunc()); + c.Execute("CREATE TABLE t(id INTEGER PRIMARY KEY, v1 INTEGER, v2 INTEGER);"); + c.Execute("INSERT INTO t VALUES(NULL, 2, 3);"); + c.Execute("INSERT INTO t VALUES(NULL, 4, 4);"); + c.Execute("INSERT INTO t VALUES(NULL, 6, 5);"); + SQLite::Statement t(c, "SELECT MYFUNC(v1, v2), v1, v2 FROM t"); + int i = 0; + while (t.Step()) + { + ASSERT_EQ(t.ColumnInt(0), 1000 + t.ColumnInt(1) * t.ColumnInt(2)); + i++; + } + ASSERT_EQ(3, i); + ASSERT_FALSE(destroyed); + } + ASSERT_TRUE(destroyed); +} + +TEST(SQLite, CascadedDeleteCallback) +{ + SQLite::Connection c; + c.OpenInMemory(); + MyDelete *func = new MyDelete(); + c.Register(func); + c.Execute("CREATE TABLE parent(id INTEGER PRIMARY KEY, dummy INTEGER);"); + c.Execute("CREATE TABLE child(" + " id INTEGER PRIMARY KEY, " + " parent INTEGER REFERENCES parent(id) ON DELETE CASCADE, " + " value INTEGER);"); + c.Execute("CREATE TRIGGER childRemoved " + "AFTER DELETE ON child " + "FOR EACH ROW BEGIN " + " SELECT MYDELETE(old.value); " + "END;"); + + c.Execute("INSERT INTO parent VALUES(42, 100);"); + c.Execute("INSERT INTO parent VALUES(43, 101);"); + + c.Execute("INSERT INTO child VALUES(NULL, 42, 4200);"); + c.Execute("INSERT INTO child VALUES(NULL, 42, 4201);"); + + c.Execute("INSERT INTO child VALUES(NULL, 43, 4300);"); + c.Execute("INSERT INTO child VALUES(NULL, 43, 4301);"); + + // The following command deletes "parent(43, 101)", then in turns + // "child(NULL, 43, 4300/4301)", then calls the MyDelete on 4300 and + // 4301 + c.Execute("DELETE FROM parent WHERE dummy=101"); + + ASSERT_EQ(2u, func->deleted_.size()); + ASSERT_TRUE(func->deleted_.find(4300) != func->deleted_.end()); + ASSERT_TRUE(func->deleted_.find(4301) != func->deleted_.end()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTests/SQLiteChromium.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,339 @@ +#include "gtest/gtest.h" + +#include "../Core/Toolbox.h" +#include "../Core/SQLite/Connection.h" +#include "../Core/SQLite/Statement.h" +#include "../Core/SQLite/Transaction.h" + +#include <sqlite3.h> + +using namespace Palantir; + + + +/******************************************************************** + ** Tests from + ** http://src.chromium.org/viewvc/chrome/trunk/src/sql/connection_unittest.cc + ********************************************************************/ + +class SQLConnectionTest : public testing::Test +{ +public: + SQLConnectionTest() + { + } + + virtual ~SQLConnectionTest() + { + } + + virtual void SetUp() + { + db_.OpenInMemory(); + } + + virtual void TearDown() + { + db_.Close(); + } + + SQLite::Connection& db() + { + return db_; + } + +private: + SQLite::Connection db_; +}; + + + +TEST_F(SQLConnectionTest, Execute) +{ + // Valid statement should return true. + ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + EXPECT_EQ(SQLITE_OK, db().GetErrorCode()); + + // Invalid statement should fail. + ASSERT_EQ(SQLITE_ERROR, + db().ExecuteAndReturnErrorCode("CREATE TAB foo (a, b")); + EXPECT_EQ(SQLITE_ERROR, db().GetErrorCode()); +} + +TEST_F(SQLConnectionTest, ExecuteWithErrorCode) { + ASSERT_EQ(SQLITE_OK, + db().ExecuteAndReturnErrorCode("CREATE TABLE foo (a, b)")); + ASSERT_EQ(SQLITE_ERROR, + db().ExecuteAndReturnErrorCode("CREATE TABLE TABLE")); + ASSERT_EQ(SQLITE_ERROR, + db().ExecuteAndReturnErrorCode( + "INSERT INTO foo(a, b) VALUES (1, 2, 3, 4)")); +} + +TEST_F(SQLConnectionTest, CachedStatement) { + SQLite::StatementId id1("foo", 12); + ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db().Execute("INSERT INTO foo(a, b) VALUES (12, 13)")); + + // Create a new cached statement. + { + SQLite::Statement s(db(), id1, "SELECT a FROM foo"); + ASSERT_TRUE(s.Step()); + EXPECT_EQ(12, s.ColumnInt(0)); + } + + // The statement should be cached still. + EXPECT_TRUE(db().HasCachedStatement(id1)); + + { + // Get the same statement using different SQL. This should ignore our + // SQL and use the cached one (so it will be valid). + SQLite::Statement s(db(), id1, "something invalid("); + ASSERT_TRUE(s.Step()); + EXPECT_EQ(12, s.ColumnInt(0)); + } + + // Make sure other statements aren't marked as cached. + EXPECT_FALSE(db().HasCachedStatement(SQLITE_FROM_HERE)); +} + +TEST_F(SQLConnectionTest, IsSQLValidTest) { + ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db().IsSQLValid("SELECT a FROM foo")); + ASSERT_FALSE(db().IsSQLValid("SELECT no_exist FROM foo")); +} + + + +TEST_F(SQLConnectionTest, DoesStuffExist) { + // Test DoesTableExist. + EXPECT_FALSE(db().DoesTableExist("foo")); + ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + EXPECT_TRUE(db().DoesTableExist("foo")); + + // Should be case sensitive. + EXPECT_FALSE(db().DoesTableExist("FOO")); + + // Test DoesColumnExist. + EXPECT_FALSE(db().DoesColumnExist("foo", "bar")); + EXPECT_TRUE(db().DoesColumnExist("foo", "a")); + + // Testing for a column on a nonexistent table. + EXPECT_FALSE(db().DoesColumnExist("bar", "b")); +} + +TEST_F(SQLConnectionTest, GetLastInsertRowId) { + ASSERT_TRUE(db().Execute("CREATE TABLE foo (id INTEGER PRIMARY KEY, value)")); + + ASSERT_TRUE(db().Execute("INSERT INTO foo (value) VALUES (12)")); + + // Last insert row ID should be valid. + int64_t row = db().GetLastInsertRowId(); + EXPECT_LT(0, row); + + // It should be the primary key of the row we just inserted. + SQLite::Statement s(db(), "SELECT value FROM foo WHERE id=?"); + s.BindInt64(0, row); + ASSERT_TRUE(s.Step()); + EXPECT_EQ(12, s.ColumnInt(0)); +} + +TEST_F(SQLConnectionTest, Rollback) { + ASSERT_TRUE(db().BeginTransaction()); + ASSERT_TRUE(db().BeginTransaction()); + EXPECT_EQ(2, db().GetTransactionNesting()); + db().RollbackTransaction(); + EXPECT_FALSE(db().CommitTransaction()); + EXPECT_TRUE(db().BeginTransaction()); +} + + + + +/******************************************************************** + ** Tests from + ** http://src.chromium.org/viewvc/chrome/trunk/src/sql/statement_unittest.cc + ********************************************************************/ + +class SQLStatementTest : public SQLConnectionTest +{ +}; + + +TEST_F(SQLStatementTest, Run) { + ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)")); + + SQLite::Statement s(db(), "SELECT b FROM foo WHERE a=?"); + // Stepping it won't work since we haven't bound the value. + EXPECT_FALSE(s.Step()); + + // Run should fail since this produces output, and we should use Step(). This + // gets a bit wonky since sqlite says this is OK so succeeded is set. + s.Reset(true); + s.BindInt(0, 3); + EXPECT_FALSE(s.Run()); + EXPECT_EQ(SQLITE_ROW, db().GetErrorCode()); + + // Resetting it should put it back to the previous state (not runnable). + s.Reset(true); + + // Binding and stepping should produce one row. + s.BindInt(0, 3); + EXPECT_TRUE(s.Step()); + EXPECT_EQ(12, s.ColumnInt(0)); + EXPECT_FALSE(s.Step()); +} + +TEST_F(SQLStatementTest, BasicErrorCallback) { + ASSERT_TRUE(db().Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)")); + // Insert in the foo table the primary key. It is an error to insert + // something other than an number. This error causes the error callback + // handler to be called with SQLITE_MISMATCH as error code. + SQLite::Statement s(db(), "INSERT INTO foo (a) VALUES (?)"); + s.BindCString(0, "bad bad"); + EXPECT_THROW(s.Run(), PalantirException); +} + +TEST_F(SQLStatementTest, Reset) { + ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)")); + ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (4, 13)")); + + SQLite::Statement s(db(), "SELECT b FROM foo WHERE a = ? "); + s.BindInt(0, 3); + ASSERT_TRUE(s.Step()); + EXPECT_EQ(12, s.ColumnInt(0)); + ASSERT_FALSE(s.Step()); + + s.Reset(false); + // Verify that we can get all rows again. + ASSERT_TRUE(s.Step()); + EXPECT_EQ(12, s.ColumnInt(0)); + EXPECT_FALSE(s.Step()); + + s.Reset(true); + ASSERT_FALSE(s.Step()); +} + + + + + + + +/******************************************************************** + ** Tests from + ** http://src.chromium.org/viewvc/chrome/trunk/src/sql/transaction_unittest.cc + ********************************************************************/ + +class SQLTransactionTest : public SQLConnectionTest +{ +public: + virtual void SetUp() + { + SQLConnectionTest::SetUp(); + ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); + } + + // Returns the number of rows in table "foo". + int CountFoo() + { + SQLite::Statement count(db(), "SELECT count(*) FROM foo"); + count.Step(); + return count.ColumnInt(0); + } +}; + + +TEST_F(SQLTransactionTest, Commit) { + { + SQLite::Transaction t(db()); + EXPECT_FALSE(t.IsOpen()); + t.Begin(); + EXPECT_TRUE(t.IsOpen()); + + EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + + t.Commit(); + EXPECT_FALSE(t.IsOpen()); + } + + EXPECT_EQ(1, CountFoo()); +} + +TEST_F(SQLTransactionTest, Rollback) { + // Test some basic initialization, and that rollback runs when you exit the + // scope. + { + SQLite::Transaction t(db()); + EXPECT_FALSE(t.IsOpen()); + t.Begin(); + EXPECT_TRUE(t.IsOpen()); + + EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + } + + // Nothing should have been committed since it was implicitly rolled back. + EXPECT_EQ(0, CountFoo()); + + // Test explicit rollback. + SQLite::Transaction t2(db()); + EXPECT_FALSE(t2.IsOpen()); + t2.Begin(); + + EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + t2.Rollback(); + EXPECT_FALSE(t2.IsOpen()); + + // Nothing should have been committed since it was explicitly rolled back. + EXPECT_EQ(0, CountFoo()); +} + +// Rolling back any part of a transaction should roll back all of them. +TEST_F(SQLTransactionTest, NestedRollback) { + EXPECT_EQ(0, db().GetTransactionNesting()); + + // Outermost transaction. + { + SQLite::Transaction outer(db()); + outer.Begin(); + EXPECT_EQ(1, db().GetTransactionNesting()); + + // The first inner one gets committed. + { + SQLite::Transaction inner1(db()); + inner1.Begin(); + EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + EXPECT_EQ(2, db().GetTransactionNesting()); + + inner1.Commit(); + EXPECT_EQ(1, db().GetTransactionNesting()); + } + + // One row should have gotten inserted. + EXPECT_EQ(1, CountFoo()); + + // The second inner one gets rolled back. + { + SQLite::Transaction inner2(db()); + inner2.Begin(); + EXPECT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (1, 2)")); + EXPECT_EQ(2, db().GetTransactionNesting()); + + inner2.Rollback(); + EXPECT_EQ(1, db().GetTransactionNesting()); + } + + // A third inner one will fail in Begin since one has already been rolled + // back. + EXPECT_EQ(1, db().GetTransactionNesting()); + { + SQLite::Transaction inner3(db()); + EXPECT_THROW(inner3.Begin(), PalantirException); + EXPECT_EQ(1, db().GetTransactionNesting()); + } + } + EXPECT_EQ(0, db().GetTransactionNesting()); + EXPECT_EQ(0, CountFoo()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTests/Versions.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,52 @@ +#include "gtest/gtest.h" + +#include <stdint.h> +#include <math.h> +#include <png.h> +#include <ctype.h> +#include <zlib.h> +#include <curl/curl.h> +#include <boost/version.hpp> + + +TEST(Versions, Zlib) +{ + ASSERT_STREQ(zlibVersion(), ZLIB_VERSION); +} + +TEST(Versions, Curl) +{ + curl_version_info_data* v = curl_version_info(CURLVERSION_NOW); + ASSERT_STREQ(LIBCURL_VERSION, v->version); +} + +TEST(Versions, Png) +{ + ASSERT_EQ(PNG_LIBPNG_VER_MAJOR * 10000 + PNG_LIBPNG_VER_MINOR * 100 + PNG_LIBPNG_VER_RELEASE, + png_access_version_number()); +} + + +#if PALANTIR_STATIC == 1 +TEST(Versions, ZlibStatic) +{ + ASSERT_STREQ("1.2.7", zlibVersion()); +} + +TEST(Versions, BoostStatic) +{ + ASSERT_EQ("1_49", BOOST_LIB_VERSION); +} + +TEST(Versions, CurlStatic) +{ + curl_version_info_data* v = curl_version_info(CURLVERSION_NOW); + ASSERT_STREQ("7.26.0", v->version); +} + +TEST(Versions, PngStatic) +{ + ASSERT_EQ(10512, png_access_version_number()); + ASSERT_STREQ("1.5.12", PNG_LIBPNG_VER_STRING); +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTests/main.cpp Thu Jul 19 14:32:22 2012 +0200 @@ -0,0 +1,265 @@ +#include "gtest/gtest.h" + +#include <ctype.h> + +#include "../Core/Compression/ZlibCompressor.h" +#include "../Core/DicomFormat/DicomTag.h" +#include "../Core/FileStorage.h" +#include "../PalantirCppClient/HttpClient.h" +#include "../Core/HttpServer/HttpHandler.h" +#include "../Core/PalantirException.h" +#include "../Core/Toolbox.h" +#include "../Core/Uuid.h" +#include "../PalantirServer/FromDcmtkBridge.h" +#include "../PalantirServer/PalantirInitialization.h" + +using namespace Palantir; + + +TEST(Uuid, Generation) +{ + for (int i = 0; i < 10; i++) + { + std::string s = Toolbox::GenerateUuid(); + ASSERT_TRUE(Toolbox::IsUuid(s)); + } +} + +TEST(Uuid, Test) +{ + ASSERT_FALSE(Toolbox::IsUuid("")); + ASSERT_FALSE(Toolbox::IsUuid("012345678901234567890123456789012345")); + ASSERT_TRUE(Toolbox::IsUuid("550e8400-e29b-41d4-a716-446655440000")); +} + +TEST(Zlib, Basic) +{ + std::string s = Toolbox::GenerateUuid(); + s = s + s + s + s; + + std::string compressed; + ZlibCompressor c; + c.Compress(compressed, s); + + std::string uncompressed; + c.Uncompress(uncompressed, compressed); + + ASSERT_EQ(s.size(), uncompressed.size()); + ASSERT_EQ(0, memcmp(&s[0], &uncompressed[0], s.size())); +} + +TEST(Zlib, Empty) +{ + std::string s = ""; + + std::string compressed; + ZlibCompressor c; + c.Compress(compressed, s); + + std::string uncompressed; + c.Uncompress(uncompressed, compressed); + + ASSERT_EQ(0u, uncompressed.size()); +} + +TEST(ParseGetQuery, Basic) +{ + HttpHandler::Arguments a; + HttpHandler::ParseGetQuery(a, "aaa=baaa&bb=a&aa=c"); + ASSERT_EQ(3u, a.size()); + ASSERT_EQ(a["aaa"], "baaa"); + ASSERT_EQ(a["bb"], "a"); + ASSERT_EQ(a["aa"], "c"); +} + +TEST(ParseGetQuery, BasicEmpty) +{ + HttpHandler::Arguments a; + HttpHandler::ParseGetQuery(a, "aaa&bb=aa&aa"); + ASSERT_EQ(3u, a.size()); + ASSERT_EQ(a["aaa"], ""); + ASSERT_EQ(a["bb"], "aa"); + ASSERT_EQ(a["aa"], ""); +} + +TEST(ParseGetQuery, Single) +{ + HttpHandler::Arguments a; + HttpHandler::ParseGetQuery(a, "aaa=baaa"); + ASSERT_EQ(1u, a.size()); + ASSERT_EQ(a["aaa"], "baaa"); +} + +TEST(ParseGetQuery, SingleEmpty) +{ + HttpHandler::Arguments a; + HttpHandler::ParseGetQuery(a, "aaa"); + ASSERT_EQ(1u, a.size()); + ASSERT_EQ(a["aaa"], ""); +} + +TEST(FileStorage, Basic) +{ + FileStorage s("FileStorageUnitTests"); + + std::string data = Toolbox::GenerateUuid(); + std::string uid = s.Create(data); + std::string d; + s.ReadFile(d, uid); + ASSERT_EQ(d.size(), data.size()); + ASSERT_FALSE(memcmp(&d[0], &data[0], data.size())); +} + +TEST(FileStorage, EndToEnd) +{ + FileStorage s("FileStorageUnitTests"); + s.Clear(); + + std::list<std::string> u; + for (unsigned int i = 0; i < 10; i++) + { + u.push_back(s.Create(Toolbox::GenerateUuid())); + } + + std::set<std::string> ss; + s.ListAllFiles(ss); + ASSERT_EQ(10u, ss.size()); + + unsigned int c = 0; + for (std::list<std::string>::iterator + i = u.begin(); i != u.end(); i++, c++) + { + ASSERT_TRUE(ss.find(*i) != ss.end()); + if (c < 5) + s.Remove(*i); + } + + s.ListAllFiles(ss); + ASSERT_EQ(5u, ss.size()); + + s.Clear(); + s.ListAllFiles(ss); + ASSERT_EQ(0u, ss.size()); +} + + +TEST(DicomFormat, Tag) +{ + ASSERT_EQ("PatientName", FromDcmtkBridge::GetName(DicomTag(0x0010, 0x0010))); + + DicomTag t = FromDcmtkBridge::FindTag("SeriesDescription"); + ASSERT_EQ(0x0008, t.GetGroup()); + ASSERT_EQ(0x103E, t.GetElement()); +} + + +TEST(Uri, SplitUriComponents) +{ + UriComponents c; + Toolbox::SplitUriComponents(c, "/cou/hello/world"); + ASSERT_EQ(3u, c.size()); + ASSERT_EQ("cou", c[0]); + ASSERT_EQ("hello", c[1]); + ASSERT_EQ("world", c[2]); + + Toolbox::SplitUriComponents(c, "/cou/hello/world/"); + ASSERT_EQ(3u, c.size()); + ASSERT_EQ("cou", c[0]); + ASSERT_EQ("hello", c[1]); + ASSERT_EQ("world", c[2]); + + Toolbox::SplitUriComponents(c, "/cou/hello/world/a"); + ASSERT_EQ(4u, c.size()); + ASSERT_EQ("cou", c[0]); + ASSERT_EQ("hello", c[1]); + ASSERT_EQ("world", c[2]); + ASSERT_EQ("a", c[3]); + + Toolbox::SplitUriComponents(c, "/"); + ASSERT_EQ(0u, c.size()); + + Toolbox::SplitUriComponents(c, "/hello"); + ASSERT_EQ(1u, c.size()); + ASSERT_EQ("hello", c[0]); + + Toolbox::SplitUriComponents(c, "/hello/"); + ASSERT_EQ(1u, c.size()); + ASSERT_EQ("hello", c[0]); + + ASSERT_THROW(Toolbox::SplitUriComponents(c, ""), PalantirException); + ASSERT_THROW(Toolbox::SplitUriComponents(c, "a"), PalantirException); +} + + +TEST(Uri, Child) +{ + UriComponents c1; Toolbox::SplitUriComponents(c1, "/hello/world"); + UriComponents c2; Toolbox::SplitUriComponents(c2, "/hello/hello"); + UriComponents c3; Toolbox::SplitUriComponents(c3, "/hello"); + UriComponents c4; Toolbox::SplitUriComponents(c4, "/world"); + UriComponents c5; Toolbox::SplitUriComponents(c5, "/"); + + ASSERT_TRUE(Toolbox::IsChildUri(c1, c1)); + ASSERT_FALSE(Toolbox::IsChildUri(c1, c2)); + ASSERT_FALSE(Toolbox::IsChildUri(c1, c3)); + ASSERT_FALSE(Toolbox::IsChildUri(c1, c4)); + ASSERT_FALSE(Toolbox::IsChildUri(c1, c5)); + + ASSERT_FALSE(Toolbox::IsChildUri(c2, c1)); + ASSERT_TRUE(Toolbox::IsChildUri(c2, c2)); + ASSERT_FALSE(Toolbox::IsChildUri(c2, c3)); + ASSERT_FALSE(Toolbox::IsChildUri(c2, c4)); + ASSERT_FALSE(Toolbox::IsChildUri(c2, c5)); + + ASSERT_TRUE(Toolbox::IsChildUri(c3, c1)); + ASSERT_TRUE(Toolbox::IsChildUri(c3, c2)); + ASSERT_TRUE(Toolbox::IsChildUri(c3, c3)); + ASSERT_FALSE(Toolbox::IsChildUri(c3, c4)); + ASSERT_FALSE(Toolbox::IsChildUri(c3, c5)); + + ASSERT_FALSE(Toolbox::IsChildUri(c4, c1)); + ASSERT_FALSE(Toolbox::IsChildUri(c4, c2)); + ASSERT_FALSE(Toolbox::IsChildUri(c4, c3)); + ASSERT_TRUE(Toolbox::IsChildUri(c4, c4)); + ASSERT_FALSE(Toolbox::IsChildUri(c4, c5)); + + ASSERT_TRUE(Toolbox::IsChildUri(c5, c1)); + ASSERT_TRUE(Toolbox::IsChildUri(c5, c2)); + ASSERT_TRUE(Toolbox::IsChildUri(c5, c3)); + ASSERT_TRUE(Toolbox::IsChildUri(c5, c4)); + ASSERT_TRUE(Toolbox::IsChildUri(c5, c5)); +} + +TEST(Uri, AutodetectMimeType) +{ + ASSERT_EQ("", Toolbox::AutodetectMimeType("../NOTES")); + ASSERT_EQ("", Toolbox::AutodetectMimeType("")); + ASSERT_EQ("", Toolbox::AutodetectMimeType("/")); + ASSERT_EQ("", Toolbox::AutodetectMimeType("a/a")); + + ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("../NOTES.txt")); + ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("../coucou.xml/NOTES.txt")); + ASSERT_EQ("text/xml", Toolbox::AutodetectMimeType("../.xml")); + + ASSERT_EQ("application/javascript", Toolbox::AutodetectMimeType("NOTES.js")); + ASSERT_EQ("application/json", Toolbox::AutodetectMimeType("NOTES.json")); + ASSERT_EQ("application/pdf", Toolbox::AutodetectMimeType("NOTES.pdf")); + ASSERT_EQ("text/css", Toolbox::AutodetectMimeType("NOTES.css")); + ASSERT_EQ("text/html", Toolbox::AutodetectMimeType("NOTES.html")); + ASSERT_EQ("text/plain", Toolbox::AutodetectMimeType("NOTES.txt")); + ASSERT_EQ("text/xml", Toolbox::AutodetectMimeType("NOTES.xml")); + ASSERT_EQ("image/gif", Toolbox::AutodetectMimeType("NOTES.gif")); + ASSERT_EQ("image/jpeg", Toolbox::AutodetectMimeType("NOTES.jpg")); + ASSERT_EQ("image/jpeg", Toolbox::AutodetectMimeType("NOTES.jpeg")); + ASSERT_EQ("image/png", Toolbox::AutodetectMimeType("NOTES.png")); +} + + +int main(int argc, char **argv) +{ + PalantirInitialize(); + ::testing::InitGoogleTest(&argc, argv); + int result = RUN_ALL_TESTS(); + PalantirFinalize(); + return result; +}