--- /dev/null
+{
+ "phabricator.uri" : "https://phabricator.kde.org/project/profile/34/",
+ "history.immutable" : true
+}
--- /dev/null
+REVIEWBOARD_URL = "https://git.reviewboard.kde.org"
+REPOSITORY = "git://anongit.kde.org/kldap"
+BRANCH = "master"
+TARGET_GROUPS = "kdepimlibs"
+TARGET_PEOPLE = "mlaurent"
--- /dev/null
+cmake_minimum_required(VERSION 2.8.12)
+
+project(KLdap)
+
+# ECM setup
+find_package(ECM 5.19.0 CONFIG REQUIRED)
+set(CMAKE_MODULE_PATH ${KLdap_SOURCE_DIR}/cmake ${ECM_MODULE_PATH})
+
+include(GenerateExportHeader)
+include(ECMGenerateHeaders)
+include(ECMGeneratePriFile)
+include(ECMPackageConfigHelpers)
+include(ECMSetupVersion)
+include(FeatureSummary)
+include(KDEInstallDirs)
+include(KDECMakeSettings)
+include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
+include(ECMQtDeclareLoggingCategory)
+
+set(KF5_VERSION "5.19.0")
+set(KLDAP_LIB_VERSION "5.2.2")
+
+ecm_setup_version(${KLDAP_LIB_VERSION} VARIABLE_PREFIX KLDAP
+ VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kldap_version.h"
+ PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5LdapConfigVersion.cmake"
+ SOVERSION 5
+)
+
+########### Find packages ###########
+find_package(KF5Completion ${KF5_VERSION} CONFIG REQUIRED)
+find_package(KF5WidgetsAddons ${KF5_VERSION} CONFIG REQUIRED)
+find_package(KF5I18n ${KF5_VERSION} CONFIG REQUIRED)
+
+
+find_package(Ldap)
+set_package_properties(Ldap PROPERTIES
+ TYPE RECOMMENDED
+ PURPOSE "Needed to provide LDAP functionality in KDE"
+)
+
+find_package(Sasl2)
+set_package_properties(Sasl2 PROPERTIES TYPE OPTIONAL)
+
+if (Ldap_FOUND)
+ set(LDAP_FOUND 1)
+endif()
+
+if (Sasl2_FOUND)
+ set(SASL2_FOUND 1)
+endif()
+
+add_definitions("-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII")
+add_definitions(-DTRANSLATION_DOMAIN=\"libkldap5\")
+
+########### CMake Config Files ###########
+set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5Ldap")
+
+ecm_configure_package_config_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/KF5LdapConfig.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5LdapConfig.cmake"
+ INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
+)
+
+install(FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5LdapConfig.cmake"
+ "${CMAKE_CURRENT_BINARY_DIR}/KF5LdapConfigVersion.cmake"
+ DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
+ COMPONENT Devel
+)
+
+install(EXPORT KF5LdapTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5LdapTargets.cmake NAMESPACE KF5::)
+
+install(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/kldap_version.h
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}
+ COMPONENT Devel
+)
+
+########### Targets ###########
+add_subdirectory(cmake)
+add_subdirectory(src)
+
+if(BUILD_TESTING)
+ add_subdirectory(autotests)
+endif()
+
+feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+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
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey 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 library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
--- /dev/null
+@PACKAGE_INIT@
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_MODULE_PATH})
+
+find_dependency(Ldap)
+find_dependency(Sasl2)
+
+include(FeatureSummary)
+
+set_package_properties(Ldap PROPERTIES
+ DESCRIPTION "LDAP (Lightweight Directory Access Protocol) libraries"
+ URL "http://www.openldap.org"
+ PURPOSE "Needed to provide LDAP functionality in KDE"
+)
+
+set_package_properties(Sasl2 PROPERTIES
+ DESCRIPTION "The Cyrus-sasl library"
+ URL "http://www.cyrussasl.org"
+)
+
+include("${CMAKE_CURRENT_LIST_DIR}/KF5LdapTargets.cmake")
--- /dev/null
+/*!
+ * @mainpage kldap - an LDAP access API for KDE.
+ *
+ * @section purpose Purpose
+ *
+ * LIBKLDAP
+ *
+ * @section desc Description
+ *
+ * Allows LDAP accessing with a convenient Qt style C++ API.
+ *
+ * @authors György Szombathelyi \<gyurco@freemail.hu\>
+ *
+ * @maintainers György Szombathelyi \<gyurco@freemail.hu\>
+ *
+ * @licenses
+ * @lgpl
+ */
+
+// DOXYGEN_PROJECTNAME=KLDAP Library
+// DOXYGEN_REFERENCES = kdecore kdeui
+// DOXYGEN_EXCLUDE = scripts
--- /dev/null
+include(ECMAddTests)
+
+find_package(Qt5Test CONFIG REQUIRED)
+
+if(Ldap_FOUND)
+ ecm_add_tests(testkldap.cpp NAME_PREFIX "kldap-" LINK_LIBRARIES KF5::Ldap Qt5::Test)
+endif()
--- /dev/null
+/*
+ This file is part of libkdepim.
+
+ Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "testkldap.h"
+
+#include "ldif.h"
+#include "ldapdn.h"
+#include "ldapurl.h"
+#include "ldapserver.h"
+#include "ldapconnection.h"
+#include "ldapmodel.h"
+#include "ldapoperation.h"
+#include "ldapsearch.h"
+#include "ber.h"
+
+#include <qdebug.h>
+#include <qtest.h>
+#include <QFile>
+QTEST_MAIN(KLdapTest)
+
+void KLdapTest::initTestCase()
+{
+ /*
+ Read in the connection details of an LDAP server to use for testing.
+ You should copy the file testurl.txt.tmpl to testurl.txt and specify a url in this file.
+ The specified server should not be a production server in case we break anything here.
+ You have been warned!
+ */
+ m_search = 0;
+ m_model = 0;
+
+ QString filename(QStringLiteral("testurl.txt"));
+ QFile file(filename);
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream stream(&file);
+ stream >> m_url;
+ file.close();
+ }
+// else
+// QCOMPARE( 0, 1 );
+
+ m_search = new LdapSearch;
+
+ /* Let's also create an LdapModel object */
+ m_model = new LdapModel(this);
+}
+
+void KLdapTest::testBer()
+{
+ Ber ber1, ber2, ber3, ber4, ber5, ber6, ber7;
+ Ber bber;
+ QByteArray flat;
+
+ int ainteger;
+ QByteArray aoctetString1, aoctetString2, aoctetString3;
+ QList<QByteArray> alist1, alist2;
+
+ int binteger;
+ QByteArray boctetString1, boctetString2, boctetString3;
+ QList<QByteArray> blist1, blist2;
+
+ aoctetString1 = "KDE";
+ aoctetString2 = "the";
+ aoctetString3 = "next generation";
+
+ alist1.append(aoctetString1);
+ alist1.append(aoctetString2);
+
+ alist2.append(aoctetString2);
+ alist2.append(aoctetString3);
+ alist2.append(aoctetString1);
+
+ ainteger = 23543;
+
+ ber1.printf(QStringLiteral("i"), ainteger);
+ ber2.printf(QStringLiteral("o"), &aoctetString1);
+ ber3.printf(QStringLiteral("O"), &aoctetString2);
+ ber4.printf(QStringLiteral("s"), &aoctetString3);
+ ber5.printf(QStringLiteral("{v}"), &alist1);
+ ber6.printf(QStringLiteral("{V}"), &alist2);
+ ber7.printf(QStringLiteral("oi{v}O"), &aoctetString1, ainteger, &alist2, &aoctetString2);
+
+ //test integer:
+ bber = ber1;
+ bber.scanf(QStringLiteral("i"), &binteger);
+ QCOMPARE(ainteger, binteger);
+
+ //test octet strings:
+ bber = ber2;
+ bber.scanf(QStringLiteral("o"), &boctetString1);
+ QCOMPARE(aoctetString1, boctetString1);
+ bber = ber3;
+ bber.scanf(QStringLiteral("o"), &boctetString2);
+ QCOMPARE(aoctetString2, boctetString2);
+ bber = ber4;
+ bber.scanf(QStringLiteral("o"), &boctetString3);
+ QCOMPARE(aoctetString3, boctetString3);
+
+ //test sequence of octet strings:
+ bber = ber5;
+ bber.scanf(QStringLiteral("v"), &blist1);
+ QCOMPARE(alist1, blist1);
+
+ bber = ber6;
+ bber.scanf(QStringLiteral("v"), &blist2);
+ QCOMPARE(alist2, blist2);
+
+ //complex tests
+ boctetString1 = boctetString2 = boctetString3 = QByteArray();
+ binteger = 0;
+ blist1.clear();
+ blist2.clear();
+
+ bber = ber7;
+ bber.scanf(QStringLiteral("oivO"), &boctetString1, &binteger, &blist2, &boctetString2);
+ QCOMPARE(aoctetString1, boctetString1);
+ QCOMPARE(aoctetString2, boctetString2);
+ QCOMPARE(alist2, blist2);
+ QCOMPARE(ainteger, binteger);
+}
+
+void KLdapTest::cleanupTestCase()
+{
+ delete m_search;
+ delete m_model;
+}
+
+void KLdapTest::testLdapUrl()
+{
+ // Test LdapUrl using some hardwired values so that we know what to compare to
+ LdapUrl url;
+ bool critical;
+
+ url.setUrl(QStringLiteral("ldap://cn=manager,dc=kde,dc=org:password@localhost:3999/"
+ "dc=kde,dc=org?cn,mail?sub?(objectClass=*)?x-dir=base"));
+ url.parseQuery();
+
+ QCOMPARE(url.userName(), QString::fromLatin1("cn=manager,dc=kde,dc=org"));
+ QCOMPARE(url.password(), QString::fromLatin1("password"));
+ QCOMPARE(url.dn(), LdapDN(QStringLiteral("dc=kde,dc=org")));
+ QCOMPARE(url.scope(), LdapUrl::Sub);
+ QCOMPARE(url.attributes().at(0), QString::fromLatin1("cn"));
+ QCOMPARE(url.attributes().at(1), QString::fromLatin1("mail"));
+ QCOMPARE(url.filter(), QString::fromLatin1("(objectClass=*)"));
+ QCOMPARE(url.extension(QString::fromLatin1("x-dir"), critical),
+ QString::fromLatin1("base"));
+}
+
+void KLdapTest::testLdapConnection()
+{
+ // Try to connect using an LdapUrl (read in from testurl.txt).
+ LdapUrl url;
+ url.setUrl(m_url);
+
+ LdapConnection conn;
+ conn.setUrl(url);
+ int ret;
+ if ((ret = conn.connect())) {
+ qDebug() << "Could not connect to LDAP server. Error was:" << conn.connectionError();
+ }
+ QCOMPARE(ret, 0);
+
+ LdapOperation op(conn);
+ // Now attempt to bind
+ if ((ret = op.bind_s())) {
+ qDebug() << "Could not bind to server. Error was:" << conn.ldapErrorString();
+ }
+ QEXPECT_FAIL("", "Will fail since no server is available for testing", Abort);
+ QCOMPARE(ret, 0);
+}
+
+void KLdapTest::testLdapSearch()
+{
+ // Lets try a search using the specified url
+ LdapUrl url;
+ url.setUrl(m_url);
+ url.parseQuery();
+ connect(m_search, SIGNAL(result(KLDAP::LdapSearch*)),
+ this, SLOT(searchResult(KLDAP::LdapSearch*)));
+ connect(m_search, SIGNAL(data(KLDAP::LdapSearch*,KLDAP::LdapObject)),
+ this, SLOT(searchData(KLDAP::LdapSearch*,KLDAP::LdapObject)));
+ bool success = m_search->search(url);
+ while (QCoreApplication::hasPendingEvents()) {
+ qApp->processEvents();
+ }
+
+ QEXPECT_FAIL("", "Will fail since no server is available for testing", Abort);
+ QCOMPARE(success, true);
+
+ qDebug() << "Search found" << m_objects.size() << "matching entries";
+}
+
+void KLdapTest::searchResult(KLDAP::LdapSearch *search)
+{
+ qDebug();
+ int err = search->error();
+ if (err) {
+ qDebug() << "Search returned the following error:" << search->errorString();
+ }
+ QCOMPARE(err, 0);
+}
+
+void KLdapTest::searchData(KLDAP::LdapSearch *search, const KLDAP::LdapObject &obj)
+{
+ Q_UNUSED(search);
+ //qDebug();
+ //qDebug() << "Object:";
+ //qDebug() << obj.toString();
+ m_objects.append(obj);
+}
+
+void KLdapTest::testLdapDN()
+{
+ QString strDN(QStringLiteral("uid=Test\\+Person+ou=accounts\\,outgoing,dc=kde,dc=org"));
+ LdapDN dn(strDN);
+ QCOMPARE(dn.isValid(), true);
+ QCOMPARE(dn.rdnString(), QStringLiteral("uid=Test\\+Person+ou=accounts\\,outgoing"));
+}
+
+void KLdapTest::testLdapModel()
+{
+ // Use the user-supplied testing url
+ LdapUrl url;
+ url.setUrl(m_url);
+
+ // Create a connection to use and bind with it
+ LdapConnection conn;
+ conn.setUrl(url);
+ int ret;
+ if ((ret = conn.connect())) {
+ qDebug() << "Could not connect to LDAP server. Error was:" << conn.connectionError();
+ }
+ QCOMPARE(ret, 0);
+
+ LdapOperation op(conn);
+ if ((ret = op.bind_s())) {
+ qDebug() << "Could not bind to server. Error was:" << conn.ldapErrorString();
+ }
+ QEXPECT_FAIL("", "Will fail since no server is available for testing", Abort);
+ QCOMPARE(ret, 0);
+
+ // Let's use this connection with the model
+ m_model->setConnection(conn);
+
+ while (QCoreApplication::hasPendingEvents()) {
+ qApp->processEvents();
+ }
+
+ QModelIndex rootIndex = QModelIndex();
+ QVariant data = m_model->data(rootIndex, Qt::DisplayRole);
+ qDebug() << "Root Item Distinguished Name =" << data.toString();
+
+ QVERIFY(m_model->hasChildren(rootIndex) == true);
+ QVERIFY(m_model->canFetchMore(rootIndex) == false);
+}
+
+/*
+ void KLdapTest::testKLdap()
+ {
+ LdapUrl url;
+ bool critical;
+
+ url.setUrl("ldap://cn=manager,dc=kde,dc=org:password@localhost:3999"
+ "/dc=kde,dc=org?cn,mail?sub?(objectClass=*)?x-dir=base");
+ url.parseQuery();
+
+ QCOMPARE( url.user(), QString::fromLatin1("cn=manager,dc=kde,dc=org") );
+ QCOMPARE( url.password(), QString::fromLatin1("password") );
+ QCOMPARE( url.dn(), QString::fromLatin1("dc=kde,dc=org") );
+ QCOMPARE( url.scope(), LdapUrl::Sub );
+ QCOMPARE( url.attributes().at(0), QString::fromLatin1("cn") );
+ QCOMPARE( url.attributes().at(1), QString::fromLatin1("mail") );
+ QCOMPARE( url.filter(), QString::fromLatin1("(objectClass=*)") );
+ QCOMPARE( url.extension(QString::fromLatin1("x-dir"), critical), QString::fromLatin1("base") );
+
+ url.setDn("ou=People,dc=kde,dc=org");
+ QCOMPARE( url.dn(), QString::fromLatin1("ou=People,dc=kde,dc=org") );
+ url.setDn("/ou=People,dc=kde,dc=org");
+ QCOMPARE( url.dn(), QString::fromLatin1("ou=People,dc=kde,dc=org") );
+
+ LdapServer server;
+// url.setUrl("ldaps://cn=manager,dc=kde,dc=org:passwor@localhost:3999/"
+ "dc=kde,dc=org????x-timelimt=5,x-sizelimit=6,x=pagesize=7,binddn=cn=apple,ou=berry");
+url.setUrl("ldaps://cn=manager,dc=kde,dc=org:password@localhost:3999/"
+ "dc=kde,dc=org??base??x-timelimit=5");
+url.parseQuery();
+server.setUrl( url );
+QCOMPARE( url.query(), QString::fromLatin1("??base??x-timelimit=5") );
+QCOMPARE( url.url(), server.url().url() );
+
+LdapControl c1;
+c1.setControl( QString::fromLatin1("1.2.3.4.5.6"), QByteArray("abcdefg"), true );
+//test copy constructor
+LdapControl c2(c1);
+QCOMPARE( c2.oid(), QString::fromLatin1("1.2.3.4.5.6") );
+QCOMPARE( c2.value(), QByteArray("abcdefg") );
+QCOMPARE( c2.critical(), true );
+//test assignment operator
+LdapControl c3;
+c3 = c1;
+QCOMPARE( c3.oid(), QString::fromLatin1("1.2.3.4.5.6") );
+QCOMPARE( c3.value(), QByteArray("abcdefg") );
+QCOMPARE( c3.critical(), true );
+*/
+//test Ber functions
+/*
+ QByteArray left1("bertest"), right1;
+ int left2 = 0, right2;
+ int left3 = 1, right3;
+ int left4 = 2, right4;
+ int left5 = 3, right5;
+ int left6 = 1, right6;
+ QList<QByteArray> left7, right7;
+ left7.append( "abcdefghij" );
+ left7.append( "123456789" );
+ left7.append( "1234\0\0\056789" );
+
+ Ber ber;
+ ber.printf("{seeiib}", &left1, left2, left3, left4, left5, left6 );
+
+// ber.printf("{ioOi{i}}", left3, &left1, &left2, left4, left4 );
+Ber ber2 = ber;
+
+unsigned int a;
+int b;
+a = ber2.skipTag( b );
+qDebug() << "next tag:" << a << "size:" << b;
+a = ber2.skipTag( b );
+qDebug() << "next tag:" << a << "size:" << b;
+a = ber2.skipTag( b );
+qDebug() << "next tag:" << a << "size:" << b;
+a = ber2.skipTag( b );
+qDebug() << "next tag:" << a << "size:" << b;
+a = ber2.skipTag( b );
+qDebug() << "next tag:" << a << "size:" << b;
+a = ber2.skipTag( b );
+qDebug() << "next tag:" << a << "size:" << b;
+a = ber2.skipTag( b );
+qDebug() << "next tag:" << a << "size:" << b;
+a = ber2.skipTag( b );
+qDebug() << "next tag:" << a << "size:" << b;
+
+BerElement *_ber, *_ber2;
+_ber = ber_alloc_t( LBER_USE_DER );
+
+ber_len_t bl;
+ber_printf( _ber, "{i}", 5 );
+qDebug() << "native";
+_ber2 = ber_dup( _ber );
+a = ber_skip_tag( _ber2, &bl );
+qDebug() << "next tag:" << a << "size:" << bl;
+// ber_dump( _ber, 0 );
+
+// ber2.scanf("{v}", &right5 );
+
+// ber2.scanf("{inoOi{v}}", &right3, &right1, &right2, &right4, &right5 );
+
+// QCOMPARE( left1, right1 );
+// QCOMPARE( left2, right2 );
+// QCOMPARE( left3, right3 );
+// QCOMPARE( left4, right4 );
+// QCOMPARE( left5, right5 );
+*/
+/*
+ url.setUrl("ldap://localhost/dc=gyurco,dc=localdomain");
+ url.parseQuery();
+ server.setUrl( url );
+ LdapConnection conn( server );
+ int result = conn.connect();
+ qDebug() << "connect result" << result << conn.errorString();
+
+ LdapOperation op( conn );
+ int msgid = op.search( "ou=People,dc=gyurco,dc=localdomain", LdapUrl::One, "", QStringList() );
+ qDebug() << "search msgid" << msgid;
+ result = op.result( msgid );
+ qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
+ while ( result == LdapOperation::RES_SEARCH_ENTRY ) {
+ qDebug() << op.object().toString();
+ result = op.result( msgid );
+ }
+ qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
+
+ msgid = op.del( "ou=People,dc=gyurco,dc=localdomain" );
+ qDebug() << "search msgid" << msgid;
+ result = op.result( msgid );
+ qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
+
+ msgid = op.compare( "ou=People,dc=gyurco,dc=localdomain", "objectClass", QByteArray("top") );
+ qDebug() << "search msgid" << msgid;
+ result = op.result( msgid );
+ qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
+
+ msgid = op.compare( "ou=People,dc=gyurco,dc=localdomain", "objectClass",
+ QByteArray("inetOrgPerson") );
+ qDebug() << "search msgid" << msgid;
+ result = op.result( msgid );
+ qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
+
+ msgid = op.exop( "1.2.3.4.5.6.7.8", QByteArray("inetOrgPerson") );
+ qDebug() << "search msgid" << msgid;
+ result = op.result( msgid );
+ qDebug() << "error code" << conn.ldapErrorCode() << "str:" << conn.ldapErrorString();
+*/
+/*
+ }
+*/
--- /dev/null
+/*
+ Copyright (c) 2006 Volker Krause <vkrause@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef TESTKLDAP_H
+#define TESTKLDAP_H
+
+#include <QtCore/QObject>
+#include <ldapmodel.h>
+#include <ldapobject.h>
+#include <ldapsearch.h>
+
+using namespace KLDAP;
+
+class KLdapTest : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ //void testKLdap();
+
+ void initTestCase();
+ void cleanupTestCase();
+
+ void testLdapUrl();
+ void testBer();
+ void testLdapConnection();
+ void testLdapSearch();
+ void testLdapDN();
+ void testLdapModel();
+
+public Q_SLOTS:
+ void searchResult(KLDAP::LdapSearch *search);
+ void searchData(KLDAP::LdapSearch *search, const KLDAP::LdapObject &obj);
+
+private:
+ QString m_url;
+ LdapSearch *m_search;
+ LdapObjects m_objects;
+ LdapModel *m_model;
+};
+
+#endif
--- /dev/null
+ldap://cn=admin,dc=kde,dc=org:password@ldap.kde.org:389/ou=people,dc=kde,dc=org?cn,mail,loginShell?sub?(uid=*)
--- /dev/null
+install(FILES
+ FindLdap.cmake
+ FindSasl2.cmake
+ DESTINATION ${CMAKECONFIG_INSTALL_DIR}
+)
--- /dev/null
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null
+#.rst:
+# FindLdap
+# --------
+#
+# Try to find the LDAP client libraries.
+#
+# This will define the following variables:
+#
+# ``Ldap_FOUND``
+# True if libldap is available.
+#
+# ``Ldap_VERSION``
+# The version of libldap
+#
+# ``Ldap_INCLUDE_DIRS``
+# This should be passed to target_include_directories() if
+# the target is not used for linking
+#
+# ``Ldap_LIBRARIES``
+# The LDAP libraries (libldap + liblber if available)
+# This can be passed to target_link_libraries() instead of
+# the ``Ldap::Ldap`` target
+#
+# If ``Ldap_FOUND`` is TRUE, the following imported target
+# will be available:
+#
+# ``Ldap::Ldap``
+# The LDAP library
+#
+# Since pre-5.0.0.
+#
+# Imported target since 5.1.41
+#
+#=============================================================================
+# Copyright 2006 Szombathelyi György <gyurco@freemail.hu>
+# Copyright 2007-2016 Laurent Montel <montel@kde.org>
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
+find_path(Ldap_INCLUDE_DIRS NAMES ldap.h)
+
+if(APPLE)
+ find_library(Ldap_LIBRARIES NAMES LDAP
+ PATHS
+ /System/Library/Frameworks
+ /Library/Frameworks
+ )
+else()
+ find_library(Ldap_LIBRARIES NAMES ldap)
+ find_library(Lber_LIBRARIES NAMES lber)
+endif()
+
+if(Ldap_LIBRARIES AND Lber_LIBRARIES)
+ set(Ldap_LIBRARIES ${Ldap_LIBRARIES} ${Lber_LIBRARIES})
+endif()
+
+if(EXISTS ${Ldap_INCLUDE_DIRS}/ldap_features.h)
+ file(READ ${Ldap_INCLUDE_DIRS}/ldap_features.h LDAP_FEATURES_H_CONTENT)
+ string(REGEX MATCH "#define LDAP_VENDOR_VERSION_MAJOR[ ]+[0-9]+" _LDAP_VERSION_MAJOR_MATCH ${LDAP_FEATURES_H_CONTENT})
+ string(REGEX MATCH "#define LDAP_VENDOR_VERSION_MINOR[ ]+[0-9]+" _LDAP_VERSION_MINOR_MATCH ${LDAP_FEATURES_H_CONTENT})
+ string(REGEX MATCH "#define LDAP_VENDOR_VERSION_PATCH[ ]+[0-9]+" _LDAP_VERSION_PATCH_MATCH ${LDAP_FEATURES_H_CONTENT})
+
+ string(REGEX REPLACE ".*_MAJOR[ ]+(.*)" "\\1" LDAP_VERSION_MAJOR ${_LDAP_VERSION_MAJOR_MATCH})
+ string(REGEX REPLACE ".*_MINOR[ ]+(.*)" "\\1" LDAP_VERSION_MINOR ${_LDAP_VERSION_MINOR_MATCH})
+ string(REGEX REPLACE ".*_PATCH[ ]+(.*)" "\\1" LDAP_VERSION_PATCH ${_LDAP_VERSION_PATCH_MATCH})
+
+ set(Ldap_VERSION "${LDAP_VERSION_MAJOR}.${LDAP_VERSION_MINOR}.${LDAP_VERSION_PATCH}")
+endif()
+
+include(FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args(Ldap
+ FOUND_VAR Ldap_FOUND
+ REQUIRED_VARS Ldap_LIBRARIES Ldap_INCLUDE_DIRS
+ VERSION_VAR Ldap_VERSION
+)
+
+if(Ldap_FOUND AND NOT TARGET Ldap::Ldap)
+ add_library(Ldap::Ldap UNKNOWN IMPORTED)
+ set_target_properties(Ldap::Ldap PROPERTIES
+ IMPORTED_LOCATION "${Ldap_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${Ldap_INCLUDE_DIRS}")
+endif()
+
+mark_as_advanced(Ldap_INCLUDE_DIRS Ldap_LIBRARIES Lber_LIBRARIES Ldap_VERSION)
+
+include(FeatureSummary)
+set_package_properties(Ldap PROPERTIES
+ URL "http://www.openldap.org/"
+ DESCRIPTION "LDAP (Lightweight Directory Access Protocol) libraries."
+)
--- /dev/null
+#.rst:
+# FindSasl2
+# ---------
+#
+# Try to find the SASL2 library.
+#
+# This will define the following variables:
+#
+# ``Sasl2_FOUND``
+# System has SASL2.
+#
+# ``Sasl2_VERSION``
+# The version of SASL2.
+#
+# ``Sasl2_INCLUDE_DIRS``
+# This should be passed to target_include_directories() if
+# the target is not used for linking.
+#
+# ``Sasl2_LIBRARIES``
+# The SASL2 library.
+# This can be passed to target_link_libraries() instead of
+# the ``Sasl2::Sasl2`` target
+#
+# If ``Sasl2_FOUND`` is TRUE, the following imported target
+# will be available:
+#
+# ``Sasl2::Sasl2``
+# The SASL2 library
+#
+# Since pre-5.0.0.
+#
+# Imported target since 5.1.41
+#
+#=============================================================================
+# Copyright 2006, 2007 Laurent Montel <montel@kde.org>
+#
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
+# NOTE: libsasl2.pc doesn't export the include dir.
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_Sasl2 libsasl2)
+
+find_path(Sasl2_INCLUDE_DIRS NAMES sasl/sasl.h)
+
+# libsasl2 add for windows, because the windows package of cyrus-sasl2
+# contains a libsasl2 also for msvc which is not standard conform
+find_library(Sasl2_LIBRARIES
+ NAMES sasl2 libsasl2
+ HINTS ${PC_Sasl2_LIBRARY_DIRS}
+)
+
+set(Sasl2_VERSION ${PC_Sasl2_VERSION})
+
+if(NOT Sasl2_VERSION)
+ if(EXISTS ${Sasl2_INCLUDE_DIRS}/sasl/sasl.h)
+ file(READ ${Sasl2_INCLUDE_DIRS}/sasl/sasl.h SASL2_H_CONTENT)
+ string(REGEX MATCH "#define SASL_VERSION_MAJOR[ ]+[0-9]+" SASL2_VERSION_MAJOR_MATCH ${SASL2_H_CONTENT})
+ string(REGEX MATCH "#define SASL_VERSION_MINOR[ ]+[0-9]+" SASL2_VERSION_MINOR_MATCH ${SASL2_H_CONTENT})
+ string(REGEX MATCH "#define SASL_VERSION_STEP[ ]+[0-9]+" SASL2_VERSION_STEP_MATCH ${SASL2_H_CONTENT})
+
+ string(REGEX REPLACE ".*_MAJOR[ ]+(.*)" "\\1" SASL2_VERSION_MAJOR ${SASL2_VERSION_MAJOR_MATCH})
+ string(REGEX REPLACE ".*_MINOR[ ]+(.*)" "\\1" SASL2_VERSION_MINOR ${SASL2_VERSION_MINOR_MATCH})
+ string(REGEX REPLACE ".*_STEP[ ]+(.*)" "\\1" SASL2_VERSION_STEP ${SASL2_VERSION_STEP_MATCH})
+
+ set(Sasl2_VERSION "${SASL2_VERSION_MAJOR}.${SASL2_VERSION_MINOR}.${SASL2_VERSION_STEP}")
+ endif()
+endif()
+
+include(FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args(Sasl2
+ FOUND_VAR Sasl2_FOUND
+ REQUIRED_VARS Sasl2_LIBRARIES Sasl2_INCLUDE_DIRS
+ VERSION_VAR Sasl2_VERSION
+)
+if(Sasl2_FOUND AND NOT TARGET Sasl2::Sasl2)
+ add_library(Sasl2::Sasl2 UNKNOWN IMPORTED)
+ set_target_properties(Sasl2::Sasl2 PROPERTIES
+ IMPORTED_LOCATION "${Sasl2_LIBRARIES}"
+ INTERFACE_INCLUDE_DIRECTORIES "${Sasl2_INCLUDE_DIRS}")
+endif()
+
+mark_as_advanced(Sasl2_LIBRARIES Sasl2_INCLUDE_DIRS Sasl2_VERSION)
+
+include(FeatureSummary)
+set_package_properties(Sasl2 PROPERTIES
+ URL "http://www.cyrussasl.org/"
+ DESCRIPTION "The Cyrus-sasl library."
+)
+
--- /dev/null
+maintainer: mlaurent
+description: LDap support library
+tier: 3
+type: functional
+platforms:
+ - name: All
+portingAid: false
+deprecated: false
+release: false
+libraries:
+ - qmake: Ldap
+ cmake: "KF5::Ldap"
+cmakename: KF5Ldap
+
--- /dev/null
+include(CheckFunctionExists)
+include(CheckIncludeFiles)
+include(CheckSymbolExists)
+
+# Reactivate it
+remove_definitions(-DQT_NO_CAST_FROM_BYTEARRAY)
+
+check_include_files(sys/time.h HAVE_SYS_TIME_H)
+
+set(kldap_EXTRA_LIBS)
+
+if(Ldap_FOUND)
+ set(kldap_EXTRA_LIBS ${Ldap_LIBRARIES})
+ if(WIN32)
+ set(kldap_EXTRA_LIBS ${kldap_EXTRA_LIBS} ws2_32)
+ endif()
+ set(HAVE_LDAP_H)
+ set(CMAKE_REQUIRED_INCLUDES lber.h ldap.h)
+ set(CMAKE_REQUIRED_LIBRARIES ${Ldap_LIBRARIES})
+ check_function_exists(ldap_start_tls_s HAVE_LDAP_START_TLS_S)
+ check_function_exists(ldap_initialize HAVE_LDAP_INITIALIZE)
+ check_function_exists(ber_memfree HAVE_BER_MEMFREE)
+ check_function_exists(ldap_unbind_ext HAVE_LDAP_UNBIND_EXT)
+ check_function_exists(ldap_extended_operation HAVE_LDAP_EXTENDED_OPERATION)
+ check_function_exists(ldap_extended_operation_s HAVE_LDAP_EXTENDED_OPERATION_S)
+ check_symbol_exists(ldap_extended_operation ldap.h HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE)
+ check_symbol_exists(ldap_extended_operation_s ldap.h HAVE_LDAP_EXTENDED_OPERATION_S_PROTOTYPE)
+endif()
+
+if(Sasl2_FOUND)
+ set(kldap_EXTRA_LIBS ${kldap_EXTRA_LIBS} ${Sasl2_LIBRARIES})
+endif()
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/kldap_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kldap_config.h)
+
+########### next target ###############
+
+set(kldap_LIB_SRCS
+ ber.cpp
+ ldif.cpp
+ ldapurl.cpp
+ ldapserver.cpp
+ ldapobject.cpp
+ ldapconnection.cpp
+ ldapoperation.cpp
+ ldapcontrol.cpp
+ ldapsearch.cpp
+ ldapconfigwidget.cpp
+ ldapdn.cpp
+ ldapmodelnode_p.cpp
+ ldapmodel.cpp
+ ldapmodel_p.cpp
+ ldapstructureproxymodel.cpp
+ ldapattributeproxymodel.cpp
+)
+ecm_qt_declare_logging_category(kldap_LIB_SRCS HEADER ldap_debug.h IDENTIFIER LDAP_LOG CATEGORY_NAME log_ldap)
+
+add_library(KF5Ldap ${kldap_LIB_SRCS})
+
+generate_export_header(KF5Ldap BASE_NAME kldap)
+
+add_library(KF5::Ldap ALIAS KF5Ldap)
+
+target_link_libraries(KF5Ldap
+PRIVATE
+ KF5::Completion
+ Qt5::Widgets
+ KF5::I18n
+ KF5::WidgetsAddons
+ ${kldap_EXTRA_LIBS}
+)
+
+target_include_directories(KF5Ldap INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF5}/KLDAP;${Ldap_INCLUDE_DIRS}>")
+target_include_directories(KF5Ldap PUBLIC "$<BUILD_INTERFACE:${KLdap_SOURCE_DIR}/src;${KLdap_BINARY_DIR}/src;${Ldap_INCLUDE_DIRS}>")
+
+if(Sasl2_FOUND)
+ target_include_directories(KF5Ldap INTERFACE "$<INSTALL_INTERFACE:${Sasl2_INCLUDE_DIRS}>")
+ target_include_directories(KF5Ldap PUBLIC "$<BUILD_INTERFACE:${Sasl2_INCLUDE_DIRS}>")
+endif()
+
+set_target_properties(KF5Ldap PROPERTIES
+ VERSION ${KLDAP_VERSION_STRING}
+ SOVERSION ${KLDAP_SOVERSION}
+ EXPORT_NAME Ldap
+)
+
+
+install(TARGETS KF5Ldap EXPORT KF5LdapTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS})
+
+########### install files ###############
+
+ecm_generate_headers(KLdap_CamelCase_HEADERS
+ HEADER_NAMES
+ Ber
+ LdapAttributeProxyModel
+ LdapConfigWidget
+ LdapConnection
+ LdapControl
+ LdapDN
+ LdapModel
+ LdapObject
+ LdapOperation
+ LdapSearch
+ LdapServer
+ LdapDefs
+ LdapStructureProxyModel
+ LdapUrl
+ Ldif
+ PREFIX KLDAP
+ REQUIRED_HEADERS KLdap_HEADERS
+)
+
+install(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/kldap_export.h
+ ${KLdap_HEADERS}
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KLDAP/kldap
+ COMPONENT Devel
+)
+
+install(FILES
+ ${KLdap_CamelCase_HEADERS}
+ DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KLDAP/KLDAP/
+ COMPONENT Devel
+)
+
+ecm_generate_pri_file(BASE_NAME Ldap LIB_NAME KF5Ldap FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KLDAP/)
+install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
+
--- /dev/null
+#! /bin/sh
+$XGETTEXT *.cpp -o $podir/libkldap5.pot
+
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ber.h"
+#include "kldap_config.h"
+
+#include "ldap_debug.h"
+
+#include <QtCore/QList>
+#include <qvarlengtharray.h>
+
+#include <cstdarg>
+
+#ifdef LDAP_FOUND
+
+#ifdef Q_OS_SOLARIS //krazy:exclude=cpp
+#define BC31 1
+#endif
+
+#ifndef HAVE_WINLDAP_H
+#include <lber.h>
+#include <ldap.h>
+#else
+#include <w32-ldap-help.h>
+#endif
+
+#ifndef LBER_USE_DER
+#define LBER_USE_DER 1
+#endif
+
+#ifndef HAVE_BER_MEMFREE
+# ifndef HAVE_WINLDAP_H
+# define ber_memfree(x) ldap_memfree(x)
+# else
+# define ber_memfree(x) win_ldap_memfree(x)
+# endif
+#endif
+
+#endif
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN Ber::BerPrivate
+{
+public:
+#ifdef LDAP_FOUND
+ BerElement *mBer;
+#endif
+};
+
+#ifdef LDAP_FOUND
+Ber::Ber()
+ : d(new BerPrivate)
+{
+ d->mBer = ber_alloc_t(LBER_USE_DER);
+ Q_ASSERT(d->mBer);
+}
+
+Ber::Ber(const QByteArray &value)
+ : d(new BerPrivate)
+{
+ struct berval bv;
+ bv.bv_val = (char *) value.data();
+ bv.bv_len = value.size();
+ d->mBer = ber_init(&bv);
+ Q_ASSERT(d->mBer);
+}
+
+Ber::~Ber()
+{
+ ber_free(d->mBer, 1);
+ delete d;
+}
+
+Ber::Ber(const Ber &that)
+ : d(new BerPrivate)
+{
+ struct berval *bv;
+ if (ber_flatten(that.d->mBer, &bv) == 0) {
+ d->mBer = ber_init(bv);
+ ber_bvfree(bv);
+ }
+}
+
+Ber &Ber::operator=(const Ber &that)
+{
+ if (this == &that) {
+ return *this;
+ }
+
+ struct berval *bv;
+ if (ber_flatten(that.d->mBer, &bv) == 0) {
+ d->mBer = ber_init(bv);
+ ber_bvfree(bv);
+ }
+ return *this;
+}
+
+QByteArray Ber::flatten() const
+{
+ QByteArray ret;
+ struct berval *bv;
+ if (ber_flatten(d->mBer, &bv) == 0) {
+ ret = QByteArray(bv->bv_val, bv->bv_len);
+ ber_bvfree(bv);
+ }
+ return ret;
+}
+
+int Ber::printf(QString format, ...)
+{
+ char fmt[2];
+ va_list args;
+ va_start(args, format);
+ fmt[1] = '\0';
+
+ int i = 0, ret = 0;
+ while (i < format.length()) {
+ fmt[0] = format[i].toLatin1();
+ i++;
+ switch (fmt[0]) {
+ case 'b':
+ case 'e':
+ case 'i': {
+ ber_int_t v = va_arg(args, int);
+ ret = ber_printf(d->mBer, fmt, v);
+ break;
+ }
+ case 'B': {
+ //FIXME: QBitArray vould be logical, but how to access the bits?
+ QByteArray *B = va_arg(args, QByteArray *);
+ int Bc = va_arg(args, int);
+ ret = ber_printf(d->mBer, fmt, B->data(), Bc);
+ break;
+ }
+ case 'o': {
+ QByteArray *o = va_arg(args, QByteArray *);
+ ret = ber_printf(d->mBer, fmt, o->data(), o->size());
+ break;
+ }
+ case 'O': {
+ QByteArray *O = va_arg(args, QByteArray *);
+ struct berval bv;
+ bv.bv_val = (char *) O->data();
+ bv.bv_len = O->size();
+ ret = ber_printf(d->mBer, fmt, &bv);
+ break;
+ }
+ break;
+ case 's': {
+ QByteArray *s = va_arg(args, QByteArray *);
+ ret = ber_printf(d->mBer, fmt, s->data());
+ break;
+ }
+ break;
+ case 't': {
+ unsigned int t = va_arg(args, unsigned int);
+ ret = ber_printf(d->mBer, fmt, t);
+ break;
+ }
+ break;
+ case 'v': {
+ QList<QByteArray> *v = va_arg(args, QList<QByteArray> *);
+ QVarLengthArray<const char *> l(v->count() + 1);
+ int j;
+ for (j = 0; j < v->count(); j++) {
+ l[j] = v->at(j).data();
+ }
+ l[j] = Q_NULLPTR;
+ ret = ber_printf(d->mBer, fmt, l.data());
+ break;
+ }
+ case 'V': {
+ QList<QByteArray> *V = va_arg(args, QList<QByteArray> *);
+ QVarLengthArray<struct berval *> bv(V->count() + 1);
+ QVarLengthArray<struct berval> bvs(V->count());
+ int j;
+ for (j = 0; j < V->count(); j++) {
+ bvs[j].bv_val = (char *) V->at(j).data();
+ bvs[j].bv_len = V->at(j).size();
+ bv[j] = &bvs[j];
+ }
+ bv[V->count()] = Q_NULLPTR;
+ ret = ber_printf(d->mBer, fmt, bv.data());
+ break;
+ }
+ case 'n':
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ ret = ber_printf(d->mBer, fmt);
+ break;
+ default:
+ qCWarning(LDAP_LOG) << "Invalid BER format parameter: '" << fmt << "'";
+ ret = -1;
+ }
+ qCDebug(LDAP_LOG) << "ber_printf format:" << fmt << "ret:" << ret;
+ if (ret == -1) {
+ break;
+ }
+ }
+ va_end(args);
+ return ret;
+}
+
+int Ber::scanf(QString format, ...)
+{
+ char fmt[2];
+ va_list args;
+ va_start(args, format);
+ fmt[1] = '\0';
+
+ int i = 0, ret = 0;
+ while (i < format.length()) {
+ fmt[0] = format[i].toLatin1();
+ i++;
+ switch (fmt[0]) {
+ case 'l':
+ case 'b':
+ case 'e':
+ case 'i': {
+ int *v = va_arg(args, int *);
+ ret = ber_scanf(d->mBer, fmt, v);
+ break;
+ }
+ case 'B': {
+ //FIXME: QBitArray vould be logical, but how to access the bits?
+ QByteArray *B = va_arg(args, QByteArray *);
+ int *Bc = va_arg(args, int *);
+ char *c;
+ ret = ber_scanf(d->mBer, fmt, &c, Bc);
+ if (ret != -1) {
+ *B = QByteArray(c, (*Bc + 7) / 8);
+ ber_memfree(c);
+ }
+ break;
+ }
+ case 'o': {
+ QByteArray *o = va_arg(args, QByteArray *);
+ struct berval bv;
+ ret = ber_scanf(d->mBer, fmt, &bv);
+ if (ret != -1) {
+ *o = QByteArray(bv.bv_val, bv.bv_len);
+ ber_memfree(bv.bv_val);
+ }
+ break;
+ }
+ case 'O': {
+ QByteArray *O = va_arg(args, QByteArray *);
+ struct berval *bv;
+ ret = ber_scanf(d->mBer, fmt, &bv);
+ if (ret != -1) {
+ *O = QByteArray(bv->bv_val, bv->bv_len);
+ ber_bvfree(bv);
+ }
+ break;
+ }
+ break;
+ case 'm': { //the same as 'O', just *bv should not be freed.
+ QByteArray *m = va_arg(args, QByteArray *);
+ struct berval *bv;
+ ret = ber_scanf(d->mBer, fmt, &bv);
+ if (ret != -1) {
+ *m = QByteArray(bv->bv_val, bv->bv_len);
+ }
+ break;
+ }
+ case 'a': {
+ QByteArray *a = va_arg(args, QByteArray *);
+ char *c;
+ ret = ber_scanf(d->mBer, fmt, &c);
+ if (ret != -1) {
+ *a = QByteArray(c);
+ ber_memfree(c);
+ }
+ break;
+ }
+
+ case 's': {
+ QByteArray *s = va_arg(args, QByteArray *);
+ char buf[255];
+ ber_len_t l = sizeof(buf);
+ ret = ber_scanf(d->mBer, fmt, &buf, &l);
+ if (ret != -1) {
+ *s = QByteArray(buf, l);
+ }
+ break;
+ }
+ case 't':
+ case 'T': {
+ unsigned int *t = va_arg(args, unsigned int *);
+ ret = ber_scanf(d->mBer, fmt, t);
+ break;
+ }
+ break;
+ case 'v': {
+ QList<QByteArray> *v = va_arg(args, QList<QByteArray> *);
+ char **c, **c2;
+ ret = ber_scanf(d->mBer, fmt, &c);
+ if (ret != -1 && c) {
+ c2 = c;
+ while (*c) {
+ v->append(QByteArray(*c));
+ ber_memfree(*c);
+ c++;
+ }
+ ber_memfree((char *) c2);
+ }
+ break;
+ }
+ case 'V': {
+ QList<QByteArray> *v = va_arg(args, QList<QByteArray> *);
+ struct berval **bv, **bv2;
+ ret = ber_scanf(d->mBer, fmt, &bv);
+ if (ret != -1 && bv) {
+ bv2 = bv;
+ while (*bv) {
+ v->append(QByteArray((*bv)->bv_val, (*bv)->bv_len));
+ bv++;
+ }
+ ber_bvecfree(bv2);
+ }
+ break;
+ }
+ case 'x':
+ case 'n':
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ ret = ber_scanf(d->mBer, fmt);
+ break;
+ default:
+ qCWarning(LDAP_LOG) << "Invalid BER format parameter: '" << fmt << "'";
+ ret = -1;
+ }
+
+ qCDebug(LDAP_LOG) << "ber_scanf format:" << fmt << "ret:" << ret;
+ if (ret == -1) {
+ break;
+ }
+
+ }
+ va_end(args);
+ return ret;
+}
+
+unsigned int Ber::peekTag(int &size)
+{
+ unsigned int ret;
+ ber_len_t len;
+ ret = ber_peek_tag(d->mBer, &len);
+ size = len;
+ return ret;
+}
+
+unsigned int Ber::skipTag(int &size)
+{
+ unsigned int ret;
+ ber_len_t len;
+ ret = ber_skip_tag(d->mBer, &len);
+ size = len;
+ return ret;
+}
+#else
+
+Ber::Ber()
+ : d(new BerPrivate)
+{
+ qCritical() << "LDAP support not compiled";
+}
+
+Ber::Ber(const QByteArray &)
+ : d(new BerPrivate)
+{
+ qCritical() << "LDAP support not compiled";
+}
+
+Ber::~Ber()
+{
+ delete d;
+}
+
+Ber::Ber(const Ber &)
+ : d(new BerPrivate)
+{
+ qCritical() << "LDAP support not compiled";
+}
+
+Ber &Ber::operator=(const Ber &that)
+{
+ if (this == &that) {
+ return *this;
+ }
+ qCritical() << "LDAP support not compiled";
+ return *this;
+}
+
+QByteArray Ber::flatten() const
+{
+ qCritical() << "LDAP support not compiled";
+ return QByteArray();
+}
+
+int Ber::printf(const QString &format, ...)
+{
+ Q_UNUSED(format);
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int Ber::scanf(const QString &format, ...)
+{
+ Q_UNUSED(format);
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+unsigned int Ber::peekTag(int &size)
+{
+ Q_UNUSED(size);
+ qCritical() << "LDAP support not compiled";
+ return 0;
+}
+
+unsigned int Ber::skipTag(int &size)
+{
+ Q_UNUSED(size);
+ qCritical() << "LDAP support not compiled";
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_BER_H
+#define KLDAP_BER_H
+
+#include <QtCore/QByteArray>
+
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+/**
+ * This class allows encoding and decoding Qt structures using Basic
+ * Encoding Rules.
+ */
+class KLDAP_EXPORT Ber
+{
+public:
+ /**
+ * Constructs a Ber object.
+ */
+ Ber();
+ /**
+ * Constructs a Ber object from the value.
+ */
+ explicit Ber(const QByteArray &value);
+ /**
+ * Destroys the Ber object.
+ */
+ virtual ~Ber();
+
+ Ber(const Ber &that);
+ Ber &operator=(const Ber &that);
+
+ /**
+ * Returns the Ber object as a flat QByteArray.
+ */
+ QByteArray flatten() const;
+
+ /**
+ * Appends the data with the specified format to the Ber object.
+ * This function works like printf, except that it's appending the
+ * parameters, not replacing them. The allowed format characters and
+ * the expected parameter types are:
+ * <ul>
+ * <li>
+ * b Boolean. An int parameter should be supplied.
+ * A boolean element is output.
+ * </li>
+ * <li>
+ * e Enumeration. An int parameter should be supplied.
+ * An enumeration element is output.
+ * </li>
+ * <li>
+ * i Integer. An int parameter should be supplied.
+ * An integer element is output.
+ * </li>
+ * <li>
+ * B Bitstring. A pointer to a QByteArray which contains the
+ * bitstring is supplied, followed by the number of bits in the
+ * bitstring. A bitstring element is output.
+ * </li>
+ * <li>
+ * n Null. No parameter is required. A null element is output.
+ * </li>
+ * <li>
+ * O,o,s Octet string. A QByteArray * is supplied.
+ * An octet string element is output.
+ * Due to versatility of Qt's QByteArray, these three format
+ * strings are all accepts the same parameter, but using the 's'
+ * format the string will be encoded only to the first zero
+ * character (a null terminated string)!
+ * </li>
+ * <li>
+ * t Tag. An int specifying the tag to give the next element
+ * is provided. This works across calls.
+ * </li>
+ * <li>
+ * v,V Several octet strings. A QList<QByteArray>* is supplied.
+ * Note that a construct like ’{v}’ is required to get an actual
+ * SEQUENCE OF octet strings. Also note that the 'v' format recognizes
+ * the QByteArray only to the first zero character, so it's not
+ * appropriate for binary data, just only for null terminated strings!
+ * </li>
+ * <li>
+ * { Begin sequence. No parameter is required.
+ * </li>
+ * <li>
+ * } End sequence. No parameter is required.
+ * </li>
+ * <li>
+ * [ Begin set. No parameter is required.
+ * </li>
+ * <li>
+ * ] End set. No parameter is required.
+ * </li>
+ * </ul>
+ */
+ int printf(QString format, ...); // Passing by-value since it's used by va_start
+ int scanf(QString format, ...);
+ unsigned int peekTag(int &size);
+ unsigned int skipTag(int &size);
+
+private:
+ class BerPrivate;
+ BerPrivate *const d;
+};
+
+}
+#endif
--- /dev/null
+#cmakedefine LDAP_FOUND
+#cmakedefine SASL2_FOUND
+#cmakedefine HAVE_WINLDAP_H
+#cmakedefine HAVE_LDAP_H
+#cmakedefine HAVE_SYS_TIME_H
+#cmakedefine HAVE_LDAP_START_TLS_S
+#cmakedefine HAVE_LDAP_INITIALIZE
+#cmakedefine HAVE_BER_MEMFREE
+#cmakedefine HAVE_LDAP_UNBIND_EXT
+#cmakedefine HAVE_LDAP_EXTENDED_OPERATION
+#cmakedefine HAVE_LDAP_EXTENDED_OPERATION_S
+#cmakedefine HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE
+#cmakedefine HAVE_LDAP_EXTENDED_OPERATION_S_PROTOTYPE
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapattributeproxymodel.h"
+#include "ldapmodel.h"
+#include "ldapmodelnode_p.h"
+
+#include "ldap_debug.h"
+#include <klocalizedstring.h>
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN LdapAttributeProxyModel::LdapAttributeProxyModelPrivate
+{
+public:
+ LdapAttributeProxyModelPrivate();
+
+};
+
+LdapAttributeProxyModel::LdapAttributeProxyModelPrivate::LdapAttributeProxyModelPrivate()
+{
+
+}
+
+LdapAttributeProxyModel::LdapAttributeProxyModel(QObject *parent)
+ : QSortFilterProxyModel(parent),
+ m_d(new LdapAttributeProxyModelPrivate())
+{
+
+}
+
+LdapAttributeProxyModel::~LdapAttributeProxyModel()
+{
+ delete m_d;
+}
+
+QVariant LdapAttributeProxyModel::data(const QModelIndex &index,
+ int role) const
+{
+ // Included just in case we decide to do any special presentation of the data
+ // at some other point throughout the 4.x series.
+ return sourceModel()->data(mapToSource(index), role);
+}
+
+bool LdapAttributeProxyModel::setData(const QModelIndex &index,
+ const QVariant &value,
+ int role)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(value);
+ Q_UNUSED(role);
+ return false;
+}
+
+bool LdapAttributeProxyModel::filterAcceptsRow(int sourceRow,
+ const QModelIndex &sourceParent) const
+{
+ QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent);
+ LdapModelNode::NodeType nodeType =
+ static_cast<LdapModelNode::NodeType>(
+ sourceModel()->data(idx, LdapModel::NodeTypeRole).toUInt());
+ return nodeType == LdapModelNode::Attr;
+}
+
+QVariant LdapAttributeProxyModel::headerData(int section,
+ Qt::Orientation orientation,
+ int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ if (section == 0) {
+ return QVariant(i18n("Attribute"));
+ } else if (section == 1) {
+ return QVariant(i18n("Value"));
+ }
+ }
+
+ return QVariant();
+}
+
+int LdapAttributeProxyModel::columnCount(const QModelIndex &/*parent*/) const
+{
+ return 2;
+}
+
+Qt::ItemFlags LdapAttributeProxyModel::flags(const QModelIndex &index) const
+{
+ // Included so as not to break BC in case we wish to use this later in 4.x
+ return sourceModel()->flags(mapToSource(index));
+}
+
+bool LdapAttributeProxyModel::hasChildren(const QModelIndex &parent) const
+{
+ // We need to handle this carefully bacause of the filtering out of attributes
+ // and the lazy population approach.
+ LdapModel *model = static_cast<LdapModel *>(sourceModel());
+ return model->hasChildrenOfType(mapToSource(parent), LdapModel::Attribute);
+}
+
+QModelIndex LdapAttributeProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ return QSortFilterProxyModel::mapFromSource(sourceIndex);
+}
+
+QModelIndex LdapAttributeProxyModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ return QSortFilterProxyModel::mapToSource(proxyIndex);
+}
+
+bool LdapAttributeProxyModel::insertRows(int row, int count,
+ const QModelIndex &parent)
+{
+ Q_UNUSED(row);
+ Q_UNUSED(count);
+ Q_UNUSED(parent);
+ return false;
+}
+
+bool LdapAttributeProxyModel::removeRows(int row, int count,
+ const QModelIndex &parent)
+{
+ Q_UNUSED(row);
+ Q_UNUSED(count);
+ Q_UNUSED(parent);
+ return false;
+}
+
+void LdapAttributeProxyModel::sort(int column, Qt::SortOrder order)
+{
+ Q_UNUSED(column);
+ Q_UNUSED(order);
+}
+
+Qt::DropActions LdapAttributeProxyModel::supportedDropActions() const
+{
+ return Qt::MoveAction;
+}
+
+QMimeData *LdapAttributeProxyModel::mimeData(const QModelIndexList &indexes) const
+{
+ Q_UNUSED(indexes);
+ return Q_NULLPTR;
+}
+
+bool LdapAttributeProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ /** \todo Implement drag and drop for LdapModel */
+ Q_UNUSED(data);
+ Q_UNUSED(action);
+ Q_UNUSED(row);
+ Q_UNUSED(column);
+ Q_UNUSED(parent);
+ return false;
+}
+
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPATTRIBUTEPROXYMODEL_H
+#define KLDAP_LDAPATTRIBUTEPROXYMODEL_H
+
+#include <QSortFilterProxyModel>
+
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+class KLDAP_EXPORT LdapAttributeProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ explicit LdapAttributeProxyModel(QObject *parent = Q_NULLPTR);
+ ~LdapAttributeProxyModel();
+
+ QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::setData(). This is a placeholder for when
+ * LdapAttributeProxyModel beomes writeable and always returns false.
+ */
+ bool setData(const QModelIndex &index,
+ const QVariant &value,
+ int role = Qt::EditRole) Q_DECL_OVERRIDE;
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
+ int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
+ bool hasChildren(const QModelIndex &parent) const Q_DECL_OVERRIDE;
+
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const Q_DECL_OVERRIDE;
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const Q_DECL_OVERRIDE;
+
+ /**
+ * Reimplemented from QAbstractItemModel::insertRows(). This is a placeholder for when
+ * LdapAttributeProxyModel beomes writeable and always returns false.
+ */
+ virtual bool insertRows(int row, int count,
+ const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::removeRows(). This is a placeholder for when
+ * LdapAttributeProxyModel beomes writeable and always returns false.
+ */
+ virtual bool removeRows(int row, int count,
+ const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::removeRows(). The default implementation
+ * does nothing.
+ */
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) Q_DECL_OVERRIDE;
+
+ //
+ // Drag and drop support
+ //
+ /**
+ * Reimplemented from QAbstractItemModel::supportedDropActions(). The default
+ * implementation returns Qt::MoveAction.
+ */
+ Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::mimedata(). This is a placeholder for when
+ * LdapAttributeProxyModel beomes writeable and always returns 0.
+ */
+ QMimeData *mimeData(const QModelIndexList &indexes) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::dropMimedata(). This is a placeholder for when
+ * LdapAttributeProxyModel beomes writeable and always returns false.
+ */
+ virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) Q_DECL_OVERRIDE;
+
+private:
+ class LdapAttributeProxyModelPrivate;
+ LdapAttributeProxyModelPrivate *const m_d;
+};
+
+}
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapconfigwidget.h"
+#include "ldapsearch.h"
+
+#include <qprogressdialog.h>
+#include <kcombobox.h>
+#include "ldap_debug.h"
+#include <klocalizedstring.h>
+#include <klineedit.h>
+#include <kmessagebox.h>
+
+#include <QtCore/QObject>
+#include <QCheckBox>
+#include <QGroupBox>
+#include <QLabel>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QSpinBox>
+#include <QGridLayout>
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN LdapConfigWidget::Private
+{
+public:
+ Private(LdapConfigWidget *parent)
+ : mParent(parent), mFeatures(W_ALL), mProg(Q_NULLPTR)
+ {
+ mainLayout = new QGridLayout(mParent);
+ mainLayout->setMargin(0);
+ }
+
+ void setLDAPPort();
+ void setLDAPSPort();
+ void setAnonymous(bool on);
+ void setSimple(bool on);
+ void setSASL(bool on);
+ void queryDNClicked();
+ void queryMechClicked();
+ void loadData(LdapSearch *search, const LdapObject &object);
+ void loadResult(LdapSearch *search);
+ void sendQuery();
+ void initWidget();
+
+ LdapConfigWidget *mParent;
+ WinFlags mFeatures;
+ QStringList mQResult;
+ QString mAttr;
+
+ QLineEdit *mUser;
+ QLineEdit *mPassword;
+ QLineEdit *mHost;
+ QSpinBox *mPort, *mVersion, *mSizeLimit, *mTimeLimit, *mPageSize;
+ QLineEdit *mDn, *mBindDn, *mRealm;
+ QLineEdit *mFilter;
+ QRadioButton *mAnonymous, *mSimple, *mSASL;
+ QCheckBox *mSubTree;
+ QPushButton *mEditButton;
+ QPushButton *mQueryMech;
+ QRadioButton *mSecNo, *mSecTLS, *mSecSSL;
+ KComboBox *mMech;
+
+ bool mCancelled;
+ QProgressDialog *mProg;
+
+ QGridLayout *mainLayout;
+};
+
+void LdapConfigWidget::Private::initWidget()
+{
+ QLabel *label;
+
+ mUser = mPassword = mHost = mDn = mBindDn = mRealm = mFilter = Q_NULLPTR;
+ mPort = mVersion = mTimeLimit = mSizeLimit = Q_NULLPTR;
+ mAnonymous = mSimple = mSASL = mSecNo = mSecTLS = mSecSSL = Q_NULLPTR;
+ mEditButton = mQueryMech = Q_NULLPTR;
+ mPageSize = Q_NULLPTR;
+ mMech = Q_NULLPTR;
+ int row = 0;
+ int col;
+
+ if (mFeatures & W_USER) {
+ label = new QLabel(i18n("User:"), mParent);
+ mUser = new QLineEdit(mParent);
+ mUser->setObjectName(QStringLiteral("kcfg_ldapuser"));
+
+ mainLayout->addWidget(label, row, 0);
+ mainLayout->addWidget(mUser, row, 1, 1, 3);
+ row++;
+ }
+
+ if (mFeatures & W_BINDDN) {
+ label = new QLabel(i18n("Bind DN:"), mParent);
+ mBindDn = new QLineEdit(mParent);
+ mBindDn->setObjectName(QStringLiteral("kcfg_ldapbinddn"));
+
+ mainLayout->addWidget(label, row, 0);
+ mainLayout->addWidget(mBindDn, row, 1, 1, 3);
+ row++;
+ }
+
+ if (mFeatures & W_REALM) {
+ label = new QLabel(i18n("Realm:"), mParent);
+ mRealm = new QLineEdit(mParent);
+ mRealm->setObjectName(QStringLiteral("kcfg_ldaprealm"));
+
+ mainLayout->addWidget(label, row, 0);
+ mainLayout->addWidget(mRealm, row, 1, 1, 3);
+ row++;
+ }
+
+ if (mFeatures & W_PASS) {
+ label = new QLabel(i18n("Password:"), mParent);
+ mPassword = new QLineEdit(mParent);
+ mPassword->setObjectName(QStringLiteral("kcfg_ldappassword"));
+ mPassword->setEchoMode(QLineEdit::Password);
+
+ mainLayout->addWidget(label, row, 0);
+ mainLayout->addWidget(mPassword, row, 1, 1, 3);
+ row++;
+ }
+
+ if (mFeatures & W_HOST) {
+ label = new QLabel(i18n("Host:"), mParent);
+ mHost = new QLineEdit(mParent);
+ mHost->setObjectName(QStringLiteral("kcfg_ldaphost"));
+ mParent->connect(mHost, &QLineEdit::textChanged, mParent, &LdapConfigWidget::hostNameChanged);
+ mainLayout->addWidget(label, row, 0);
+ mainLayout->addWidget(mHost, row, 1, 1, 3);
+ row++;
+ }
+
+ col = 0;
+ if (mFeatures & W_PORT) {
+ label = new QLabel(i18n("Port:"), mParent);
+ mPort = new QSpinBox(mParent);
+ mPort->setRange(0, 65535);
+ mPort->setObjectName(QStringLiteral("kcfg_ldapport"));
+ mPort->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
+ mPort->setValue(389);
+
+ mainLayout->addWidget(label, row, col);
+ mainLayout->addWidget(mPort, row, col + 1);
+ col += 2;
+ }
+
+ if (mFeatures & W_VER) {
+ label = new QLabel(i18n("LDAP version:"), mParent);
+ mVersion = new QSpinBox(mParent);
+ mVersion->setRange(2, 3);
+ mVersion->setObjectName(QStringLiteral("kcfg_ldapver"));
+ mVersion->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
+ mVersion->setValue(3);
+ mainLayout->addWidget(label, row, col);
+ mainLayout->addWidget(mVersion, row, col + 1);
+ }
+ if (mFeatures & (W_PORT | W_VER)) {
+ row++;
+ }
+
+ col = 0;
+ if (mFeatures & W_SIZELIMIT) {
+ label = new QLabel(i18n("Size limit:"), mParent);
+ mSizeLimit = new QSpinBox(mParent);
+ mSizeLimit->setRange(0, 9999999);
+ mSizeLimit->setObjectName(QStringLiteral("kcfg_ldapsizelimit"));
+ mSizeLimit->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
+ mSizeLimit->setValue(0);
+ mSizeLimit->setSpecialValueText(i18nc("default ldap size limit", "Default"));
+ mainLayout->addWidget(label, row, col);
+ mainLayout->addWidget(mSizeLimit, row, col + 1);
+ col += 2;
+ }
+
+ if (mFeatures & W_TIMELIMIT) {
+ label = new QLabel(i18n("Time limit:"), mParent);
+ mTimeLimit = new QSpinBox(mParent);
+ mTimeLimit->setRange(0, 9999999);
+ mTimeLimit->setObjectName(QStringLiteral("kcfg_ldaptimelimit"));
+ mTimeLimit->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
+ mTimeLimit->setValue(0);
+ mTimeLimit->setSuffix(i18n(" sec"));
+ mTimeLimit->setSpecialValueText(i18nc("default ldap time limit", "Default"));
+ mainLayout->addWidget(label, row, col);
+ mainLayout->addWidget(mTimeLimit, row, col + 1);
+ }
+ if (mFeatures & (W_SIZELIMIT | W_TIMELIMIT)) {
+ row++;
+ }
+
+ if (mFeatures & W_PAGESIZE) {
+ label = new QLabel(i18n("Page size:"), mParent);
+ mPageSize = new QSpinBox(mParent);
+ mPageSize->setRange(0, 9999999);
+ mPageSize->setObjectName(QStringLiteral("kcfg_ldappagesize"));
+ mPageSize->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
+ mPageSize->setValue(0);
+ mPageSize->setSpecialValueText(i18n("No paging"));
+ mainLayout->addWidget(label, row, 0);
+ mainLayout->addWidget(mPageSize, row++, 1);
+ }
+
+ if (mFeatures & W_DN) {
+ label = new QLabel(i18nc("Distinguished Name", "DN:"), mParent);
+ mDn = new QLineEdit(mParent);
+ mDn->setObjectName(QStringLiteral("kcfg_ldapdn"));
+
+ mainLayout->addWidget(label, row, 0);
+ mainLayout->addWidget(mDn, row, 1, 1, 1);
+ //without host query doesn't make sense
+ if (mHost) {
+ QPushButton *dnquery = new QPushButton(i18n("Query Server"), mParent);
+ connect(dnquery, SIGNAL(clicked()), mParent, SLOT(queryDNClicked()));
+ mainLayout->addWidget(dnquery, row, 2, 1, 1);
+ }
+ row++;
+ }
+
+ if (mFeatures & W_FILTER) {
+ label = new QLabel(i18n("Filter:"), mParent);
+ mFilter = new QLineEdit(mParent);
+ mFilter->setObjectName(QStringLiteral("kcfg_ldapfilter"));
+
+ mainLayout->addWidget(label, row, 0);
+ mainLayout->addWidget(mFilter, row, 1, 1, 3);
+ row++;
+ }
+
+ if (mFeatures & W_SECBOX) {
+ QGroupBox *btgroup = new QGroupBox(i18n("Security"), mParent);
+ QHBoxLayout *hbox = new QHBoxLayout;
+ btgroup->setLayout(hbox);
+ mSecNo = new QRadioButton(i18nc("@option:radio set no security", "No"), btgroup);
+ mSecNo->setObjectName(QStringLiteral("kcfg_ldapnosec"));
+ hbox->addWidget(mSecNo);
+ mSecTLS = new QRadioButton(i18nc("@option:radio use TLS security", "TLS"), btgroup);
+ mSecTLS->setObjectName(QStringLiteral("kcfg_ldaptls"));
+ hbox->addWidget(mSecTLS);
+ mSecSSL = new QRadioButton(i18nc("@option:radio use SSL security", "SSL"), btgroup);
+ mSecSSL->setObjectName(QStringLiteral("kcfg_ldapssl"));
+ hbox->addWidget(mSecSSL);
+ mainLayout->addWidget(btgroup, row, 0, 1, 4);
+
+ connect(mSecNo, SIGNAL(clicked()), mParent, SLOT(setLDAPPort()));
+ connect(mSecTLS, SIGNAL(clicked()), mParent, SLOT(setLDAPPort()));
+ connect(mSecSSL, SIGNAL(clicked()), mParent, SLOT(setLDAPSPort()));
+
+ mSecNo->setChecked(true);
+ row++;
+ }
+
+ if (mFeatures & W_AUTHBOX) {
+
+ QGroupBox *authbox =
+ new QGroupBox(i18n("Authentication"), mParent);
+ QVBoxLayout *vbox = new QVBoxLayout;
+ authbox->setLayout(vbox);
+ QHBoxLayout *hbox = new QHBoxLayout;
+ vbox->addLayout(hbox);
+
+ mAnonymous =
+ new QRadioButton(i18nc("@option:radio anonymous authentication", "Anonymous"), authbox);
+ mAnonymous->setObjectName(QStringLiteral("kcfg_ldapanon"));
+ hbox->addWidget(mAnonymous);
+ mSimple =
+ new QRadioButton(i18nc("@option:radio simple authentication", "Simple"), authbox);
+ mSimple->setObjectName(QStringLiteral("kcfg_ldapsimple"));
+ hbox->addWidget(mSimple);
+ mSASL =
+ new QRadioButton(i18nc("@option:radio SASL authentication", "SASL"), authbox);
+ mSASL->setObjectName(QStringLiteral("kcfg_ldapsasl"));
+ hbox->addWidget(mSASL);
+
+ hbox = new QHBoxLayout;
+ vbox->addLayout(hbox);
+ label = new QLabel(i18n("SASL mechanism:"), authbox);
+ hbox->addWidget(label);
+ mMech = new KComboBox(false, authbox);
+ mMech->setObjectName(QStringLiteral("kcfg_ldapsaslmech"));
+ mMech->setEditable(true);
+ mMech->addItem(QStringLiteral("DIGEST-MD5"));
+ mMech->addItem(QStringLiteral("GSSAPI"));
+ mMech->addItem(QStringLiteral("PLAIN"));
+ hbox->addWidget(mMech);
+
+ //without host query doesn't make sense
+ if (mHost) {
+ mQueryMech = new QPushButton(i18n("Query Server"), authbox);
+ hbox->addWidget(mQueryMech);
+ connect(mQueryMech, SIGNAL(clicked()), mParent, SLOT(queryMechClicked()));
+ }
+
+ mainLayout->addWidget(authbox, row, 0, 2, 4);
+
+ connect(mAnonymous, SIGNAL(toggled(bool)), mParent, SLOT(setAnonymous(bool)));
+ connect(mSimple, SIGNAL(toggled(bool)), mParent, SLOT(setSimple(bool)));
+ connect(mSASL, SIGNAL(toggled(bool)), mParent, SLOT(setSASL(bool)));
+
+ mAnonymous->setChecked(true);
+ }
+}
+
+void LdapConfigWidget::Private::sendQuery()
+{
+ LdapServer _server(mParent->server());
+
+ mQResult.clear();
+ mCancelled = true;
+
+ if (mAttr == QLatin1String("supportedsaslmechanisms")) {
+ _server.setAuth(LdapServer::Anonymous);
+ }
+
+ LdapUrl _url(_server.url());
+
+ _url.setDn(LdapDN(QStringLiteral("")));
+ _url.setAttributes(QStringList(mAttr));
+ _url.setScope(LdapUrl::Base);
+
+ qCDebug(LDAP_LOG) << "sendQuery url:" << _url.toDisplayString();
+
+ LdapSearch search;
+ connect(&search, SIGNAL(data(KLDAP::LdapSearch*,KLDAP::LdapObject)),
+ mParent, SLOT(loadData(KLDAP::LdapSearch*,KLDAP::LdapObject)));
+ connect(&search, SIGNAL(result(KLDAP::LdapSearch*)),
+ mParent, SLOT(loadResult(KLDAP::LdapSearch*)));
+
+ if (!search.search(_url)) {
+ KMessageBox::error(mParent, search.errorString());
+ return;
+ }
+
+ if (mProg == Q_NULLPTR) {
+ mProg = new QProgressDialog(mParent);
+ mProg->setWindowTitle(i18n("LDAP Query"));
+ mProg->setModal(true);
+ }
+ mProg->setLabelText(_url.toDisplayString());
+ mProg->setMaximum(1);
+ mProg->setMinimum(0);
+ mProg->setValue(0);
+ mProg->exec();
+ if (mCancelled) {
+ qCDebug(LDAP_LOG) << "query canceled!";
+ search.abandon();
+ } else {
+ if (search.error()) {
+ if (search.errorString().isEmpty()) {
+ KMessageBox::error(mParent, i18nc("%1 is a url to ldap server", "Unknown error connecting %1", _url.toDisplayString()));
+ } else {
+ KMessageBox::error(mParent, search.errorString());
+ }
+ }
+ }
+}
+
+void LdapConfigWidget::Private::queryMechClicked()
+{
+ mAttr = QStringLiteral("supportedsaslmechanisms");
+ sendQuery();
+ if (!mQResult.isEmpty()) {
+ mQResult.sort();
+ mMech->clear();
+ mMech->addItems(mQResult);
+ }
+}
+
+void LdapConfigWidget::Private::queryDNClicked()
+{
+ mAttr = QStringLiteral("namingcontexts");
+ sendQuery();
+ if (!mQResult.isEmpty()) {
+ mDn->setText(mQResult.first());
+ }
+}
+
+void LdapConfigWidget::Private::loadData(LdapSearch *, const LdapObject &object)
+{
+ qCDebug(LDAP_LOG) << "object:" << object.toString();
+ mProg->setValue(mProg->value() + 1);
+ LdapAttrMap::ConstIterator end(object.attributes().constEnd());
+ for (LdapAttrMap::ConstIterator it = object.attributes().constBegin();
+ it != end; ++it) {
+ LdapAttrValue::ConstIterator end2((*it).constEnd());
+ for (LdapAttrValue::ConstIterator it2 = (*it).constBegin();
+ it2 != end2; ++it2) {
+ mQResult.push_back(QString::fromUtf8(*it2));
+ }
+ }
+}
+
+void LdapConfigWidget::Private::loadResult(LdapSearch *search)
+{
+ Q_UNUSED(search);
+ mCancelled = false;
+ mProg->close();
+}
+
+void LdapConfigWidget::Private::setAnonymous(bool on)
+{
+ if (!on) {
+ return;
+ }
+ if (mUser) {
+ mUser->setEnabled(false);
+ }
+ if (mPassword) {
+ mPassword->setEnabled(false);
+ }
+ if (mBindDn) {
+ mBindDn->setEnabled(false);
+ }
+ if (mRealm) {
+ mRealm->setEnabled(false);
+ }
+ if (mMech) {
+ mMech->setEnabled(false);
+ }
+ if (mQueryMech) {
+ mQueryMech->setEnabled(false);
+ }
+}
+
+void LdapConfigWidget::Private::setSimple(bool on)
+{
+ if (!on) {
+ return;
+ }
+ if (mUser) {
+ mUser->setEnabled(false);
+ }
+ if (mPassword) {
+ mPassword->setEnabled(true);
+ }
+ if (mBindDn) {
+ mBindDn->setEnabled(true);
+ }
+ if (mRealm) {
+ mRealm->setEnabled(false);
+ }
+ if (mMech) {
+ mMech->setEnabled(false);
+ }
+ if (mQueryMech) {
+ mQueryMech->setEnabled(false);
+ }
+}
+
+void LdapConfigWidget::Private::setSASL(bool on)
+{
+ if (!on) {
+ return;
+ }
+ if (mUser) {
+ mUser->setEnabled(true);
+ }
+ if (mPassword) {
+ mPassword->setEnabled(true);
+ }
+ if (mBindDn) {
+ mBindDn->setEnabled(true);
+ }
+ if (mRealm) {
+ mRealm->setEnabled(true);
+ }
+ if (mMech) {
+ mMech->setEnabled(true);
+ }
+ if (mQueryMech) {
+ mQueryMech->setEnabled(true);
+ }
+}
+
+void LdapConfigWidget::Private::setLDAPPort()
+{
+ if (mPort) {
+ mPort->setValue(389);
+ }
+}
+
+void LdapConfigWidget::Private::setLDAPSPort()
+{
+ if (mPort) {
+ mPort->setValue(636);
+ }
+}
+
+LdapConfigWidget::LdapConfigWidget(QWidget *parent, Qt::WindowFlags fl)
+ : QWidget(parent, fl), d(new Private(this))
+{
+}
+
+LdapConfigWidget::LdapConfigWidget(LdapConfigWidget::WinFlags flags,
+ QWidget *parent, Qt::WindowFlags fl)
+ : QWidget(parent, fl), d(new Private(this))
+{
+ d->mFeatures = flags;
+
+ d->initWidget();
+}
+
+LdapConfigWidget::~LdapConfigWidget()
+{
+ delete d;
+}
+
+LdapUrl LdapConfigWidget::url() const
+{
+ return server().url();
+}
+
+void LdapConfigWidget::setUrl(const LdapUrl &url)
+{
+ LdapServer _server;
+ _server.setUrl(url);
+ setServer(_server);
+}
+
+LdapServer LdapConfigWidget::server() const
+{
+ LdapServer _server;
+ if (d->mSecSSL && d->mSecSSL->isChecked()) {
+ _server.setSecurity(LdapServer::SSL);
+ } else if (d->mSecTLS && d->mSecTLS->isChecked()) {
+ _server.setSecurity(LdapServer::TLS);
+ } else {
+ _server.setSecurity(LdapServer::None);
+ }
+
+ if (d->mUser) {
+ _server.setUser(d->mUser->text());
+ }
+ if (d->mBindDn) {
+ _server.setBindDn(d->mBindDn->text());
+ }
+ if (d->mPassword) {
+ _server.setPassword(d->mPassword->text());
+ }
+ if (d->mRealm) {
+ _server.setRealm(d->mRealm->text());
+ }
+ if (d->mHost) {
+ _server.setHost(d->mHost->text());
+ }
+ if (d->mPort) {
+ _server.setPort(d->mPort->value());
+ }
+ if (d->mDn) {
+ _server.setBaseDn(LdapDN(d->mDn->text()));
+ }
+ if (d->mFilter) {
+ _server.setFilter(d->mFilter->text());
+ }
+ if (d->mVersion) {
+ _server.setVersion(d->mVersion->value());
+ }
+ if (d->mSizeLimit && d->mSizeLimit->value() != 0) {
+ _server.setSizeLimit(d->mSizeLimit->value());
+ }
+ if (d->mTimeLimit && d->mTimeLimit->value() != 0) {
+ _server.setTimeLimit(d->mTimeLimit->value());
+ }
+ if (d->mPageSize && d->mPageSize->value() != 0) {
+ _server.setPageSize(d->mPageSize->value());
+ }
+ if (d->mAnonymous && d->mAnonymous->isChecked()) {
+ _server.setAuth(LdapServer::Anonymous);
+ } else if (d->mSimple && d->mSimple->isChecked()) {
+ _server.setAuth(LdapServer::Simple);
+ } else if (d->mSASL && d->mSASL->isChecked()) {
+ _server.setAuth(LdapServer::SASL);
+ _server.setMech(d->mMech->currentText());
+ }
+ return _server;
+}
+
+void LdapConfigWidget::setServer(const LdapServer &server)
+{
+ switch (server.security()) {
+ case LdapServer::SSL:
+ if (d->mSecSSL) {
+ d->mSecSSL->setChecked(true);
+ }
+ break;
+ case LdapServer::TLS:
+ if (d->mSecTLS) {
+ d->mSecTLS->setChecked(true);
+ }
+ break;
+ case LdapServer::None:
+ if (d->mSecNo) {
+ d->mSecNo->setChecked(true);
+ }
+ break;
+ }
+
+ switch (server.auth()) {
+ case LdapServer::Anonymous:
+ if (d->mAnonymous) {
+ d->mAnonymous->setChecked(true);
+ }
+ break;
+ case LdapServer::Simple:
+ if (d->mSimple) {
+ d->mSimple->setChecked(true);
+ }
+ break;
+ case LdapServer::SASL:
+ if (d->mSASL) {
+ d->mSASL->setChecked(true);
+ }
+ break;
+ }
+
+ setUser(server.user());
+ setBindDn(server.bindDn());
+ setPassword(server.password());
+ setRealm(server.realm());
+ setHost(server.host());
+ setPort(server.port());
+ setFilter(server.filter());
+ setDn(server.baseDn());
+ setVersion(server.version());
+ setSizeLimit(server.sizeLimit());
+ setTimeLimit(server.timeLimit());
+ setPageSize(server.pageSize());
+ setMech(server.mech());
+}
+
+void LdapConfigWidget::setUser(const QString &user)
+{
+ if (d->mUser) {
+ d->mUser->setText(user);
+ }
+}
+
+QString LdapConfigWidget::user() const
+{
+ return d->mUser ? d->mUser->text() : QString();
+}
+
+void LdapConfigWidget::setPassword(const QString &password)
+{
+ if (d->mPassword) {
+ d->mPassword->setText(password);
+ }
+}
+
+QString LdapConfigWidget::password() const
+{
+ return d->mPassword ? d->mPassword->text() : QString();
+}
+
+void LdapConfigWidget::setBindDn(const QString &binddn)
+{
+ if (d->mBindDn) {
+ d->mBindDn->setText(binddn);
+ }
+}
+
+QString LdapConfigWidget::bindDn() const
+{
+ return d->mBindDn ? d->mBindDn->text() : QString();
+}
+
+void LdapConfigWidget::setRealm(const QString &realm)
+{
+ if (d->mRealm) {
+ d->mRealm->setText(realm);
+ }
+}
+
+QString LdapConfigWidget::realm() const
+{
+ return d->mRealm ? d->mRealm->text() : QString();
+}
+
+void LdapConfigWidget::setHost(const QString &host)
+{
+ if (d->mHost) {
+ d->mHost->setText(host);
+ }
+}
+
+QString LdapConfigWidget::host() const
+{
+ return d->mHost ? d->mHost->text() : QString();
+}
+
+void LdapConfigWidget::setPort(int port)
+{
+ if (d->mPort) {
+ d->mPort->setValue(port);
+ }
+}
+
+int LdapConfigWidget::port() const
+{
+ return d->mPort ? d->mPort->value() : 389;
+}
+
+void LdapConfigWidget::setVersion(int version)
+{
+ if (d->mVersion) {
+ d->mVersion->setValue(version);
+ }
+}
+
+int LdapConfigWidget::version() const
+{
+ return d->mVersion ? d->mVersion->value() : 3;
+}
+
+void LdapConfigWidget::setDn(const LdapDN &dn)
+{
+ if (d->mDn) {
+ d->mDn->setText(dn.toString());
+ }
+}
+
+LdapDN LdapConfigWidget::dn() const
+{
+ return d->mDn ? LdapDN(d->mDn->text()) : LdapDN();
+}
+
+void LdapConfigWidget::setFilter(const QString &filter)
+{
+ if (d->mFilter) {
+ d->mFilter->setText(filter);
+ }
+}
+
+QString LdapConfigWidget::filter() const
+{
+ return d->mFilter ? d->mFilter->text() : QString();
+}
+
+void LdapConfigWidget::setMech(const QString &mech)
+{
+ if (d->mMech == Q_NULLPTR) {
+ return;
+ }
+ if (!mech.isEmpty()) {
+ int i = 0;
+ while (i < d->mMech->count()) {
+ if (d->mMech->itemText(i) == mech) {
+ break;
+ }
+ i++;
+ }
+ if (i == d->mMech->count()) {
+ d->mMech->addItem(mech);
+ }
+ d->mMech->setCurrentIndex(i);
+ }
+}
+
+QString LdapConfigWidget::mech() const
+{
+ return d->mMech ? d->mMech->currentText() : QString();
+}
+
+void LdapConfigWidget::setSecurity(Security security)
+{
+ switch (security) {
+ case None:
+ d->mSecNo->setChecked(true);
+ break;
+ case SSL:
+ d->mSecSSL->setChecked(true);
+ break;
+ case TLS:
+ d->mSecTLS->setChecked(true);
+ break;
+ }
+}
+
+LdapConfigWidget::Security LdapConfigWidget::security() const
+{
+ if (d->mSecTLS->isChecked()) {
+ return TLS;
+ }
+ if (d->mSecSSL->isChecked()) {
+ return SSL;
+ }
+ return None;
+}
+
+void LdapConfigWidget::setAuth(Auth auth)
+{
+ switch (auth) {
+ case Anonymous:
+ d->mAnonymous->setChecked(true);
+ break;
+ case Simple:
+ d->mSimple->setChecked(true);
+ break;
+ case SASL:
+ d->mSASL->setChecked(true);
+ break;
+ }
+}
+
+LdapConfigWidget::Auth LdapConfigWidget::auth() const
+{
+ if (d->mSimple->isChecked()) {
+ return Simple;
+ }
+ if (d->mSASL->isChecked()) {
+ return SASL;
+ }
+ return Anonymous;
+}
+
+void LdapConfigWidget::setSizeLimit(int sizelimit)
+{
+ if (d->mSizeLimit) {
+ d->mSizeLimit->setValue(sizelimit);
+ }
+}
+
+int LdapConfigWidget::sizeLimit() const
+{
+ return d->mSizeLimit ? d->mSizeLimit->value() : 0;
+}
+
+void LdapConfigWidget::setTimeLimit(int timelimit)
+{
+ if (d->mTimeLimit) {
+ d->mTimeLimit->setValue(timelimit);
+ }
+}
+
+int LdapConfigWidget::timeLimit() const
+{
+ return d->mTimeLimit ? d->mTimeLimit->value() : 0;
+}
+
+void LdapConfigWidget::setPageSize(int pagesize)
+{
+ if (d->mPageSize) {
+ d->mPageSize->setValue(pagesize);
+ }
+}
+
+int LdapConfigWidget::pageSize() const
+{
+ return d->mPageSize ? d->mPageSize->value() : 0;
+}
+
+LdapConfigWidget::WinFlags LdapConfigWidget::features() const
+{
+ return d->mFeatures;
+}
+
+void LdapConfigWidget::setFeatures(LdapConfigWidget::WinFlags features)
+{
+ d->mFeatures = features;
+
+ // First delete all the child widgets.
+ // FIXME: I hope it's correct
+ QList<QObject *> ch = children();
+ const int numberOfChild(ch.count());
+ for (int i = 0; i < numberOfChild; ++i) {
+ QWidget *widget = dynamic_cast<QWidget *>(ch[ i ]);
+ if (widget && widget->parent() == this) {
+ delete(widget);
+ }
+ }
+
+ // Re-create child widgets according to the new flags
+ d->initWidget();
+}
+
+#include "moc_ldapconfigwidget.cpp"
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPCONFIGWIDGET_H
+#define KLDAP_LDAPCONFIGWIDGET_H
+
+#include <QtCore/QString>
+#include <QWidget>
+
+#include "ldapdn.h"
+#include "kldap_export.h"
+#include "ldapobject.h"
+#include "ldapserver.h"
+#include "ldapurl.h"
+
+namespace KLDAP
+{
+
+class LdapSearch;
+
+/**
+ @brief LDAP Configuration widget
+
+ This class can be used to query the user for LDAP connection parameters.
+ It's KConfigXT compatible, using widget names starting with kcfg_
+*/
+
+class KLDAP_EXPORT LdapConfigWidget : public QWidget
+{
+ Q_OBJECT
+ Q_FLAGS(WinFlags)
+ Q_ENUMS(Security)
+ Q_ENUMS(Auth)
+ Q_PROPERTY(WinFlags features READ features WRITE setFeatures)
+ Q_PROPERTY(QString user READ user WRITE setUser)
+ Q_PROPERTY(QString bindDn READ bindDn WRITE setBindDn)
+ Q_PROPERTY(QString realm READ realm WRITE setRealm)
+ Q_PROPERTY(QString password READ password WRITE setPassword)
+ Q_PROPERTY(QString host READ host WRITE setHost)
+ Q_PROPERTY(int port READ port WRITE setPort)
+ Q_PROPERTY(int version READ version WRITE setVersion)
+ Q_PROPERTY(LdapDN dn READ dn WRITE setDn)
+ Q_PROPERTY(QString filter READ filter WRITE setFilter)
+ Q_PROPERTY(QString mech READ mech WRITE setMech)
+ Q_PROPERTY(Security security READ security WRITE setSecurity)
+ Q_PROPERTY(Auth auth READ auth WRITE setAuth)
+ Q_PROPERTY(int sizeLimit READ sizeLimit WRITE setSizeLimit)
+ Q_PROPERTY(int timeLimit READ timeLimit WRITE setTimeLimit)
+ Q_PROPERTY(int pageSize READ pageSize WRITE setPageSize)
+
+public:
+
+ enum WinFlag {
+ W_USER = 0x1,
+ W_BINDDN = 0x2,
+ W_REALM = 0x4,
+ W_PASS = 0x8,
+ W_HOST = 0x10,
+ W_PORT = 0x20,
+ W_VER = 0x40,
+ W_DN = 0x80,
+ W_FILTER = 0x100,
+ W_SECBOX = 0x200,
+ W_AUTHBOX = 0x400,
+ W_TIMELIMIT = 0x800,
+ W_SIZELIMIT = 0x1000,
+ W_PAGESIZE = 0x2000,
+ W_ALL = 0x2fff
+ };
+
+ typedef enum {
+ None, SSL, TLS
+ } Security;
+ typedef enum {
+ Anonymous, Simple, SASL
+ } Auth;
+
+ Q_DECLARE_FLAGS(WinFlags, WinFlag)
+
+ /** Constructs an empty configuration widget.
+ * You need to call setFlags() after this.
+ * @param parent the QWidget parent
+ * @param fl the window flags to set
+ */
+ explicit LdapConfigWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags fl = 0);
+ /** Constructs a configuration widget */
+ explicit LdapConfigWidget(WinFlags flags, QWidget *parent = Q_NULLPTR,
+ Qt::WindowFlags fl = 0);
+ /** Destructs a configuration widget */
+ virtual ~LdapConfigWidget();
+
+ /** Sets the user name. Kconfig widget name: kcfg_ldapuser
+ * @param user the user name to set
+ */
+ void setUser(const QString &user);
+ /** Gets the user name. Kconfig widget name: kcfg_ldapuser */
+ QString user() const;
+
+ /** Sets the password. Kconfig widget name: kcfg_ldappassword
+ * @param password the password to set
+ */
+ void setPassword(const QString &password);
+ /** Gets the password. Kconfig widget name: kcfg_ldappassword */
+ QString password() const;
+
+ /**
+ * Sets the bind dn.
+ * Kconfig widget name: kcfg_ldapbinddn
+ * @param binddn the LDAP Bind DN to set
+ */
+ void setBindDn(const QString &binddn);
+ /** Gets the bind dn. Kconfig widget name: kcfg_ldapbinddn*/
+ QString bindDn() const;
+
+ /** Sets the SASL realm. Kconfig widget name: kcfg_ldaprealm
+ * @param realm the SASL realm to set
+ */
+ void setRealm(const QString &realm);
+ /** Gets the SASL realm. Kconfig widget name: kcfg_ldaprealm */
+ QString realm() const;
+
+ /** Sets the host name. Kconfig widget name: kcfg_ldaphost
+ * @param host the LDAP host to set
+ */
+ void setHost(const QString &host);
+ /** Gets the host name. Kconfig widget name: kcfg_ldaphost */
+ QString host() const;
+
+ /** Sets the LDAP port. Kconfig widget name: kcfg_ldapport
+ * @param port the LDAP port to set
+ */
+ void setPort(int port);
+ /** Gets the LDAP port. Kconfig widget name: kcfg_ldapport */
+ int port() const;
+
+ /** Sets the LDAP protocol version. Kconfig widget name: kcfg_ldapver
+ * @param version the LDAP protocol version to set
+ */
+ void setVersion(int version);
+ /** Gets the LDAP protocol version. Kconfig widget name: kcfg_ldapver */
+ int version() const;
+
+ /** Sets the LDAP Base DN. Kconfig widget name: kcfg_ldapdn
+ * @param dn the LDAP Base DN to set
+ */
+ void setDn(const LdapDN &dn);
+ /** Gets the LDAP Base DN. Kconfig widget name: kcfg_ldapdn */
+ LdapDN dn() const;
+
+ /** Sets the LDAP Filter. Kconfig widget name: kcfg_ldapfilter
+ * @param filter the LDAP Filter to set
+ */
+ void setFilter(const QString &filter);
+ /** Gets the LDAP Filter. Kconfig widget name: kcfg_ldapfilter */
+ QString filter() const;
+
+ /** Sets the SASL Mechanism. Kconfig widget name: kcfg_ldapsaslmech
+ * @param mech the SASL Mechanism to set
+ */
+ void setMech(const QString &mech);
+ /** Gets the SASL Mechanism. Kconfig widget name: kcfg_ldapsaslmech */
+ QString mech() const;
+
+ /**
+ * Sets the security type (None, SSL, TLS).
+ * Kconfig widget names: kcfg_ldapnosec, kcfg_ldaptls, kcfg_ldapssl
+ * @param security the security type to set
+ */
+ void setSecurity(Security security);
+ /**
+ * Returns the security type.
+ * Kconfig widget names: kcfg_ldapnosec, kcfg_ldaptls, kcfg_ldapssl
+ * @param security the security type to set
+ */
+ Security security() const;
+
+ /**
+ * Sets the authentication type (Anonymous, Simple, SASL).
+ * Kconfig widget names: kcfg_ldapanon, kcfg_ldapsimple, kcfg_ldapsasl
+ * @param auth the authentication type to set
+ */
+ void setAuth(Auth auth);
+ /**
+ * Returns the authentication type.
+ * Kconfig widget names: kcfg_ldapanon, kcfg_ldapsimple, kcfg_ldapsasl
+ * @param auth the authentication type to set
+ */
+ Auth auth() const;
+
+ /**
+ * Sets the size limit.
+ * KConfig widget name: kcfg_ldapsizelimit
+ * @param sizelimit the size limit to set
+ */
+ void setSizeLimit(int sizelimit);
+ /**
+ * Returns the size limit.
+ * KConfig widget name: kcfg_ldapsizelimit
+ */
+ int sizeLimit() const;
+
+ /**
+ * Sets the time limit.
+ * KConfig widget name: kcfg_ldaptimelimit
+ * @param timelimit the time limit to set
+ */
+ void setTimeLimit(int timelimit);
+ /**
+ * Returns the time limit.
+ * KConfig widget name: kcfg_ldaptimelimit
+ */
+ int timeLimit() const;
+
+ /**
+ * Sets the page size.
+ * KConfig widget name: kcfg_ldappagesize
+ * @param pagesize the page size to set
+ */
+ void setPageSize(int pagesize);
+ /**
+ * Returns the page size.
+ * KConfig widget name: kcfg_ldappagesize
+ */
+ int pageSize() const;
+
+ WinFlags features() const;
+ void setFeatures(WinFlags features);
+
+ /**
+ * Returns a LDAP Url constructed from the settings given.
+ * Extensions are filled for use in the LDAP ioslave
+ */
+ LdapUrl url() const;
+ /**
+ * Set up the widget via an LDAP Url.
+ * @param url the LDAP Url to set
+ */
+ void setUrl(const LdapUrl &url);
+
+ /**
+ * Returns an LdapServer object constructed from the settings given.
+ */
+ LdapServer server() const;
+ /**
+ * Set up the widget via an LdapServer object.
+ * @param server the LdapServer object to set
+ */
+ void setServer(const LdapServer &server);
+
+Q_SIGNALS:
+ /**
+ * @since 4.13
+ */
+ void hostNameChanged(const QString &);
+
+private:
+ class Private;
+ Private *const d;
+
+ Q_PRIVATE_SLOT(d, void setLDAPPort())
+ Q_PRIVATE_SLOT(d, void setLDAPSPort())
+ Q_PRIVATE_SLOT(d, void setAnonymous(bool))
+ Q_PRIVATE_SLOT(d, void setSimple(bool))
+ Q_PRIVATE_SLOT(d, void setSASL(bool))
+ Q_PRIVATE_SLOT(d, void queryDNClicked())
+ Q_PRIVATE_SLOT(d, void queryMechClicked())
+ Q_PRIVATE_SLOT(d, void loadData(KLDAP::LdapSearch *, const KLDAP::LdapObject &))
+ Q_PRIVATE_SLOT(d, void loadResult(KLDAP::LdapSearch *))
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(LdapConfigWidget::WinFlags)
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapconnection.h"
+#include "ldapdefs.h"
+#include "kldap_config.h" // SASL2_FOUND, LDAP_FOUND
+
+#include <stdlib.h>
+#include <klocalizedstring.h>
+#include "ldap_debug.h"
+
+#ifdef SASL2_FOUND
+#include <sasl/sasl.h>
+static const sasl_callback_t callbacks[] = {
+ { SASL_CB_ECHOPROMPT, Q_NULLPTR, Q_NULLPTR },
+ { SASL_CB_NOECHOPROMPT, Q_NULLPTR, Q_NULLPTR },
+ { SASL_CB_GETREALM, Q_NULLPTR, Q_NULLPTR },
+ { SASL_CB_USER, Q_NULLPTR, Q_NULLPTR },
+ { SASL_CB_AUTHNAME, Q_NULLPTR, Q_NULLPTR },
+ { SASL_CB_PASS, Q_NULLPTR, Q_NULLPTR },
+ { SASL_CB_CANON_USER, Q_NULLPTR, Q_NULLPTR },
+ { SASL_CB_LIST_END, Q_NULLPTR, Q_NULLPTR }
+};
+
+static bool ldapoperation_sasl_initialized = false;
+#endif
+
+#ifdef LDAP_FOUND
+# ifndef HAVE_WINLDAP_H
+# include <lber.h>
+# include <ldap.h>
+#else
+# include <w32-ldap-help.h>
+#endif // HAVE_WINLDAP_H
+
+#ifndef LDAP_OPT_SUCCESS
+#define LDAP_OPT_SUCCESS 0
+#endif
+
+#endif
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN LdapConnection::LdapConnectionPrivate
+{
+public:
+ LdapConnectionPrivate();
+ LdapServer mServer;
+ QString mConnectionError;
+
+#ifdef LDAP_FOUND
+ LDAP *mLDAP;
+#else
+ void *mLDAP;
+#endif
+#ifdef SASL2_FOUND
+ sasl_conn_t *mSASLconn;
+#else
+ void *mSASLconn;
+#endif
+
+};
+
+LdapConnection::LdapConnectionPrivate::LdapConnectionPrivate()
+{
+ mSASLconn = Q_NULLPTR;
+#ifdef SASL2_FOUND
+ if (!ldapoperation_sasl_initialized) {
+ sasl_client_init(Q_NULLPTR);
+ ldapoperation_sasl_initialized = true;
+ }
+#endif
+}
+
+LdapConnection::LdapConnection()
+ : d(new LdapConnectionPrivate)
+{
+ d->mLDAP = Q_NULLPTR;
+}
+
+LdapConnection::LdapConnection(const LdapUrl &url)
+ : d(new LdapConnectionPrivate)
+{
+ d->mLDAP = Q_NULLPTR;
+ setUrl(url);
+}
+
+LdapConnection::LdapConnection(const LdapServer &server)
+ : d(new LdapConnectionPrivate)
+{
+ d->mLDAP = Q_NULLPTR;
+ setServer(server);
+}
+
+LdapConnection::~LdapConnection()
+{
+ close();
+ delete d;
+}
+
+void LdapConnection::setUrl(const LdapUrl &url)
+{
+ d->mServer.setUrl(url);
+}
+
+void LdapConnection::setServer(const LdapServer &server)
+{
+ d->mServer = server;
+}
+
+const LdapServer &LdapConnection::server() const
+{
+ return d->mServer;
+}
+
+void *LdapConnection::handle() const
+{
+ return (void *)d->mLDAP;
+}
+
+void *LdapConnection::saslHandle() const
+{
+ return (void *)d->mSASLconn;
+}
+
+QString LdapConnection::errorString(int code)
+{
+ //No translated error messages yet
+#ifdef LDAP_FOUND
+ return QString::fromUtf8(ldap_err2string(code));
+#else
+ return i18n("No LDAP Support...");
+#endif
+}
+
+QString LdapConnection::saslErrorString() const
+{
+#ifdef SASL2_FOUND
+ const char *str;
+ str = sasl_errdetail(d->mSASLconn);
+ return QString::fromLocal8Bit(str);
+#else
+ return i18n("SASL support is not available. Please recompile libkldap with the "
+ "Cyrus-SASL (or compatible) client libraries, or complain to your "
+ "distribution packagers.");
+#endif
+}
+
+QString LdapConnection::connectionError() const
+{
+ return d->mConnectionError;
+}
+
+#ifdef LDAP_FOUND
+int LdapConnection::getOption(int option, void *value) const
+{
+ Q_ASSERT(d->mLDAP);
+ return ldap_get_option(d->mLDAP, option, value);
+}
+
+int LdapConnection::setOption(int option, void *value)
+{
+ Q_ASSERT(d->mLDAP);
+ return ldap_set_option(d->mLDAP, option, value);
+}
+
+int LdapConnection::ldapErrorCode() const
+{
+ Q_ASSERT(d->mLDAP);
+ int err;
+ ldap_get_option(d->mLDAP, LDAP_OPT_ERROR_NUMBER, &err);
+ return err;
+}
+
+QString LdapConnection::ldapErrorString() const
+{
+ Q_ASSERT(d->mLDAP);
+ char *errmsg;
+ ldap_get_option(d->mLDAP, LDAP_OPT_ERROR_STRING, &errmsg);
+ QString msg = QString::fromLocal8Bit(errmsg);
+ free(errmsg);
+ return msg;
+}
+
+bool LdapConnection::setSizeLimit(int sizelimit)
+{
+ Q_ASSERT(d->mLDAP);
+ qCDebug(LDAP_LOG) << "sizelimit:" << sizelimit;
+ if (setOption(LDAP_OPT_SIZELIMIT, &sizelimit) != LDAP_OPT_SUCCESS) {
+ return false;
+ }
+ return true;
+}
+
+int LdapConnection::sizeLimit() const
+{
+ Q_ASSERT(d->mLDAP);
+ int sizelimit;
+ if (getOption(LDAP_OPT_SIZELIMIT, &sizelimit) != LDAP_OPT_SUCCESS) {
+ return -1;
+ }
+ return sizelimit;
+}
+
+bool LdapConnection::setTimeLimit(int timelimit)
+{
+ Q_ASSERT(d->mLDAP);
+ qCDebug(LDAP_LOG) << "timelimit:" << timelimit;
+ if (setOption(LDAP_OPT_TIMELIMIT, &timelimit) != LDAP_OPT_SUCCESS) {
+ return false;
+ }
+ return true;
+}
+
+int LdapConnection::timeLimit() const
+{
+ Q_ASSERT(d->mLDAP);
+ int timelimit;
+ if (getOption(LDAP_OPT_TIMELIMIT, &timelimit) != LDAP_OPT_SUCCESS) {
+ return -1;
+ }
+ return timelimit;
+}
+
+int LdapConnection::connect()
+{
+ int ret;
+ QString url;
+ if (d->mLDAP) {
+ close();
+ }
+
+ int version = d->mServer.version();
+ int timeout = d->mServer.timeout();
+
+ url = d->mServer.security() == LdapServer::SSL ? QStringLiteral("ldaps") : QStringLiteral("ldap");
+ url += QLatin1String("://");
+ url += d->mServer.host();
+ url += QLatin1Char(':');
+ url += QString::number(d->mServer.port());
+ qCDebug(LDAP_LOG) << "ldap url:" << url;
+#ifdef HAVE_LDAP_INITIALIZE
+ ret = ldap_initialize(&d->mLDAP, url.toLatin1().constData());
+#else
+ d->mLDAP = ldap_init(d->mServer.host().toLatin1().data(), d->mServer.port());
+ if (d->mLDAP == 0) {
+ ret = -1;
+ } else {
+ ret = LDAP_SUCCESS;
+ }
+#endif
+ if (ret != LDAP_SUCCESS) {
+ d->mConnectionError = i18n("An error occurred during the connection initialization phase.");
+ return ret;
+ }
+
+ qCDebug(LDAP_LOG) << "setting version to:" << version;
+ if (setOption(LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
+ ret = ldapErrorCode();
+ d->mConnectionError = i18n("Cannot set protocol version to %1.", version);
+ close();
+ return ret;
+ }
+
+#if defined(LDAP_OPT_TIMEOUT)
+ qCDebug(LDAP_LOG) << "setting timeout to:" << timeout;
+
+ if (timeout) {
+ if (setOption(LDAP_OPT_TIMEOUT, &timeout) != LDAP_OPT_SUCCESS) {
+ ret = ldapErrorCode();
+ d->mConnectionError = i18np("Cannot set timeout to %1 second.",
+ "Cannot set timeout to %1 seconds.",
+ timeout);
+ close();
+ return ret;
+ }
+ }
+#endif
+
+ //FIXME: accessing to certificate handling would be good
+ qCDebug(LDAP_LOG) << "setting security to:" << d->mServer.security();
+ if (d->mServer.security() == LdapServer::TLS) {
+ qCDebug(LDAP_LOG) << "start TLS";
+#ifdef HAVE_LDAP_START_TLS_S
+ if ((ret = ldap_start_tls_s(d->mLDAP, Q_NULLPTR, Q_NULLPTR)) != LDAP_SUCCESS) {
+ d->mConnectionError = ldapErrorString();
+ close();
+ return ret;
+ }
+#else
+ close();
+ d->mConnectionError = i18n("TLS support not available in the LDAP client libraries.");
+ return -1;
+#endif
+ }
+
+ qCDebug(LDAP_LOG) << "setting sizelimit to:" << d->mServer.sizeLimit();
+ if (d->mServer.sizeLimit()) {
+ if (!setSizeLimit(d->mServer.sizeLimit())) {
+ ret = ldapErrorCode();
+ close();
+ d->mConnectionError = i18n("Cannot set size limit.");
+ return ret;
+ }
+ }
+
+ qCDebug(LDAP_LOG) << "setting timelimit to:" << d->mServer.timeLimit();
+ if (d->mServer.timeLimit()) {
+ if (!setTimeLimit(d->mServer.timeLimit())) {
+ ret = ldapErrorCode();
+ close();
+ d->mConnectionError = i18n("Cannot set time limit.");
+ return ret;
+ }
+ }
+
+#ifdef SASL2_FOUND
+ qCDebug(LDAP_LOG) << "initializing SASL client";
+ int saslresult = sasl_client_new("ldap", d->mServer.host().toLatin1(),
+ Q_NULLPTR, Q_NULLPTR, callbacks, 0, &d->mSASLconn);
+ if (saslresult != SASL_OK) {
+ d->mConnectionError = i18n("Cannot initialize the SASL client.");
+ return KLDAP_SASL_ERROR;
+ }
+#endif
+
+ return 0;
+}
+
+void LdapConnection::close()
+{
+ if (d->mLDAP) {
+#ifdef HAVE_LDAP_UNBIND_EXT
+ ldap_unbind_ext(d->mLDAP, Q_NULLPTR, Q_NULLPTR);
+#else
+ ldap_unbind(d->mLDAP);
+#endif
+ }
+ d->mLDAP = Q_NULLPTR;
+#ifdef SASL2_FOUND
+ if (d->mSASLconn) {
+ sasl_dispose(&d->mSASLconn);
+ d->mSASLconn = Q_NULLPTR;
+ }
+#endif
+ qCDebug(LDAP_LOG) << "connection closed!";
+}
+#else //LDAP_FOUND
+
+int LdapConnection::getOption(int option, void *value) const
+{
+ qCritical() << "No LDAP support...";
+ return -1;
+}
+
+int LdapConnection::setOption(int option, void *value)
+{
+ qCritical() << "No LDAP support...";
+ return -1;
+}
+
+int LdapConnection::ldapErrorCode() const
+{
+ qCritical() << "No LDAP support...";
+ return -1;
+}
+
+QString LdapConnection::ldapErrorString() const
+{
+ qCritical() << "No LDAP support...";
+ return QString();
+}
+
+bool LdapConnection::setSizeLimit(int sizelimit)
+{
+ qCritical() << "No LDAP support...";
+ return false;
+}
+
+int LdapConnection::sizeLimit() const
+{
+ qCritical() << "No LDAP support...";
+ return -1;
+}
+
+bool LdapConnection::setTimeLimit(int timelimit)
+{
+ qCritical() << "No LDAP support...";
+ return false;
+}
+
+int LdapConnection::timeLimit() const
+{
+ qCritical() << "No LDAP support...";
+ return -1;
+}
+
+int LdapConnection::connect()
+{
+ d->mConnectionError =
+ i18n("LDAP support not compiled in. Please recompile libkldap with the "
+ "OpenLDAP (or compatible) client libraries, or complain to your "
+ "distribution packagers.");
+ qCritical() << "No LDAP support...";
+ return -1;
+}
+
+void LdapConnection::close()
+{
+ qCritical() << "No LDAP support...";
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPCONNECTION_H
+#define KLDAP_LDAPCONNECTION_H
+
+#include <QtCore/QString>
+
+#include "ldapurl.h"
+#include "ldapserver.h"
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+/**
+ * @brief
+ * This class represents a connection to an LDAP server.
+ */
+class KLDAP_EXPORT LdapConnection
+{
+public:
+
+ enum SASL_Fields {
+ SASL_Authname = 0x1,
+ SASL_Authzid = 0x2,
+ SASL_Realm = 0x4,
+ SASL_Password = 0x8
+ };
+
+ /** Constructs an LdapConnection object */
+ LdapConnection();
+ /** Constructs an LdapConnection with the parameters given in url */
+ explicit LdapConnection(const LdapUrl &url);
+ /** Constructs an LdapConnection with the parameters given in server */
+ explicit LdapConnection(const LdapServer &server);
+
+ virtual ~LdapConnection();
+
+ /**
+ * Sets the connection parameters via the specified url. After this,
+ * you need to call connect() to connect with the new parameters.
+ * @param url the URL containing the connection parameters
+ */
+ void setUrl(const LdapUrl &url);
+ /**
+ * Returns the connection parameters which was specified with an LDAP Url
+ * or a LdapServer structure.
+ */
+ const LdapServer &server() const;
+ /**
+ * Sets the connection parameters via the specified server structure. After
+ * this, you need to call connect() to connect with the new parameters.
+ * @param server the server object containing the connection parameters
+ */
+ void setServer(const LdapServer &server);
+
+ /**
+ * Sets up the connection parameters with creating a handle to the LDAP server.
+ * Also sets sizelimit and timelimit and starts TLS if it is requested.
+ * Returns 0 if successful, else returns an LDAP error code, and an error
+ * string which is available via connectionError().
+ */
+ int connect();
+ /**
+ * Returns a translated error string if connect() failed.
+ */
+ QString connectionError() const;
+ /**
+ * Closes the LDAP connection.
+ */
+ void close();
+
+ /** Sets the size limit for the connection.
+ * @param sizelimit the connection size limit to set
+ */
+ bool setSizeLimit(int sizelimit);
+ /** Returns the current size limit. */
+ int sizeLimit() const;
+
+ /** Sets the time limit for the connection.
+ * @param timelimit the connection time limit to set
+ */
+ bool setTimeLimit(int timelimit);
+ /** Returns the current time limit. */
+ int timeLimit() const;
+
+ /** Gets an option from the connection. The option value can be client
+ * library specific, so avoid this function if possible
+ * @param option the connection option to return
+ * @param value the value of option to get
+ */
+ int getOption(int option, void *value) const;
+ /** Sets an option in the connection. The option value can be client
+ * library specific, so avoid this function if possible */
+ int setOption(int option, void *value);
+
+ /** Returns the LDAP error code from the last operation */
+ int ldapErrorCode() const;
+ /** Returns the LDAP error string from the last operation */
+ QString ldapErrorString() const;
+ /** Returns a translated error message from the specified LDAP error code */
+ static QString errorString(int code);
+
+ /** Returns the SASL error string from the last SASL operation */
+ QString saslErrorString() const;
+
+ /**
+ * Returns the opaqe client-library specific LDAP object.
+ * Avoid its usage if you can.
+ */
+ void *handle() const;
+
+ /**
+ * Returns the opaqe sasl-library specific SASL object.
+ * Avoid its usage if you can.
+ */
+ void *saslHandle() const;
+
+private:
+ class LdapConnectionPrivate;
+ LdapConnectionPrivate *const d;
+
+ Q_DISABLE_COPY(LdapConnection)
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapcontrol.h"
+#include "ber.h"
+
+#include <QtCore/QSharedData>
+
+using namespace KLDAP;
+
+class LdapControlPrivate : public QSharedData
+{
+public:
+ LdapControlPrivate()
+ {
+ mCritical = false;
+ }
+
+ LdapControlPrivate(const LdapControlPrivate &other)
+ : QSharedData(other)
+ {
+ mOid = other.mOid;
+ mValue = other.mValue;
+ mCritical = other.mCritical;
+ }
+
+ QString mOid;
+ QByteArray mValue;
+ bool mCritical;
+};
+
+LdapControl::LdapControl()
+ : d(new LdapControlPrivate)
+{
+ setControl(QString(), QByteArray(), false);
+}
+
+LdapControl::LdapControl(const QString &oid, const QByteArray &value, bool critical)
+ : d(new LdapControlPrivate)
+{
+ setControl(oid, value, critical);
+}
+
+LdapControl::LdapControl(const LdapControl &that)
+ : d(that.d)
+{
+ setControl(that.d->mOid, that.d->mValue, that.d->mCritical);
+}
+
+LdapControl &LdapControl::operator= (const LdapControl &that)
+{
+ if (this != &that) {
+ d = that.d;
+ }
+
+ setControl(that.d->mOid, that.d->mValue, that.d->mCritical);
+
+ return *this;
+}
+
+LdapControl::~LdapControl()
+{
+}
+
+void LdapControl::setControl(const QString &oid, const QByteArray &value, bool critical)
+{
+ d->mOid = oid;
+ d->mValue = value;
+ d->mCritical = critical;
+}
+
+QString LdapControl::oid() const
+{
+ return d->mOid;
+}
+
+QByteArray LdapControl::value() const
+{
+ return d->mValue;
+}
+
+bool LdapControl::critical() const
+{
+ return d->mCritical;
+}
+
+void LdapControl::setOid(const QString &oid)
+{
+ d->mOid = oid;
+}
+
+void LdapControl::setValue(const QByteArray &value)
+{
+ d->mValue = value;
+}
+
+void LdapControl::setCritical(bool critical)
+{
+ d->mCritical = critical;
+}
+
+int LdapControl::parsePageControl(QByteArray &cookie) const
+{
+ if (d->mOid != QLatin1String("1.2.840.113556.1.4.319")) {
+ return -1;
+ }
+
+ Ber ber(d->mValue);
+ int size;
+ if (ber.scanf(QStringLiteral("{iO}"), &size, &cookie) == -1) {
+ return -1;
+ } else {
+ return size;
+ }
+}
+
+LdapControl LdapControl::createPageControl(int pagesize, const QByteArray &cookie)
+{
+ LdapControl control;
+ Ber ber;
+
+ ber.printf(QStringLiteral("{iO}"), pagesize, &cookie);
+ control.setOid(QStringLiteral("1.2.840.113556.1.4.319"));
+ control.setValue(ber.flatten());
+ return control;
+}
+
+void LdapControl::insert(LdapControls &list, const LdapControl &ctrl)
+{
+ LdapControls::iterator it;
+ LdapControls::iterator endit = list.end();
+ const QString oid = ctrl.oid();
+
+ for (it = list.begin(); it != endit; ++it) {
+ if (it->oid() == oid) {
+ *it = ctrl;
+ return;
+ }
+ }
+ list.append(ctrl);
+}
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPCONTROL_H
+#define KLDAP_LDAPCONTROL_H
+
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtCore/QSharedDataPointer>
+class LdapControlPrivate;
+
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+class LdapControl;
+typedef QVector<LdapControl> LdapControls;
+
+/**
+ @brief
+ This class represents an LDAP Control
+*/
+class KLDAP_EXPORT LdapControl
+{
+public:
+ /**
+ * Creates an empty control.
+ */
+ LdapControl();
+ /**
+ * Creates a control with the given OID, value and criticality.
+ */
+ LdapControl(const QString &oid, const QByteArray &value, bool critical = false);
+
+ LdapControl(const LdapControl &that);
+ LdapControl &operator= (const LdapControl &that);
+ /**
+ * Destroys the control object.
+ */
+ virtual ~LdapControl();
+ /**
+ * Sets the control's OID, value and criticality.
+ */
+ void setControl(const QString &oid, const QByteArray &value,
+ bool critical = false);
+ /**
+ * Sets the control's OID.
+ */
+ void setOid(const QString &oid);
+ /**
+ * Sets the control's value.
+ */
+ void setValue(const QByteArray &value);
+ /**
+ * Sets the control's criticality.
+ */
+ void setCritical(bool critical);
+ /**
+ * Returns the control's OID.
+ */
+ QString oid() const;
+ /**
+ * Returns the control's value.
+ */
+ QByteArray value() const;
+ /**
+ * Returns the control's criticality.
+ */
+ bool critical() const;
+
+ /**
+ * Parses a paging results control, which the server returned.
+ * Puts the server's cookie into @p cookie, and returns the estimated
+ * result set size. If the OID is not the page control's OID, or the
+ * value cannot be decoded, returns -1.
+ * @param cookie the cookie to hold server's cookie
+ */
+ int parsePageControl(QByteArray &cookie) const;
+ /**
+ * Creates a paging search control.
+ */
+ static LdapControl createPageControl(int pagesize, const QByteArray &cookie = QByteArray());
+
+ /**
+ * Inserts a unique control against a list of controls.
+ * If the control already exists in the list is is updated, otherwise
+ * it is appended to the list.
+ * @param list the current list of controls
+ * @param ctrl the control to insert
+ * @since 4.4
+ */
+ static void insert(LdapControls &list, const LdapControl &ctrl);
+
+private:
+ QSharedDataPointer<LdapControlPrivate> d;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_DEFS_H
+#define KLDAP_DEFS_H
+
+/**
+ * LDAP Error codes.
+ * These codes taken from openldap's ldap.h, and prefixed with KLDAP_
+ * instead of LDAP_, just for applications which uses the kldap library
+ * doesn't need to include openldap headers
+ */
+
+#define KLDAP_SUCCESS 0x00
+
+#define KLDAP_RANGE(n,x,y) (((x) <= (n)) && ((n) <= (y)))
+
+#define KLDAP_OPERATIONS_ERROR 0x01
+#define KLDAP_PROTOCOL_ERROR 0x02
+#define KLDAP_TIMELIMIT_EXCEEDED 0x03
+#define KLDAP_SIZELIMIT_EXCEEDED 0x04
+#define KLDAP_COMPARE_FALSE 0x05
+#define KLDAP_COMPARE_TRUE 0x06
+#define KLDAP_AUTH_METHOD_NOT_SUPPORTED 0x07
+#define KLDAP_STRONG_AUTH_NOT_SUPPORTED KLDAP_AUTH_METHOD_NOT_SUPPORTED
+#define KLDAP_STRONG_AUTH_REQUIRED 0x08
+#define KLDAP_STRONGER_AUTH_REQUIRED KLDAP_STRONG_AUTH_REQUIRED
+#define KLDAP_PARTIAL_RESULTS 0x09 /* LDAPv2+ (not LDAPv3) */
+
+#define KLDAP_REFERRAL 0x0a /* LDAPv3 */
+#define KLDAP_ADMINLIMIT_EXCEEDED 0x0b /* LDAPv3 */
+#define KLDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* LDAPv3 */
+#define KLDAP_CONFIDENTIALITY_REQUIRED 0x0d /* LDAPv3 */
+#define KLDAP_SASL_BIND_IN_PROGRESS 0x0e /* LDAPv3 */
+
+#define KLDAP_ATTR_ERROR(n) KLDAP_RANGE((n),0x10,0x15) /* 16-21 */
+
+#define KLDAP_NO_SUCH_ATTRIBUTE 0x10
+#define KLDAP_UNDEFINED_TYPE 0x11
+#define KLDAP_INAPPROPRIATE_MATCHING 0x12
+#define KLDAP_CONSTRAINT_VIOLATION 0x13
+#define KLDAP_TYPE_OR_VALUE_EXISTS 0x14
+#define KLDAP_INVALID_SYNTAX 0x15
+
+#define KLDAP_NAME_ERROR(n) KLDAP_RANGE((n),0x20,0x24) /* 32-34,36 */
+
+#define KLDAP_NO_SUCH_OBJECT 0x20
+#define KLDAP_ALIAS_PROBLEM 0x21
+#define KLDAP_INVALID_DN_SYNTAX 0x22
+#define KLDAP_IS_LEAF 0x23 /* not LDAPv3 */
+#define KLDAP_ALIAS_DEREF_PROBLEM 0x24
+
+#define KLDAP_SECURITY_ERROR(n) KLDAP_RANGE((n),0x2F,0x32) /* 47-50 */
+
+#define KLDAP_PROXY_AUTHZ_FAILURE 0x2F /* LDAPv3 proxy authorization */
+#define KLDAP_INAPPROPRIATE_AUTH 0x30
+#define KLDAP_INVALID_CREDENTIALS 0x31
+#define KLDAP_INSUFFICIENT_ACCESS 0x32
+
+#define KLDAP_SERVICE_ERROR(n) KLDAP_RANGE((n),0x33,0x36) /* 51-54 */
+
+#define KLDAP_BUSY 0x33
+#define KLDAP_UNAVAILABLE 0x34
+#define KLDAP_UNWILLING_TO_PERFORM 0x35
+#define KLDAP_LOOP_DETECT 0x36
+
+#define KLDAP_UPDATE_ERROR(n) KLDAP_RANGE((n),0x40,0x47) /* 64-69,71 */
+
+#define KLDAP_NAMING_VIOLATION 0x40
+#define KLDAP_OBJECT_CLASS_VIOLATION 0x41
+#define KLDAP_NOT_ALLOWED_ON_NONLEAF 0x42
+#define KLDAP_NOT_ALLOWED_ON_RDN 0x43
+#define KLDAP_ALREADY_EXISTS 0x44
+#define KLDAP_NO_OBJECT_CLASS_MODS 0x45
+#define KLDAP_RESULTS_TOO_LARGE 0x46 /* CLDAP */
+#define KLDAP_AFFECTS_MULTIPLE_DSAS 0x47
+
+#define KLDAP_OTHER 0x50
+
+/* LCUP operation codes (113-117) - not implemented */
+#define KLDAP_CUP_RESOURCES_EXHAUSTED 0x71
+#define KLDAP_CUP_SECURITY_VIOLATION 0x72
+#define KLDAP_CUP_INVALID_DATA 0x73
+#define KLDAP_CUP_UNSUPPORTED_SCHEME 0x74
+#define KLDAP_CUP_RELOAD_REQUIRED 0x75
+
+/* Cancel operation codes (118-121) */
+#define KLDAP_CANCELLED 0x76
+#define KLDAP_NO_SUCH_OPERATION 0x77
+#define KLDAP_TOO_LATE 0x78
+
+#define KLDAP_CANNOT_CANCEL 0x79
+
+/* Assertion control (122) */
+#define KLDAP_ASSERTION_FAILED 0x7A
+
+/* Experimental result codes */
+#define KLDAP_E_ERROR(n) KLDAP_RANGE((n),0x1000,0x3FFF)
+
+/* LDAP Sync (4096) */
+#define KLDAP_SYNC_REFRESH_REQUIRED 0x1000
+
+/* Private Use result codes */
+#define KLDAP_X_ERROR(n) KLDAP_RANGE((n),0x4000,0xFFFF)
+
+#define KLDAP_X_SYNC_REFRESH_REQUIRED 0x4100 /* defunct */
+#define KLDAP_X_ASSERTION_FAILED 0x410f /* defunct */
+
+/* for the LDAP No-Op control */
+#define KLDAP_X_NO_OPERATION 0x410e
+
+/** API Error Codes
+ *
+ * Based on draft-ietf-ldap-c-api-xx
+ * but with new negative code values
+ */
+#define KLDAP_API_ERROR(n) ((n)<0)
+#define KLDAP_API_RESULT(n) ((n)<=0)
+
+#define KLDAP_SERVER_DOWN (-1)
+#define KLDAP_LOCAL_ERROR (-2)
+#define KLDAP_ENCODING_ERROR (-3)
+#define KLDAP_DECODING_ERROR (-4)
+#define KLDAP_TIMEOUT (-5)
+#define KLDAP_AUTH_UNKNOWN (-6)
+#define KLDAP_FILTER_ERROR (-7)
+#define KLDAP_USER_CANCELLED (-8)
+#define KLDAP_PARAM_ERROR (-9)
+#define KLDAP_NO_MEMORY (-10)
+#define KLDAP_CONNECT_ERROR (-11)
+#define KLDAP_NOT_SUPPORTED (-12)
+#define KLDAP_CONTROL_NOT_FOUND (-13)
+#define KLDAP_NO_RESULTS_RETURNED (-14)
+#define KLDAP_MORE_RESULTS_TO_RETURN (-15) /* Obsolete */
+#define KLDAP_CLIENT_LOOP (-16)
+#define KLDAP_REFERRAL_LIMIT_EXCEEDED (-17)
+
+/*
+ * KLDAP Specific
+ */
+
+#define KLDAP_SASL_ERROR -0xff
+
+#endif //KLDAP_DEFS_H
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapdn.h"
+
+#include <algorithm>
+
+#include "ldap_debug.h"
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN LdapDN::LdapDNPrivate
+{
+public:
+ LdapDNPrivate() : m_dn() {}
+ ~LdapDNPrivate() {}
+
+ bool isValidRDNString(const QString &rdn) const;
+ QStringList splitOnNonEscapedChar(const QString &rdn, QChar ch) const;
+
+ QString m_dn;
+};
+
+bool LdapDN::LdapDNPrivate::isValidRDNString(const QString &rdn) const
+{
+ qCDebug(LDAP_LOG) << "Testing rdn:" << rdn;
+
+ // If it is a muli-valued rdn, split it into its constituent parts
+ const QStringList rdnParts = splitOnNonEscapedChar(rdn, QLatin1Char('+'));
+ const int rdnPartsSize(rdnParts.size());
+ if (rdnPartsSize > 1) {
+ for (int i = 0; i < rdnPartsSize; i++) {
+ if (!isValidRDNString(rdnParts.at(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Split the rdn into the attribute name and value parts
+ QStringList components = rdn.split(QLatin1Char('='));
+
+ // We should have exactly two parts
+ if (components.size() != 2) {
+ return false;
+ }
+
+ return true;
+}
+
+QStringList LdapDN::LdapDNPrivate::splitOnNonEscapedChar(const QString &str, QChar ch) const
+{
+ QStringList strParts;
+ int index = 0;
+ int searchFrom = 0;
+ int strPartStartIndex = 0;
+ while ((index = str.indexOf(ch, searchFrom)) != -1) {
+ const QChar prev = str[std::max(0, index - 1)];
+ if (prev != QLatin1Char('\\')) {
+ // Found a component of a multi-valued RDN
+ //qCDebug(LDAP_LOG) << "Found" << ch << "at index" << index;
+ QString tmp = str.mid(strPartStartIndex, index - strPartStartIndex);
+ //qCDebug(LDAP_LOG) << "Adding part:" << tmp;
+ strParts.append(tmp);
+ strPartStartIndex = index + 1;
+ }
+
+ searchFrom = index + 1;
+ }
+
+ // Add on the part after the last found delimeter
+ QString tmp = str.mid(strPartStartIndex);
+ //qCDebug(LDAP_LOG) << "Adding part:" << tmp;
+ strParts.append(tmp);
+
+ return strParts;
+}
+
+LdapDN::LdapDN()
+ : d(new LdapDNPrivate)
+{
+
+}
+
+LdapDN::LdapDN(const QString &dn)
+ : d(new LdapDNPrivate)
+{
+ d->m_dn = dn;
+}
+
+LdapDN::LdapDN(const LdapDN &that)
+ : d(new LdapDNPrivate)
+{
+ *d = *that.d;
+}
+
+LdapDN &LdapDN::operator=(const LdapDN &that)
+{
+ if (this == &that) {
+ return *this;
+ }
+
+ *d = *that.d;
+ return *this;
+}
+
+LdapDN::~LdapDN()
+{
+ delete d;
+}
+
+void LdapDN::clear()
+{
+ d->m_dn.clear();
+}
+
+bool LdapDN::isEmpty() const
+{
+ return d->m_dn.isEmpty();
+}
+
+QString LdapDN::toString() const
+{
+ return d->m_dn;
+}
+
+QString LdapDN::toString(int depth) const
+{
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+ if (depth >= rdns.size()) {
+ return QString();
+ }
+
+ // Construct a DN down to the requested depth
+ QString dn;
+ for (int i = depth; i >= 0; i--) {
+ dn += rdns.at(rdns.size() - 1 - i) + QLatin1Char(',');
+ qCDebug(LDAP_LOG) << "dn =" << dn;
+ }
+ dn = dn.left(dn.length() - 1); // Strip off the extraneous comma
+
+ return dn;
+}
+
+QString LdapDN::rdnString() const
+{
+ /** \TODO We should move this into the d pointer as we calculate rdns quite a lot */
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+ return rdns.at(0);
+}
+
+QString LdapDN::rdnString(int depth) const
+{
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+ if (depth >= rdns.size()) {
+ return QString();
+ }
+ return rdns.at(rdns.size() - 1 - depth);
+}
+
+bool LdapDN::isValid() const
+{
+ qCDebug(LDAP_LOG) << "Testing dn:" << d->m_dn;
+
+ // Break the string into rdn's
+ const QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+
+ // Test to see if each rdn is valid
+ const int rdnsSize(rdns.size());
+ for (int i = 0; i < rdnsSize; i++) {
+ if (!d->isValidRDNString(rdns.at(i))) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int LdapDN::depth() const
+{
+ QStringList rdns = d->splitOnNonEscapedChar(d->m_dn, QLatin1Char(','));
+ return rdns.size();
+}
+
+bool LdapDN::operator == (const LdapDN &rhs) const
+{
+ return d->m_dn == rhs.d->m_dn;
+}
+
+bool LdapDN::operator != (const LdapDN &rhs) const
+{
+ return d->m_dn != rhs.d->m_dn;
+}
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPDN_H
+#define KLDAP_LDAPDN_H
+
+#include "kldap_export.h"
+
+#include <QtCore/QStringList>
+
+namespace KLDAP
+{
+
+class KLDAP_EXPORT LdapDN
+{
+public:
+ explicit LdapDN();
+ explicit LdapDN(const QString &dn);
+
+ LdapDN(const LdapDN &that);
+ LdapDN &operator=(const LdapDN &that);
+
+ ~LdapDN();
+
+ void clear();
+
+ bool isEmpty() const;
+
+ /**
+ * \returns A QString representing the DN.
+ */
+ QString toString() const;
+
+ /**
+ * \param depth The depth of the DN to return using a zero-based index.
+ * \returns A QString representing the DN levels deep in the directory.
+ */
+ QString toString(int depth) const;
+
+ /**
+ * \returns A QString representing the RDN of this DN.
+ */
+ QString rdnString() const;
+
+ /**
+ * \param depth The depth of the RDN to return using a zero-based index.
+ * \returns A QString representing the RDN levels deep in the directory.
+ */
+ QString rdnString(int depth) const;
+
+ /**
+ * \returns True if this is a valid DN, false otherwise.
+ */
+ bool isValid() const;
+
+ /**
+ * \returns The depth of this DN in the directory.
+ */
+ int depth() const;
+
+ bool operator == (const LdapDN &rhs) const;
+
+ bool operator != (const LdapDN &rhs) const;
+
+private:
+ class LdapDNPrivate;
+ LdapDNPrivate *const d;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapmodel.h"
+#include "ldapmodel_p.h"
+#include "ldapmodelnode_p.h"
+#include "ldapsearch.h"
+
+#include "ldap_debug.h"
+#include <klocalizedstring.h>
+
+using namespace KLDAP;
+
+LdapModel::LdapModel(QObject *parent)
+ : QAbstractItemModel(parent),
+ m_d(new LdapModelPrivate(this))
+{
+ m_d->createConnections();
+}
+
+LdapModel::LdapModel(LdapConnection &connection, QObject *parent)
+ : QAbstractItemModel(parent),
+ m_d(new LdapModelPrivate(this, connection))
+{
+ m_d->createConnections();
+
+ // Populate items from the root object to that representing the baseDN
+ m_d->populateRootToBaseDN();
+}
+
+LdapModel::~LdapModel()
+{
+ delete m_d;
+}
+
+void LdapModel::setConnection(LdapConnection &connection)
+{
+ m_d->setConnection(connection);
+
+ // Refresh the model
+ m_d->recreateRootItem();
+
+ // Populate the root object by searching the baseDN
+ m_d->populateRootToBaseDN();
+}
+
+QModelIndex LdapModel::parent(const QModelIndex &child) const
+{
+ if (!child.isValid()) {
+ return QModelIndex();
+ }
+
+ LdapModelNode *childItem = static_cast<LdapModelNode *>(child.internalPointer());
+ LdapModelDNNode *parentItem = childItem->parent();
+
+ if (parentItem == m_d->rootNode()) {
+ return QModelIndex();
+ }
+
+ return createIndex(parentItem->row(), 0, parentItem);
+}
+
+QModelIndex LdapModel::index(int row, int col, const QModelIndex &parent) const
+{
+ // Retrieve a pointer to the parent item
+ LdapModelDNNode *parentItem;
+ if (!parent.isValid()) {
+ parentItem = m_d->rootNode();
+ } else {
+ parentItem = static_cast<LdapModelDNNode *>(parent.internalPointer());
+ }
+
+ LdapModelNode *childItem = parentItem->child(row);
+ if (childItem) {
+ return createIndex(row, col, childItem);
+ }
+ qCDebug(LDAP_LOG) << "Could not create valid index for row =" << row << ", col =" << col;
+ return QModelIndex();
+}
+
+QVariant LdapModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid()) {
+ return QVariant();
+ }
+
+ if (role == Qt::DisplayRole) {
+ // This is what gets displayed by the view delegates.
+ LdapModelNode *node = static_cast<LdapModelNode *>(index.internalPointer());
+ if (node->nodeType() == LdapModelNode::DN) {
+ LdapModelDNNode *dn = static_cast<LdapModelDNNode *>(node);
+ if (index.column() == 0) {
+ return dn->dn().rdnString();
+ } else {
+ return QVariant();
+ }
+ } else {
+ LdapModelAttrNode *attr = static_cast<LdapModelAttrNode *>(node);
+ if (index.column() == 0) {
+ return QVariant(attr->attributeName());
+ } else {
+ return QVariant(QLatin1String(attr->attributeData().constData()));
+ }
+ }
+ } else if (role == NodeTypeRole) {
+ LdapModelNode *node = static_cast<LdapModelNode *>(index.internalPointer());
+ return QVariant(int(node->nodeType()));
+ }
+
+ /** \todo Include support for nice decorative icons dependent upon
+ the objectClass + other role data. */
+ /** \todo Include support for other roles as needed */
+
+ return QVariant();
+}
+
+bool LdapModel::setData(const QModelIndex &index,
+ const QVariant &value,
+ int role)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(value);
+ Q_UNUSED(role);
+ return false;
+}
+
+QVariant LdapModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ if (section == 0) {
+ return i18n("Attribute");
+ } else {
+ return i18n("Value");
+ }
+ }
+
+ return QVariant();
+}
+
+Qt::ItemFlags LdapModel::flags(const QModelIndex &index) const
+{
+ /** \TODO Read-only for now, make read-write upon request */
+ if (!index.isValid()) {
+ return Qt::ItemIsEnabled;
+ }
+
+ return Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+}
+
+int LdapModel::columnCount(const QModelIndex &parent) const
+{
+ LdapModelDNNode *parentNode =
+ parent.isValid() ? static_cast<LdapModelDNNode *>(parent.internalPointer()) : m_d->rootNode();
+ return parentNode->columnCount();
+}
+
+int LdapModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.column() > 0) {
+ return 0;
+ }
+
+ const LdapModelDNNode *parentNode =
+ parent.isValid() ? static_cast<LdapModelDNNode *>(parent.internalPointer()) : m_d->rootNode();
+ return parentNode->childCount();
+}
+
+bool LdapModel::hasChildren(const QModelIndex &parent) const
+{
+ // We return true unless the item has been populated and we are able to do a definitive test
+ const LdapModelNode *node = parent.isValid() ?
+ static_cast<const LdapModelNode *>(parent.internalPointer()) :
+ m_d->rootNode();
+
+ if (node->nodeType() != LdapModelNode::DN) {
+ return false;
+ }
+
+ const LdapModelDNNode *parentNode = static_cast<const LdapModelDNNode *>(node);
+ if (!parent.isValid() || parentNode->isPopulated()) {
+ return parentNode->childCount() > 0;
+ }
+ return true;
+}
+
+bool LdapModel::canFetchMore(const QModelIndex &parent) const
+{
+ const LdapModelDNNode *parentNode =
+ parent.isValid() ? static_cast<LdapModelDNNode *>(parent.internalPointer()) : m_d->rootNode();
+ return !parentNode->isPopulated();
+}
+
+void LdapModel::fetchMore(const QModelIndex &parent)
+{
+ LdapModelDNNode *parentNode =
+ parent.isValid() ? static_cast<LdapModelDNNode *>(parent.internalPointer()) : m_d->rootNode();
+
+ // Search for the immediate children of parentItem.
+ m_d->searchResults().clear();
+ m_d->setSearchType(LdapModelPrivate::ChildObjects, parentNode);
+ m_d->search(parentNode->dn(), // DN to search from
+ LdapUrl::One, // What to search
+ QString()); // Attributes to retrieve
+ parentNode->setPopulated(true);
+}
+
+bool LdapModel::insertRows(int row, int count,
+ const QModelIndex &parent)
+{
+ Q_UNUSED(row);
+ Q_UNUSED(count);
+ Q_UNUSED(parent);
+ return false;
+}
+
+bool LdapModel::removeRows(int row, int count,
+ const QModelIndex &parent)
+{
+ Q_UNUSED(row);
+ Q_UNUSED(count);
+ Q_UNUSED(parent);
+ return false;
+}
+
+void LdapModel::sort(int column, Qt::SortOrder order)
+{
+ Q_UNUSED(column);
+ Q_UNUSED(order);
+}
+
+Qt::DropActions LdapModel::supportedDropActions() const
+{
+ return Qt::MoveAction;
+}
+
+QMimeData *LdapModel::mimeData(const QModelIndexList &indexes) const
+{
+ Q_UNUSED(indexes);
+ return Q_NULLPTR;
+}
+
+bool LdapModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ /** \todo Implement drag and drop for LdapModel */
+ Q_UNUSED(data);
+ Q_UNUSED(action);
+ Q_UNUSED(row);
+ Q_UNUSED(column);
+ Q_UNUSED(parent);
+ return false;
+}
+
+bool LdapModel::hasChildrenOfType(const QModelIndex &parent, LdapDataType type) const
+{
+ // Map from LdapDataType to our internal NodeType
+ LdapModelNode::NodeType nodeType;
+ switch (type) {
+ case Attribute:
+ nodeType = LdapModelNode::Attr;
+ break;
+
+ case DistinguishedName:
+ default:
+ nodeType = LdapModelNode::DN;
+ break;
+ }
+
+ const LdapModelNode *node = parent.isValid() ?
+ static_cast<const LdapModelNode *>(parent.internalPointer()) :
+ m_d->rootNode();
+
+ const LdapModelDNNode *parentNode = static_cast<const LdapModelDNNode *>(node);
+ if (!parent.isValid() || parentNode->isPopulated()) {
+ // Check to see if the parent has any children of the specified type
+ const QList<LdapModelNode *> &children = parentNode->children();
+ foreach (LdapModelNode *child, children) {
+ if (child->nodeType() == nodeType) {
+ return true;
+ }
+ }
+
+ // Either there are no children or only children of a different type
+ return false;
+ }
+
+ // If the node is not populated or is the root node (invalid), then return
+ // true to be on the safe side.
+ return true;
+}
+
+void LdapModel::revert()
+{
+
+}
+
+bool LdapModel::submit()
+{
+ return false;
+}
+
+#include "moc_ldapmodel.cpp"
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPMODEL_H
+#define KLDAP_LDAPMODEL_H
+
+#include <QtCore/QAbstractItemModel>
+
+#include "ldapconnection.h"
+#include "ldapobject.h"
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+/**
+ * A ModelView interface to an LDAP tree. At present the model is read only. Editing is
+ * planned for a future release.
+ *
+ * This class is best used in conjunction with an LdapStructureProxyModel object for
+ * displaying the structure of an LDAP tree, and with LdapAttributeProxyModel for
+ * displaying the attributes of particular objects within the tree.
+ *
+ * \author Sean Harmer <sh@theharmers.co.uk>
+ */
+class KLDAP_EXPORT LdapModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ enum Roles {
+ NodeTypeRole = Qt::UserRole + 1
+ };
+
+ enum LdapDataType {
+ DistinguishedName = 0,
+ Attribute
+ };
+
+ /**
+ * Constructs an LdapModel. You should set a connection for the model to use with
+ * setConnection(). Clients of this class should connect a slot to the ready() signal
+ * before setting this model onto a view.
+ * @param parent the parent QObject
+ * \see setConnection()
+ * \see ready()
+ */
+ explicit LdapModel(QObject *parent = Q_NULLPTR);
+ /**
+ * Constructs an LdapModel. Clients of this class should connect a slot to the ready()
+ * signal before setting this model onto a view.
+ * @param connection the Ldap connection to use in model construction
+ * @param parent the parent QObject
+ * \see setConnection()
+ * \see ready()
+ */
+ explicit LdapModel(LdapConnection &connection, QObject *parent = Q_NULLPTR);
+ virtual ~LdapModel();
+
+ /**
+ * Set the connection that the model should use.
+ * @param connection the model connection to set
+ * \see LdapConnection
+ * \see LdapUrl
+ */
+ void setConnection(LdapConnection &connection);
+
+ //
+ // Implement the usual QAbstractItemModel interface
+ //
+ /**
+ * Reimplemented from QAbstractItemModel::index().
+ */
+ QModelIndex index(int row, int col, const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::parent().
+ */
+ QModelIndex parent(const QModelIndex &child) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::data().
+ */
+ QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::setData(). This is a placeholder for when
+ * LdapModel beomes writeable and always returns false.
+ */
+ bool setData(const QModelIndex &index,
+ const QVariant &value,
+ int role = Qt::EditRole) Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::headerData().
+ */
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::flags().
+ */
+ Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::columnCount().
+ */
+ int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::rowCount().
+ */
+ int rowCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::hasChildren().
+ */
+ bool hasChildren(const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::canFetchMore().
+ */
+ bool canFetchMore(const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::fetchMore().
+ */
+ void fetchMore(const QModelIndex &parent) Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::insertRows(). This is a placeholder for when
+ * LdapModel beomes writeable and always returns false.
+ */
+ bool insertRows(int row, int count,
+ const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::removeRows(). This is a placeholder for when
+ * LdapModel beomes writeable and always returns false.
+ */
+ bool removeRows(int row, int count,
+ const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::removeRows(). The default implementation
+ * does nothing.
+ */
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) Q_DECL_OVERRIDE;
+
+ //
+ // Drag and drop support
+ //
+ /**
+ * Reimplemented from QAbstractItemModel::supportedDropActions(). The default
+ * implementation returns Qt::MoveAction.
+ */
+ Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::mimedata(). This is a placeholder for when
+ * LdapModel beomes writeable and always returns 0.
+ */
+ QMimeData *mimeData(const QModelIndexList &indexes) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::dropMimedata(). This is a placeholder for when
+ * LdapModel beomes writeable and always returns false.
+ */
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) Q_DECL_OVERRIDE;
+
+ //
+ // Other public utility functions
+ //
+ /**
+ * Checks to see if the item referenced by \p parent has any children of
+ * the type \p type. If the item has not been populated by fetchMore() yet,
+ * then this function returns true.
+ *
+ * \see fetchMore()
+ * \param parent Index to the item to query.
+ * \param type The type of child item to search for.
+ */
+ bool hasChildrenOfType(const QModelIndex &parent, LdapDataType type) const;
+
+public Q_SLOTS:
+ /**
+ * Reimplemented from QAbstractItemModel::revert(). This is a placeholder for when
+ * LdapModel beomes writeable. This implementation does nothing.
+ */
+ void revert() Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::revert(). This is a placeholder for when
+ * LdapModel beomes writeable. This implementation does nothing and returns false.
+ */
+ bool submit() Q_DECL_OVERRIDE;
+
+Q_SIGNALS:
+ /**
+ * The ready() signal is emitted when the model is ready for use by other components.
+ * When the model is first created and a connection is set, the model queries the
+ * LDAP server for its base DN and automatically creates items down to that level.
+ * This requires the event loop to be running. This signal indicates that this process
+ * has completed and the model can now be set onto views or queried directly from code.
+ */
+ void ready();
+
+private:
+ class LdapModelPrivate;
+ LdapModelPrivate *const m_d;
+
+ Q_PRIVATE_SLOT(m_d, void gotSearchResult(KLDAP::LdapSearch *))
+ Q_PRIVATE_SLOT(m_d, void gotSearchData(KLDAP::LdapSearch *, const KLDAP::LdapObject &))
+};
+
+}
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapmodel_p.h"
+#include "ldapmodelnode_p.h"
+#include "ldapsearch.h"
+
+#include "ldap_debug.h"
+
+using namespace KLDAP;
+
+LdapModel::LdapModelPrivate::LdapModelPrivate(LdapModel *parent)
+ : m_parent(parent),
+ m_root(new LdapModelDNNode),
+ m_search(new LdapSearch),
+ m_searchResultObjects(),
+ m_baseDN(),
+ m_searchType(NotSearching),
+ m_searchItem(Q_NULLPTR)
+{
+}
+
+LdapModel::LdapModelPrivate::LdapModelPrivate(LdapModel *parent, LdapConnection &connection)
+ : m_parent(parent),
+ m_root(new LdapModelDNNode),
+ m_search(new LdapSearch(connection)),
+ m_searchResultObjects(),
+ m_baseDN(),
+ m_searchType(NotSearching),
+ m_searchItem(Q_NULLPTR)
+{
+}
+
+LdapModel::LdapModelPrivate::~LdapModelPrivate()
+{
+ delete m_root;
+
+ delete m_search;
+}
+
+void LdapModel::LdapModelPrivate::setConnection(LdapConnection &connection)
+{
+ m_search->setConnection(connection);
+}
+
+bool LdapModel::LdapModelPrivate::search(const LdapDN &searchBase,
+ LdapUrl::Scope scope,
+ const QString &filter,
+ const QStringList &attributes,
+ int pagesize)
+{
+ return m_search->search(searchBase, scope, filter, attributes, pagesize);
+}
+
+void LdapModel::LdapModelPrivate::setSearchType(SearchType t, LdapModelDNNode *item)
+{
+ //qCDebug(LDAP_LOG) << "item =" << item;
+ m_searchType = t;
+ m_searchItem = item;
+}
+
+void LdapModel::LdapModelPrivate::recreateRootItem()
+{
+ //qCDebug(LDAP_LOG);
+ delete m_root;
+ m_root = new LdapModelDNNode;
+ //qCDebug(LDAP_LOG) << "&m_root =" << &m_root;
+}
+
+void LdapModel::LdapModelPrivate::createConnections()
+{
+ connect(search(), SIGNAL(result(KLDAP::LdapSearch*)),
+ m_parent, SLOT(gotSearchResult(KLDAP::LdapSearch*)));
+ connect(search(), SIGNAL(data(KLDAP::LdapSearch*,KLDAP::LdapObject)),
+ m_parent, SLOT(gotSearchData(KLDAP::LdapSearch*,KLDAP::LdapObject)));
+}
+
+void LdapModel::LdapModelPrivate::populateRootToBaseDN()
+{
+ //qCDebug(LDAP_LOG);
+
+ if (baseDN().isEmpty()) {
+ // Query the server for the base DN
+ //qCDebug(LDAP_LOG) << "Searching for the baseDN";
+ setSearchType(LdapModelPrivate::NamingContexts, rootNode());
+ search(LdapDN(), LdapUrl::Base, QString(), QStringList() << QStringLiteral("namingContexts"));
+ return;
+ }
+
+ // Start a search for the details of the baseDN object
+ //qCDebug(LDAP_LOG) << "Searching for attributes of the baseDN";
+ searchResults().clear();
+ setSearchType(LdapModelPrivate::BaseDN, rootNode());
+ search(baseDN(), LdapUrl::Base, QString(), QStringList() << QStringLiteral("dn") << QStringLiteral("objectClass"));
+}
+
+void LdapModel::LdapModelPrivate::gotSearchResult(KLDAP::LdapSearch *search)
+{
+ Q_UNUSED(search);
+ qCDebug(LDAP_LOG);
+
+ switch (searchType()) {
+ case LdapModelPrivate::NamingContexts: {
+ // Set the baseDN
+ QString baseDN;
+ if (!searchResults().isEmpty() &&
+ searchResults().at(0).hasAttribute(QStringLiteral("namingContexts"))) {
+ baseDN = QLatin1String(searchResults().at(0).value(QStringLiteral("namingContexts")));
+ //qCDebug(LDAP_LOG) << "Found baseDN =" << baseDN;
+ }
+ setBaseDN(LdapDN(baseDN));
+
+ // Flag that we are no longer searching for the baseDN
+ setSearchType(LdapModelPrivate::NotSearching);
+
+ // Populate the root item
+ populateRootToBaseDN();
+
+ break;
+ }
+ case LdapModelPrivate::BaseDN: {
+ //qCDebug(LDAP_LOG) << "Found details of the baseDN object."
+ // << "Creating objects down to this level.";
+
+ // Get the baseDN LdapObject
+ LdapObject baseDNObj = searchResults().at(0);
+
+ // How many levels of items do we need to create?
+ int depth = baseDNObj.dn().depth();
+
+ // Create items that represent objects down to the baseDN
+ LdapModelDNNode *parent = rootNode();
+ LdapModelDNNode *item = Q_NULLPTR;
+ for (int i = 0; i < depth; ++i) {
+ QString dn = baseDN().toString(i);
+ qCDebug(LDAP_LOG) << "Creating item for DN :" << dn;
+
+ //LdapObject obj( dn );
+ item = new LdapModelDNNode(parent, LdapDN(dn));
+ parent = item;
+ }
+
+ // Store the search result
+ if (item) {
+ item->setLdapObject(baseDNObj);
+ }
+
+ // Flag that we are no longer searching
+ setSearchType(LdapModelPrivate::NotSearching);
+ //emit( layoutChanged() );
+
+ // Let the world know we are ready for action
+ emit m_parent->ready();
+
+ break;
+ }
+ case LdapModelPrivate::ChildObjects: {
+ //qCDebug(LDAP_LOG) << "Found" << searchResults().size() << "child objects";
+
+ if (searchResults().size() != 0) {
+ // Create an index for the soon-to-be-a-parent item
+ LdapModelDNNode *parentNode = searchItem();
+ int r = parentNode->row();
+ QModelIndex parentIndex = m_parent->createIndex(r, 0, parentNode);
+
+ m_parent->beginInsertRows(parentIndex, 0, searchResults().size());
+ for (int i = 0; i < searchResults().size(); i++) {
+ LdapObject object = searchResults().at(i);
+ LdapModelDNNode *item = new LdapModelDNNode(parentNode, object.dn());
+ item->setLdapObject(object);
+ }
+
+ m_parent->endInsertRows();
+ emit m_parent->layoutChanged();
+ }
+
+ // Flag that we are no longer searching
+ setSearchType(LdapModelPrivate::NotSearching);
+
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void LdapModel::LdapModelPrivate::gotSearchData(KLDAP::LdapSearch *search,
+ const KLDAP::LdapObject &obj)
+{
+ Q_UNUSED(search);
+ //qCDebug(LDAP_LOG);
+ //qCDebug(LDAP_LOG) << "Object:";
+ //qCDebug(LDAP_LOG) << obj.toString();
+ searchResults().append(obj);
+}
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPMODELPRIVATE_H
+#define KLDAP_LDAPMODELPRIVATE_H
+
+#include "ldapconnection.h"
+#include "ldapdn.h"
+#include "ldapmodel.h"
+#include "ldapobject.h"
+
+namespace KLDAP
+{
+
+class LdapModelDNNode;
+class LdapSearch;
+
+/**
+ * @internal
+ */
+class Q_DECL_HIDDEN LdapModel::LdapModelPrivate
+{
+public:
+ enum SearchType {
+ NotSearching = 0,
+ NamingContexts,
+ BaseDN,
+ ChildObjects
+ };
+
+ explicit LdapModelPrivate(LdapModel *parent);
+ explicit LdapModelPrivate(LdapModel *parent, LdapConnection &connection);
+
+ ~LdapModelPrivate();
+
+ void setConnection(LdapConnection &connection);
+
+ bool search(const LdapDN &searchBase,
+ LdapUrl::Scope scope = LdapUrl::Sub,
+ const QString &filter = QString(),
+ const QStringList &attributes = QStringList(),
+ int pagesize = 0);
+
+ LdapModelDNNode *rootNode()
+ {
+ return m_root;
+ }
+ LdapSearch *search()
+ {
+ return m_search;
+ }
+
+ LdapObjects &searchResults()
+ {
+ return m_searchResultObjects;
+ }
+ const LdapObjects &searchResults() const
+ {
+ return m_searchResultObjects;
+ }
+
+ void recreateRootItem();
+
+ void setBaseDN(const LdapDN &baseDN)
+ {
+ m_baseDN = baseDN;
+ }
+ LdapDN &baseDN()
+ {
+ return m_baseDN;
+ }
+ const LdapDN &baseDN() const
+ {
+ return m_baseDN;
+ }
+
+ void setSearchType(SearchType t, LdapModelDNNode *item = Q_NULLPTR);
+
+ SearchType searchType()
+ {
+ return m_searchType;
+ }
+ LdapModelDNNode *searchItem()
+ {
+ return m_searchItem;
+ }
+
+ void createConnections();
+ void populateRootToBaseDN();
+ void gotSearchResult(KLDAP::LdapSearch *search);
+ void gotSearchData(KLDAP::LdapSearch *search, const KLDAP::LdapObject &obj);
+
+private:
+ LdapModel *m_parent;
+ LdapModelDNNode *m_root;
+ LdapSearch *m_search;
+ LdapObjects m_searchResultObjects;
+ LdapDN m_baseDN;
+ SearchType m_searchType;
+ LdapModelDNNode *m_searchItem;
+};
+
+}
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapmodelnode_p.h"
+
+#include "ldap_debug.h"
+
+using namespace KLDAP;
+
+LdapModelNode::LdapModelNode(LdapModelDNNode *parent)
+ : m_parent(parent),
+ m_isPopulated(false)
+{
+ if (m_parent) {
+ m_parent->appendChild(this);
+ }
+}
+
+LdapModelNode::~LdapModelNode()
+{
+
+}
+
+LdapModelDNNode *LdapModelNode::parent()
+{
+ return m_parent;
+}
+
+int LdapModelNode::row() const
+{
+ if (m_parent) {
+ return m_parent->children().indexOf(const_cast<LdapModelNode *>(this));
+ }
+ return 0;
+}
+
+//
+// LdapModelDNNode imlpementation
+//
+
+LdapModelDNNode::LdapModelDNNode(LdapModelDNNode *parent,
+ const LdapDN &dn)
+ : LdapModelNode(parent),
+ m_childItems(),
+ m_dn(dn)
+{
+ qCDebug(LDAP_LOG) << "Creating DN =" << m_dn.toString();
+}
+
+LdapModelDNNode::~LdapModelDNNode()
+{
+ qDeleteAll(m_childItems);
+}
+
+void LdapModelDNNode::appendChild(LdapModelNode *pItem)
+{
+ m_childItems.append(pItem);
+ setPopulated(true);
+}
+
+LdapModelNode *LdapModelDNNode::child(int row)
+{
+ return m_childItems.value(row);
+}
+
+void LdapModelDNNode::setLdapObject(const LdapObject &object)
+{
+ // Remember whether this item is populated or not
+ bool populated = isPopulated();
+
+ const LdapAttrMap &attrs = object.attributes();
+ /*
+ int attributeCount = 0;
+ for ( LdapAttrMap::ConstIterator it = attrs.begin(); it != attrs.end(); ++it ) {
+ attributeCount += (*it).size();
+ }
+
+ for ( int i = 0; i < attributeCount; i++ )
+ {
+ LdapModelNode* node = new LdapModelAttrNode( this, QString::number( i ) );
+ Q_UNUSED( node );
+ }
+ */
+ LdapAttrMap::ConstIterator end(attrs.constEnd());
+ for (LdapAttrMap::ConstIterator it = attrs.constBegin(); it != end; ++it) {
+ const QString attr = it.key();
+ LdapAttrValue::ConstIterator end2((*it).constEnd());
+ for (LdapAttrValue::ConstIterator it2 = (*it).constBegin(); it2 != end2; ++it2) {
+ LdapModelNode *node = new LdapModelAttrNode(this, attr, *it2);
+ Q_UNUSED(node);
+ }
+ }
+
+ // Reset the populated flag so that we don't stop the model querying for children
+ setPopulated(populated);
+}
+
+//
+// LdapModelAttrNode imlpementation
+//
+
+LdapModelAttrNode::LdapModelAttrNode(LdapModelDNNode *parent,
+ const QString &attrName,
+ const QByteArray &attrData)
+ : LdapModelNode(parent),
+ m_attrName(attrName),
+ m_attrData(attrData)
+{
+ qCDebug(LDAP_LOG) << "Creating Name =" << m_attrName << " Data =" << m_attrData;
+}
+
+LdapModelAttrNode::~LdapModelAttrNode()
+{
+
+}
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPMODELNODE_P_H
+#define KLDAP_LDAPMODELNODE_P_H
+
+#include <QByteArray>
+#include <QString>
+#include <QtCore/QList>
+#include <QtCore/QVariant>
+
+#include "ldapdn.h"
+#include "ldapobject.h"
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+class LdapModelDNNode;
+
+/**
+ * @internal
+ */
+class LdapModelNode
+{
+public:
+ explicit LdapModelNode(LdapModelDNNode *parent = Q_NULLPTR);
+ virtual ~LdapModelNode();
+
+ enum NodeType {
+ DN,
+ Attr
+ };
+
+ virtual NodeType nodeType() const = 0;
+
+ LdapModelDNNode *parent();
+ int columnCount() const
+ {
+ return 2;
+ }
+ int row() const;
+
+ void setPopulated(bool b)
+ {
+ m_isPopulated = b;
+ }
+ bool isPopulated() const
+ {
+ return m_isPopulated;
+ }
+
+private:
+ LdapModelDNNode *m_parent;
+ bool m_isPopulated;
+};
+
+/**
+ * @internal
+ */
+class LdapModelDNNode : public LdapModelNode
+{
+public:
+ explicit LdapModelDNNode(LdapModelDNNode *parent = Q_NULLPTR,
+ const LdapDN &dn = LdapDN());
+ ~LdapModelDNNode();
+
+ LdapModelNode::NodeType nodeType() const Q_DECL_OVERRIDE
+ {
+ return LdapModelNode::DN;
+ }
+
+ void appendChild(LdapModelNode *pItem);
+ LdapModelNode *child(int row);
+ int childCount() const
+ {
+ return m_childItems.size();
+ }
+ const QList<LdapModelNode *> &children() const
+ {
+ return m_childItems;
+ }
+
+ const LdapDN &dn() const
+ {
+ return m_dn;
+ }
+
+ /**
+ * Creates child LdapModelAttrNode object to store \p object's attributes
+ * and adds them as children of this node.
+ *
+ * \param The LdapObject to store in this node.
+ */
+ void setLdapObject(const LdapObject &object);
+
+private:
+ QList<LdapModelNode *> m_childItems;
+ LdapDN m_dn;
+};
+
+/**
+ * @internal
+ */
+class LdapModelAttrNode : public LdapModelNode
+{
+public:
+ explicit LdapModelAttrNode(LdapModelDNNode *parent = Q_NULLPTR,
+ const QString &attrName = QString(),
+ const QByteArray &attrData = QByteArray());
+ ~LdapModelAttrNode();
+
+ LdapModelNode::NodeType nodeType() const Q_DECL_OVERRIDE
+ {
+ return LdapModelNode::Attr;
+ }
+
+ const QString &attributeName()
+ {
+ return m_attrName;
+ }
+ const QByteArray &attributeData()
+ {
+ return m_attrData;
+ }
+
+private:
+ QString m_attrName;
+ QByteArray m_attrData;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapobject.h"
+#include "ldif.h"
+
+#include <QtCore/QSharedData>
+
+using namespace KLDAP;
+
+class LdapObjectPrivate : public QSharedData
+{
+public:
+ LdapObjectPrivate()
+ {
+ }
+
+ LdapObjectPrivate(const LdapObjectPrivate &other)
+ : QSharedData(other)
+ {
+ mDn = other.mDn;
+ mAttrs = other.mAttrs;
+ }
+
+ LdapDN mDn;
+ LdapAttrMap mAttrs;
+};
+
+LdapObject::LdapObject()
+ : d(new LdapObjectPrivate)
+{
+}
+
+LdapObject::LdapObject(const QString &dn)
+ : d(new LdapObjectPrivate)
+{
+ d->mDn = LdapDN(dn);
+}
+
+LdapObject::~LdapObject()
+{
+}
+
+LdapObject::LdapObject(const LdapObject &that)
+ : d(that.d)
+{
+}
+
+LdapObject &LdapObject::operator=(const LdapObject &that)
+{
+ if (this != &that) {
+ d = that.d;
+ }
+
+ return *this;
+}
+
+void LdapObject::setDn(const LdapDN &dn)
+{
+ d->mDn = dn;
+}
+
+void LdapObject::setDn(const QString &dn)
+{
+ d->mDn = LdapDN(dn);
+}
+
+void LdapObject::setAttributes(const LdapAttrMap &attrs)
+{
+ d->mAttrs = attrs;
+}
+
+LdapDN LdapObject::dn() const
+{
+ return d->mDn;
+}
+
+const LdapAttrMap &LdapObject::attributes() const
+{
+ return d->mAttrs;
+}
+
+QString LdapObject::toString() const
+{
+ QString result = QStringLiteral("dn: %1\n").arg(d->mDn.toString());
+ LdapAttrMap::ConstIterator end(d->mAttrs.constEnd());
+ for (LdapAttrMap::ConstIterator it = d->mAttrs.constBegin(); it != end; ++it) {
+ const QString attr = it.key();
+ LdapAttrValue::ConstIterator end2((*it).constEnd());
+ for (LdapAttrValue::ConstIterator it2 = (*it).constBegin(); it2 != end2; ++it2) {
+ result += QString::fromUtf8(Ldif::assembleLine(attr, *it2, 76)) + QLatin1Char('\n');
+ }
+ }
+ return result;
+}
+
+void LdapObject::clear()
+{
+ d->mDn.clear();
+ d->mAttrs.clear();
+}
+
+void LdapObject::setValues(const QString &attributeName, const LdapAttrValue &values)
+{
+ d->mAttrs[ attributeName ] = values;
+}
+
+void LdapObject::addValue(const QString &attributeName, const QByteArray &value)
+{
+ d->mAttrs[ attributeName ].append(value);
+}
+
+LdapAttrValue LdapObject::values(const QString &attributeName) const
+{
+ if (hasAttribute(attributeName)) {
+ return d->mAttrs.value(attributeName);
+ } else {
+ return LdapAttrValue();
+ }
+}
+
+QByteArray LdapObject::value(const QString &attributeName) const
+{
+ if (hasAttribute(attributeName)) {
+ return d->mAttrs.value(attributeName).first();
+ } else {
+ return QByteArray();
+ }
+}
+
+bool LdapObject::hasAttribute(const QString &attributeName) const
+{
+ return d->mAttrs.contains(attributeName);
+}
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPOBJECT_H
+#define KLDAP_LDAPOBJECT_H
+
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QSharedDataPointer>
+#include <QtCore/QString>
+class LdapObjectPrivate;
+
+#include "ldapdn.h"
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+typedef QList<QByteArray> LdapAttrValue;
+typedef QMap<QString, LdapAttrValue > LdapAttrMap;
+
+/**
+ * @brief
+ * This class represents an LDAP Object
+*/
+class KLDAP_EXPORT LdapObject
+{
+public:
+ LdapObject();
+ explicit LdapObject(const QString &dn);
+ virtual ~LdapObject();
+
+ LdapObject(const LdapObject &that);
+ LdapObject &operator=(const LdapObject &that);
+
+ /**
+ * Returns the text presentation (LDIF format) of the object.
+ */
+ QString toString() const;
+
+ /**
+ * Clears the name and attributes of the object.
+ */
+ void clear();
+ /**
+ * Sets the Distinguished Name of the object.
+ */
+ void setDn(const LdapDN &dn);
+ /**
+ * Sets the Distinguished Name of the object.
+ */
+ void setDn(const QString &dn);
+ /**
+ * Sets the attributes and attribute values of the object.
+ */
+ void setAttributes(const LdapAttrMap &attrs);
+ /**
+ * Sets the given attribute values. If the given attribute not exists,
+ * then it's created, if exists, it's overwritten.
+ * @param attributeName the attribute name for which to set values
+ * @param values the values of attribute to set
+ */
+ void setValues(const QString &attributeName, const LdapAttrValue &values);
+ /**
+ * Adds the given value to the specified attribute. If the given attribute
+ * not exists, then it's created.
+ * @param attributeName the attribute for which to add a value
+ * @param value the attribute value to add
+ */
+ void addValue(const QString &attributeName, const QByteArray &value);
+ /**
+ * Return the Distinguished Name of the object.
+ */
+ LdapDN dn() const;
+ /**
+ * Returns the attributes and their values.
+ */
+ const LdapAttrMap &attributes() const;
+ /**
+ * Returns all values of the attribute with the given name.
+ */
+ LdapAttrValue values(const QString &attributeName) const;
+ /**
+ * Returns the first value of the attribute with the given name
+ * or an empty byte array if the attribute does not exists.
+ */
+ QByteArray value(const QString &attributeName) const;
+ /**
+ * Returns true if the given attributethe exists, false otherwise.
+ */
+ bool hasAttribute(const QString &attributeName) const;
+
+private:
+ QSharedDataPointer<LdapObjectPrivate> d;
+};
+
+typedef QVector<LdapObject> LdapObjects;
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapoperation.h"
+#include "kldap_config.h"
+
+#include "ldap_debug.h"
+
+#include <QtCore/QTime>
+
+#include <stdlib.h>
+
+//for struct timeval
+#if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+#elif defined(_WIN32)
+# include <winsock2.h>
+#endif
+
+#ifdef SASL2_FOUND
+#include <sasl/sasl.h>
+#endif
+
+#ifdef LDAP_FOUND
+# ifndef HAVE_WINLDAP_H
+# include <lber.h>
+# include <ldap.h>
+# else
+# include <w32-ldap-help.h>
+# endif // HAVE_WINLDAP_H
+#endif // LDAP_FOUND
+
+#include "ldapdefs.h"
+
+using namespace KLDAP;
+
+#ifdef LDAP_FOUND
+static void extractControls(LdapControls &ctrls, LDAPControl **pctrls);
+#endif // LDAP_FOUND
+
+/*
+ Returns the difference between msecs and elapsed. If msecs is -1,
+ however, -1 is returned.
+*/
+static int kldap_timeout_value(int msecs, int elapsed)
+{
+ if (msecs == -1) {
+ return -1;
+ }
+
+ int timeout = msecs - elapsed;
+ return timeout < 0 ? 0 : timeout;
+}
+
+class Q_DECL_HIDDEN LdapOperation::LdapOperationPrivate
+{
+public:
+ LdapOperationPrivate();
+ ~LdapOperationPrivate();
+#ifdef LDAP_FOUND
+ int processResult(int rescode, LDAPMessage *msg);
+ int bind(const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data, bool async);
+#endif
+ LdapControls mClientCtrls, mServerCtrls, mControls;
+ LdapObject mObject;
+ QByteArray mExtOid, mExtData;
+ QByteArray mServerCred;
+ QString mMatchedDn;
+ QList<QByteArray> mReferrals;
+
+ LdapConnection *mConnection;
+};
+
+LdapOperation::LdapOperation()
+ : d(new LdapOperationPrivate)
+{
+ d->mConnection = Q_NULLPTR;
+}
+
+LdapOperation::LdapOperation(LdapConnection &conn)
+ : d(new LdapOperationPrivate)
+{
+ setConnection(conn);
+}
+
+LdapOperation::~LdapOperation()
+{
+ delete d;
+}
+
+void LdapOperation::setConnection(LdapConnection &conn)
+{
+ d->mConnection = &conn;
+}
+
+LdapConnection &LdapOperation::connection()
+{
+ return *d->mConnection;
+}
+
+void LdapOperation::setClientControls(const LdapControls &ctrls)
+{
+ d->mClientCtrls = ctrls;
+}
+
+void LdapOperation::setServerControls(const LdapControls &ctrls)
+{
+ d->mServerCtrls = ctrls;
+}
+
+LdapControls LdapOperation::clientControls() const
+{
+ return d->mClientCtrls;
+}
+
+LdapControls LdapOperation::serverControls() const
+{
+ return d->mServerCtrls;
+}
+
+LdapObject LdapOperation::object() const
+{
+ return d->mObject;
+}
+
+LdapControls LdapOperation::controls() const
+{
+ return d->mControls;
+}
+
+QByteArray LdapOperation::extendedOid() const
+{
+ return d->mExtOid;
+}
+
+QByteArray LdapOperation::extendedData() const
+{
+ return d->mExtData;
+}
+
+QString LdapOperation::matchedDn() const
+{
+ return d->mMatchedDn;
+}
+
+QList<QByteArray> LdapOperation::referrals() const
+{
+ return d->mReferrals;
+}
+
+QByteArray LdapOperation::serverCred() const
+{
+ return d->mServerCred;
+}
+
+LdapOperation::LdapOperationPrivate::LdapOperationPrivate()
+ : mConnection(Q_NULLPTR)
+{
+}
+
+LdapOperation::LdapOperationPrivate::~LdapOperationPrivate()
+{
+}
+
+#ifdef LDAP_FOUND
+
+#ifdef SASL2_FOUND
+static int kldap_sasl_interact(sasl_interact_t *interact, LdapOperation::SASL_Data *data)
+{
+ if (data->proc) {
+ for (; interact->id != SASL_CB_LIST_END; interact++) {
+ switch (interact->id) {
+ case SASL_CB_GETREALM:
+ data->creds.fields |= LdapOperation::SASL_Realm;
+ break;
+ case SASL_CB_AUTHNAME:
+ data->creds.fields |= LdapOperation::SASL_Authname;
+ break;
+ case SASL_CB_PASS:
+ data->creds.fields |= LdapOperation::SASL_Password;
+ break;
+ case SASL_CB_USER:
+ data->creds.fields |= LdapOperation::SASL_Authzid;
+ break;
+ }
+ }
+ int retval;
+ if ((retval = data->proc(data->creds, data->data))) {
+ return retval;
+ }
+ }
+
+ QString value;
+
+ while (interact->id != SASL_CB_LIST_END) {
+ value.clear();
+ switch (interact->id) {
+ case SASL_CB_GETREALM:
+ value = data->creds.realm;
+ qCDebug(LDAP_LOG) << "SASL_REALM=" << value;
+ break;
+ case SASL_CB_AUTHNAME:
+ value = data->creds.authname;
+ qCDebug(LDAP_LOG) << "SASL_AUTHNAME=" << value;
+ break;
+ case SASL_CB_PASS:
+ value = data->creds.password;
+ qCDebug(LDAP_LOG) << "SASL_PASSWD=[hidden]";
+ break;
+ case SASL_CB_USER:
+ value = data->creds.authzid;
+ qCDebug(LDAP_LOG) << "SASL_AUTHZID=" << value;
+ break;
+ }
+ if (value.isEmpty()) {
+ interact->result = Q_NULLPTR;
+ interact->len = 0;
+ } else {
+ interact->result = strdup(value.toUtf8());
+ interact->len = strlen((const char *)interact->result);
+ }
+ interact++;
+ }
+ return KLDAP_SUCCESS;
+}
+#endif
+
+int LdapOperation::LdapOperationPrivate::bind(const QByteArray &creds,
+ SASL_Callback_Proc *saslproc,
+ void *data, bool async)
+{
+ Q_ASSERT(mConnection);
+ LDAP *ld = (LDAP *) mConnection->handle();
+ LdapServer server;
+ server = mConnection->server();
+
+ int ret;
+
+ if (server.auth() == LdapServer::SASL) {
+#if defined( SASL2_FOUND ) && !defined( HAVE_WINLDAP_H )
+ sasl_conn_t *saslconn = (sasl_conn_t *)mConnection->saslHandle();
+ sasl_interact_t *client_interact = Q_NULLPTR;
+ const char *out = Q_NULLPTR;
+ uint outlen;
+ const char *mechusing = Q_NULLPTR;
+ struct berval ccred, *scred;
+ int saslresult;
+ QByteArray sdata = creds;
+
+ QString mech = server.mech();
+ if (mech.isEmpty()) {
+ mech = QStringLiteral("DIGEST-MD5");
+ }
+
+ SASL_Data sasldata;
+ sasldata.proc = saslproc;
+ sasldata.data = data;
+ sasldata.creds.fields = 0;
+ sasldata.creds.realm = server.realm();
+ sasldata.creds.authname = server.user();
+ sasldata.creds.authzid = server.bindDn();
+ sasldata.creds.password = server.password();
+
+ do {
+ if (sdata.isEmpty()) {
+ do {
+ saslresult = sasl_client_start(saslconn, mech.toLatin1(),
+ &client_interact, &out, &outlen, &mechusing);
+
+ if (saslresult == SASL_INTERACT) {
+ if (kldap_sasl_interact(client_interact, &sasldata) != KLDAP_SUCCESS) {
+ return KLDAP_SASL_ERROR;
+ }
+ }
+ qCDebug(LDAP_LOG) << "sasl_client_start mech: "
+ << mechusing << " outlen " << outlen
+ << " result: " << saslresult;
+ } while (saslresult == SASL_INTERACT);
+ if (saslresult != SASL_CONTINUE && saslresult != SASL_OK) {
+ return KLDAP_SASL_ERROR;
+ }
+
+ } else {
+ qCDebug(LDAP_LOG) << "sasl_client_step";
+ do {
+ saslresult = sasl_client_step(saslconn, sdata.data(), sdata.size(),
+ &client_interact, &out, &outlen);
+ if (saslresult == SASL_INTERACT) {
+ if (kldap_sasl_interact(client_interact, &sasldata) != KLDAP_SUCCESS) {
+ return KLDAP_SASL_ERROR;
+ }
+ }
+ } while (saslresult == SASL_INTERACT);
+ qCDebug(LDAP_LOG) << "sasl_client_step result" << saslresult;
+ if (saslresult != SASL_CONTINUE && saslresult != SASL_OK) {
+ return KLDAP_SASL_ERROR;
+ }
+ }
+
+ ccred.bv_val = (char *) out;
+ ccred.bv_len = outlen;
+
+ if (async) {
+ qCDebug(LDAP_LOG) << "ldap_sasl_bind";
+ int msgid;
+ ret =
+ ldap_sasl_bind(ld, server.bindDn().toUtf8().data(), mech.toLatin1(),
+ &ccred, Q_NULLPTR, Q_NULLPTR, &msgid);
+ if (ret == 0) {
+ ret = msgid;
+ }
+ qCDebug(LDAP_LOG) << "ldap_sasl_bind msgid" << ret;
+ } else {
+ qCDebug(LDAP_LOG) << "ldap_sasl_bind_s";
+ ret =
+ ldap_sasl_bind_s(ld, server.bindDn().toUtf8().data(), mech.toLatin1(),
+ &ccred, Q_NULLPTR, Q_NULLPTR, &scred);
+ qCDebug(LDAP_LOG) << "ldap_sasl_bind_s ret" << ret;
+ if (scred) {
+ sdata = QByteArray(scred->bv_val, scred->bv_len);
+ } else {
+ sdata = QByteArray();
+ }
+ }
+ } while (!async && ret == KLDAP_SASL_BIND_IN_PROGRESS);
+#else
+ qCritical() << "SASL authentication is not available "
+ << "(re-compile kldap with cyrus-sasl and OpenLDAP development).";
+ return KLDAP_SASL_ERROR;
+#endif
+ } else { //simple auth
+ QByteArray bindname, pass;
+ struct berval ccred;
+ if (server.auth() == LdapServer::Simple) {
+ bindname = server.bindDn().toUtf8();
+ pass = server.password().toUtf8();
+ }
+ ccred.bv_val = pass.data();
+ ccred.bv_len = pass.size();
+ qCDebug(LDAP_LOG) << "binding to server, bindname: " << bindname << " password: *****";
+
+ if (async) {
+ qCDebug(LDAP_LOG) << "ldap_sasl_bind (simple)";
+#ifndef HAVE_WINLDAP_H
+ int msgid = 0;
+ ret = ldap_sasl_bind(ld, bindname.data(), Q_NULLPTR, &ccred, Q_NULLPTR, Q_NULLPTR, &msgid);
+ if (ret == 0) {
+ ret = msgid;
+ }
+#else
+ ret = ldap_simple_bind(ld, bindname.data(), pass.data());
+#endif
+ } else {
+ qCDebug(LDAP_LOG) << "ldap_sasl_bind_s (simple)";
+#ifndef HAVE_WINLDAP_H
+ ret = ldap_sasl_bind_s(ld, bindname.data(), Q_NULLPTR, &ccred, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR);
+#else
+ ret = ldap_simple_bind_s(ld, bindname.data(), pass.data());
+#endif
+ }
+ }
+ return ret;
+}
+
+int LdapOperation::LdapOperationPrivate::processResult(int rescode, LDAPMessage *msg)
+{
+ //qCDebug(LDAP_LOG);
+ int retval;
+ LDAP *ld = (LDAP *) mConnection->handle();
+
+ qCDebug(LDAP_LOG) << "rescode: " << rescode;
+ switch (rescode) {
+ case RES_SEARCH_ENTRY: {
+ //qCDebug(LDAP_LOG) << "Found search entry";
+ mObject.clear();
+ LdapAttrMap attrs;
+ char *name;
+ struct berval **bvals;
+ BerElement *entry;
+
+ char *dn = ldap_get_dn(ld, msg);
+ mObject.setDn(QString::fromUtf8(dn));
+ ldap_memfree(dn);
+
+ // iterate over the attributes
+ name = ldap_first_attribute(ld, msg, &entry);
+ while (name != Q_NULLPTR) {
+ // print the values
+ bvals = ldap_get_values_len(ld, msg, name);
+ LdapAttrValue values;
+ if (bvals) {
+ for (int i = 0; bvals[i] != Q_NULLPTR; i++) {
+ char *val = bvals[i]->bv_val;
+ unsigned long len = bvals[i]->bv_len;
+ values.append(QByteArray(val, len));
+ }
+ ldap_value_free_len(bvals);
+ }
+ attrs[ QString::fromLatin1(name) ] = values;
+ ldap_memfree(name);
+
+ // next attribute
+ name = ldap_next_attribute(ld, msg, entry);
+ }
+ ber_free(entry, 0);
+ mObject.setAttributes(attrs);
+ break;
+ }
+ case RES_SEARCH_REFERENCE:
+ // Will only get this if following references is disabled. ignore it
+ rescode = 0;
+ break;
+ case RES_EXTENDED: {
+ char *retoid;
+ struct berval *retdata;
+ retval = ldap_parse_extended_result(ld, msg, &retoid, &retdata, 0);
+ if (retval != KLDAP_SUCCESS) {
+ ldap_msgfree(msg);
+ return -1;
+ }
+ mExtOid = retoid ? QByteArray(retoid) : QByteArray();
+ mExtData = retdata ? QByteArray(retdata->bv_val, retdata->bv_len) : QByteArray();
+ ldap_memfree(retoid);
+ ber_bvfree(retdata);
+ break;
+ }
+ case RES_BIND: {
+ struct berval *servercred = Q_NULLPTR;
+#ifndef HAVE_WINLDAP_H
+ // FIXME: Error handling Winldap does not have ldap_parse_sasl_bind_result
+ retval = ldap_parse_sasl_bind_result(ld, msg, &servercred, 0);
+#else
+ retval = KLDAP_SUCCESS;
+#endif
+ if (retval != KLDAP_SUCCESS && retval != KLDAP_SASL_BIND_IN_PROGRESS) {
+ qCDebug(LDAP_LOG) << "RES_BIND error: " << retval;
+ ldap_msgfree(msg);
+ return -1;
+ }
+ qCDebug(LDAP_LOG) << "RES_BIND rescode" << rescode << "retval:" << retval;
+ if (servercred) {
+ mServerCred = QByteArray(servercred->bv_val, servercred->bv_len);
+ ber_bvfree(servercred);
+ } else {
+ mServerCred = QByteArray();
+ }
+ break;
+ }
+ default: {
+ LDAPControl **serverctrls = Q_NULLPTR;
+ char *matcheddn = Q_NULLPTR, *errmsg = Q_NULLPTR;
+ char **referralsp;
+ int errcodep;
+ retval =
+ ldap_parse_result(ld, msg, &errcodep, &matcheddn, &errmsg, &referralsp,
+ &serverctrls, 0);
+ qCDebug(LDAP_LOG) << "rescode" << rescode << "retval:" << retval
+ << "matcheddn:" << matcheddn << "errcode:"
+ << errcodep << "errmsg:" << errmsg;
+ if (retval != KLDAP_SUCCESS) {
+ ldap_msgfree(msg);
+ return -1;
+ }
+ mControls.clear();
+ if (serverctrls) {
+ extractControls(mControls, serverctrls);
+ ldap_controls_free(serverctrls);
+ }
+ mReferrals.clear();
+ if (referralsp) {
+ char **tmp = referralsp;
+ while (*tmp) {
+ mReferrals.append(QByteArray(*tmp));
+ ldap_memfree(*tmp);
+ tmp++;
+ }
+ ldap_memfree((char *) referralsp);
+ }
+ mMatchedDn.clear();
+ if (matcheddn) {
+ mMatchedDn = QString::fromUtf8(matcheddn);
+ ldap_memfree(matcheddn);
+ }
+ if (errmsg) {
+ ldap_memfree(errmsg);
+ }
+ }
+ }
+
+ ldap_msgfree(msg);
+
+ return rescode;
+}
+
+static void addModOp(LDAPMod ***pmods, int mod_type, const QString &attr,
+ const QByteArray *value = Q_NULLPTR)
+{
+ // qCDebug(LDAP_LOG) << "type:" << mod_type << "attr:" << attr <<
+ // "value:" << QString::fromUtf8(value,value.size()) <<
+ // "size:" << value.size();
+ LDAPMod **mods;
+
+ mods = *pmods;
+
+ uint i = 0;
+
+ if (mods == Q_NULLPTR) {
+ mods = (LDAPMod **)malloc(2 * sizeof(LDAPMod *));
+ mods[ 0 ] = (LDAPMod *)malloc(sizeof(LDAPMod));
+ mods[ 1 ] = Q_NULLPTR;
+ memset(mods[ 0 ], 0, sizeof(LDAPMod));
+ } else {
+ while (mods[ i ] != Q_NULLPTR &&
+ (strcmp(attr.toUtf8(), mods[i]->mod_type) != 0 ||
+ (mods[ i ]->mod_op & ~LDAP_MOD_BVALUES) != mod_type)) {
+ i++;
+ }
+
+ if (mods[ i ] == Q_NULLPTR) {
+ mods = (LDAPMod **)realloc(mods, (i + 2) * sizeof(LDAPMod *));
+ if (mods == Q_NULLPTR) {
+ qCritical() << "addModOp: realloc";
+ return;
+ }
+ mods[ i + 1 ] = Q_NULLPTR;
+ mods[ i ] = (LDAPMod *) malloc(sizeof(LDAPMod));
+ memset(mods[ i ], 0, sizeof(LDAPMod));
+ }
+ }
+
+ mods[ i ]->mod_op = mod_type | LDAP_MOD_BVALUES;
+ if (mods[ i ]->mod_type == Q_NULLPTR) {
+ mods[ i ]->mod_type = strdup(attr.toUtf8());
+ }
+
+ *pmods = mods;
+
+ if (value == Q_NULLPTR) {
+ return;
+ }
+
+ int vallen = value->size();
+ BerValue *berval;
+ berval = (BerValue *) malloc(sizeof(BerValue));
+ berval -> bv_len = vallen;
+ if (vallen > 0) {
+ berval -> bv_val = (char *) malloc(vallen);
+ memcpy(berval -> bv_val, value->data(), vallen);
+ } else {
+ berval -> bv_val = Q_NULLPTR;
+ }
+
+ if (mods[ i ] -> mod_vals.modv_bvals == Q_NULLPTR) {
+ mods[ i ]->mod_vals.modv_bvals =
+ (BerValue **) malloc(sizeof(BerValue *) * 2);
+ mods[ i ]->mod_vals.modv_bvals[ 0 ] = berval;
+ mods[ i ]->mod_vals.modv_bvals[ 1 ] = Q_NULLPTR;
+// qCDebug(LDAP_LOG) << "new bervalue struct" << attr << value;
+ } else {
+ uint j = 0;
+ while (mods[ i ]->mod_vals.modv_bvals[ j ] != Q_NULLPTR) {
+ j++;
+ }
+ mods[ i ]->mod_vals.modv_bvals =
+ (BerValue **)realloc(mods[ i ]->mod_vals.modv_bvals,
+ (j + 2) * sizeof(BerValue *));
+ if (mods[ i ]->mod_vals.modv_bvals == Q_NULLPTR) {
+ qCritical() << "addModOp: realloc";
+ free(berval);
+ return;
+ }
+ mods[ i ]->mod_vals.modv_bvals[ j ] = berval;
+ mods[ i ]->mod_vals.modv_bvals[ j + 1 ] = Q_NULLPTR;
+ qCDebug(LDAP_LOG) << j << ". new bervalue";
+ }
+}
+
+static void addControlOp(LDAPControl ***pctrls, const QString &oid,
+ const QByteArray &value, bool critical)
+{
+ LDAPControl **ctrls;
+ LDAPControl *ctrl = (LDAPControl *) malloc(sizeof(LDAPControl));
+
+ ctrls = *pctrls;
+
+ qCDebug(LDAP_LOG) << "oid:'" << oid << "' val: '" << value << "'";
+ int vallen = value.size();
+ ctrl->ldctl_value.bv_len = vallen;
+ if (vallen) {
+ ctrl->ldctl_value.bv_val = (char *) malloc(vallen);
+ memcpy(ctrl->ldctl_value.bv_val, value.data(), vallen);
+ } else {
+ ctrl->ldctl_value.bv_val = Q_NULLPTR;
+ }
+ ctrl->ldctl_iscritical = critical;
+ ctrl->ldctl_oid = strdup(oid.toUtf8());
+
+ uint i = 0;
+
+ if (ctrls == Q_NULLPTR) {
+ ctrls = (LDAPControl **)malloc(2 * sizeof(LDAPControl *));
+ ctrls[ 0 ] = Q_NULLPTR;
+ ctrls[ 1 ] = Q_NULLPTR;
+ } else {
+ while (ctrls[ i ] != Q_NULLPTR) {
+ i++;
+ }
+ ctrls[ i + 1 ] = Q_NULLPTR;
+ ctrls =
+ (LDAPControl **)realloc(ctrls, (i + 2) * sizeof(LDAPControl *));
+ }
+ ctrls[ i ] = ctrl;
+ *pctrls = ctrls;
+}
+
+static void createControls(LDAPControl ***pctrls, const LdapControls &ctrls)
+{
+ for (int i = 0; i < ctrls.count(); ++i) {
+ addControlOp(pctrls, ctrls[i].oid(), ctrls[i].value(), ctrls[i].critical());
+ }
+}
+
+static void extractControls(LdapControls &ctrls, LDAPControl **pctrls)
+{
+ LDAPControl *ctrl;
+ LdapControl control;
+ int i = 0;
+
+ while (pctrls[i]) {
+ ctrl = pctrls[ i ];
+ control.setOid(QString::fromUtf8(ctrl->ldctl_oid));
+ control.setValue(QByteArray(ctrl->ldctl_value.bv_val,
+ ctrl->ldctl_value.bv_len));
+ control.setCritical(ctrl->ldctl_iscritical);
+ ctrls.append(control);
+ i++;
+ }
+}
+
+int LdapOperation::bind(const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data)
+{
+ return d->bind(creds, saslproc, data, true);
+}
+
+int LdapOperation::bind_s(SASL_Callback_Proc *saslproc, void *data)
+{
+ return d->bind(QByteArray(), saslproc, data, false);
+}
+
+int LdapOperation::search(const LdapDN &base, LdapUrl::Scope scope,
+ const QString &filter, const QStringList &attributes)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ char **attrs = Q_NULLPTR;
+ int msgid;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int count = attributes.count();
+ if (count > 0) {
+ attrs = static_cast<char **>(malloc((count + 1) * sizeof(char *)));
+ for (int i = 0; i < count; i++) {
+ attrs[i] = strdup(attributes.at(i).toUtf8());
+ }
+ attrs[count] = Q_NULLPTR;
+ }
+
+ int lscope = LDAP_SCOPE_BASE;
+ switch (scope) {
+ case LdapUrl::Base:
+ lscope = LDAP_SCOPE_BASE;
+ break;
+ case LdapUrl::One:
+ lscope = LDAP_SCOPE_ONELEVEL;
+ break;
+ case LdapUrl::Sub:
+ lscope = LDAP_SCOPE_SUBTREE;
+ break;
+ }
+
+ qCDebug(LDAP_LOG) << "asyncSearch() base=\"" << base.toString()
+ << "\" scope=" << (int)scope
+ << "filter=\"" << filter
+ << "\" attrs=" << attributes;
+ int retval =
+ ldap_search_ext(ld, base.toString().toUtf8().data(), lscope,
+ filter.isEmpty() ? QByteArray("objectClass=*").data() :
+ filter.toUtf8().data(),
+ attrs, 0, serverctrls, clientctrls, Q_NULLPTR,
+ d->mConnection->sizeLimit(), &msgid);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ // free the attributes list again
+ if (count > 0) {
+ for (int i = 0; i < count; i++) {
+ free(attrs[i]);
+ }
+ free(attrs);
+ }
+
+ if (retval == 0) {
+ retval = msgid;
+ }
+ return retval;
+}
+
+int LdapOperation::add(const LdapObject &object)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ int msgid;
+ LDAPMod **lmod = Q_NULLPTR;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ for (LdapAttrMap::ConstIterator it = object.attributes().begin();
+ it != object.attributes().end(); ++it) {
+ QString attr = it.key();
+ for (LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) {
+ addModOp(&lmod, 0, attr, &(*it2));
+ }
+ }
+
+ int retval =
+ ldap_add_ext(ld, object.dn().toString().toUtf8().data(), lmod, serverctrls,
+ clientctrls, &msgid);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+ ldap_mods_free(lmod, 1);
+ if (retval == 0) {
+ retval = msgid;
+ }
+ return retval;
+}
+
+int LdapOperation::add_s(const LdapObject &object)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ LDAPMod **lmod = Q_NULLPTR;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ for (LdapAttrMap::ConstIterator it = object.attributes().begin();
+ it != object.attributes().end(); ++it) {
+ QString attr = it.key();
+ for (LdapAttrValue::ConstIterator it2 = (*it).begin(); it2 != (*it).end(); ++it2) {
+ addModOp(&lmod, 0, attr, &(*it2));
+ }
+ }
+
+ int retval =
+ ldap_add_ext_s(ld, object.dn().toString().toUtf8().data(), lmod, serverctrls,
+ clientctrls);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+ ldap_mods_free(lmod, 1);
+ return retval;
+}
+
+int LdapOperation::add(const LdapDN &dn, const ModOps &ops)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ int msgid;
+ LDAPMod **lmod = Q_NULLPTR;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ for (int i = 0; i < ops.count(); ++i) {
+ for (int j = 0; j < ops[i].values.count(); ++j) {
+ addModOp(&lmod, 0, ops[i].attr, &ops[i].values[j]);
+ }
+ }
+
+ int retval =
+ ldap_add_ext(ld, dn.toString().toUtf8().data(), lmod, serverctrls,
+ clientctrls, &msgid);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+ ldap_mods_free(lmod, 1);
+ if (retval == 0) {
+ retval = msgid;
+ }
+ return retval;
+}
+
+int LdapOperation::add_s(const LdapDN &dn, const ModOps &ops)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ LDAPMod **lmod = Q_NULLPTR;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ for (int i = 0; i < ops.count(); ++i) {
+ for (int j = 0; j < ops[i].values.count(); ++j) {
+ addModOp(&lmod, 0, ops[i].attr, &ops[i].values[j]);
+ }
+ }
+ qCDebug(LDAP_LOG) << dn.toString();
+ int retval =
+ ldap_add_ext_s(ld, dn.toString().toUtf8().data(), lmod, serverctrls,
+ clientctrls);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+ ldap_mods_free(lmod, 1);
+ return retval;
+}
+
+int LdapOperation::rename(const LdapDN &dn, const QString &newRdn,
+ const QString &newSuperior, bool deleteold)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ int msgid;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int retval = ldap_rename(ld, dn.toString().toUtf8().data(), newRdn.toUtf8().data(),
+ newSuperior.isEmpty() ? (char *) Q_NULLPTR : newSuperior.toUtf8().data(),
+ deleteold, serverctrls, clientctrls, &msgid);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ if (retval == 0) {
+ retval = msgid;
+ }
+ return retval;
+}
+
+int LdapOperation::rename_s(const LdapDN &dn, const QString &newRdn,
+ const QString &newSuperior, bool deleteold)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int retval = ldap_rename_s(ld, dn.toString().toUtf8().data(), newRdn.toUtf8().data(),
+ newSuperior.isEmpty() ? (char *) Q_NULLPTR : newSuperior.toUtf8().data(),
+ deleteold, serverctrls, clientctrls);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ return retval;
+}
+
+int LdapOperation::del(const LdapDN &dn)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ int msgid;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int retval =
+ ldap_delete_ext(ld, dn.toString().toUtf8().data(), serverctrls, clientctrls, &msgid);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ if (retval == 0) {
+ retval = msgid;
+ }
+ return retval;
+}
+
+int LdapOperation::del_s(const LdapDN &dn)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int retval = ldap_delete_ext_s(ld, dn.toString().toUtf8().data(), serverctrls, clientctrls);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ return retval;
+}
+
+int LdapOperation::modify(const LdapDN &dn, const ModOps &ops)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *)d->mConnection->handle();
+
+ int msgid;
+ LDAPMod **lmod = Q_NULLPTR;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ for (int i = 0; i < ops.count(); ++i) {
+ int mtype = 0;
+ switch (ops[i].type) {
+ case Mod_None:
+ mtype = 0;
+ break;
+ case Mod_Add:
+ mtype = LDAP_MOD_ADD;
+ break;
+ case Mod_Replace:
+ mtype = LDAP_MOD_REPLACE;
+ break;
+ case Mod_Del:
+ mtype = LDAP_MOD_DELETE;
+ break;
+ }
+ addModOp(&lmod, mtype, ops[i].attr, Q_NULLPTR);
+ for (int j = 0; j < ops[i].values.count(); ++j) {
+ addModOp(&lmod, mtype, ops[i].attr, &ops[i].values[j]);
+ }
+ }
+
+ int retval =
+ ldap_modify_ext(ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls, &msgid);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+ ldap_mods_free(lmod, 1);
+ if (retval == 0) {
+ retval = msgid;
+ }
+ return retval;
+}
+
+int LdapOperation::modify_s(const LdapDN &dn, const ModOps &ops)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ LDAPMod **lmod = Q_NULLPTR;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ for (int i = 0; i < ops.count(); ++i) {
+ int mtype = 0;
+ switch (ops[i].type) {
+ case Mod_None:
+ mtype = 0;
+ break;
+ case Mod_Add:
+ mtype = LDAP_MOD_ADD;
+ break;
+ case Mod_Replace:
+ mtype = LDAP_MOD_REPLACE;
+ break;
+ case Mod_Del:
+ mtype = LDAP_MOD_DELETE;
+ break;
+ }
+ addModOp(&lmod, mtype, ops[i].attr, Q_NULLPTR);
+ for (int j = 0; j < ops[i].values.count(); ++j) {
+ addModOp(&lmod, mtype, ops[i].attr, &ops[i].values[j]);
+ }
+ }
+
+ int retval =
+ ldap_modify_ext_s(ld, dn.toString().toUtf8().data(), lmod, serverctrls, clientctrls);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+ ldap_mods_free(lmod, 1);
+ return retval;
+}
+
+int LdapOperation::compare(const LdapDN &dn, const QString &attr, const QByteArray &value)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+ int msgid;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int vallen = value.size();
+ BerValue *berval;
+ berval = (BerValue *) malloc(sizeof(BerValue));
+ berval -> bv_val = (char *) malloc(vallen);
+ berval -> bv_len = vallen;
+ memcpy(berval -> bv_val, value.data(), vallen);
+
+ int retval = ldap_compare_ext(ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval,
+ serverctrls, clientctrls, &msgid);
+
+ ber_bvfree(berval);
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ if (retval == 0) {
+ retval = msgid;
+ }
+ return retval;
+}
+
+int LdapOperation::compare_s(const LdapDN &dn, const QString &attr, const QByteArray &value)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int vallen = value.size();
+ BerValue *berval;
+ berval = (BerValue *) malloc(sizeof(BerValue));
+ berval -> bv_val = (char *) malloc(vallen);
+ berval -> bv_len = vallen;
+ memcpy(berval -> bv_val, value.data(), vallen);
+
+ int retval = ldap_compare_ext_s(ld, dn.toString().toUtf8().data(), attr.toUtf8().data(), berval,
+ serverctrls, clientctrls);
+
+ ber_bvfree(berval);
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ return retval;
+}
+
+int LdapOperation::exop(const QString &oid, const QByteArray &data)
+{
+ Q_ASSERT(d->mConnection);
+#if defined(HAVE_LDAP_EXTENDED_OPERATION) && defined(HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE)
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+ int msgid;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int vallen = data.size();
+ BerValue *berval;
+ berval = (BerValue *) malloc(sizeof(BerValue));
+ berval -> bv_val = (char *) malloc(vallen);
+ berval -> bv_len = vallen;
+ memcpy(berval -> bv_val, data.data(), vallen);
+
+ int retval = ldap_extended_operation(ld, oid.toUtf8().data(), berval,
+ serverctrls, clientctrls, &msgid);
+
+ ber_bvfree(berval);
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ if (retval == 0) {
+ retval = msgid;
+ }
+ return retval;
+#else
+ qCritical() << "Your LDAP client libraries don't support extended operations.";
+ return -1;
+#endif
+}
+
+int LdapOperation::exop_s(const QString &oid, const QByteArray &data)
+{
+#if defined(HAVE_LDAP_EXTENDED_OPERATION) && defined(HAVE_LDAP_EXTENDED_OPERATION_PROTOTYPE)
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+ BerValue *retdata;
+ char *retoid;
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int vallen = data.size();
+ BerValue *berval;
+ berval = (BerValue *) malloc(sizeof(BerValue));
+ berval -> bv_val = (char *) malloc(vallen);
+ berval -> bv_len = vallen;
+ memcpy(berval -> bv_val, data.data(), vallen);
+
+ int retval = ldap_extended_operation_s(ld, oid.toUtf8().data(), berval,
+ serverctrls, clientctrls, &retoid, &retdata);
+
+ ber_bvfree(berval);
+ ber_bvfree(retdata);
+ free(retoid);
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ return retval;
+#else
+ qCritical() << "Your LDAP client libraries don't support extended operations.";
+ return -1;
+#endif
+}
+
+int LdapOperation::abandon(int id)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ LDAPControl **serverctrls = Q_NULLPTR, **clientctrls = Q_NULLPTR;
+ createControls(&serverctrls, d->mServerCtrls);
+ createControls(&serverctrls, d->mClientCtrls);
+
+ int retval = ldap_abandon_ext(ld, id, serverctrls, clientctrls);
+
+ ldap_controls_free(serverctrls);
+ ldap_controls_free(clientctrls);
+
+ return retval;
+}
+
+int LdapOperation::waitForResult(int id, int msecs)
+{
+ Q_ASSERT(d->mConnection);
+ LDAP *ld = (LDAP *) d->mConnection->handle();
+
+ LDAPMessage *msg;
+ int rescode;
+
+ QTime stopWatch;
+ stopWatch.start();
+ int attempt(1);
+ int timeout(0);
+
+ do {
+ // Calculate the timeout value to use and assign it to a timeval structure
+ // see man select (2) for details
+ timeout = kldap_timeout_value(msecs, stopWatch.elapsed());
+ qCDebug(LDAP_LOG) << "(" << id << "," << msecs
+ << "): Waiting" << timeout
+ << "msecs for result. Attempt #" << attempt++;
+ struct timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+ // Wait for a result
+ rescode = ldap_result(ld, id, 0, timeout < 0 ? Q_NULLPTR : &tv, &msg);
+ if (rescode == -1) {
+ return -1;
+ }
+ // Act on the return code
+ if (rescode != 0) {
+ // Some kind of result is available for processing
+ return d->processResult(rescode, msg);
+ }
+ } while (msecs == -1 || stopWatch.elapsed() < msecs);
+
+ return 0; //timeout
+}
+
+#else
+
+int LdapOperation::bind(const QByteArray &creds, SASL_Callback_Proc *saslproc, void *data)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::bind_s(SASL_Callback_Proc *saslproc, void *data)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::search(const LdapDN &base, LdapUrl::Scope scope,
+ const QString &filter, const QStringList &attributes)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::add(const LdapObject &object)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::add_s(const LdapObject &object)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::add(const LdapDN &dn, const ModOps &ops)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::add_s(const LdapDN &dn, const ModOps &ops)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::rename(const LdapDN &dn, const QString &newRdn,
+ const QString &newSuperior, bool deleteold)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::rename_s(const LdapDN &dn, const QString &newRdn,
+ const QString &newSuperior, bool deleteold)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::del(const LdapDN &dn)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::del_s(const LdapDN &dn)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::modify(const LdapDN &dn, const ModOps &ops)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::modify_s(const LdapDN &dn, const ModOps &ops)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::compare(const LdapDN &dn, const QString &attr, const QByteArray &value)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::exop(const QString &oid, const QByteArray &data)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::compare_s(const LdapDN &dn, const QString &attr, const QByteArray &value)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::exop_s(const QString &oid, const QByteArray &data)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::waitForResult(int id, int msecs)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+int LdapOperation::abandon(int id)
+{
+ qCritical() << "LDAP support not compiled";
+ return -1;
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPOPERATION_H
+#define KLDAP_LDAPOPERATION_H
+
+#include "kldap_export.h"
+#include "ldapconnection.h"
+#include "ldapcontrol.h"
+#include "ldapobject.h"
+#include "ldapdn.h"
+#include "ldapserver.h"
+#include "ldapurl.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QString>
+
+namespace KLDAP
+{
+
+/**
+ * @brief
+ * This class allows sending an ldap operation
+ * (search, rename, modify, delete, compare, exop) to an LDAP server.
+ */
+class KLDAP_EXPORT LdapOperation
+{
+public:
+ typedef enum {
+ Mod_None, Mod_Add, Mod_Replace, Mod_Del
+ } ModType;
+
+ typedef enum {
+ RES_BIND = 0x61,
+ RES_SEARCH_ENTRY = 0x64,
+ RES_SEARCH_REFERENCE = 0x73,
+ RES_SEARCH_RESULT = 0x65,
+ RES_MODIFY = 0x67,
+ RES_ADD = 0x69,
+ RES_DELETE = 0x69,
+ RES_MODDN = 0x6d,
+ RES_COMPARE = 0x6f,
+ RES_EXTENDED = 0x78,
+ RES_EXTENDED_PARTIAL = 0x79
+ } ResultType;
+
+ typedef struct {
+ ModType type;
+ QString attr;
+ QList<QByteArray> values;
+ } ModOp ;
+
+ typedef QVector<ModOp> ModOps;
+
+ enum SASL_Fields {
+ SASL_Authname = 0x1,
+ SASL_Authzid = 0x2,
+ SASL_Realm = 0x4,
+ SASL_Password = 0x8
+ };
+
+ struct SASL_Credentials {
+ int fields;
+ QString authname;
+ QString authzid;
+ QString realm;
+ QString password;
+ };
+
+ typedef int (SASL_Callback_Proc)(SASL_Credentials &cred, void *data);
+
+ struct SASL_Data {
+ SASL_Callback_Proc *proc;
+ void *data;
+ SASL_Credentials creds;
+ };
+
+ LdapOperation();
+ LdapOperation(LdapConnection &conn);
+ virtual ~LdapOperation();
+
+ /**
+ * Sets the connection object. Without living connection object,
+ * LDAP operations are not possible.
+ * @param the connection object to set
+ */
+ void setConnection(LdapConnection &conn);
+ /**
+ * Returns the connection object.
+ */
+ LdapConnection &connection();
+ /**
+ * Sets the client controls which will sent with each operation.
+ */
+ void setClientControls(const LdapControls &ctrls);
+ /**
+ * Sets the server controls which will sent with each operation.
+ */
+ void setServerControls(const LdapControls &ctrls);
+ /**
+ * Returns the client controls (which set by setClientControls()).
+ */
+ LdapControls clientControls() const;
+ /**
+ * Returns the server controls (which set by setServerControls()).
+ */
+ LdapControls serverControls() const;
+
+ /**
+ * Binds to the server which specified in the connection object.
+ * Can do simple or SASL bind. Returns a message id if successful, negative value if not.
+ */
+ int bind(const QByteArray &creds = QByteArray(),
+ SASL_Callback_Proc *saslproc = Q_NULLPTR, void *data = Q_NULLPTR);
+
+ /**
+ * Binds to the server which specified in the connection object.
+ * Can do simple or SASL bind. This is the synchronous version.
+ * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
+ */
+ int bind_s(SASL_Callback_Proc *saslproc = Q_NULLPTR, void *data = Q_NULLPTR);
+
+ /**
+ * Starts a search operation with the given base DN, scope, filter and
+ * result attributes. Returns a message id if successful, -1 if not.
+ */
+ int search(const LdapDN &base, LdapUrl::Scope scope,
+ const QString &filter, const QStringList &attrs);
+ /**
+ * Starts an addition operation.
+ * Returns a message id if successful, -1 if not.
+ * @param object the additional operation to start
+ */
+ int add(const LdapObject &object);
+ /**
+ * Adds the specified object to the LDAP database.
+ * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
+ * @param object the object to add to LDAP database
+ */
+ int add_s(const LdapObject &object);
+ /**
+ * Starts an addition operation. This version accepts ModOps not LdapObject.
+ * Returns a message id if successful, -1 if not.
+ * @param dn the LdapDN operation to start
+ * @param ops the ModOps operation to start
+ */
+ int add(const LdapDN &dn, const ModOps &ops);
+ /**
+ * Adds the specified object to the LDAP database. This version accepts ModOps not LdapObject.
+ * This is the synchronous version.
+ * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
+ * @param dn the LdapDN object to add
+ * @param ops the ModOps object to add
+ */
+ int add_s(const LdapDN &dn, const ModOps &ops);
+ /**
+ * Starts a modrdn operation on given DN, changing its RDN to newRdn,
+ * changing its parent to newSuperior (if it's not empty), and deletes
+ * the old dn if deleteold is true.
+ * Returns a message id if successful, -1 if not.
+ */
+ int rename(const LdapDN &dn, const QString &newRdn,
+ const QString &newSuperior, bool deleteold = true);
+ /**
+ * Performs a modrdn operation on given DN, changing its RDN to newRdn,
+ * changing its parent to newSuperior (if it's not empty), and deletes
+ * the old dn if deleteold is true. This is the synchronous version.
+ * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
+ */
+ int rename_s(const LdapDN &dn, const QString &newRdn,
+ const QString &newSuperior, bool deleteold = true);
+ /**
+ * Starts a delete operation on the given DN.
+ * Returns a message id if successful, -1 if not.
+ */
+ int del(const LdapDN &dn);
+ /**
+ * Deletes the given DN. This is the synchronous version.
+ * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
+ * @param dn the dn to delete
+ */
+ int del_s(const LdapDN &dn);
+ /**
+ * Starts a modify operation on the given DN.
+ * Returns a message id if successful, -1 if not.
+ * @param dn the DN to start modify operation on
+ */
+ int modify(const LdapDN &dn, const ModOps &ops);
+ /**
+ * Performs a modify operation on the given DN.
+ * This is the synchronous version.
+ * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
+ */
+ int modify_s(const LdapDN &dn, const ModOps &ops);
+ /**
+ * Starts a compare operation on the given DN, compares the specified
+ * attribute with the given value.
+ * Returns a message id if successful, -1 if not.
+ */
+ int compare(const LdapDN &dn, const QString &attr, const QByteArray &value);
+ /**
+ * Performs a compare operation on the given DN, compares the specified
+ * attribute with the given value. This is the synchronous version.
+ * Returns KLDAP_COMPARE_TRUE if the entry contains the attribute value
+ * and KLDAP_COMPARE_FALSE if it does not. Otherwise, some error code
+ * is returned.
+ */
+ int compare_s(const LdapDN &dn, const QString &attr, const QByteArray &value);
+ /**
+ * Starts an extended operation specified with oid and data.
+ * Returns a message id if successful, -1 if not.
+ */
+ int exop(const QString &oid, const QByteArray &data);
+ /**
+ * Performs an extended operation specified with oid and data.
+ * This is the synchronous version.
+ * Returns KLDAP_SUCCESS id if successful, else an LDAP error code.
+ */
+ int exop_s(const QString &oid, const QByteArray &data);
+ /**
+ * Abandons a long-running operation. Requires the message id.
+ */
+ int abandon(int id);
+ /**
+ * Waits for up to \p msecs milliseconds for a result message from the LDAP
+ * server. If \p msecs is -1, then this function will block indefinitely.
+ * If \p msecs is 0, then this function will return immediately, that is it
+ * will perform a poll for a result message.
+ *
+ * Returns the type of the result LDAP message (RES_XXX constants).
+ * -1 if error occurred, 0 if the timeout value elapsed. Note!
+ * Return code -1 means that fetching the message resulted in error,
+ * not the LDAP operation error. Call connection().ldapErrorCode() to
+ * determine if the operation succeeded.
+ */
+ int waitForResult(int id, int msecs = -1);
+ /**
+ * Returns the result object if result() returned RES_SEARCH_ENTRY.
+ */
+ LdapObject object() const;
+ /**
+ * Returns the server controls from the returned ldap message (grabbed
+ * by result()).
+ */
+ LdapControls controls() const;
+ /**
+ * Returns the OID of the extended operation response (result
+ * returned RES_EXTENDED).
+ */
+ QByteArray extendedOid() const;
+ /**
+ * Returns the data from the extended operation response (result
+ * returned RES_EXTENDED).
+ */
+ QByteArray extendedData() const;
+ /**
+ * The server might supply a matched DN string in the message indicating
+ * how much of a name in a request was recognized. This can be grabbed by
+ * matchedDn().
+ */
+ QString matchedDn() const;
+ /**
+ * This function returns the referral strings from the parsed message
+ * (if any).
+ */
+ QList<QByteArray> referrals() const;
+ /**
+ * Returns the server response for a bind request (result
+ * returned RES_BIND).
+ */
+ QByteArray serverCred() const;
+
+private:
+ class LdapOperationPrivate;
+ LdapOperationPrivate *const d;
+
+ Q_DISABLE_COPY(LdapOperation)
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapsearch.h"
+#include "ldapdn.h"
+#include "ldapdefs.h"
+
+#include <QtCore/QEventLoop>
+#include <QtCore/QTimer>
+
+#include "ldap_debug.h"
+#include <KLocalizedString>
+using namespace KLDAP;
+
+//blocking the GUI for xxx milliseconds
+#define LDAPSEARCH_BLOCKING_TIMEOUT 10
+
+class LdapSearchPrivate
+{
+public:
+ LdapSearchPrivate(LdapSearch *parent)
+ : mParent(parent)
+ {
+ }
+
+ void result();
+ bool connect();
+ void closeConnection();
+ bool startSearch(const LdapDN &base, LdapUrl::Scope scope,
+ const QString &filter, const QStringList &attributes,
+ int pagesize, int count);
+
+ LdapSearch *mParent;
+ LdapConnection *mConn;
+ LdapOperation mOp;
+ bool mOwnConnection, mAbandoned;
+ int mId, mPageSize;
+ LdapDN mBase;
+ QString mFilter;
+ QStringList mAttributes;
+ LdapUrl::Scope mScope;
+
+ QString mErrorString;
+ int mError;
+ int mCount, mMaxCount;
+ bool mFinished;
+};
+
+void LdapSearchPrivate::result()
+{
+ if (mAbandoned) {
+ mOp.abandon(mId);
+ return;
+ }
+ int res = mOp.waitForResult(mId, LDAPSEARCH_BLOCKING_TIMEOUT);
+
+ qCDebug(LDAP_LOG) << "LDAP result:" << res;
+
+ if (res != 0 &&
+ (res == -1 ||
+ (mConn->ldapErrorCode() != KLDAP_SUCCESS &&
+ mConn->ldapErrorCode() != KLDAP_SASL_BIND_IN_PROGRESS))) {
+ //error happened, but no timeout
+ mError = mConn->ldapErrorCode();
+ mErrorString = mConn->ldapErrorString();
+ emit mParent->result(mParent);
+ return;
+ }
+
+ //binding
+ if (res == LdapOperation::RES_BIND) {
+
+ QByteArray servercc;
+ servercc = mOp.serverCred();
+
+ qCDebug(LDAP_LOG) << "LdapSearch RES_BIND";
+ if (mConn->ldapErrorCode() == KLDAP_SUCCESS) { //bind succeeded
+ qCDebug(LDAP_LOG) << "bind succeeded";
+ LdapControls savedctrls = mOp.serverControls();
+ if (mPageSize) {
+ LdapControls ctrls = savedctrls;
+ LdapControl::insert(ctrls, LdapControl::createPageControl(mPageSize));
+ mOp.setServerControls(ctrls);
+ }
+
+ mId = mOp.search(mBase, mScope, mFilter, mAttributes);
+ mOp.setServerControls(savedctrls);
+ } else { //next bind step
+ qCDebug(LDAP_LOG) << "bind next step";
+ mId = mOp.bind(servercc);
+ }
+ if (mId < 0) {
+ if (mId == KLDAP_SASL_ERROR) {
+ mError = mId;
+ mErrorString = mConn->saslErrorString();
+ } else {
+ mError = mConn->ldapErrorCode();
+ mErrorString = mConn->ldapErrorString();
+ }
+ emit mParent->result(mParent);
+ return;
+ }
+ QTimer::singleShot(0, mParent, SLOT(result()));
+ return;
+ }
+
+ //End of entries
+ if (res == LdapOperation::RES_SEARCH_RESULT) {
+ if (mPageSize) {
+ QByteArray cookie;
+ int estsize = -1;
+ const int numberOfControls(mOp.controls().count());
+ for (int i = 0; i < numberOfControls; ++i) {
+ estsize = mOp.controls().at(i).parsePageControl(cookie);
+ if (estsize != -1) {
+ break;
+ }
+ }
+ qCDebug(LDAP_LOG) << " estimated size:" << estsize;
+ if (estsize != -1 && !cookie.isEmpty()) {
+ LdapControls ctrls, savedctrls;
+ savedctrls = mOp.serverControls();
+ ctrls = savedctrls;
+ LdapControl::insert(ctrls, LdapControl::createPageControl(mPageSize, cookie));
+ mOp.setServerControls(ctrls);
+ mId = mOp.search(mBase, mScope, mFilter, mAttributes);
+ mOp.setServerControls(savedctrls);
+ if (mId == -1) {
+ mError = mConn->ldapErrorCode();
+ mErrorString = mConn->ldapErrorString();
+ emit mParent->result(mParent);
+ return;
+ }
+ //continue with the next page
+ QTimer::singleShot(0, mParent, SLOT(result()));
+ return;
+ }
+ }
+ mFinished = true;
+ emit mParent->result(mParent);
+ return;
+ }
+
+ //Found an entry
+ if (res == LdapOperation::RES_SEARCH_ENTRY) {
+ emit mParent->data(mParent, mOp.object());
+ mCount++;
+ }
+
+ //If not reached the requested entries, continue
+ if (mMaxCount <= 0 || mCount < mMaxCount) {
+ QTimer::singleShot(0, mParent, SLOT(result()));
+ }
+ //If reached the requested entries, indicate it
+ if (mMaxCount > 0 && mCount == mMaxCount) {
+ qCDebug(LDAP_LOG) << mCount << " entries reached";
+ emit mParent->result(mParent);
+ }
+}
+
+bool LdapSearchPrivate::connect()
+{
+ int ret = mConn->connect();
+ if (ret != KLDAP_SUCCESS) {
+ mError = ret;
+ mErrorString = mConn->connectionError();
+ closeConnection();
+ return false;
+ }
+ return true;
+}
+
+void LdapSearchPrivate::closeConnection()
+{
+ if (mOwnConnection && mConn) {
+ delete mConn;
+ mConn = Q_NULLPTR;
+ }
+}
+
+//This starts the real job
+bool LdapSearchPrivate::startSearch(const LdapDN &base, LdapUrl::Scope scope,
+ const QString &filter,
+ const QStringList &attributes, int pagesize, int count)
+{
+ qCDebug(LDAP_LOG) << "search: base=" << base.toString() << "scope=" << (int)scope
+ << "filter=" << filter << "attributes=" << attributes
+ << "pagesize=" << pagesize;
+ mAbandoned = false;
+ mError = 0;
+ mErrorString.clear();
+ mOp.setConnection(*mConn);
+ mPageSize = pagesize;
+ mBase = base;
+ mScope = scope;
+ mFilter = filter;
+ mAttributes = attributes;
+ mMaxCount = count;
+ mCount = 0;
+ mFinished = false;
+
+ LdapControls savedctrls = mOp.serverControls();
+ if (pagesize) {
+ LdapControls ctrls = savedctrls;
+ mConn->setOption(0x0008, Q_NULLPTR); // Disable referals or paging won't work
+ LdapControl::insert(ctrls, LdapControl::createPageControl(pagesize));
+ mOp.setServerControls(ctrls);
+ }
+
+ mId = mOp.bind();
+ if (mId < 0) {
+ if (mId == KLDAP_SASL_ERROR) {
+ mError = mId;
+ mErrorString = mConn->saslErrorString();
+ } else {
+ mError = mConn->ldapErrorCode();
+ mErrorString = mConn->ldapErrorString();
+ if (mError == -1 && mErrorString.isEmpty()) {
+ mErrorString = i18n("Cannot access to server. Please reconfigure it.");
+ }
+ }
+ return false;
+ }
+ qCDebug(LDAP_LOG) << "startSearch msg id=" << mId;
+
+ //maybe do this with threads?- need thread-safe client libs!!!
+ QTimer::singleShot(0, mParent, SLOT(result()));
+
+ return true;
+}
+
+///////////////////////////////////////////////
+
+LdapSearch::LdapSearch()
+ : d(new LdapSearchPrivate(this))
+{
+ d->mOwnConnection = true;
+ d->mConn = Q_NULLPTR;
+}
+
+LdapSearch::LdapSearch(LdapConnection &connection)
+ : d(new LdapSearchPrivate(this))
+{
+ d->mOwnConnection = false;
+ d->mConn = &connection;
+}
+
+LdapSearch::~LdapSearch()
+{
+ d->closeConnection();
+ delete d;
+}
+
+void LdapSearch::setConnection(LdapConnection &connection)
+{
+ d->closeConnection();
+ d->mOwnConnection = false;
+ d->mConn = &connection;
+}
+
+void LdapSearch::setClientControls(const LdapControls &ctrls)
+{
+ d->mOp.setClientControls(ctrls);
+}
+
+void LdapSearch::setServerControls(const LdapControls &ctrls)
+{
+ d->mOp.setServerControls(ctrls);
+}
+
+bool LdapSearch::search(const LdapServer &server,
+ const QStringList &attributes, int count)
+{
+ if (d->mOwnConnection) {
+ d->closeConnection();
+ d->mConn = new LdapConnection(server);
+ if (!d->connect()) {
+ return false;
+ }
+ }
+ return d->startSearch(server.baseDn(), server.scope(), server.filter(),
+ attributes, server.pageSize(), count);
+}
+
+bool LdapSearch::search(const LdapUrl &url, int count)
+{
+ if (d->mOwnConnection) {
+ d->closeConnection();
+ d->mConn = new LdapConnection(url);
+ if (!d->connect()) {
+ return false;
+ }
+ }
+ bool critical = true;
+ int pagesize = url.extension(QStringLiteral("x-pagesize"), critical).toInt();
+ return d->startSearch(url.dn(), url.scope(), url.filter(),
+ url.attributes(), pagesize, count);
+}
+
+bool LdapSearch::search(const LdapDN &base, LdapUrl::Scope scope,
+ const QString &filter, const QStringList &attributes,
+ int pagesize, int count)
+{
+ Q_ASSERT(!d->mOwnConnection);
+ return d->startSearch(base, scope, filter, attributes, pagesize, count);
+}
+
+void LdapSearch::continueSearch()
+{
+ Q_ASSERT(!d->mFinished);
+ d->mCount = 0;
+ QTimer::singleShot(0, this, SLOT(result()));
+}
+
+bool LdapSearch::isFinished()
+{
+ return d->mFinished;
+}
+
+void LdapSearch::abandon()
+{
+ d->mAbandoned = true;
+}
+
+int LdapSearch::error() const
+{
+ return d->mError;
+}
+
+QString LdapSearch::errorString() const
+{
+ return d->mErrorString;
+}
+
+#include "moc_ldapsearch.cpp"
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPSEARCH_H
+#define KLDAP_LDAPSEARCH_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+class LdapSearchPrivate;
+
+#include "kldap_export.h"
+
+#include "ldapconnection.h"
+#include "ldapcontrol.h"
+#include "ldapobject.h"
+#include "ldapoperation.h"
+#include "ldapserver.h"
+#include "ldapurl.h"
+
+namespace KLDAP
+{
+
+/**
+ * @brief
+ * This class starts a search operation on a LDAP server and returns the
+ * search values via a Qt signal.
+ */
+class KLDAP_EXPORT LdapSearch : public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructs an LdapSearch object
+ */
+ LdapSearch();
+
+ /**
+ * Constructs an LdapConnection object with the given connection. If this
+ * form of constructor used, then always this connection will be used
+ * regardless of the LDAP Url or LdapServer object passed to search().
+ * @param connection the connection used to construct LdapConnection object
+ */
+ explicit LdapSearch(LdapConnection &connection);
+
+ virtual ~LdapSearch();
+
+ /**
+ * Sets the connection for this object to use for searches from now
+ * onwards, regardless of the LDAP Url or LdapServer object passed to
+ * search().
+ */
+ void setConnection(LdapConnection &connection);
+
+ /**
+ * Sets the client controls which will sent with each operation.
+ */
+ void setClientControls(const LdapControls &ctrls);
+
+ /**
+ * Sets the server controls which will sent with each operation.
+ */
+ void setServerControls(const LdapControls &ctrls);
+
+ /**
+ * Starts a search operation on the LDAP server @param server,
+ * returning the attributes specified with @param attributes.
+ * @param count means how many entries to list. If it's >0, then result()
+ * will be emitted when the number of entries is reached, but with
+ * isFinished() set to false.
+ */
+ bool search(const LdapServer &server,
+ const QStringList &attributes = QStringList(), int count = 0);
+
+ /**
+ * Starts a search operation on the given LDAP URL.
+ */
+ bool search(const LdapUrl &url, int count = 0);
+
+ /**
+ * Starts a search operation if the LdapConnection object already set
+ * in the constructor.
+ */
+ bool search(const LdapDN &base,
+ LdapUrl::Scope scope = LdapUrl::Sub,
+ const QString &filter = QString(),
+ const QStringList &attributes = QStringList(),
+ int pagesize = 0, int count = 0);
+
+ /**
+ * Continues the search (if you set count to non-zero in search(), and isFinished() is false)
+ */
+ void continueSearch();
+ /**
+ * Returns true if the search is finished else returns false.
+ */
+ bool isFinished();
+ /**
+ * Tries to abandon the search.
+ */
+ void abandon();
+
+ /**
+ * Returns the error code of the search operation (0 if no error).
+ */
+ int error() const;
+
+ /**
+ * Returns the error description of the search operation.
+ */
+ QString errorString() const;
+
+Q_SIGNALS:
+ /**
+ * Emitted for each result object.
+ */
+ void data(KLDAP::LdapSearch *search, const KLDAP::LdapObject &obj);
+
+ /**
+ * Emitted when the searching finished.
+ */
+ void result(KLDAP::LdapSearch *search);
+
+private:
+ LdapSearchPrivate *const d;
+
+ Q_PRIVATE_SLOT(d, void result())
+
+ Q_DISABLE_COPY(LdapSearch)
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapserver.h"
+
+#include "ldap_debug.h"
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN LdapServer::LdapServerPrivate
+{
+public:
+ QString mHost;
+ int mPort;
+ LdapDN mBaseDn;
+ QString mUser;
+ QString mBindDn;
+ QString mRealm;
+ QString mPassword;
+ QString mMech;
+ QString mFilter;
+ int mTimeLimit;
+ int mSizeLimit;
+ int mVersion;
+ int mPageSize;
+ int mTimeout;
+ Security mSecurity;
+ Auth mAuth;
+ LdapUrl::Scope mScope;
+};
+
+LdapServer::LdapServer()
+ : d(new LdapServerPrivate)
+{
+ clear();
+}
+
+LdapServer::LdapServer(const LdapUrl &url)
+ : d(new LdapServerPrivate)
+{
+ clear();
+
+ setUrl(url);
+}
+
+LdapServer::LdapServer(const LdapServer &that)
+ : d(new LdapServerPrivate)
+{
+ *d = *that.d;
+}
+
+LdapServer &LdapServer::operator= (const LdapServer &that)
+{
+ if (this == &that) {
+ return *this;
+ }
+
+ *d = *that.d;
+
+ return *this;
+}
+
+LdapServer::~LdapServer()
+{
+ delete d;
+}
+
+void LdapServer::clear()
+{
+ d->mPort = 389;
+ d->mHost.clear();
+ d->mUser.clear();
+ d->mBindDn.clear();
+ d->mMech.clear();
+ d->mPassword.clear();
+ d->mSecurity = None;
+ d->mAuth = Anonymous;
+ d->mVersion = 3;
+ d->mTimeout = 0;
+ d->mSizeLimit = d->mTimeLimit = d->mPageSize = 0;
+}
+
+QString LdapServer::host() const
+{
+ return d->mHost;
+}
+
+int LdapServer::port() const
+{
+ return d->mPort;
+}
+
+LdapDN LdapServer::baseDn() const
+{
+ return d->mBaseDn;
+}
+
+QString LdapServer::user() const
+{
+ return d->mUser;
+}
+
+QString LdapServer::bindDn() const
+{
+ return d->mBindDn;
+}
+
+QString LdapServer::realm() const
+{
+ return d->mRealm;
+}
+
+QString LdapServer::password() const
+{
+ return d->mPassword;
+}
+
+QString LdapServer::filter() const
+{
+ return d->mFilter;
+}
+
+LdapUrl::Scope LdapServer::scope() const
+{
+ return d->mScope;
+}
+
+int LdapServer::timeLimit() const
+{
+ return d->mTimeLimit;
+}
+
+int LdapServer::sizeLimit() const
+{
+ return d->mSizeLimit;
+}
+
+int LdapServer::pageSize() const
+{
+ return d->mPageSize;
+}
+
+int LdapServer::version() const
+{
+ return d->mVersion;
+}
+
+LdapServer::Security LdapServer::security() const
+{
+ return d->mSecurity;
+}
+
+LdapServer::Auth LdapServer::auth() const
+{
+ return d->mAuth;
+}
+
+QString LdapServer::mech() const
+{
+ return d->mMech;
+}
+
+int LdapServer::timeout() const
+{
+ return d->mTimeout;
+}
+
+void LdapServer::setHost(const QString &host)
+{
+ d->mHost = host;
+}
+
+void LdapServer::setPort(int port)
+{
+ d->mPort = port;
+}
+
+void LdapServer::setBaseDn(const LdapDN &baseDn)
+{
+ d->mBaseDn = baseDn;
+}
+
+void LdapServer::setUser(const QString &user)
+{
+ d->mUser = user;
+}
+
+void LdapServer::setBindDn(const QString &bindDn)
+{
+ d->mBindDn = bindDn;
+}
+
+void LdapServer::setRealm(const QString &realm)
+{
+ d->mRealm = realm;
+}
+
+void LdapServer::setPassword(const QString &password)
+{
+ d->mPassword = password;
+}
+
+void LdapServer::setTimeLimit(int timelimit)
+{
+ d->mTimeLimit = timelimit;
+}
+
+void LdapServer::setSizeLimit(int sizelimit)
+{
+ d->mSizeLimit = sizelimit;
+}
+
+void LdapServer::setPageSize(int pagesize)
+{
+ d->mPageSize = pagesize;
+}
+
+void LdapServer::setFilter(const QString &filter)
+{
+ d->mFilter = filter;
+}
+
+void LdapServer::setScope(LdapUrl::Scope scope)
+{
+ d->mScope = scope;
+}
+
+void LdapServer::setVersion(int version)
+{
+ d->mVersion = version;
+}
+
+void LdapServer::setSecurity(Security security)
+{
+ d->mSecurity = security;
+}
+
+void LdapServer::setAuth(Auth auth)
+{
+ d->mAuth = auth;
+}
+
+void LdapServer::setMech(const QString &mech)
+{
+ d->mMech = mech;
+}
+
+void LdapServer::setTimeout(int timeout)
+{
+ d->mTimeout = timeout;
+}
+
+void LdapServer::setUrl(const LdapUrl &url)
+{
+ bool critical = true;
+
+ d->mHost = url.host();
+ int port = url.port();
+ if (port <= 0) {
+ d->mPort = 389;
+ } else {
+ d->mPort = port;
+ }
+ d->mBaseDn = url.dn();
+ d->mScope = url.scope();
+
+ d->mFilter = url.filter();
+
+ d->mSecurity = None;
+ if (url.scheme() == QLatin1String("ldaps")) {
+ d->mSecurity = SSL;
+ } else if (url.hasExtension(QStringLiteral("x-tls"))) {
+ d->mSecurity = TLS;
+ }
+ qCDebug(LDAP_LOG) << "security:" << d->mSecurity;
+
+ d->mMech.clear();
+ d->mUser.clear();
+ d->mBindDn.clear();
+ if (url.hasExtension(QStringLiteral("x-sasl"))) {
+ d->mAuth = SASL;
+ if (url.hasExtension(QStringLiteral("x-mech"))) {
+ d->mMech = url.extension(QStringLiteral("x-mech"), critical);
+ }
+ if (url.hasExtension(QStringLiteral("x-realm"))) {
+ d->mRealm = url.extension(QStringLiteral("x-realm"), critical);
+ }
+ if (url.hasExtension(QStringLiteral("bindname"))) {
+ d->mBindDn = url.extension(QStringLiteral("bindname"), critical);
+ }
+ d->mUser = url.userName();
+ } else if (url.hasExtension(QStringLiteral("bindname"))) {
+ d->mAuth = Simple;
+ d->mBindDn = url.extension(QStringLiteral("bindname"), critical);
+ } else {
+ QString user = url.userName();
+ if (user.isEmpty()) {
+ d->mAuth = Anonymous;
+ } else {
+ d->mAuth = Simple;
+ d->mBindDn = user;
+ }
+ }
+ d->mPassword = url.password();
+ if (url.hasExtension(QStringLiteral("x-version"))) {
+ d->mVersion = url.extension(QStringLiteral("x-version"), critical).toInt();
+ } else {
+ d->mVersion = 3;
+ }
+
+ if (url.hasExtension(QStringLiteral("x-timeout"))) {
+ d->mTimeout = url.extension(QStringLiteral("x-timeout"), critical).toInt();
+ } else {
+ d->mTimeout = 0;
+ }
+
+ if (url.hasExtension(QStringLiteral("x-timelimit"))) {
+ d->mTimeLimit = url.extension(QStringLiteral("x-timelimit"), critical).toInt();
+ } else {
+ d->mTimeLimit = 0;
+ }
+
+ if (url.hasExtension(QStringLiteral("x-sizelimit"))) {
+ d->mSizeLimit = url.extension(QStringLiteral("x-sizelimit"), critical).toInt();
+ } else {
+ d->mSizeLimit = 0;
+ }
+
+ if (url.hasExtension(QStringLiteral("x-pagesize"))) {
+ d->mPageSize = url.extension(QStringLiteral("x-pagesize"), critical).toInt();
+ } else {
+ d->mPageSize = 0;
+ }
+}
+
+LdapUrl LdapServer::url() const
+{
+ LdapUrl url;
+ url.setScheme(d->mSecurity == SSL ? QStringLiteral("ldaps") : QStringLiteral("ldap"));
+ url.setPort(d->mPort);
+ url.setHost(d->mHost);
+ url.setDn(d->mBaseDn);
+ url.setFilter(d->mFilter);
+ url.setScope(d->mScope);
+ if (d->mAuth == SASL) {
+ url.setUserName(d->mUser);
+ url.setPassword(d->mPassword);
+ url.setExtension(QStringLiteral("bindname"), d->mBindDn, true);
+ url.setExtension(QStringLiteral("x-sasl"), QString());
+ if (!d->mMech.isEmpty()) {
+ url.setExtension(QStringLiteral("x-mech"), d->mMech);
+ }
+ if (!d->mRealm.isEmpty()) {
+ url.setExtension(QStringLiteral("x-realm"), d->mRealm);
+ }
+ } else if (d->mAuth == Simple) {
+ url.setUserName(d->mBindDn);
+ url.setPassword(d->mPassword);
+ }
+ if (d->mVersion == 2) {
+ url.setExtension(QStringLiteral("x-version"), d->mVersion);
+ }
+ if (d->mTimeout) {
+ url.setExtension(QStringLiteral("x-timeout"), d->mTimeout);
+ }
+ if (d->mTimeLimit != 0) {
+ url.setExtension(QStringLiteral("x-timelimit"), d->mTimeLimit);
+ }
+ if (d->mSizeLimit != 0) {
+ url.setExtension(QStringLiteral("x-sizelimit"), d->mSizeLimit);
+ }
+ if (d->mPageSize != 0) {
+ url.setExtension(QStringLiteral("x-pagesize"), d->mPageSize);
+ }
+ if (d->mSecurity == TLS) {
+ url.setExtension(QStringLiteral("x-tls"), 1, true);
+ }
+ return url;
+}
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPSERVER_H
+#define KLDAP_LDAPSERVER_H
+
+#include <QtCore/QString>
+
+#include "ldapurl.h"
+#include "ldapdn.h"
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+/**
+ * @short A class that contains LDAP server connection settings.
+ *
+ * This class holds various parameters that are needed to connect
+ * to an LDAP server.
+ */
+class KLDAP_EXPORT LdapServer
+{
+public:
+ /**
+ * Creates an empty LDAP server object.
+ */
+ LdapServer();
+
+ /**
+ * Creates a new LDAP server object.
+ *
+ * @param url The LDAP url of the server.
+ */
+ LdapServer(const LdapUrl &url);
+
+ /**
+ * Creates a new LDAP server object from an @p other object.
+ */
+ LdapServer(const LdapServer &other);
+
+ /**
+ * Overwrites the values of the LDAP server object with
+ * the values from an @p other object.
+ */
+ LdapServer &operator=(const LdapServer &other);
+
+ /**
+ * Destroys the LDAP server object.
+ */
+ virtual ~LdapServer();
+
+ /**
+ * Describes the encryption settings that can be used
+ * for the LDAP connection.
+ */
+ typedef enum {
+ None, ///< Do not use any encryption.
+ TLS, ///< Use TLS encryption.
+ SSL ///< Use SSL encryption.
+ } Security;
+
+ /**
+ * Describes the authentication method that can be used
+ * for the LDAP connection.
+ */
+ typedef enum {
+ Anonymous, ///< Do no authentication.
+ Simple, ///< Authenticate via login and password.
+ SASL ///< Azthenticate with the SASL framework.
+ } Auth;
+
+ /**
+ * Clears all server settings.
+ */
+ void clear();
+
+ /**
+ * Sets the host of the LDAP connection.
+ */
+ void setHost(const QString &host);
+
+ /**
+ * Returns the host of the LDAP connection.
+ */
+ QString host() const;
+
+ /**
+ * Sets the port of the LDAP connection.
+ * If not port is set, 389 is used as default.
+ * @param port the LDAP port connection to set
+ */
+ void setPort(int port);
+
+ /**
+ * Returns the port of the LDAP connection.
+ */
+ int port() const;
+
+ /**
+ * Sets the @p baseDn of the LDAP connection.
+ */
+ void setBaseDn(const LdapDN &baseDn);
+
+ /**
+ * Returns the baseDn of the LDAP connection.
+ */
+ LdapDN baseDn() const;
+
+ /**
+ * Sets the @p user of the LDAP connection.
+ */
+ void setUser(const QString &user);
+
+ /**
+ * Returns the user of the LDAP connection.
+ */
+ QString user() const;
+
+ /**
+ * Sets the @p bindDn of the LDAP connection.
+ */
+ void setBindDn(const QString &bindDn);
+
+ /**
+ * Returns the bindDn of the LDAP connection.
+ */
+ QString bindDn() const;
+
+ /**
+ * Sets the @p realm of the LDAP connection.
+ */
+ void setRealm(const QString &realm);
+
+ /**
+ * Returns the realm of the LDAP connection.
+ */
+ QString realm() const;
+
+ /**
+ * Sets the @p password of the LDAP connection.
+ */
+ void setPassword(const QString &password);
+
+ /**
+ * Returns the password of the LDAP connection.
+ */
+ QString password() const;
+
+ /**
+ * Sets the protocol @p version of the LDAP connection.
+ * If no version is set, 3 is used as default.
+ * @param version the protocol version to set
+ */
+ void setVersion(int version);
+
+ /**
+ * Returns the protocol version of the LDAP connection.
+ */
+ int version() const;
+
+ /**
+ * Sets the security @p mode of the LDAP connection.
+ * If no security is set, None is used as default.
+ * @param mode the security mode to set
+ */
+ void setSecurity(Security mode);
+
+ /**
+ * Returns the security mode of the LDAP connection.
+ */
+ Security security() const;
+
+ /**
+ * Sets the @p authentication method of the LDAP connection.
+ * If no authentication method is set, Anonymous is used as default.
+ * @param authentication the authentication method to set
+ */
+ void setAuth(Auth authentication);
+
+ /**
+ * Returns the authentication method of the LDAP connection.
+ */
+ Auth auth() const;
+
+ /**
+ * Sets the @p mech of the LDAP connection.
+ */
+ void setMech(const QString &mech);
+
+ /**
+ * Returns the mech of the LDAP connection.
+ */
+ QString mech() const;
+
+ /**
+ * Sets the @p timeout of the LDAP connection.
+ */
+ void setTimeout(int timeout);
+
+ /**
+ * Returns the timeout of the LDAP connection.
+ */
+ int timeout() const;
+
+ /**
+ * Sets the search @p scope of the LDAP connection.
+ */
+ void setScope(LdapUrl::Scope scope);
+
+ /**
+ * Returns the search scope of the LDAP connection.
+ */
+ LdapUrl::Scope scope() const;
+
+ /**
+ * Sets the time @p limit of the LDAP connection.
+ */
+ void setTimeLimit(int limit);
+
+ /**
+ * Returns the time limit of the LDAP connection.
+ */
+ int timeLimit() const;
+
+ /**
+ * Sets the size @p limit of the LDAP connection.
+ */
+ void setSizeLimit(int sizelimit);
+
+ /**
+ * Returns the size limit of the LDAP connection.
+ */
+ int sizeLimit() const;
+
+ /**
+ * Sets the page @p size of the LDAP connection.
+ */
+ void setPageSize(int size);
+
+ /**
+ * Returns the page size of the LDAP connection.
+ */
+ int pageSize() const;
+
+ /**
+ * Sets the @p filter string of the LDAP connection.
+ */
+ void setFilter(const QString &filter);
+
+ /**
+ * Returns the filter string of the LDAP connection.
+ */
+ QString filter() const;
+
+ /**
+ * Sets the server parameters from an RFC2255 compliant LDAP @p url.
+ */
+ void setUrl(const LdapUrl &url);
+
+ /**
+ * Returns the server parameters as an RFC2255 compliant LDAP Url.
+ * The URL extensions which are supported:
+ * Standard: bindname
+ * KLDAP extensions: x-tls, x-version, x-sasl, x-mech, x-realm,
+ * x-sizelimit, x-timelimit, x-pagesize, x-timeout
+ */
+ LdapUrl url() const;
+
+private:
+ class LdapServerPrivate;
+ LdapServerPrivate *const d;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapstructureproxymodel.h"
+#include "ldapmodel.h"
+#include "ldapmodelnode_p.h"
+
+#include "ldap_debug.h"
+#include <klocalizedstring.h>
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN LdapStructureProxyModel::LdapStructureProxyModelPrivate
+{
+public:
+ LdapStructureProxyModelPrivate();
+
+};
+
+LdapStructureProxyModel::LdapStructureProxyModelPrivate::LdapStructureProxyModelPrivate()
+{
+
+}
+
+LdapStructureProxyModel::LdapStructureProxyModel(QObject *parent)
+ : QSortFilterProxyModel(parent),
+ m_d(new LdapStructureProxyModelPrivate())
+{
+
+}
+
+LdapStructureProxyModel::~LdapStructureProxyModel()
+{
+ delete m_d;
+}
+
+QVariant LdapStructureProxyModel::data(const QModelIndex &index,
+ int role) const
+{
+ // Included just in case we decide to do any special presentation of the data
+ // at some other point throughout the 4.x series.
+ return sourceModel()->data(mapToSource(index), role);
+}
+
+bool LdapStructureProxyModel::setData(const QModelIndex &index,
+ const QVariant &value,
+ int role)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(value);
+ Q_UNUSED(role);
+ return false;
+}
+
+bool LdapStructureProxyModel::filterAcceptsRow(int sourceRow,
+ const QModelIndex &sourceParent) const
+{
+ QModelIndex idx = sourceModel()->index(sourceRow, 0, sourceParent);
+ LdapModelNode::NodeType nodeType =
+ static_cast<LdapModelNode::NodeType>(
+ sourceModel()->data(idx, LdapModel::NodeTypeRole).toUInt());
+ return nodeType == LdapModelNode::DN;
+}
+
+QVariant LdapStructureProxyModel::headerData(int section,
+ Qt::Orientation orientation,
+ int role) const
+{
+ Q_UNUSED(section);
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ return i18n("Distinguished Name");
+ }
+
+ return QVariant();
+}
+
+int LdapStructureProxyModel::columnCount(const QModelIndex &/*parent*/) const
+{
+ // No need for more than one column just to show the structure
+ return 1;
+}
+
+Qt::ItemFlags LdapStructureProxyModel::flags(const QModelIndex &index) const
+{
+ // Included so as not to break BC in case we wish to use this later in 4.x
+ return sourceModel()->flags(mapToSource(index));
+}
+
+bool LdapStructureProxyModel::hasChildren(const QModelIndex &parent) const
+{
+ // We need to handle this carefully bacause of the filtering out of attributes
+ // and the lazy population approach.
+ LdapModel *model = static_cast<LdapModel *>(sourceModel());
+ return model->hasChildrenOfType(mapToSource(parent), LdapModel::DistinguishedName);
+}
+
+QModelIndex LdapStructureProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ return QSortFilterProxyModel::mapFromSource(sourceIndex);
+}
+
+QModelIndex LdapStructureProxyModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ return QSortFilterProxyModel::mapToSource(proxyIndex);
+}
+
+bool LdapStructureProxyModel::insertRows(int row, int count,
+ const QModelIndex &parent)
+{
+ Q_UNUSED(row);
+ Q_UNUSED(count);
+ Q_UNUSED(parent);
+ return false;
+}
+
+bool LdapStructureProxyModel::removeRows(int row, int count,
+ const QModelIndex &parent)
+{
+ Q_UNUSED(row);
+ Q_UNUSED(count);
+ Q_UNUSED(parent);
+ return false;
+}
+
+void LdapStructureProxyModel::sort(int column, Qt::SortOrder order)
+{
+ Q_UNUSED(column);
+ Q_UNUSED(order);
+}
+
+Qt::DropActions LdapStructureProxyModel::supportedDropActions() const
+{
+ return Qt::MoveAction;
+}
+
+QMimeData *LdapStructureProxyModel::mimeData(const QModelIndexList &indexes) const
+{
+ Q_UNUSED(indexes);
+ return Q_NULLPTR;
+}
+
+bool LdapStructureProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ /** \todo Implement drag and drop for LdapModel */
+ Q_UNUSED(data);
+ Q_UNUSED(action);
+ Q_UNUSED(row);
+ Q_UNUSED(column);
+ Q_UNUSED(parent);
+ return false;
+}
+
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPSTRUCTUREPROXYMODEL_H
+#define KLDAP_LDAPSTRUCTUREPROXYMODEL_H
+
+#include <QSortFilterProxyModel>
+
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+class KLDAP_EXPORT LdapStructureProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ explicit LdapStructureProxyModel(QObject *parent = Q_NULLPTR);
+ ~LdapStructureProxyModel();
+
+ QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::setData(). This is a placeholder for when
+ * LdapStructureProxyModel beomes writeable and always returns false.
+ */
+ bool setData(const QModelIndex &index,
+ const QVariant &value,
+ int role = Qt::EditRole) Q_DECL_OVERRIDE;
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
+ int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
+ Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
+ bool hasChildren(const QModelIndex &parent) const Q_DECL_OVERRIDE;
+
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const Q_DECL_OVERRIDE;
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const Q_DECL_OVERRIDE;
+
+ /**
+ * Reimplemented from QAbstractItemModel::insertRows(). This is a placeholder for when
+ * LdapStructureProxyModel beomes writeable and always returns false.
+ */
+ bool insertRows(int row, int count,
+ const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::removeRows(). This is a placeholder for when
+ * LdapStructureProxyModel beomes writeable and always returns false.
+ */
+ bool removeRows(int row, int count,
+ const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::removeRows(). The default implementation
+ * does nothing.
+ */
+ void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) Q_DECL_OVERRIDE;
+ //
+ // Drag and drop support
+ //
+ /**
+ * Reimplemented from QAbstractItemModel::supportedDropActions(). The default
+ * implementation returns Qt::MoveAction.
+ */
+ Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::mimedata(). This is a placeholder for when
+ * LdapStructureProxyModel beomes writeable and always returns 0.
+ */
+ QMimeData *mimeData(const QModelIndexList &indexes) const Q_DECL_OVERRIDE;
+ /**
+ * Reimplemented from QAbstractItemModel::dropMimedata(). This is a placeholder for when
+ * LdapStructureProxyModel beomes writeable and always returns false.
+ */
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent) Q_DECL_OVERRIDE;
+
+private:
+ class LdapStructureProxyModelPrivate;
+ LdapStructureProxyModelPrivate *const m_d;
+};
+
+}
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldapurl.h"
+
+#include "ldap_debug.h"
+
+#include <QtCore/QStringList>
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN LdapUrl::LdapUrlPrivate
+{
+public:
+ LdapUrlPrivate()
+ : m_scope(Base)
+ {
+ }
+
+ QMap<QString, Extension> m_extensions;
+ QStringList m_attributes;
+ Scope m_scope;
+ QString m_filter;
+};
+
+LdapUrl::LdapUrl()
+ : d(new LdapUrlPrivate)
+{
+}
+
+LdapUrl::LdapUrl(const QUrl &_url)
+ : QUrl(_url), d(new LdapUrlPrivate)
+{
+ QString tmp = path();
+ if (tmp.startsWith(QLatin1Char('/'))) {
+ tmp = tmp.mid(1);
+ }
+ setPath(tmp);
+ parseQuery();
+}
+
+LdapUrl::LdapUrl(const LdapUrl &that)
+ : QUrl(that), d(new LdapUrlPrivate)
+{
+ *d = *that.d;
+}
+
+LdapUrl &LdapUrl::operator=(const LdapUrl &that)
+{
+ if (this == &that) {
+ return *this;
+ }
+
+ QUrl::operator=(that);
+ *d = *that.d;
+
+ return *this;
+}
+
+LdapUrl::~LdapUrl()
+{
+ delete d;
+}
+
+void LdapUrl::setDn(const LdapDN &dn)
+{
+ QString tmp = dn.toString();
+ if (tmp.startsWith(QLatin1Char('/'))) {
+ setPath(tmp);
+ } else {
+ setPath(QLatin1Char('/') + tmp);
+ }
+}
+
+LdapDN LdapUrl::dn() const
+{
+ QString tmp = path();
+ if (tmp.startsWith(QLatin1Char('/'))) {
+ tmp = tmp.mid(1);
+ }
+ LdapDN tmpDN(tmp);
+ return tmpDN;
+}
+
+QStringList LdapUrl::attributes() const
+{
+ return d->m_attributes;
+}
+
+void LdapUrl::setAttributes(const QStringList &attributes)
+{
+ d->m_attributes = attributes;
+ updateQuery();
+}
+
+LdapUrl::Scope LdapUrl::scope() const
+{
+ return d->m_scope;
+}
+
+void LdapUrl::setScope(Scope scope)
+{
+ d->m_scope = scope;
+ updateQuery();
+}
+
+QString LdapUrl::filter() const
+{
+ return d->m_filter;
+}
+
+void LdapUrl::setFilter(const QString &filter)
+{
+ d->m_filter = filter;
+ updateQuery();
+}
+
+bool LdapUrl::hasExtension(const QString &key) const
+{
+ return d->m_extensions.contains(key);
+}
+
+LdapUrl::Extension LdapUrl::extension(const QString &key) const
+{
+ QMap<QString, Extension>::const_iterator it;
+
+ it = d->m_extensions.constFind(key);
+ if (it != d->m_extensions.constEnd()) {
+ return (*it);
+ } else {
+ Extension ext;
+ ext.value = QLatin1String("");
+ ext.critical = false;
+ return ext;
+ }
+}
+
+QString LdapUrl::extension(const QString &key, bool &critical) const
+{
+ Extension ext;
+
+ ext = extension(key);
+ critical = ext.critical;
+ return ext.value;
+}
+
+void LdapUrl::setExtension(const QString &key, const LdapUrl::Extension &ext)
+{
+ d->m_extensions[ key ] = ext;
+ updateQuery();
+}
+
+void LdapUrl::setExtension(const QString &key, const QString &value, bool critical)
+{
+ Extension ext;
+ ext.value = value;
+ ext.critical = critical;
+ setExtension(key, ext);
+}
+
+void LdapUrl::setExtension(const QString &key, int value, bool critical)
+{
+ Extension ext;
+ ext.value = QString::number(value);
+ ext.critical = critical;
+ setExtension(key, ext);
+}
+
+void LdapUrl::removeExtension(const QString &key)
+{
+ d->m_extensions.remove(key);
+ updateQuery();
+}
+
+void LdapUrl::updateQuery()
+{
+ QMap<QString, Extension>::const_iterator it;
+ QString q(QLatin1Char('?'));
+
+ // set the attributes to query
+ if (!d->m_attributes.isEmpty()) {
+ q += d->m_attributes.join(QStringLiteral(","));
+ }
+
+ // set the scope
+ q += QLatin1Char('?');
+ switch (d->m_scope) {
+ case Sub:
+ q += QStringLiteral("sub");
+ break;
+ case One:
+ q += QStringLiteral("one");
+ break;
+ case Base:
+ q += QStringLiteral("base");
+ break;
+ }
+
+ // set the filter
+ q += QLatin1Char('?');
+ if (d->m_filter != QLatin1String("(objectClass=*)") && !d->m_filter.isEmpty()) {
+ q += QLatin1String(toPercentEncoding(d->m_filter));
+ }
+
+ // set the extensions
+ q += QLatin1Char('?');
+ for (it = d->m_extensions.constBegin(); it != d->m_extensions.constEnd(); ++it) {
+ if (it.value().critical) {
+ q += QLatin1Char('!');
+ }
+ q += it.key();
+ if (!it.value().value.isEmpty()) {
+ q += QLatin1Char('=') + QLatin1String(toPercentEncoding(it.value().value));
+ }
+ q += QLatin1Char(',');
+ }
+ while (q.endsWith(QLatin1Char('?')) || q.endsWith(QLatin1Char(','))) {
+ q.remove(q.length() - 1, 1);
+ }
+
+ setQuery(q);
+ qCDebug(LDAP_LOG) << "LDAP URL updateQuery():" << toDisplayString();
+}
+
+void LdapUrl::parseQuery()
+{
+ Extension ext;
+ QStringList extensions;
+ QString q = query();
+ // remove first ?
+ if (q.startsWith(QLatin1Char('?'))) {
+ q.remove(0, 1);
+ }
+
+ // split into a list
+ QStringList url_items = q.split(QLatin1Char('?'));
+
+ d->m_attributes.clear();
+ d->m_scope = Base;
+ d->m_filter = QStringLiteral("(objectClass=*)");
+ d->m_extensions.clear();
+
+ int i = 0;
+ QStringList::const_iterator end(url_items.constEnd());
+ for (QStringList::const_iterator it = url_items.constBegin();
+ it != end; ++it, i++) {
+ switch (i) {
+ case 0:
+ d->m_attributes = (*it).split(QLatin1Char(','), QString::SkipEmptyParts);
+ break;
+ case 1:
+ if ((*it) == QLatin1String("sub")) {
+ d->m_scope = Sub;
+ } else if ((*it) == QLatin1String("one")) {
+ d->m_scope = One;
+ }
+ break;
+ case 2:
+ d->m_filter = fromPercentEncoding((*it).toLatin1());
+ break;
+ case 3:
+ extensions = (*it).split(QLatin1Char(','), QString::SkipEmptyParts);
+ break;
+ }
+ }
+
+ QString name, value;
+ QStringList::const_iterator end2(extensions.constEnd());
+ for (QStringList::const_iterator it = extensions.constBegin();
+ it != end2; ++it) {
+ ext.critical = false;
+ name = fromPercentEncoding((*it).section(QLatin1Char('='), 0, 0).toLatin1()).toLower();
+ value = fromPercentEncoding((*it).section(QLatin1Char('='), 1).toLatin1());
+ if (name.startsWith(QLatin1Char('!'))) {
+ ext.critical = true;
+ name.remove(0, 1);
+ }
+ qCDebug(LDAP_LOG) << "LdapUrl extensions name=" << name << "value:" << value;
+ ext.value = value.replace(QLatin1String("%2"), QLatin1String(","));
+ setExtension(name, ext);
+ }
+}
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDAPURL_H
+#define KLDAP_LDAPURL_H
+
+#include <QtCore/QMap>
+#include <QtCore/QStringList>
+
+#include <QUrl>
+
+#include "ldapdn.h"
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+/**
+ * @short A special url class for LDAP.
+ *
+ * LdapUrl implements an RFC 2255 compliant LDAP Url parser, with minimal
+ * differences. LDAP Urls implemented by this class has the following format:
+ * ldap[s]://[user[:password]@]hostname[:port]["/" [dn ["?" [attributes]
+ * ["?" [scope] ["?" [filter] ["?" extensions]]]]]]
+ */
+class KLDAP_EXPORT LdapUrl : public QUrl
+{
+public:
+
+ /**
+ * A class holding the extension name and state whether
+ * the extension is critical.
+ */
+ typedef struct {
+ QString value;
+ bool critical;
+ } Extension;
+
+ /**
+ * Describes the scope of the LDAP url.
+ */
+ typedef enum {
+ Base, ///< Only the same level as the url.
+ One, ///< The level of the url and the one below.
+ Sub ///< All levels below the url's level.
+ } Scope;
+
+ /**
+ * Constructs an empty LDAP url.
+ */
+ LdapUrl();
+
+ /**
+ * Constructs a LDAP url from a KUrl @p url.
+ */
+ explicit LdapUrl(const QUrl &url);
+
+ /**
+ * Constructs a LDAP url from an other url.
+ */
+ LdapUrl(const LdapUrl &other);
+
+ /**
+ * Overwrites the values of the LDAP url with values
+ * from an @p other url.
+ */
+ LdapUrl &operator=(const LdapUrl &other);
+
+ /**
+ * Destroys the LDAP url.
+ */
+ virtual ~LdapUrl();
+
+ /**
+ * Sets the @p dn part of the LDAP url.
+ */
+ void setDn(const LdapDN &dn);
+
+ /**
+ * Returns the dn part of the LDAP url.
+ * This is equal to path() with the slash removed from the beginning.
+ */
+ LdapDN dn() const;
+
+ /**
+ * Sets the @p attributes part of the LDAP url.
+ */
+ void setAttributes(const QStringList &attributes);
+
+ /**
+ * Returns the attributes part of the LDAP url.
+ */
+ QStringList attributes() const;
+
+ /**
+ * Sets the scope part of the LDAP url.
+ */
+ void setScope(Scope scope);
+
+ /**
+ * Returns the scope part of the LDAP url.
+ */
+ Scope scope() const;
+
+ /**
+ * Sets the filter part of the LDAP url.
+ */
+ void setFilter(const QString &filter);
+
+ /**
+ * Returns the filter part of the LDAP url.
+ */
+ QString filter() const;
+
+ /**
+ * Returns whether the specified @p extension exists in the LDAP url.
+ */
+ bool hasExtension(const QString &extension) const;
+
+ /**
+ * Returns the specified @p extension.
+ */
+ Extension extension(const QString &extension) const;
+
+ /**
+ * Returns the specified @p extension.
+ */
+ QString extension(const QString &extension, bool &critical) const;
+
+ /**
+ * Sets the specified extension @p key with the value and criticality in @p extension.
+ */
+ void setExtension(const QString &key, const Extension &extension);
+
+ /**
+ * Sets the specified extension @p key with the @p value and criticality specified.
+ */
+ void setExtension(const QString &key, const QString &value, bool critical = false);
+
+ /**
+ * Sets the specified extension @p key with the @p value and criticality specified.
+ */
+ void setExtension(const QString &key, int value, bool critical = false);
+
+ /**
+ * Removes the specified @p extension.
+ */
+ void removeExtension(const QString &extension);
+
+ /**
+ * Updates the query component from the attributes, scope, filter and extensions.
+ */
+ void updateQuery();
+
+ /**
+ * Parses the query argument of the URL and makes it available via the
+ * attributes(), extension(), filter() and scope() methods
+ */
+ void parseQuery();
+
+private:
+ class LdapUrlPrivate;
+ LdapUrlPrivate *const d;
+};
+
+}
+
+#endif
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "ldif.h"
+
+#include "ldap_debug.h"
+
+using namespace KLDAP;
+
+class Q_DECL_HIDDEN Ldif::LdifPrivate
+{
+public:
+ int mModType;
+ bool mDelOldRdn, mUrl;
+ LdapDN mDn;
+ QString mAttr, mNewRdn, mNewSuperior, mOid;
+ QByteArray mLdif, mValue;
+ EntryType mEntryType;
+
+ bool mIsNewLine, mIsComment, mCritical;
+ ParseValue mLastParseValue;
+ uint mPos, mLineNumber;
+ QByteArray mLine;
+};
+
+Ldif::Ldif() : d(new LdifPrivate)
+{
+ startParsing();
+}
+
+Ldif::Ldif(const Ldif &that) : d(new LdifPrivate)
+{
+ *d = *that.d;
+
+ startParsing();
+}
+
+Ldif &Ldif::operator=(const Ldif &that)
+{
+ if (this == &that) {
+ return *this;
+ }
+
+ *d = *that.d;
+
+ return *this;
+}
+
+Ldif::~Ldif()
+{
+ delete d;
+}
+
+QByteArray Ldif::assembleLine(const QString &fieldname,
+ const QByteArray &value,
+ uint linelen, bool url)
+{
+ bool safe = false;
+ bool isDn;
+ QByteArray result;
+
+ if (url) {
+ result = fieldname.toUtf8() + ":< " + value;
+ } else {
+ isDn = fieldname.toLower() == QLatin1String("dn");
+ //SAFE-INIT-CHAR
+ if (value.size() > 0 && value[0] > 0 && value[0] != '\n' &&
+ value[0] != '\r' && value[0] != ':' && value[0] != '<') {
+ safe = true;
+ }
+
+ //SAFE-CHAR
+ if (safe) {
+ for (int i = 1; i < value.size(); i++) {
+ //allow utf-8 in Distinguished Names
+ if ((isDn && value[i] == 0) ||
+ (!isDn && value[i] <= 0) ||
+ value[i] == '\r' || value[i] == '\n') {
+ safe = false;
+ break;
+ }
+ }
+ }
+
+ if (value.size() == 0) {
+ safe = true;
+ }
+
+ if (safe) {
+ result = fieldname.toUtf8() + ": " + value;
+ } else {
+ result = fieldname.toUtf8() + ":: " + value.toBase64();
+ }
+
+ if (linelen > 0) {
+ int i = (uint)(fieldname.length() + 2) > linelen ? fieldname.length() + 2 : linelen;
+ while (i < result.length()) {
+ result.insert(i, "\n ");
+ i += linelen + 2;
+ }
+ }
+ }
+ return result;
+}
+
+QByteArray Ldif::assembleLine(const QString &fieldname, const QString &value,
+ uint linelen, bool url)
+{
+ return assembleLine(fieldname, value.toUtf8(), linelen, url);
+}
+
+bool Ldif::splitLine(const QByteArray &line, QString &fieldname, QByteArray &value)
+{
+ int position;
+ QByteArray tmp;
+ int linelen;
+
+// qCDebug(LDAP_LOG) << "line:" << QString::fromUtf8(line);
+
+ position = line.indexOf(":");
+ if (position == -1) {
+ // strange: we did not find a fieldname
+ fieldname = QLatin1String("");
+ value = line.trimmed();
+// qCDebug(LDAP_LOG) << "value :" << value[0];
+ return false;
+ }
+
+ linelen = line.size();
+ fieldname = QString::fromUtf8(line.left(position).trimmed());
+
+ if (linelen > (position + 1) && line[ position + 1 ] == ':') {
+ // String is BASE64 encoded -> decode it now.
+ if (linelen <= (position + 3)) {
+ value.resize(0);
+ return false;
+ }
+ value = QByteArray::fromBase64(line.mid(position + 3));
+ return false;
+ }
+
+ if (linelen > (position + 1) && line[ position + 1 ] == '<') {
+ // String is an URL.
+ if (linelen <= (position + 3)) {
+ value.resize(0);
+ return false;
+ }
+ value = QByteArray::fromBase64(line.mid(position + 3));
+ return true;
+ }
+
+ if (linelen <= (position + 2)) {
+ value.resize(0);
+ return false;
+ }
+ value = line.mid(position + 2);
+ return false;
+}
+
+bool Ldif::splitControl(const QByteArray &line, QString &oid, bool &critical,
+ QByteArray &value)
+{
+ QString tmp;
+ critical = false;
+ bool url = splitLine(line, tmp, value);
+
+ qCDebug(LDAP_LOG) << "value:" << QString::fromUtf8(value);
+ if (tmp.isEmpty()) {
+ tmp = QString::fromUtf8(value);
+ value.resize(0);
+ }
+ if (tmp.endsWith(QLatin1String("true"))) {
+ critical = true;
+ tmp.truncate(tmp.length() - 5);
+ } else if (tmp.endsWith(QLatin1String("false"))) {
+ critical = false;
+ tmp.truncate(tmp.length() - 6);
+ }
+ oid = tmp;
+ return url;
+}
+
+Ldif::ParseValue Ldif::processLine()
+{
+
+ if (d->mIsComment) {
+ return None;
+ }
+
+ ParseValue retval = None;
+ if (d->mLastParseValue == EndEntry) {
+ d->mEntryType = Entry_None;
+ }
+
+ d->mUrl = splitLine(d->mLine, d->mAttr, d->mValue);
+
+ QString attrLower = d->mAttr.toLower();
+
+ switch (d->mEntryType) {
+ case Entry_None:
+ if (attrLower == QLatin1String("version")) {
+ if (!d->mDn.isEmpty()) {
+ retval = Err;
+ }
+ } else if (attrLower == QLatin1String("dn")) {
+ qCDebug(LDAP_LOG) << "ldapentry dn:" << QString::fromUtf8(d->mValue);
+ d->mDn = LdapDN(QString::fromUtf8(d->mValue));
+ d->mModType = Mod_None;
+ retval = NewEntry;
+ } else if (attrLower == QLatin1String("changetype")) {
+ if (d->mDn.isEmpty()) {
+ retval = Err;
+ } else {
+ QString tmpval = QString::fromUtf8(d->mValue);
+ qCDebug(LDAP_LOG) << "changetype:" << tmpval;
+ if (tmpval == QLatin1String("add")) {
+ d->mEntryType = Entry_Add;
+ } else if (tmpval == QLatin1String("delete")) {
+ d->mEntryType = Entry_Del;
+ } else if (tmpval == QLatin1String("modrdn") || tmpval == QLatin1String("moddn")) {
+ d->mNewRdn.clear();
+ d->mNewSuperior.clear();
+ d->mDelOldRdn = true;
+ d->mEntryType = Entry_Modrdn;
+ } else if (tmpval == QLatin1String("modify")) {
+ d->mEntryType = Entry_Mod;
+ } else {
+ retval = Err;
+ }
+ }
+ } else if (attrLower == QLatin1String("control")) {
+ d->mUrl = splitControl(d->mValue, d->mOid, d->mCritical, d->mValue);
+ retval = Control;
+ } else if (!d->mAttr.isEmpty() && d->mValue.size() > 0) {
+ d->mEntryType = Entry_Add;
+ retval = Item;
+ }
+ break;
+ case Entry_Add:
+ if (d->mAttr.isEmpty() && d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else {
+ retval = Item;
+ }
+ break;
+ case Entry_Del:
+ if (d->mAttr.isEmpty() && d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else {
+ retval = Err;
+ }
+ break;
+ case Entry_Mod:
+ if (d->mModType == Mod_None) {
+ qCDebug(LDAP_LOG) << "new modtype" << d->mAttr;
+ if (d->mAttr.isEmpty() && d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else if (attrLower == QLatin1String("add")) {
+ d->mModType = Mod_Add;
+ } else if (attrLower == QLatin1String("replace")) {
+ d->mModType = Mod_Replace;
+ d->mAttr = QString::fromUtf8(d->mValue);
+ d->mValue = QByteArray();
+ retval = Item;
+ } else if (attrLower == QLatin1String("delete")) {
+ d->mModType = Mod_Del;
+ d->mAttr = QString::fromUtf8(d->mValue);
+ d->mValue = QByteArray();
+ retval = Item;
+ } else {
+ retval = Err;
+ }
+ } else {
+ if (d->mAttr.isEmpty()) {
+ if (QString::fromUtf8(d->mValue) == QLatin1String("-")) {
+ d->mModType = Mod_None;
+ } else if (d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else {
+ retval = Err;
+ }
+ } else {
+ retval = Item;
+ }
+ }
+ break;
+ case Entry_Modrdn:
+ if (d->mAttr.isEmpty() && d->mValue.size() == 0) {
+ retval = EndEntry;
+ } else if (attrLower == QLatin1String("newrdn")) {
+ d->mNewRdn = QString::fromUtf8(d->mValue);
+ } else if (attrLower == QLatin1String("newsuperior")) {
+ d->mNewSuperior = QString::fromUtf8(d->mValue);
+ } else if (attrLower == QLatin1String("deleteoldrdn")) {
+ if (d->mValue.size() > 0 && d->mValue[0] == '0') {
+ d->mDelOldRdn = false;
+ } else if (d->mValue.size() > 0 && d->mValue[0] == '1') {
+ d->mDelOldRdn = true;
+ } else {
+ retval = Err;
+ }
+ } else {
+ retval = Err;
+ }
+ break;
+ }
+ return retval;
+}
+
+Ldif::ParseValue Ldif::nextItem()
+{
+ ParseValue retval = None;
+ char c = 0;
+
+ while (retval == None) {
+ if (d->mPos < (uint)d->mLdif.size()) {
+ c = d->mLdif[d->mPos];
+ d->mPos++;
+ if (d->mIsNewLine && c == '\r') {
+ continue; //handle \n\r line end
+ }
+ if (d->mIsNewLine && (c == ' ' || c == '\t')) { //line folding
+ d->mIsNewLine = false;
+ continue;
+ }
+ if (d->mIsNewLine) {
+ d->mIsNewLine = false;
+ retval = processLine();
+ d->mLastParseValue = retval;
+ d->mLine.resize(0);
+ d->mIsComment = (c == '#');
+ }
+ if (c == '\n' || c == '\r') {
+ d->mLineNumber++;
+ d->mIsNewLine = true;
+ continue;
+ }
+ } else {
+ retval = MoreData;
+ break;
+ }
+
+ if (!d->mIsComment) {
+ d->mLine += c;
+ }
+ }
+ return retval;
+}
+
+void Ldif::endLdif()
+{
+ QByteArray tmp(3, '\n');
+ d->mLdif = tmp;
+ d->mPos = 0;
+}
+
+void Ldif::startParsing()
+{
+ d->mPos = d->mLineNumber = 0;
+ d->mDelOldRdn = false;
+ d->mEntryType = Entry_None;
+ d->mModType = Mod_None;
+ d->mDn = LdapDN();
+ d->mNewRdn.clear();
+ d->mNewSuperior.clear();
+ d->mLine = QByteArray();
+ d->mIsNewLine = false;
+ d->mIsComment = false;
+ d->mLastParseValue = None;
+}
+
+void Ldif::setLdif(const QByteArray &ldif)
+{
+ d->mLdif = ldif;
+ d->mPos = 0;
+}
+
+Ldif::EntryType Ldif::entryType() const
+{
+ return d->mEntryType;
+}
+
+int Ldif::modType() const
+{
+ return d->mModType;
+}
+
+LdapDN Ldif::dn() const
+{
+ return d->mDn;
+}
+
+QString Ldif::newRdn() const
+{
+ return d->mNewRdn;
+}
+
+QString Ldif::newSuperior() const
+{
+ return d->mNewSuperior;
+}
+
+bool Ldif::delOldRdn() const
+{
+ return d->mDelOldRdn;
+}
+
+QString Ldif::attr() const
+{
+ return d->mAttr;
+}
+
+QByteArray Ldif::value() const
+{
+ return d->mValue;
+}
+
+bool Ldif::isUrl() const
+{
+ return d->mUrl;
+}
+
+bool Ldif::isCritical() const
+{
+ return d->mCritical;
+}
+
+QString Ldif::oid() const
+{
+ return d->mOid;
+}
+
+uint Ldif::lineNumber() const
+{
+ return d->mLineNumber;
+}
--- /dev/null
+/*
+ This file is part of libkldap.
+ Copyright (c) 2004-2006 Szombathelyi György <gyurco@freemail.hu>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KLDAP_LDIF_H
+#define KLDAP_LDIF_H
+
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+
+#include "ldapdn.h"
+#include "kldap_export.h"
+
+namespace KLDAP
+{
+
+/**
+ * Ldif
+ *
+ * Ldif implements an RFC 2849 compliant Ldif parser. Ldif files are used to
+ * represent directory information on LDAP-based servers, or to describe a set
+ * of changes which are to be applied to a directory.
+ */
+
+class KLDAP_EXPORT Ldif
+{
+public:
+
+ typedef enum {
+ None, NewEntry, EndEntry, Item, Control, Err, MoreData
+ } ParseValue;
+
+ typedef enum {
+ Entry_None, Entry_Add, Entry_Del, Entry_Mod, Entry_Modrdn
+ } EntryType;
+
+ typedef enum {
+ Mod_None, Mod_Add, Mod_Replace, Mod_Del
+ } ModType;
+
+ Ldif();
+
+ Ldif(const Ldif &that);
+ Ldif &operator=(const Ldif &that);
+
+ virtual ~Ldif();
+
+ /**
+ * Assembles fieldname and value into a valid Ldif line, BASE64 encodes the
+ * value if necessary and optionally splits into more lines.
+ * @param fieldname The name of the entry.
+ * @param value The value of the entry.
+ * @param linelen Maximum length of the lines in the result.
+ * @param url If true, encode value as url ( use :< ).
+ */
+ static QByteArray assembleLine(const QString &fieldname,
+ const QByteArray &value, uint linelen = 0,
+ bool url = false);
+ /**
+ * This is the same as the above function, the only difference that
+ * this accepts QString as the value.
+ */
+ static QByteArray assembleLine(const QString &fieldname,
+ const QString &value, uint linelen = 0,
+ bool url = false);
+
+ /**
+ * Splits one line from an Ldif file to attribute and value components.
+ * @return true if value is an URL, false otherwise
+ */
+ static bool splitLine(const QByteArray &line, QString &fieldname,
+ QByteArray &value);
+
+ /**
+ * Splits a control specification (without the "control:" directive)
+ * @param line is the control directive
+ * @param oid will contain the OID
+ * @param critical will contain the criticality of control
+ * @param value is the control value
+ */
+ static bool splitControl(const QByteArray &line, QString &oid,
+ bool &critical, QByteArray &value);
+
+ /**
+ * Starts the parsing of a new Ldif
+ */
+ void startParsing();
+
+ /**
+ * Process one Ldif line
+ */
+ ParseValue processLine();
+
+ /**
+ * Process the Ldif until a complete item can be returned
+ * @return NewEntry if a new DN encountered, Item if a new item returned,
+ * Err if the Ldif contains error, EndEntry if the parser reached the end
+ * of the current entry and MoreData if the parser encountered the end of
+ * the current chunk of the Ldif.
+ *
+ * If you want to finish the parsing after receiving MoreData, then call
+ * endLdif(), so the parser can safely flush the current entry.
+ */
+ ParseValue nextItem();
+
+ /**
+ * Sets a chunk of Ldif. Call before startParsing(), or if nextItem()
+ * returned MoreData.
+ * @param ldif the Ldif chunk to set
+ */
+ void setLdif(const QByteArray &ldif);
+
+ /**
+ * Indicates the end of the Ldif file/stream. Call if nextItem() returned
+ * MoreData, but actually you don't have more data.
+ */
+ void endLdif();
+
+ /**
+ * Returns the requested LDAP operation extracted from the current entry.
+ */
+ EntryType entryType() const;
+
+ /**
+ * Returns the LDAP modify request type if entryType() returned Entry_Mod.
+ */
+ int modType() const;
+
+ /**
+ * Returns the Distinguished Name of the current entry.
+ */
+ LdapDN dn() const;
+
+ /**
+ * Returns the new Relative Distinguished Name if modType() returned
+ * Entry_Modrdn.
+ */
+ QString newRdn() const;
+
+ /**
+ * Returns the new parent of the entry if modType() returned Entry_Modrdn.
+ */
+ QString newSuperior() const;
+
+ /**
+ * Returns if the delete of the old RDN is required.
+ */
+ bool delOldRdn() const;
+
+ /**
+ * Returns the attribute name.
+ */
+ QString attr() const;
+
+ /**
+ * Returns the attribute value.
+ */
+ QByteArray value() const;
+
+ /**
+ * Returns if val() is an url
+ */
+ bool isUrl() const;
+
+ /**
+ * Returns the criticality level when modType() returned Control.
+ */
+ bool isCritical() const;
+
+ /**
+ * Returns the OID when modType() returned Control.
+ */
+ QString oid() const;
+
+ /**
+ * Returns the line number which the parser processes.
+ */
+ uint lineNumber() const;
+
+private:
+ class LdifPrivate;
+ LdifPrivate *const d;
+};
+
+}
+
+#endif
--- /dev/null
+//krazy:excludeall=style
+/* w32-ldap-help.h - Map utf8 based API into a wchar_t API.
+
+ Copyright (c) 2010 Andre Heinecke <aheinecke@intevation.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ */
+
+#ifndef W32_LDAP_HELP_H
+#define W32_LDAP_HELP_H
+
+#include <windows.h>
+#ifdef UNICODE
+# undef UNICODE
+# include <winldap.h>
+# include <winber.h>
+# define UNICODE
+#else
+# include <winldap.h>
+# include <winber.h>
+#endif // UNICODE
+
+/*
+ * From the openldap manpage:
+ * ber_len_t is an unsigned integer of at least 32 bits used to represent
+ * a length. It is commonly equivalent to a size_t. ber_slen_t is the
+ * signed variant to ber_len_t.
+ */
+typedef ULONG ber_len_t;
+
+#ifndef timeval
+#define timeval l_timeval
+#endif
+
+/* Redirect used ldap functions to functions with win_ prefix
+ * to further redirect those depending on the Windows Flavour */
+//#define ldap_err2string(a) win_ldap_err2string(a)
+#define ldap_init(a,b) win_ldap_init(a,b)
+#define ldap_sasl_bind(a, b, c, d, e, f, g) \
+ win_ldap_sasl_bind(a, b, c, d, e, f, g)
+#define ldap_sasl_bind_s(a, b, c, d, e, f, g) \
+ win_ldap_sasl_bind_s(a, b, c, d, e, f, g)
+#define ldap_parse_sasl_bind_result ( a, b, c, d, e ) \
+ win_ldap_parse_sasl_bind_result((a), (b), (c), (d), (e))
+#define ldap_get_dn(a, b) win_ldap_get_dn(a,b)
+#define ldap_memfree(a) win_ldap_memfree(a)
+#define ldap_mods_free(a, b) win_ldap_mods_free(a, b)
+#define ldap_first_attribute(a, b, c) \
+ win_ldap_first_attribute(a, b, c)
+#define ldap_get_values_len(a, b, c) \
+ win_ldap_get_values_len(a, b, c)
+#define ldap_next_attribute(a, b, c ) \
+ win_ldap_next_attribute(a, b, c)
+#define ldap_parse_result(a, b, c, d, e, f, g, h) \
+ win_ldap_parse_result(a, b, c, d, e, f, g, h)
+#define ldap_parse_extended_result(a, b, c, d, e) \
+ win_ldap_parse_extended_result(a, b, c, d, e)
+#define ldap_add_ext(a, b, c, d, e, f) \
+ win_ldap_add_ext((a), (b), (c), (d), (e), (f))
+#define ldap_add_ext_s(a, b, c, d, e) \
+ win_ldap_add_ext_s((a), (b), (c), (d), (e))
+# define ldap_compare_ext_s(a, b, c, d, e, f) \
+ win_ldap_compare_ext_s((a), (b), (c), (d), (e), (f))
+# define ldap_compare_ext(a, b, c, d, e, f, g) \
+ win_ldap_compare_ext((a), (b), (c), (d), (e), (f), (g))
+# define ldap_modify_ext_s(a, b, c, d, e ) \
+ win_ldap_modify_ext_s((a), (b), (c), (d), (e))
+# define ldap_search_ext(a, b, c, d, e, f, g, h, i, j, k) \
+ win_ldap_search_ext((a), (b), (c), (d), (e), (f), (g), (h), (i), (j), (k))
+#define ldap_rename_ext( a, b, c, d, e, f, g, h ) \
+ win_ldap_rename_ext((a), (b), (c), (d), (e), (f), (g), (h) )
+#define ldap_rename( a, b, c, d, e, f, g, h ) \
+ ldap_rename_ext((a), (b), (c), (d), (e), (f), (g), (h) )
+#define ldap_delete_ext(a, b, c, d, e ) \
+ win_ldap_delete_ext((a), (b), (c), (d), (e) )
+#define ldap_modify_ext(a, b, c, d, e, f ) \
+ win_ldap_modify_ext( (a), (b), (c), (d), (e), (f))
+#define ldap_abandon_ext(a, b, c, d) \
+ win_ldap_abandon_ext((a), (b), (c), (d))
+#define ldap_controls_free(a) win_ldap_controls_free(a)
+
+// Use the functions that are available on the platform
+// or redirect to wrapper functions
+
+/* Windows offers ASCII variants of most LDAP functions
+ * we only have to ensure that those are used */
+# define LDAPControl LDAPControlA
+# define LDAPMod LDAPModA
+# define win_ldap_init(a,b) ldap_initA ((a), (b))
+# define win_ldap_simple_bind_s(a,b,c) ldap_simple_bind_sA ((a), (b), (c))
+# define win_ldap_sasl_bind(a, b, c, d, e, f, g) \
+ ldap_sasl_bindA(a, b, c, d, e, f, g)
+# define win_ldap_sasl_bind_s(a, b, c, d, e, f, g) \
+ ldap_sasl_bind_sA(a, b, c, d, e, f, g)
+# define win_ldap_search_st(a,b,c,d,e,f,g,h) \
+ ldap_search_stA ((a), (b), (c), (d), (e), (f), (g), (h))
+# define win_ldap_search_ext(a, b, c, d, e, f, g, h, i, j, k) \
+ my_win_ldap_search_ext((a), (b), (c), (d), (e), (f), (g), (h), (i), (j), (k))
+# define win_ldap_get_dn(a, b) ldap_get_dnA((a), (b))
+# define win_ldap_first_attribute(a,b,c) ldap_first_attributeA ((a), (b), (c))
+# define win_ldap_next_attribute(a,b,c) ldap_next_attributeA ((a), (b), (c))
+# define win_ldap_get_values_len(a,b,c) ldap_get_values_lenA ((a), (b), (c))
+# define win_ldap_memfree(a) ldap_memfreeA ((a))
+# define win_ldap_err2string(a) ldap_err2stringA((a))
+# define win_ldap_controls_free(a) ldap_controls_freeA((a))
+# define win_ldap_mods_free(a, b) ldap_mods_freeA((a), (b))
+# define win_ldap_add_ext(a, b, c, d, e, f) \
+ ldap_add_extA((a), (b), (c), (d), (e), ((ulong*)f))
+# define win_ldap_add_ext_s(a, b, c, d, e) \
+ ldap_add_ext_sA((a), (b), (c), (d), (e))
+# define win_ldap_parse_extended_result(a, b, c, d, e ) \
+ ldap_parse_extended_resultA((*a), (b), (c), (d), (e))
+# define win_ldap_parse_result(a, b, c, d, e, f, g, h ) \
+ ldap_parse_resultA((a), (b), ((ulong *)c), (d), (e), (f), (g), (h))
+# define win_ldap_modify_ext_s(a, b, c, d, e ) \
+ ldap_modify_ext_sW((a), (b), (c), (d), (e))
+# define win_ldap_compare_ext_s(a, b, c, d, e, f ) \
+ ldap_compare_ext_sA((a), (b), (c), (d), (e), (f))
+#endif /*W32_LDAP_HELP_H*/