polkit-qt6: vendor as full-fork recipe (path=source, patches baked)

This commit is contained in:
2026-08-01 04:46:06 +03:00
parent 42ddb534a1
commit f679c8abab
101 changed files with 8288 additions and 2 deletions
+6 -2
View File
@@ -8,8 +8,12 @@ version = "0.3.1"
# polkit-1 backend (delegates to the redbear-polkit D-Bus daemon for
# real authorization) instead of the prior FAKE backend (always denies).
[source]
git = "https://invent.kde.org/libraries/polkit-qt-1.git"
branch = "master"
# Vendored local fork (full-fork model): builds from the committed source/
# tree (offline, reproducible). source/ = pristine upstream + the patches below
# BAKED IN. .patch files kept tracked so a version bump can re-apply them via
# sync-recipe-source.sh.
# upstream: https://invent.kde.org/libraries/polkit-qt-1.git
path = "source"
[build]
template = "custom"
@@ -0,0 +1,29 @@
*~
build/
apidocs/
Doxyfile
*.patch
# CMake
CMakeCache.txt
CMakeFiles
cmake_install.cmake
CMakeLists.txt.user
CMakeLists.txt.user.*
# QtCreator
qtcreator-build
# Misc
*.moc
moc_*
ui_*
Makefile
# LSP and IDEs
/.clang-format
/compile_commands.json
.clangd
.cache
.idea
.vscode
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0
include:
- project: sysadmin/ci-utilities
file:
- /gitlab-templates/linux-qt6.yml
- /gitlab-templates/linux-qt6-next.yml
- /gitlab-templates/linux.yml
- /gitlab-templates/freebsd-qt6.yml
@@ -0,0 +1,2 @@
Options:
cmake-options: '-DBUILD_EXAMPLES=ON'
@@ -0,0 +1 @@
polkit-qt-1.git
@@ -0,0 +1,9 @@
Main Authors:
- Daniel Nicoletti <dantti85-dev@yahoo.com.br>
- Dario Freddi <drf@kde.org>
- Jaroslav Reznik <jreznik@redhat.com>
Contributors:
- Pino Toscano <pino@kde.org>
- Lukas Tinkl <ltinkl@redhat.com>
- Radek Novacek <rnovacek@redhat.com>
@@ -0,0 +1,195 @@
cmake_minimum_required(VERSION 3.11)
## Polkit Qt Library
project("PolkitQt-1")
set(CMAKE_AUTOMOC TRUE)
set(CMAKE_AUTOUIC TRUE)
set(CMAKE_AUTORCC TRUE)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
# Used to create CMake config files
include(CMakePackageConfigHelpers)
# Used to generate export headers
include(GenerateExportHeader)
# Used to set installation paths
include(GNUInstallDirs)
include(FeatureSummary)
set(REQUIRED_QT_VERSION 5.5.0)
set(CMAKE_CXX_STANDARD 11)
option(BUILD_WITH_QT6 "Build against Qt 6" OFF)
if (NOT DEFINED QT_MAJOR_VERSION)
if (BUILD_WITH_QT6)
set(QT_MAJOR_VERSION 6)
else()
set(QT_MAJOR_VERSION 5)
endif()
endif()
find_package(Qt${QT_MAJOR_VERSION} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core DBus Widgets)
find_package(PkgConfig REQUIRED)
set(POLKITQT-1_PCNAME "polkit-qt${QT_MAJOR_VERSION}-1")
set(POLKITQT-1_CORE_PCNAME "polkit-qt${QT_MAJOR_VERSION}-core-1")
set(POLKITQT-1_GUI_PCNAME "polkit-qt${QT_MAJOR_VERSION}-gui-1")
set(POLKITQT-1_AGENT_PCNAME "polkit-qt${QT_MAJOR_VERSION}-agent-1")
set(POLKITQT-1_CAMEL_NAME "PolkitQt${QT_MAJOR_VERSION}-1")
set(POLKITQT-1_EXAMPLE "polkit-example-qt${QT_MAJOR_VERSION}")
set(POLKITQT-1_EXAMPLE_HELPER "polkit-example-helper-qt${QT_MAJOR_VERSION}")
set(POLKITQT-1_AGENT_EXAMPLE "polkit-agent-example-qt${QT_MAJOR_VERSION}")
set(POLKITQT-1_INCLUDE_PATH "polkit-qt${QT_MAJOR_VERSION}-1")
pkg_check_modules(POLKIT_GOBJECT polkit-gobject-1 REQUIRED IMPORTED_TARGET)
pkg_check_modules(POLKIT_AGENT polkit-agent-1 REQUIRED IMPORTED_TARGET)
pkg_check_modules(GLIB2 glib-2.0>=2.36 REQUIRED IMPORTED_TARGET)
pkg_check_modules(GOBJECT gobject-2.0 REQUIRED IMPORTED_TARGET)
add_definitions(-DQT_NO_KEYWORDS)
include (CheckFunctionExists)
# Check for older polkit
set(CMAKE_REQUIRED_INCLUDES ${POLKIT_GOBJECT_INCLUDE_DIRS} ${POLKIT_AGENT_INCLUDE_DIRS})
set(CMAKE_REQUIRED_LIBRARIES ${POLKIT_GOBJECT_LIBRARIES} ${POLKIT_AGENT_LIBRARIES})
check_function_exists(polkit_agent_listener_register HAVE_POLKIT_AGENT_LISTENER_REGISTER)
check_function_exists(polkit_authority_get_sync HAVE_POLKIT_AUTHORITY_GET_SYNC)
check_function_exists(polkit_system_bus_name_get_user_sync HAVE_POLKIT_SYSTEM_BUS_NAME_GET_USER_SYNC)
if (NOT HAVE_POLKIT_AGENT_LISTENER_REGISTER OR NOT HAVE_POLKIT_AUTHORITY_GET_SYNC)
message(STATUS "You have an older polkit-1 version: Polkit-Qt-1 will be built in compatibility mode")
add_definitions(-DPOLKIT_QT_1_COMPATIBILITY_MODE)
endif (NOT HAVE_POLKIT_AGENT_LISTENER_REGISTER OR NOT HAVE_POLKIT_AUTHORITY_GET_SYNC)
option(USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR "Prefer to install the <package>Config.cmake files to lib/cmake/<package> instead of lib/<package>/cmake" TRUE)
set(POLKITQT-1_VERSION_MAJOR "0")
set(POLKITQT-1_VERSION_MINOR "201")
set(POLKITQT-1_VERSION_PATCH "1")
set(POLKITQT-1_VERSION_STRING
"${POLKITQT-1_VERSION_MAJOR}.${POLKITQT-1_VERSION_MINOR}.${POLKITQT-1_VERSION_PATCH}")
# The SONUMBER of the polkit-qt-1 libraries
set(POLKITQT-1_ABI_VERSION 1)
# The version number of the polkit-qt-1 libraries
set(POLKITQT-1_LIBRARY_VERSION "${POLKITQT-1_ABI_VERSION}.${POLKITQT-1_VERSION_MINOR}.${POLKITQT-1_VERSION_PATCH}")
set(POLKITQT-1_LIB_NAMESPACE ${POLKITQT-1_CAMEL_NAME})
configure_file(polkitqt1-version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/core/polkitqt1-version.h)
configure_file(polkitqt1-config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/core/polkitqt1-config.h)
install(FILES
gui/polkitqt1-gui-action.h
gui/polkitqt1-gui-actionbutton.h
gui/polkitqt1-gui-actionbuttons.h
core/polkitqt1-authority.h
core/polkitqt1-details.h
core/polkitqt1-identity.h
core/polkitqt1-subject.h
core/polkitqt1-temporaryauthorization.h
core/polkitqt1-actiondescription.h
agent/polkitqt1-agent-listener.h
agent/polkitqt1-agent-session.h
${CMAKE_CURRENT_BINARY_DIR}/core/polkitqt1-version.h
${CMAKE_CURRENT_BINARY_DIR}/core/polkitqt1-core-export.h
${CMAKE_CURRENT_BINARY_DIR}/gui/polkitqt1-gui-export.h
${CMAKE_CURRENT_BINARY_DIR}/agent/polkitqt1-agent-export.h
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}/${POLKITQT-1_INCLUDE_PATH} COMPONENT Devel)
install(FILES
includes/PolkitQt1/Authority
includes/PolkitQt1/Details
includes/PolkitQt1/Identity
includes/PolkitQt1/Subject
includes/PolkitQt1/TemporaryAuthorization
includes/PolkitQt1/ActionDescription
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}/${POLKITQT-1_INCLUDE_PATH}/PolkitQt1 COMPONENT Devel)
install(FILES
includes/PolkitQt1/Gui/Action
includes/PolkitQt1/Gui/ActionButton
includes/PolkitQt1/Gui/ActionButtons
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}/${POLKITQT-1_INCLUDE_PATH}/PolkitQt1/Gui COMPONENT Devel)
install(FILES
includes/PolkitQt1/Agent/Listener
includes/PolkitQt1/Agent/Session
DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}/${POLKITQT-1_INCLUDE_PATH}/PolkitQt1/Agent COMPONENT Devel)
if(NOT WIN32)
# Pkgconfig
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${POLKITQT-1_PCNAME}.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/${POLKITQT-1_PCNAME}.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${POLKITQT-1_PCNAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${POLKITQT-1_CORE_PCNAME}.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/${POLKITQT-1_CORE_PCNAME}.pc
@ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${POLKITQT-1_CORE_PCNAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${POLKITQT-1_GUI_PCNAME}.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/${POLKITQT-1_GUI_PCNAME}.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${POLKITQT-1_GUI_PCNAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${POLKITQT-1_AGENT_PCNAME}.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/${POLKITQT-1_AGENT_PCNAME}.pc
@ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${POLKITQT-1_AGENT_PCNAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig )
endif(NOT WIN32)
if(USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR)
set(_PolkitQt-1Config_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/${POLKITQT-1_CAMEL_NAME})
else(USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR)
set(_PolkitQt-1Config_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/${POLKITQT-1_CAMEL_NAME}/cmake)
endif(USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR)
# Create the CMake Config files
configure_package_config_file(PolkitQt-1Config.cmake.in
${CMAKE_BINARY_DIR}/${POLKITQT-1_CAMEL_NAME}Config.cmake
INSTALL_DESTINATION ${_PolkitQt-1Config_INSTALL_DIR}
PATH_VARS CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR
)
write_basic_package_version_file(${CMAKE_BINARY_DIR}/${POLKITQT-1_CAMEL_NAME}ConfigVersion.cmake
VERSION ${POLKITQT-1_VERSION_STRING}
COMPATIBILITY SameMajorVersion
)
install(FILES ${CMAKE_BINARY_DIR}/${POLKITQT-1_CAMEL_NAME}Config.cmake
${CMAKE_BINARY_DIR}/${POLKITQT-1_CAMEL_NAME}ConfigVersion.cmake
DESTINATION ${_PolkitQt-1Config_INSTALL_DIR}
)
install(EXPORT ${POLKITQT-1_CAMEL_NAME}Export FILE ${POLKITQT-1_CAMEL_NAME}Targets.cmake
DESTINATION ${_PolkitQt-1Config_INSTALL_DIR}
NAMESPACE ${POLKITQT-1_LIB_NAMESPACE}::)
option(BUILD_EXAMPLES "Builds a set of examples for polkit-qt-1" OFF)
if (BUILD_EXAMPLES)
find_package(Qt${QT_MAJOR_VERSION}Xml ${REQUIRED_QT_VERSION} REQUIRED)
add_subdirectory(examples)
endif (BUILD_EXAMPLES)
option(BUILD_TEST "Builds unit tests for polkit-qt-1" OFF)
if (BUILD_TEST)
find_package(Qt${QT_MAJOR_VERSION}Test ${REQUIRED_QT_VERSION} REQUIRED)
add_subdirectory(test)
endif (BUILD_TEST)
add_subdirectory(core)
add_subdirectory(gui)
add_subdirectory(agent)
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
@@ -0,0 +1,26 @@
Polkit-qt's build system uses cmake.
So to compile Polkit-qt first create a build dir
mkdir build
cd build
then run cmake:
cmake ..
(a typical cmake option that is often used is: -DCMAKE_INSTALL_PREFIX=<prefix>)
cmake then presents a configuration summary. At this point you may
want to install missing dependencies (if you do, remove the CMakeCache.txt)
and run cmake again.
Finally build Polkit-qt:
make
And install it (in most cases root privileges are required):
make install
That's all :)
@@ -0,0 +1,26 @@
Copyright (c) <year> <owner>. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
@@ -0,0 +1,311 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, 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.
Preamble
The licenses for most software are designed to take away your freedom to share
and change it. By contrast, the GNU General Public License is intended to
guarantee your freedom to share and change free software--to make sure the
software is free for all its users. This General Public License applies to
most of the Free Software Foundation's software and to any other program whose
authors commit to using it. (Some other Free Software Foundation software
is covered by the GNU Lesser General Public License instead.) You can apply
it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom
to distribute copies of free software (and charge for this service if you
wish), that you receive source code or can get it if you want it, that you
can change the software or use pieces of it in new free programs; and that
you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to
deny you these rights or to ask you to surrender the rights. These restrictions
translate to certain responsibilities for you if you distribute copies of
the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or
for a fee, you must give the recipients all the rights that you have. You
must make sure that they, too, receive or can get the source code. And you
must show them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2)
offer you this license which gives you legal permission to copy, distribute
and/or modify the software.
Also, for each author's protection and ours, we want to make certain that
everyone understands that there is no warranty for this free software. If
the software is modified by someone else and passed on, we want its recipients
to know that what they have is not the original, so that any problems introduced
by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We
wish to avoid the danger that redistributors of a free program will individually
obtain patent licenses, in effect making the program proprietary. To prevent
this, we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification
follow.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains a notice
placed by the copyright holder saying it may be distributed under the terms
of this General Public License. The "Program", below, refers to any such program
or work, and a "work based on the Program" means either the Program or any
derivative work under copyright law: that is to say, a work containing the
Program or a portion of it, either verbatim or with modifications and/or translated
into another language. (Hereinafter, translation is included without limitation
in the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not covered
by this License; they are outside its scope. The act of running the Program
is not restricted, and the output from the Program is covered only if its
contents constitute a work based on the Program (independent of having been
made by running the Program). Whether that is true depends on what the Program
does.
1. You may copy and distribute verbatim copies of the Program's source code
as you receive it, in any medium, provided that you conspicuously and appropriately
publish on each copy an appropriate copyright notice and disclaimer of warranty;
keep intact all the notices that refer to this License and to the absence
of any warranty; and give any other recipients of the Program a copy of this
License along with the Program.
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.
2. You may modify your copy or copies of the Program or any portion of it,
thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating that
you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or
in part contains or is derived from the Program or any part thereof, to be
licensed as a whole at no charge to all third parties under the terms of this
License.
c) If the modified program normally reads commands interactively when run,
you must cause it, when started running for such interactive use in the most
ordinary way, to print or display an announcement including an appropriate
copyright notice and a notice that there is no warranty (or else, saying that
you provide a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this License.
(Exception: if the Program itself is interactive but does not normally print
such an announcement, your work based on the Program is not required to print
an announcement.)
These requirements apply to the modified work as a whole. If identifiable
sections of that work are not derived from the Program, 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 Program, 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 Program.
In addition, mere aggregation of another work not based on the Program with
the Program (or with a work based on the Program) on a volume of a storage
or distribution medium does not bring the other work under the scope of this
License.
3. You may copy and distribute the Program (or a work based on it, under Section
2) in object code or executable form under the terms of Sections 1 and 2 above
provided that you also do one of the following:
a) 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; or,
b) Accompany it with a written offer, valid for at least three years, to give
any third party, for a charge no more than your cost of physically performing
source distribution, a complete machine-readable copy of the corresponding
source code, to be distributed under the terms of Sections 1 and 2 above on
a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute
corresponding source code. (This alternative is allowed only for noncommercial
distribution and only if you received the program in object code or executable
form with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making
modifications to it. For an executable work, 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 executable. However, as a special exception, the source code 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.
If distribution of executable or 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 counts as distribution of the source code,
even though third parties are not compelled to copy the source along with
the object code.
4. You may not copy, modify, sublicense, or distribute the Program except
as expressly provided under this License. Any attempt otherwise to copy, modify,
sublicense or distribute the Program 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.
5. 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
Program or its derivative works. These actions are prohibited by law if you
do not accept this License. Therefore, by modifying or distributing the Program
(or any work based on the Program), you indicate your acceptance of this License
to do so, and all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program),
the recipient automatically receives a license from the original licensor
to copy, distribute or modify the Program 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 to this License.
7. 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 Program at all. For example, if a
patent license would not permit royalty-free redistribution of the Program
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 Program.
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.
8. If the distribution and/or use of the Program is restricted in certain
countries either by patents or by copyrighted interfaces, the original copyright
holder who places the Program 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.
9. The Free Software Foundation may publish revised and/or new versions of
the General Public License from time to time. Such new versions will be similar
in spirit to the present version, but may differ in detail to address new
problems or concerns.
Each version is given a distinguishing version number. If the Program specifies
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
Program does not specify a version number of this License, you may choose
any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs
whose distribution conditions are different, 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
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. 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 PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible
use to the public, the best way to achieve this is to make it free software
which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach
them to the start of each source file to most effectively 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 program's name and an idea of what it does. Copyright
(C) yyyy name of author
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how
to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when
it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software,
and you are welcome to redistribute it under certain conditions; type `show
c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may be
called something other than `show w' and `show c'; they could even be mouse-clicks
or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your school,
if any, to sign a "copyright disclaimer" for the program, if necessary. Here
is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision'
(which makes passes at compilers) written by James Hacker.
signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice
@@ -0,0 +1,444 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 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 library GPL. It is numbered 2
because it goes with version 2 of the ordinary GPL.]
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 Library General Public License, applies to some specially
designated Free Software Foundation software, and to any other libraries whose
authors decide to use it. You can use it for your libraries, too.
When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the freedom
to distribute copies of free software (and charge for this service if you
wish), that you receive source code or can get it if you want it, that you
can change the software or use pieces of it in new free programs; and that
you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to
deny you these rights or to ask you to surrender the 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
a program 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.
Our method of protecting your rights has two steps: (1) copyright the library,
and (2) offer you this license which gives you legal permission to copy, distribute
and/or modify the library.
Also, for each distributor's protection, we want to make certain that everyone
understands that there is no warranty for this free library. If the library
is modified by someone else and passed on, we want its recipients to know
that what they have is not the original version, so that any problems introduced
by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We
wish to avoid the danger that companies distributing free software will individually
obtain patent licenses, thus in effect transforming the program into proprietary
software. To prevent this, we have made it clear that any patent must be licensed
for everyone's free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary GNU
General Public License, which was designed for utility programs. This license,
the GNU Library General Public License, applies to certain designated libraries.
This license is quite different from the ordinary one; be sure to read it
in full, and don't assume that anything in it is the same as in the ordinary
license.
The reason we have a separate public license for some libraries is that they
blur the distinction we usually make between modifying or adding to a program
and simply using it. Linking a program with a library, without changing the
library, is in some sense simply using the library, and is analogous to running
a utility program or application program. However, in a textual and legal
sense, the linked executable is a combined work, a derivative of the original
library, and the ordinary General Public License treats it as such.
Because of this blurred distinction, using the ordinary General Public License
for libraries did not effectively promote software sharing, because most developers
did not use the libraries. We concluded that weaker conditions might promote
sharing better.
However, unrestricted linking of non-free programs would deprive the users
of those programs of all benefit from the free status of the libraries themselves.
This Library General Public License is intended to permit developers of non-free
programs to use free libraries, while preserving your freedom as a user of
such programs to change the free libraries that are incorporated in them.
(We have not seen how to achieve this as regards changes in header files,
but we have achieved it as regards changes in the actual functions of the
Library.) The hope is that this will lead to faster development of free libraries.
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, while the latter only works together with the library.
Note that it is possible for a library to be covered by the ordinary General
Public License rather than by this special one.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which contains a
notice placed by the copyright holder or other authorized party saying it
may be distributed under the terms of this Library 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.
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.
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.
6. As an exception to the Sections above, you may also compile 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) 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.
c) 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.
d) 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 source code 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.
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 to this License.
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 Library 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.
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
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 an 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 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; 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!
@@ -0,0 +1,107 @@
/**
\mainpage Polkit-qt-1 - Qt wrapper around polkit-1
\section polkitqt1_overview Overview
\note Please note that if you're developing an application which can rely not just on Qt modules,
but also Qt extensions like from the KDE Frameworks, you might want to use instead
KAuth from KDE Frameworks.
polkit-qt-1 aims to make it easy for Qt developers to take advantage of
polkit API. It is a convenience wrapper around QAction and QAbstractButton
that lets you integrate those two components easily with polkit.
polkit-qt-1 is not a direct replacement of polkit-qt: it is based on polkit-1, which is not
backwards compatible in any way with Policykit <= 0.9, which was the backend of polkit-qt.
You are encouraged to port polkit-qt applications to polkit-qt or KAuth (from KDE Frameworks),
since PolicyKit <= 0.9 is no longer maintained.
polkit-qt-1 is split in three libraries: polkit-qt-core-1, polkit-qt-gui-1 and polkit-qt-agent-1
\b polkit-qt-core-1 lets you control actions and authentication without a GUI, with some very
simple functions. It also lets you retrieve and control useful information on the polkit
authority. You will be mostly interested in the \c Authority class.
\b polkit-qt-gui-1 lets you easily associate GUI items with polkit actions. Through some simple
wrapper classes you are able to associate QAction and QAbstractButton to a polkit action,
and get their properties changed accordingly to polkit's result. It includes the classes
Action, ActionButton and ActionButtons
\b polkit-qt-agent-1 lets you write your own polkit authentication agents in a very simple way.
\li A sample usage of polkit-qt-1 can be found in \ref polkitqt1_example
\li <a href="classes.html">Alphabetical Class List</a>
\li <a href="hierarchy.html">Class Hierarchy</a>
\page polkitqt1_example Polkit-qt-1 usage example
You can find an example usage of Polkit-qt-1 in the examples/ dir. You can
build it by passing \c -DBUILD_EXAMPLES=TRUE to your cmake line. The structure
consists of a .ui file and a main class, to demonstrate how easy it is to integrate
polkit support in an existing application. Let's see some details about it:
\code
bt = new ActionButton(kickPB, "org.qt.policykit.examples.kick", this);
bt->setText("Kick... (long)");
// here we set the behavior of PolKitResul = No
bt->setVisible(true, Action::No);
bt->setEnabled(true, Action::No);
bt->setText("Kick (long)", Action::No);
bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No);
bt->setToolTip("If your admin wasn't annoying, you could do this", Action::No);
// here we set the behavior of PolKitResul = Auth
bt->setVisible(true, Action::Auth);
bt->setEnabled(true, Action::Auth);
bt->setText("Kick... (long)", Action::Auth);
bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth);
bt->setToolTip("Only card carrying tweakers can do this!", Action::Auth);
// here we set the behavior of PolKitResul = Yes
bt->setVisible(true, Action::Yes);
bt->setEnabled(true, Action::Yes);
bt->setText("Kick! (long)", Action::Yes);
bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes);
bt->setToolTip("Go ahead, kick kick kick!", Action::Yes);
\endcode
This small paragraph sets up an action button using an existing button defined in the
UI file, \c kickPB . As you can see, you can set custom properties on your button depending
on the action status/result. The code is mostly self-explainatory
\code
bt = new ActionButtons(QList<QAbstractButton*>() << listenPB << listenCB,
"org.qt.policykit.examples.listen", this);
bt->setIcon(QPixmap(":/Icons/action-locked.png"));
bt->setIcon(QPixmap(":/Icons/action-unlocked.png"), Action::Yes);
bt->setText("Click to make changes...");
\endcode
This demonstrates the use of ActionButtons, that lets you associate multiple buttons with a
single action with extreme ease. \c listenPB and \c listenCB, both defined in the ui file,
are kept in sync with the action.
\code
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
\endcode
Those three signals are all you need to control the action and the activation. Action::triggered()
lets you start the activation/revoke when needed, ActionButton::clicked() lets you do the same thing
with even more ease, just by manually connecting the signal to ActionButton::activate() (see the docs
to understand why this connection doesn't happen automatically), and Action::authorized() signal notifies
you when polkit has authorized you to perform the action.
As you can see, usage of polkit-qt-1 is extremely simple. Have a look at the complete example
and to the API Docs for more details.
*/
// DOXYGEN_PROJECTVERSION=0.96.1
// DOXYGEN_PROJECTNAME=PolkitQt-1
// DOXYGEN_ENABLE=YES
// vim:ts=4:sw=4:expandtab:filetype=doxygen
@@ -0,0 +1,55 @@
@PACKAGE_INIT@
# Config file for POLKITQT-1
# The following variables are defined:
# POLKITQT-1_FOUND - True if POLKITQT-1 has been found.
# POLKITQT-1_INCLUDE_DIR - The include directory.
# POLKITQT-1_LIB_DIR - The libraries directory.
# POLKITQT-1_LIBRARIES - Libraries needed to use PolkitQt-1.
########## The PolkitQt-1 version ##########
set(POLKITQT-1_VERSION_MAJOR @POLKITQT-1_VERSION_MAJOR@)
set(POLKITQT-1_VERSION_MINOR @POLKITQT-1_VERSION_MINOR@)
set(POLKITQT-1_VERSION_PATCH @POLKITQT-1_VERSION_PATCH@)
set(POLKITQT-1_VERSION @POLKITQT-1_VERSION_STRING@)
set(POLKITQT-1_VERSION_STRING "@POLKITQT-1_VERSION_STRING@")
#########################################
########## Install dirs ##########
if(NOT POLKITQT-1_INSTALL_DIR)
set(POLKITQT-1_INSTALL_DIR "@CMAKE_INSTALL_PREFIX@")
endif(NOT POLKITQT-1_INSTALL_DIR)
set_and_check(POLKITQT-1_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@")
set_and_check(POLKITQT-1_INCLUDE_DIRS "${POLKITQT-1_INCLUDE_DIR}")
set_and_check(POLKITQT-1_LIB_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@")
set(POLKITQT-1_POLICY_FILES_INSTALL_DIR "${POLKITQT-1_INSTALL_DIR}/share/polkit-1/actions")
##################################
########## Compatibility ##########
if(WIN32)
if(MINGW)
set(POLKITQT-1_CORE_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_CORE_PCNAME@.dll.a")
set(POLKITQT-1_AGENT_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_AGENT_PCNAME@.dll.a")
set(POLKITQT-1_GUI_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_GUI_PCNAME@.dll.a")
else(MINGW)
set(POLKITQT-1_CORE_LIBRARY "${POLKITQT-1_LIB_DIR}/@POLKITQT-1_CORE_PCNAME@.lib")
set(POLKITQT-1_AGENT_LIBRARY "${POLKITQT-1_LIB_DIR}/@POLKITQT-1_AGENT_PCNAME@.lib")
set(POLKITQT-1_GUI_LIBRARY "${POLKITQT-1_LIB_DIR}/@POLKITQT-1_GUI_PCNAME@.lib")
endif(MINGW)
elseif(APPLE)
set(POLKITQT-1_CORE_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_CORE_PCNAME@.dylib")
set(POLKITQT-1_AGENT_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_AGENT_PCNAME@.dylib")
set(POLKITQT-1_GUI_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_GUI_PCNAME@.dylib")
else()
set(POLKITQT-1_CORE_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_CORE_PCNAME@.so")
set(POLKITQT-1_AGENT_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_AGENT_PCNAME@.so")
set(POLKITQT-1_GUI_LIBRARY "${POLKITQT-1_LIB_DIR}/lib@POLKITQT-1_GUI_PCNAME@.so")
endif()
########## The PolkitQt-1 libraries ##########
# Load the exported targets.
include("${CMAKE_CURRENT_LIST_DIR}/@POLKITQT-1_CAMEL_NAME@Targets.cmake")
set(POLKITQT-1_LIBRARIES @POLKITQT-1_CAMEL_NAME@::Core @POLKITQT-1_CAMEL_NAME@::Gui @POLKITQT-1_CAMEL_NAME@::Agent)
###########################################
@@ -0,0 +1,23 @@
Polkit-qt
========
What is Polkit-qt?
------------------
Polkit-qt is a library that lets developers use the PolicyKit API through a nice
Qt-styled API. It is mainly a wrapper around QAction and QAbstractButton that
lets you integrate those two component easily with PolicyKit
This directory contains the sources of the library.
Structure
----------
* cmake/
Contains the cmake checks that are needed to build the library,
and a FindPolkitQt.cmake module.
* .
Contains the sources of the library
See INSTALL for installation instructions.
@@ -0,0 +1,25 @@
Policy Kit 1 support for polkit-qt
==================================
This is initial port to PK1.
What's working?
---------------
polkit-qt-core
polkit-qt-gui
TO-DO
-----
* polkit-qt-core
- temporary authorization handling functions
- move from Auth namespace to Authority class?
- tests
Documentation
-------------
http://fedoraproject.org/wiki/Features/PolicyKitOne
http://hal.freedesktop.org/docs/polkit/index.html
Porting guide
-------------
http://cgit.freedesktop.org/PolicyKit/tree/docs/PORTING-GUIDE
+11
View File
@@ -0,0 +1,11 @@
TODO
====
- Policy Kit 1 port
* polkit-qt
+ Console Kit support
* polkit-qt-gui
+ authorization checking for non privileged user
- document Listener and co.
@@ -0,0 +1,39 @@
add_library(${POLKITQT-1_AGENT_PCNAME} SHARED)
add_library(${POLKITQT-1_CAMEL_NAME}::Agent ALIAS ${POLKITQT-1_AGENT_PCNAME})
target_sources(${POLKITQT-1_AGENT_PCNAME} PRIVATE
polkitqt1-agent-session.cpp
polkitqt1-agent-listener.cpp
listeneradapter.cpp
polkitqtlistener.cpp
)
generate_export_header(${POLKITQT-1_AGENT_PCNAME}
BASE_NAME polkitqt1-agent
EXPORT_FILE_NAME polkitqt1-agent-export.h
)
target_link_libraries(${POLKITQT-1_AGENT_PCNAME}
PUBLIC
Qt${QT_MAJOR_VERSION}::Core
${POLKITQT-1_CORE_PCNAME}
PRIVATE
Qt${QT_MAJOR_VERSION}::Core
PkgConfig::POLKIT_AGENT
PkgConfig::GOBJECT
)
set_target_properties(${POLKITQT-1_AGENT_PCNAME} PROPERTIES VERSION ${POLKITQT-1_LIBRARY_VERSION}
SOVERSION ${POLKITQT-1_ABI_VERSION}
DEFINE_SYMBOL MAKE_POLKITQT1_LIB
EXPORT_NAME Agent)
target_include_directories(${POLKITQT-1_AGENT_PCNAME}
INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${POLKITQT-1_INCLUDE_PATH}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
)
install(TARGETS ${POLKITQT-1_AGENT_PCNAME} EXPORT ${POLKITQT-1_CAMEL_NAME}Export ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION bin)
@@ -0,0 +1,135 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "listeneradapter_p.h"
#include <QDebug>
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE 1
#include <polkitagent/polkitagent.h>
namespace PolkitQt1
{
namespace Agent
{
class ListenerAdapterHelper
{
public:
ListenerAdapterHelper() : q(nullptr) {}
~ListenerAdapterHelper() {
delete q;
}
ListenerAdapter *q;
};
Q_GLOBAL_STATIC(ListenerAdapterHelper, s_globalListenerAdapter)
ListenerAdapter *ListenerAdapter::instance()
{
if (!s_globalListenerAdapter()->q) {
new ListenerAdapter();
}
return s_globalListenerAdapter()->q;
}
ListenerAdapter::ListenerAdapter(QObject *parent)
: QObject(parent)
{
Q_ASSERT(!s_globalListenerAdapter()->q);
s_globalListenerAdapter()->q = this;
}
Listener* ListenerAdapter::findListener(PolkitAgentListener *listener)
{
Listener *listItem;
Q_FOREACH(listItem, m_listeners) {
Q_ASSERT(listItem);
if (listItem->listener() == listener) {
return listItem;
}
}
return nullptr;
}
void ListenerAdapter::polkit_qt_listener_initiate_authentication(PolkitAgentListener *listener,
const gchar *action_id,
const gchar *message,
const gchar *icon_name,
PolkitDetails *details,
const gchar *cookie,
GList *identities,
GCancellable *cancellable,
GSimpleAsyncResult *result)
{
qDebug() << "polkit_qt_listener_initiate_authentication callback for " << listener;
PolkitQt1::Details dets(details);
Listener *list = findListener(listener);
// Polkit enumerates identities without regard for their hash value, potentially leading to duplicated entries.
// Unique the identities on our end.
// https://github.com/polkit-org/polkit/issues/542
QHash<guint, PolkitQt1::Identity> uniqueIdentities;
for (GList *entry = g_list_first(identities); entry != nullptr; entry = g_list_next(entry)) {
auto identity = static_cast<PolkitIdentity *>(entry->data);
uniqueIdentities.insert(polkit_identity_hash(identity), PolkitQt1::Identity(identity));
}
list->initiateAuthentication(QString::fromUtf8(action_id),
QString::fromUtf8(message),
QString::fromUtf8(icon_name),
dets,
QString::fromUtf8(cookie),
uniqueIdentities.values(),
new AsyncResult(result));
}
gboolean ListenerAdapter::polkit_qt_listener_initiate_authentication_finish(PolkitAgentListener *listener,
GAsyncResult *res,
GError **error)
{
qDebug() << "polkit_qt_listener_initiate_authentication_finish callback for " << listener;
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
if (g_simple_async_result_propagate_error(simple, error)) {
return false;
}
return true;
}
void ListenerAdapter::cancelled_cb(PolkitAgentListener *listener)
{
qDebug() << "cancelled_cb for " << listener;
Listener *list = findListener(listener);
list->cancelAuthentication();
}
void ListenerAdapter::addListener(Listener *listener)
{
qDebug() << "Adding new listener " << listener << "for " << listener->listener();
m_listeners.append(listener);
}
void ListenerAdapter::removeListener(Listener *listener)
{
qDebug() << "Removing listener " << listener;
// should be safe as we don't have more than one same listener registered in one time
m_listeners.removeOne(listener);
}
}
}
@@ -0,0 +1,70 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef LISTENER_ADAPTER_P_H
#define LISTENER_ADAPTER_P_H
#include <QObject>
#include "polkitqt1-agent-listener.h"
#include "polkitqt1-identity.h"
#include "polkitqt1-details.h"
typedef struct _GList GList;
typedef struct _GCancellable GCancellable;
typedef struct _GAsyncResult GAsyncResult;
typedef struct _GSimpleAsyncResult GSimpleAsyncResult;
typedef struct _GError GError;
typedef int gboolean;
typedef char gchar;
namespace PolkitQt1
{
namespace Agent
{
class AsyncResult;
class Listener;
class ListenerAdapter : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(ListenerAdapter)
public:
static ListenerAdapter* instance();
~ListenerAdapter() override {}
void polkit_qt_listener_initiate_authentication(PolkitAgentListener *listener,
const gchar *action_id,
const gchar *message,
const gchar *icon_name,
PolkitDetails *details,
const gchar *cookie,
GList *identities,
GCancellable *cancellable,
GSimpleAsyncResult *result);
gboolean polkit_qt_listener_initiate_authentication_finish(PolkitAgentListener *listener,
GAsyncResult *res,
GError **error);
void cancelled_cb(PolkitAgentListener *listener);
private:
void addListener(Listener *listener);
void removeListener(Listener *listener);
Listener* findListener(PolkitAgentListener *listener);
explicit ListenerAdapter(QObject *parent = nullptr);
QList<Listener *> m_listeners;
friend class Listener;
};
}
}
#endif
@@ -0,0 +1,109 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-agent-listener.h"
#include <QDebug>
#include "polkitqtlistener_p.h"
#include "polkitqt1-authority.h"
#include "polkitqt1-subject.h"
#include "polkitqt1-identity.h"
#include "polkitqt1-details.h"
namespace PolkitQt1
{
namespace Agent
{
class ListenerPrivate
{
public:
PolkitAgentListener *listener;
#ifndef POLKIT_QT_1_COMPATIBILITY_MODE
void *registeredHandle;
#endif
};
Listener::Listener(QObject *parent)
: QObject(parent), d(new ListenerPrivate)
{
d->listener = polkit_qt_listener_new();
qDebug() << "New PolkitAgentListener " << d->listener;
ListenerAdapter::instance()->addListener(this);
}
Listener::Listener(PolkitAgentListener *listener, QObject *parent)
: QObject(parent), d(new ListenerPrivate)
{
d->listener = listener;
if (d->listener != nullptr) {
g_object_ref(d->listener);
}
}
Listener::~Listener()
{
qDebug("Destroying listener");
ListenerAdapter::instance()->removeListener(this);
#ifndef POLKIT_QT_1_COMPATIBILITY_MODE
if (d->registeredHandle) {
polkit_agent_listener_unregister(d->registeredHandle);
}
#endif
if (d->listener != nullptr) {
g_object_unref(d->listener);
}
}
bool Listener::registerListener(const PolkitQt1::Subject &subject, const QString &objectPath)
{
GError *error = nullptr;
#ifndef POLKIT_QT_1_COMPATIBILITY_MODE
d->registeredHandle = polkit_agent_listener_register(d->listener,
POLKIT_AGENT_REGISTER_FLAGS_NONE,
#else
bool r = polkit_agent_register_listener(d->listener,
#endif
subject.subject(),
objectPath.toLatin1().data(),
#ifndef POLKIT_QT_1_COMPATIBILITY_MODE
nullptr,
#endif
&error);
if (error != nullptr) {
qWarning() << QString("Cannot register authentication agent: %1").arg(error->message);
g_error_free(error);
return false;
}
#ifndef POLKIT_QT_1_COMPATIBILITY_MODE
if (d->registeredHandle == nullptr) {
qWarning() << QString("Cannot register authentication agent!");
return false;
}
return true;
#else
return r;
#endif
}
const PolkitAgentListener *Listener::listener()
{
return d->listener;
}
}
}
@@ -0,0 +1,147 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_AGENT_LISTENER_H
#define POLKITQT1_AGENT_LISTENER_H
#include <QObject>
#include <QScopedPointer>
#include "polkitqt1-agent-session.h"
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE 1
typedef struct _PolkitAgentListener PolkitAgentListener;
namespace PolkitQt1
{
class Subject;
class Identity;
class Details;
}
namespace PolkitQt1
{
namespace Agent
{
class ListenerPrivate;
/**
* \class Listener polkitqt1-agent-listener.h Listener
* \author Jaroslav Reznik <jreznik@redhat.com>
*
* \brief Listener is abstract class used for implementing authentication agents.
*
* To implement an authentication agent, just subclass this class and implement
* virtual functions initiateAuthentication, initiateAuthenticationFinish
* and cancelAuthentication.
*
* You can also use Session class to authenticate users however it isn't required.
* \sa Session
*/
class POLKITQT1_AGENT_EXPORT Listener : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Listener)
public:
/**
* \brief Constructor of Listener class
*/
Listener(QObject *parent = nullptr);
/**
* \brief Constructor of Listener class from PolkitAgentListener
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param listener Pointer to the PolkitAgentListener
* \param parent
*/
explicit Listener(PolkitAgentListener *listener, QObject *parent = nullptr);
~Listener() override;
/**
* \brief Registers listener with polkit daemon as an authentication agent for \p subject.
*
* This is implemented by registering a DBus object at \p objectPath on the unique
* name assigned by the system message bus.
*
* Whenever the polkit daemon needs to authenticate a processes that is related to \p subject,
* the methods initiateAuthentication and initiateAuthenticationFinish will be evoked.
*
* \param subject Subject that listener will be registered for
* \param objectPath DBus object path
* \return \c True if the polkitqt1-agent-listener.has been registered, \c False otherwise
*/
bool registerListener(const PolkitQt1::Subject &subject, const QString &objectPath);
/**
* \brief Returns pointer to the PolkitAgentListener.
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \return PolkitAgentListener
*/
const PolkitAgentListener *listener();
public Q_SLOTS:
/**
* \brief Initiate authentication for the action
*
* This method will be called on a registered authentication agent when the user owning
* the session needs to prove he is one of the identities listed in \p identities.
*
* \note You have to reimplement this method in the subclass.
*
* \param actionId The action to authenticate for
* \param message The message to present to the user
* \param iconName The name of the icon which is representing the action
* \param details Details describing the action
* \param cookie The cookie for the authentization request
* \param identities A list of Identity object that the user can choose to authenticate as
* \param result This AsyncResult MUST be completed by using complete() method when the
* authentication is done. You can pass it to the constructor of the Session class
* and then call session->result()->complete() to mark the action as done.
*/
virtual void initiateAuthentication(const QString &actionId,
const QString &message,
const QString &iconName,
const PolkitQt1::Details &details,
const QString &cookie,
const PolkitQt1::Identity::List &identities,
PolkitQt1::Agent::AsyncResult *result) = 0;
/**
* TODO: Is this method really required ?
* \brief Finishes an authentication request from the polkit daemon.
*
* \note You have to reimplement this method in the subclass.
*
* \see initiateAuthentication
*/
virtual bool initiateAuthenticationFinish() = 0;
/**
* TODO: Is this method really required ?
* \brief Cancels an authentication request from the polkit daemon.
*
* \note You have to reimplement this method in the subclass.
*
* \see initiateAuthentication
*/
virtual void cancelAuthentication() = 0;
private:
QScopedPointer<ListenerPrivate> d;
};
}
}
#endif
@@ -0,0 +1,157 @@
/*
This file is part of the PolKit1-qt project
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-agent-session.h"
#include <QDebug>
#include "polkitqt1-identity.h"
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE 1
#include <polkitagent/polkitagent.h>
using namespace PolkitQt1::Agent;
class Session::Private
{
public:
Private() {}
~Private();
static void completed(PolkitAgentSession *s, gboolean gained_authorization, gpointer user_data);
static void request(PolkitAgentSession *s, gchar *request, gboolean echo_on, gpointer user_data);
static void showError(PolkitAgentSession *s, gchar *text, gpointer user_data);
static void showInfo(PolkitAgentSession *s, gchar *text, gpointer user_data);
AsyncResult *result;
PolkitAgentSession *polkitAgentSession;
};
Session::Private::~Private()
{
// polkitAgentSession is freed in Session d'tor
}
Session::Session(const PolkitQt1::Identity &identity, const QString &cookie, AsyncResult *result, QObject *parent)
: QObject(parent)
, d(new Private)
{
d->result = result;
d->polkitAgentSession = polkit_agent_session_new(identity.identity(), cookie.toUtf8().data());
g_signal_connect(G_OBJECT(d->polkitAgentSession), "completed", G_CALLBACK(Private::completed), this);
g_signal_connect(G_OBJECT(d->polkitAgentSession), "request", G_CALLBACK(Private::request), this);
g_signal_connect(G_OBJECT(d->polkitAgentSession), "show-error", G_CALLBACK(Private::showError), this);
g_signal_connect(G_OBJECT(d->polkitAgentSession), "show-info", G_CALLBACK(Private::showInfo), this);
}
Session::Session(PolkitAgentSession *pkAgentSession, QObject *parent)
: QObject(parent)
, d(new Private)
{
d->polkitAgentSession = pkAgentSession;
if (d->polkitAgentSession) {
g_object_ref(d->polkitAgentSession);
}
g_signal_connect(G_OBJECT(d->polkitAgentSession), "completed", G_CALLBACK(Private::completed), this);
g_signal_connect(G_OBJECT(d->polkitAgentSession), "request", G_CALLBACK(Private::request), this);
g_signal_connect(G_OBJECT(d->polkitAgentSession), "show-error", G_CALLBACK(Private::showError), this);
g_signal_connect(G_OBJECT(d->polkitAgentSession), "show-info", G_CALLBACK(Private::showInfo), this);
}
Session::~Session()
{
if (d->polkitAgentSession)
g_object_unref(d->polkitAgentSession);
delete d;
}
void Session::initiate()
{
polkit_agent_session_initiate(d->polkitAgentSession);
}
void Session::setResponse(const QString &response)
{
polkit_agent_session_response(d->polkitAgentSession, response.toUtf8().data());
}
void Session::cancel()
{
polkit_agent_session_cancel(d->polkitAgentSession);
}
AsyncResult *Session::result()
{
return d->result;
}
void Session::Private::completed(PolkitAgentSession *s, gboolean gained_authorization, gpointer user_data)
{
qDebug() << "COMPLETED";
Session *session = (Session *)user_data;
Q_EMIT(session)->completed(gained_authorization);
//free session here as polkit documentation asks
g_object_unref(session->d->polkitAgentSession);
session->d->polkitAgentSession = nullptr;
}
void Session::Private::request(PolkitAgentSession *s, gchar *request, gboolean echo_on, gpointer user_data)
{
qDebug() << "REQUEST";
Q_EMIT((Session *)user_data)->request(QString::fromUtf8(request), echo_on);
}
void Session::Private::showError(PolkitAgentSession *s, gchar *text, gpointer user_data)
{
qDebug() << "showError";
Q_EMIT((Session *)user_data)->showError(QString::fromUtf8(text));
}
void Session::Private::showInfo(PolkitAgentSession *s, gchar *text, gpointer user_data)
{
qDebug() << "showInfo";
Q_EMIT((Session *)user_data)->showInfo(QString::fromUtf8(text));
}
//
class AsyncResult::Private
{
public:
Private(GSimpleAsyncResult *r) : result(r) {};
GSimpleAsyncResult *result;
};
AsyncResult::AsyncResult(GSimpleAsyncResult *result)
: d(new Private(result))
{
}
AsyncResult::~AsyncResult()
{
if (d->result)
g_object_unref(d->result);
}
void AsyncResult::setCompleted()
{
if (d->result == nullptr)
return;
g_simple_async_result_complete(d->result);
// Assure that completed won't be called twice
g_object_unref(d->result);
d->result = nullptr;
}
void AsyncResult::setError(const QString &text)
{
Q_ASSERT(d->result);
g_simple_async_result_set_error(d->result, POLKIT_ERROR, POLKIT_ERROR_FAILED, "%s", text.toUtf8().data());
}
@@ -0,0 +1,168 @@
/*
This file is part of the PolKit1-qt project
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_AGENT_SESSION_H
#define POLKITQT1_AGENT_SESSION_H
#include <QObject>
#include "polkitqt1-identity.h"
#include "polkitqt1-agent-export.h"
typedef struct _GSimpleAsyncResult GSimpleAsyncResult;
typedef struct _PolkitAgentSession PolkitAgentSession;
namespace PolkitQt1
{
/**
* \namespace Agent Agent
*
* \brief Namespace wrapping Polkit-Qt Agent classes
*
* This namespace wraps all Polkit-Qt Agent classes.
*/
namespace Agent
{
/**
* \internal
* \brief Encapsulation of GSimpleAsyncResult to QObject class
*/
class POLKITQT1_AGENT_EXPORT AsyncResult
{
public:
explicit AsyncResult(GSimpleAsyncResult *result);
virtual ~AsyncResult();
/**
* \brief Mark the action that is tied to this result as completed.
*/
void setCompleted();
/**
* \brief Sets an error for the asynchronous result.
* Method complete() must be called anyway.
*
* \param text text of the error message
*/
void setError(const QString &text);
private:
class Private;
Private * const d;
};
/**
* \class Session polkitqt1-agent-session.h Session
* \author Radek Novacek <rnovacek@redhat.com>
*
* This class is interface for interacting with native
* authentication system for obtaining authorizations.
*
*/
class POLKITQT1_AGENT_EXPORT Session : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Session)
public:
/**
* Create a new authentication session.
*
* \param identity The identity to authenticate
* \param cookie The cookie obtained from the PolicyKit daemon
* \param result Result of the authentication action. Must be finished using complete() method.
* \param parent
*/
Session(const PolkitQt1::Identity& identity, const QString &cookie, AsyncResult *result = nullptr, QObject *parent = nullptr);
/**
* Create a new authentication session from PolkitAgentSession object
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param pkAgentSession PolkitAgentSession object
* \param parent
*/
explicit Session(PolkitAgentSession *pkAgentSession, QObject *parent = nullptr);
/**
* Destroy authentication session.
*/
~Session() override;
/**
* Initiate the authentication session.
*
* Use cancel() to cancel the session.
*/
void initiate();
/**
* Method for providing response to requests received via request signal.
*
* \param response Response from the user, typically a password
*/
void setResponse(const QString &response);
/**
* Cancel the authentication session.
* This will emit the completed() signal.
*/
void cancel();
/**
* Get AsyncResult that can be used to finish authentication operation
*
* \return AsyncResult object or NULL if it is not set
*/
AsyncResult *result();
Q_SIGNALS:
/**
* This signal will be emitted when the authentication
* polkitqt1-agent-session.has been completed or cancelled.
*
* \param gainedAuthorization \c True if authorization was successfully obtained.
*/
void completed(bool gainedAuthorization);
/**
* This signal will be emitted when user is requested to answer a question.
*
* \param request The request to show the user, e.g. "name: " or "password: ".
* \param echo \c True if the response to the request SHOULD be echoed on the screen,
* \c False if the response MUST NOT be echoed to the screen.
*/
void request(const QString &request, bool echo);
/**
* This signal will be emitted when there is information
* related to an error condition to be displayed to the user.
*
* \param text An error string to display to the user.
*/
void showError(const QString &text);
/**
* This signal will be emitted when there is information
* to be displayed to the user.
*
* \param text A string to be displayed to the user.
*/
void showInfo(const QString &text);
private:
class Private;
Private * const d;
};
}
}
#endif // SESSION_H
@@ -0,0 +1,135 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-FileContributor: based on code by David Zeuthen <davidz@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqtlistener_p.h"
#include <stdio.h>
#include <QDebug>
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE 1
using namespace PolkitQt1::Agent;
/**
* \internal
*/
struct _PolkitQtListener {
PolkitAgentListener parent_instance;
};
/**
* \internal
*/
struct _PolkitQtListenerClass {
PolkitAgentListenerClass parent_class;
};
static void polkit_qt_listener_initiate_authentication(PolkitAgentListener *listener,
const gchar *action_id,
const gchar *message,
const gchar *icon_name,
PolkitDetails *details,
const gchar *cookie,
GList *identities,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static gboolean polkit_qt_listener_initiate_authentication_finish(PolkitAgentListener *listener,
GAsyncResult *res,
GError **error);
G_DEFINE_TYPE(PolkitQtListener, polkit_qt_listener, POLKIT_AGENT_TYPE_LISTENER)
static void polkit_qt_listener_init(PolkitQtListener *listener)
{
}
static void polkit_qt_listener_finalize(GObject *object)
{
PolkitQtListener *listener;
listener = POLKIT_QT_LISTENER(object);
if (G_OBJECT_CLASS(polkit_qt_listener_parent_class)->finalize != nullptr) {
G_OBJECT_CLASS(polkit_qt_listener_parent_class)->finalize(object);
}
}
static void polkit_qt_listener_class_init(PolkitQtListenerClass *klass)
{
GObjectClass *gobject_class;
PolkitAgentListenerClass *listener_class;
gobject_class = G_OBJECT_CLASS(klass);
listener_class = POLKIT_AGENT_LISTENER_CLASS(klass);
gobject_class->finalize = polkit_qt_listener_finalize;
listener_class->initiate_authentication = polkit_qt_listener_initiate_authentication;
listener_class->initiate_authentication_finish = polkit_qt_listener_initiate_authentication_finish;
}
PolkitAgentListener *polkit_qt_listener_new(void)
{
return POLKIT_AGENT_LISTENER(g_object_new(POLKIT_QT_TYPE_LISTENER, nullptr));
}
static void cancelled_cb(GCancellable *cancellable, gpointer user_data)
{
ListenerAdapter::instance()->cancelled_cb((PolkitAgentListener *)user_data);
}
static void polkit_qt_listener_initiate_authentication(PolkitAgentListener *agent_listener,
const gchar *action_id,
const gchar *message,
const gchar *icon_name,
PolkitDetails *details,
const gchar *cookie,
GList *identities,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
qDebug() << "Listener adapter polkit_qt_listener_initiate_authentication";
PolkitQtListener *listener = POLKIT_QT_LISTENER(agent_listener);
if (cancellable != nullptr) {
g_cancellable_connect(cancellable,
G_CALLBACK(cancelled_cb),
agent_listener,
nullptr);
}
// The result of asynchronous method will be created here and it will be pushed to the listener.
GSimpleAsyncResult *result = g_simple_async_result_new((GObject *) listener, callback, user_data, agent_listener);
qDebug() << "GSimpleAsyncResult:" << result;
ListenerAdapter::instance()->polkit_qt_listener_initiate_authentication(agent_listener,
action_id,
message,
icon_name,
details,
cookie,
identities,
cancellable,
result);
}
static gboolean polkit_qt_listener_initiate_authentication_finish(PolkitAgentListener *listener,
GAsyncResult *res,
GError **error)
{
qDebug() << "Listener adapter polkit_qt_listener_initiate_authentication_finish";
return ListenerAdapter::instance()->polkit_qt_listener_initiate_authentication_finish(listener,
res,
error);
}
@@ -0,0 +1,35 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-FileContributor: based on code by David Zeuthen <davidz@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT_LISTENER_P_H
#define POLKITQT_LISTENER_P_H
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE 1
#include "listeneradapter_p.h"
#include <polkitagent/polkitagent.h>
G_BEGIN_DECLS
#define POLKIT_QT_TYPE_LISTENER (polkit_qt_listener_get_type())
#define POLKIT_QT_LISTENER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_QT_TYPE_LISTENER, PolkitQtListener))
#define POLKIT_QT_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), POLKIT_QT_TYPE_LISTENER, PolkitQtListenerClass))
#define POLKIT_QT_LISTENER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_QT_TYPE_LISTENER, PolkitQtListenerClass))
#define POLKIT_QT_IS_LISTENER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_QT_TYPE_LISTENER))
#define POLKIT_QT_IS_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_QT_TYPE_LISTENER))
typedef struct _PolkitQtListener PolkitQtListener;
typedef struct _PolkitQtListenerClass PolkitQtListenerClass;
GType polkit_qt_listener_get_type(void) G_GNUC_CONST;
PolkitAgentListener *polkit_qt_listener_new(void);
G_END_DECLS
#endif /* POLKIT_QT_LISTENER_H */
@@ -0,0 +1,43 @@
add_library(${POLKITQT-1_CORE_PCNAME} SHARED)
add_library(${POLKITQT-1_CAMEL_NAME}::Core ALIAS ${POLKITQT-1_CORE_PCNAME})
target_sources(${POLKITQT-1_CORE_PCNAME} PRIVATE
polkitqt1-authority.cpp
polkitqt1-identity.cpp
polkitqt1-subject.cpp
polkitqt1-temporaryauthorization.cpp
polkitqt1-details.cpp
polkitqt1-actiondescription.cpp
)
generate_export_header(${POLKITQT-1_CORE_PCNAME}
BASE_NAME polkitqt1-core
EXPORT_FILE_NAME polkitqt1-core-export.h
)
target_link_libraries(${POLKITQT-1_CORE_PCNAME}
PUBLIC
Qt${QT_MAJOR_VERSION}::Core
PRIVATE
Qt${QT_MAJOR_VERSION}::DBus
PkgConfig::POLKIT_GOBJECT
PkgConfig::GLIB2
PkgConfig::GOBJECT
)
set_target_properties(${POLKITQT-1_CORE_PCNAME} PROPERTIES VERSION ${POLKITQT-1_LIBRARY_VERSION}
SOVERSION ${POLKITQT-1_ABI_VERSION}
DEFINE_SYMBOL MAKE_POLKITQT1_LIB
EXPORT_NAME Core)
target_include_directories(${POLKITQT-1_CORE_PCNAME}
INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${POLKITQT-1_INCLUDE_PATH}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
)
install(TARGETS ${POLKITQT-1_CORE_PCNAME} EXPORT ${POLKITQT-1_CAMEL_NAME}Export ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION bin)
@@ -0,0 +1,133 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-FileCopyrightText: 2010 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-actiondescription.h"
#include <QString>
#include <polkit/polkit.h>
namespace PolkitQt1
{
class Q_DECL_HIDDEN ActionDescription::Data : public QSharedData
{
public:
Data() {}
Data(const Data& other)
: QSharedData(other)
, actionId(other.actionId)
, description(other.description)
, message(other.message)
, vendorName(other.vendorName)
, vendorUrl(other.vendorUrl)
, iconName(other.iconName)
, implicitAny(other.implicitAny)
, implicitInactive(other.implicitInactive)
, implicitActive(other.implicitActive)
{
}
virtual ~Data() {}
QString actionId;
QString description;
QString message;
QString vendorName;
QString vendorUrl;
QString iconName;
ActionDescription::ImplicitAuthorization implicitAny;
ActionDescription::ImplicitAuthorization implicitInactive;
ActionDescription::ImplicitAuthorization implicitActive;
};
ActionDescription::ActionDescription()
: d(new Data)
{
}
ActionDescription::ActionDescription(PolkitActionDescription *polkitActionDescription)
: d(new Data)
{
d->actionId = QString::fromUtf8(polkit_action_description_get_action_id(polkitActionDescription));
d->description = QString::fromUtf8(polkit_action_description_get_description(polkitActionDescription));
d->message = QString::fromUtf8(polkit_action_description_get_message(polkitActionDescription));
d->vendorName = QString::fromUtf8(polkit_action_description_get_vendor_name(polkitActionDescription));
d->vendorUrl = QString::fromUtf8(polkit_action_description_get_vendor_url(polkitActionDescription));
d->iconName = QString::fromUtf8(polkit_action_description_get_icon_name(polkitActionDescription));
d->implicitAny = static_cast<ActionDescription::ImplicitAuthorization>(polkit_action_description_get_implicit_any(
polkitActionDescription));
d->implicitInactive = static_cast<ActionDescription::ImplicitAuthorization>(polkit_action_description_get_implicit_inactive(
polkitActionDescription));
d->implicitActive = static_cast<ActionDescription::ImplicitAuthorization>(polkit_action_description_get_implicit_active(
polkitActionDescription));
}
ActionDescription::ActionDescription(const PolkitQt1::ActionDescription& other)
: d(other.d)
{
}
ActionDescription& ActionDescription::operator=(const PolkitQt1::ActionDescription& other)
{
d = other.d;
return *this;
}
ActionDescription::~ActionDescription()
{
}
QString ActionDescription::actionId() const
{
return d->actionId;
}
QString ActionDescription::description() const
{
return d->description;
}
QString ActionDescription::message() const
{
return d->message;
}
QString ActionDescription::vendorName() const
{
return d->vendorName;
}
QString ActionDescription::vendorUrl() const
{
return d->vendorUrl;
}
QString ActionDescription::iconName() const
{
return d->iconName;
}
ActionDescription::ImplicitAuthorization ActionDescription::implicitAny() const
{
return d->implicitAny;
}
ActionDescription::ImplicitAuthorization ActionDescription::implicitInactive() const
{
return d->implicitInactive;
}
ActionDescription::ImplicitAuthorization ActionDescription::implicitActive() const
{
return d->implicitActive;
}
}
@@ -0,0 +1,136 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-FileCopyrightText: 2010 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_ACTION_DESCRIPTION_H
#define POLKITQT1_ACTION_DESCRIPTION_H
#include "polkitqt1-core-export.h"
#include <QList>
#include <QMetaType>
#include <QSharedData>
typedef struct _PolkitActionDescription PolkitActionDescription;
namespace PolkitQt1
{
/**
* \class ActionDescription polkitqt1-actiondescription.h ActionDescription
* \author Jaroslav Reznik <jreznik@redhat.com>
* \author Dario Freddi <drf@kde.org>
*
* \brief Class used to encapsulate a registered action.
*/
class POLKITQT1_CORE_EXPORT ActionDescription
{
public:
enum ImplicitAuthorization {
/** Unknown whether the subject is authorized, never returned in any public API. **/
Unknown = -1,
/** Subject is not authorized. **/
NotAuthorized = 0,
/** Authentication is required. **/
AuthenticationRequired = 1,
/** Authentication as an administrator is required. **/
AdministratorAuthenticationRequired = 2,
/** Authentication is required. If the authorization is obtained, it is retained. **/
AuthenticationRequiredRetained = 3,
/** Authentication as an administrator is required. If the authorization is obtained, it is retained. **/
AdministratorAuthenticationRequiredRetained = 4,
/** The subject is authorized. **/
Authorized = 5
};
typedef QList< ActionDescription > List;
ActionDescription();
/**
* \brief Constructor of ActionDescription object from PolkitActionDescription
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param actionDesciption PolkitActionDescription
*/
explicit ActionDescription(PolkitActionDescription *actionDescription);
ActionDescription(const ActionDescription &other);
~ActionDescription();
ActionDescription &operator=(const ActionDescription &other);
/**
* \brief Gets the action id for ActionDescription
*
* \return id of the action
*/
QString actionId() const;
/**
* \brief Gets the description used for ActionDescription
*
* \return description of the action
*/
QString description() const;
/**
* \brief Gets the message used for ActionDescription
*
* \return action message
*/
QString message() const;
/**
* \brief Gets the vendor name for ActionDescription, if any
*
* \return vendor name
*/
QString vendorName() const;
/**
* \brief Gets the vendor URL for ActionDescription, if any
*
* \return vendor URL or empty QString if there is no vendor URL
*/
QString vendorUrl() const;
/**
* \brief Gets the icon name for ActionDescription, if any
*
* \return icon name or empty QString if there is no icon
*/
QString iconName() const;
/**
* \brief Gets the implicit authorization for ActionDescription used for any subject
*
* \return A value from ImplicitAuthorization enumeration
*/
ActionDescription::ImplicitAuthorization implicitAny() const;
/**
* \brief Gets the implicit authorization for ActionDescription used for subjects in inactive session on a local console
*
* \return A value from ImplicitAuthorization enumeration
*/
ActionDescription::ImplicitAuthorization implicitInactive() const;
/**
* \brief Gets the implicit authorization for ActionDescription used for subjects in active session on a local console
*
* \return A value from ImplicitAuthorization enumeration
*/
ActionDescription::ImplicitAuthorization implicitActive() const;
private:
class Data;
QSharedDataPointer< Data > d;
};
}
Q_DECLARE_METATYPE(PolkitQt1::ActionDescription::List)
#endif //POLKIT_QT_ACTION_DESCRIPTION_H
@@ -0,0 +1,902 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-authority.h"
#include <QDBusInterface>
#include <QDBusMessage>
#include <QDBusReply>
#include <polkit/polkit.h>
namespace PolkitQt1
{
class AuthorityHelper
{
public:
AuthorityHelper() : q(nullptr) {}
~AuthorityHelper() {
delete q;
}
Authority *q;
};
Q_GLOBAL_STATIC(AuthorityHelper, s_globalAuthority)
Authority *Authority::instance(PolkitAuthority *authority)
{
if (!s_globalAuthority()->q) {
new Authority(authority);
}
return s_globalAuthority()->q;
}
Authority::Result polkitResultToResult(PolkitAuthorizationResult *result)
{
if (polkit_authorization_result_get_is_challenge(result)) {
return Authority::Challenge;
} else if (polkit_authorization_result_get_is_authorized(result)) {
return Authority::Yes;
} else {
return Authority::No;
}
}
ActionDescription::List actionsToListAndFree(GList *glist)
{
ActionDescription::List result;
for (GList *glist2 = glist; glist2; glist2 = g_list_next(glist2)) {
gpointer i = glist2->data;
result.append(ActionDescription(static_cast<PolkitActionDescription *>(i)));
g_object_unref(i);
}
g_list_free(glist);
return result;
}
class Q_DECL_HIDDEN Authority::Private
{
public:
// Polkit will return NULL on failures, hence we use it instead of 0
Private(Authority *qq) : q(qq)
, pkAuthority(nullptr)
, m_hasError(false)
, m_systemBus(nullptr)
{
}
~Private();
void init();
/** Use this method to set the error message to \p message. Set recover to \c true
* to try to reinitialize this object with init() method
*/
void setError(Authority::ErrorCode code, const QString &details = QString(), bool recover = false);
void dbusFilter(const QDBusMessage &message);
void dbusSignalAdd(const QString &service, const QString &path, const QString &interface, const QString &name);
void seatSignalsConnect(const QString &seat);
Authority *q;
PolkitAuthority *pkAuthority;
bool m_hasError;
Authority::ErrorCode m_lastError;
QString m_errorDetails;
// Local system bus. QDBusConnection::systemBus() may only be safely used
// inside a QCoreApplication scope as for example destruction of connected
// objects need to happen before the bus disappears. Since this class however
// is a global static and systemBus() internally is a global static we
// cannot assure destruction order. Instead we create a local copy of the
// global systemBus instance so we can make life time to our needs.
// This prevents crashes when cleaning up the global statics.
QDBusConnection *m_systemBus;
GCancellable *m_checkAuthorizationCancellable,
*m_enumerateActionsCancellable,
*m_registerAuthenticationAgentCancellable,
*m_unregisterAuthenticationAgentCancellable,
*m_authenticationAgentResponseCancellable,
*m_enumerateTemporaryAuthorizationsCancellable,
*m_revokeTemporaryAuthorizationsCancellable,
*m_revokeTemporaryAuthorizationCancellable;
/**
* \brief Convert a Qt DetailsMap to the lower level PolkitDetails type
*
* The returned pointer needs to be freed via g_object_unref when no
* longer needed. Returns nullptr if details is empty.
*/
static PolkitDetails* convertDetailsMap(const DetailsMap &details);
static void pk_config_changed();
static void checkAuthorizationCallback(GObject *object, GAsyncResult *result, gpointer user_data);
static void enumerateActionsCallback(GObject *object, GAsyncResult *result, gpointer user_data);
static void registerAuthenticationAgentCallback(GObject *object, GAsyncResult *result, gpointer user_data);
static void unregisterAuthenticationAgentCallback(GObject *object, GAsyncResult *result, gpointer user_data);
static void authenticationAgentResponseCallback(GObject *object, GAsyncResult *result, gpointer user_data);
static void enumerateTemporaryAuthorizationsCallback(GObject *object, GAsyncResult *result, gpointer user_data);
static void revokeTemporaryAuthorizationsCallback(GObject *object, GAsyncResult *result, gpointer user_data);
static void revokeTemporaryAuthorizationCallback(GObject *object, GAsyncResult *result, gpointer user_data);
};
Authority::Private::~Private()
{
delete m_systemBus;
g_object_unref(m_checkAuthorizationCancellable);
g_object_unref(m_enumerateActionsCancellable);
g_object_unref(m_registerAuthenticationAgentCancellable);
g_object_unref(m_unregisterAuthenticationAgentCancellable);
g_object_unref(m_authenticationAgentResponseCancellable);
g_object_unref(m_enumerateTemporaryAuthorizationsCancellable);
g_object_unref(m_revokeTemporaryAuthorizationsCancellable);
g_object_unref(m_revokeTemporaryAuthorizationCancellable);
}
Authority::Authority(PolkitAuthority *authority, QObject *parent)
: QObject(parent)
, d(new Private(this))
{
qRegisterMetaType<PolkitQt1::Authority::Result> ();
qRegisterMetaType<PolkitQt1::ActionDescription::List>();
Q_ASSERT(!s_globalAuthority()->q);
s_globalAuthority()->q = this;
if (authority) {
d->pkAuthority = authority;
}
d->init();
}
Authority::~Authority()
{
if (d->pkAuthority != nullptr) {
g_object_unref(d->pkAuthority);
}
delete d;
}
void Authority::Private::init()
{
QDBusError error;
QDBusError dbus_error;
m_systemBus = new QDBusConnection(QDBusConnection::connectToBus(QDBusConnection::SystemBus,
QStringLiteral("polkit_qt_system_bus")));
m_checkAuthorizationCancellable = g_cancellable_new();
m_enumerateActionsCancellable = g_cancellable_new();
m_registerAuthenticationAgentCancellable = g_cancellable_new();
m_unregisterAuthenticationAgentCancellable = g_cancellable_new();
m_authenticationAgentResponseCancellable = g_cancellable_new();
m_enumerateTemporaryAuthorizationsCancellable = g_cancellable_new();
m_revokeTemporaryAuthorizationsCancellable = g_cancellable_new();
m_revokeTemporaryAuthorizationCancellable = g_cancellable_new();
#ifndef POLKIT_QT_1_COMPATIBILITY_MODE
GError *gerror = nullptr;
#endif
if (pkAuthority == nullptr) {
#ifndef POLKIT_QT_1_COMPATIBILITY_MODE
pkAuthority = polkit_authority_get_sync(nullptr, &gerror);
if (gerror != nullptr) {
setError(E_GetAuthority, gerror->message);
g_error_free(gerror);
return;
}
#else
pkAuthority = polkit_authority_get();
#endif
}
if (pkAuthority == nullptr) {
#ifdef POLKIT_QT_1_COMPATIBILITY_MODE
(E_GetAuthority);
#endif
return;
}
// connect changed signal
g_signal_connect(G_OBJECT(pkAuthority), "changed", G_CALLBACK(pk_config_changed), NULL);
// need to listen to NameOwnerChanged
dbusSignalAdd("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "NameOwnerChanged");
QString consoleKitService("org.freedesktop.ConsoleKit");
QString consoleKitManagerPath("/org/freedesktop/ConsoleKit/Manager");
QString consoleKitManagerInterface("org.freedesktop.ConsoleKit.Manager");
// first, add signals SeadAdded and SeatRemoved from ConsoleKit Manager
dbusSignalAdd(consoleKitService, consoleKitManagerPath, consoleKitManagerInterface, "SeatAdded");
dbusSignalAdd(consoleKitService, consoleKitManagerPath, consoleKitManagerInterface, "SeatRemoved");
// then we need to extract all seats from ConsoleKit
QDBusMessage msg = QDBusMessage::createMethodCall(consoleKitService, consoleKitManagerPath, consoleKitManagerInterface, "GetSeats");
const QDBusMessage reply = m_systemBus->call(msg);
if (reply.type() != QDBusMessage::ErrorMessage && !reply.arguments().isEmpty()) {
// this method returns a list with present seats
QStringList seats;
QVariant arg = reply.arguments()[0];
if (arg.type() == qMetaTypeId<QDBusArgument>()) {
arg.value<QDBusArgument>() >> seats;
} else {
seats = arg.toStringList();
}
// it can be multiple seats present so connect all their signals
Q_FOREACH(const QString &seat, seats) {
seatSignalsConnect(seat);
}
}
}
void Authority::Private::setError(Authority::ErrorCode code, const QString &details, bool recover)
{
if (recover) {
init();
}
m_lastError = code;
m_errorDetails = details;
m_hasError = true;
}
void Authority::Private::seatSignalsConnect(const QString &seat)
{
QString consoleKitService("org.freedesktop.ConsoleKit");
QString consoleKitSeatInterface("org.freedesktop.ConsoleKit.Seat");
// we want to connect to all slots of the seat
dbusSignalAdd(consoleKitService, seat, consoleKitSeatInterface, "DeviceAdded");
dbusSignalAdd(consoleKitService, seat, consoleKitSeatInterface, "DeviceRemoved");
dbusSignalAdd(consoleKitService, seat, consoleKitSeatInterface, "SessionAdded");
dbusSignalAdd(consoleKitService, seat, consoleKitSeatInterface, "SessionRemoved");
dbusSignalAdd(consoleKitService, seat, consoleKitSeatInterface, "ActiveSessionChanged");
}
void Authority::Private::dbusSignalAdd(const QString &service, const QString &path, const QString &interface, const QString &name)
{
// FIXME: This code seems to be nonfunctional - it needs to be fixed somewhere (is it Qt BUG?)
m_systemBus->connect(service, path, interface, name, q, SLOT(dbusFilter(QDBusMessage)));
}
void Authority::Private::dbusFilter(const QDBusMessage &message)
{
if (message.type() == QDBusMessage::SignalMessage) {
Q_EMIT q->consoleKitDBChanged();
// TODO: Test this with the multiseat support
if (message.member() == "SeatAdded") {
seatSignalsConnect(message.arguments()[0].value<QDBusObjectPath>().path());
}
}
}
bool Authority::hasError() const
{
return d->m_hasError;
}
Authority::ErrorCode Authority::lastError() const
{
return d->m_lastError;
}
const QString Authority::errorDetails() const
{
if (d->m_lastError == E_None) {
return QString();
} else {
return d->m_errorDetails;
}
}
void Authority::clearError()
{
d->m_hasError = false;
d->m_lastError = E_None;
}
PolkitDetails* Authority::Private::convertDetailsMap(const DetailsMap &details)
{
if (details.empty())
return nullptr;
auto ret = polkit_details_new();
for (const auto &entry: details.toStdMap()) {
const auto &key = entry.first;
const auto &value = entry.second;
polkit_details_insert(ret, key.toUtf8().constData(), value.toUtf8().data());
}
return ret;
}
void Authority::Private::pk_config_changed()
{
Q_EMIT Authority::instance()->configChanged();
}
PolkitAuthority *Authority::polkitAuthority() const
{
return d->pkAuthority;
}
Authority::Result Authority::checkAuthorizationSyncWithDetails(const QString &actionId, const Subject &subject, AuthorizationFlags flags, const DetailsMap &details)
{
PolkitAuthorizationResult *pk_result;
GError *error = nullptr;
if (Authority::instance()->hasError()) {
return Unknown;
}
if (!subject.isValid()) {
d->setError(E_WrongSubject);
return Unknown;
}
auto pk_details = Authority::Private::convertDetailsMap(details);
pk_result = polkit_authority_check_authorization_sync(d->pkAuthority,
subject.subject(),
actionId.toLatin1().data(),
pk_details,
(PolkitCheckAuthorizationFlags)(int)flags,
nullptr,
&error);
if (pk_details) {
g_object_unref(pk_details);
}
if (error != nullptr) {
d->setError(E_CheckFailed, error->message);
g_error_free(error);
return Unknown;
}
if (!pk_result) {
d->setError(E_UnknownResult);
return Unknown;
} else {
Authority::Result res = polkitResultToResult(pk_result);
g_object_unref(pk_result);
return res;
}
}
Authority::Result Authority::checkAuthorizationSync(const QString &actionId, const Subject &subject, AuthorizationFlags flags)
{
return checkAuthorizationSyncWithDetails(actionId, subject, flags, DetailsMap());
}
void Authority::checkAuthorizationWithDetails(const QString &actionId, const Subject &subject, AuthorizationFlags flags, const DetailsMap &details)
{
if (Authority::instance()->hasError()) {
return;
}
if (!subject.isValid()) {
d->setError(E_WrongSubject);
return;
}
auto pk_details = Authority::Private::convertDetailsMap(details);
polkit_authority_check_authorization(d->pkAuthority,
subject.subject(),
actionId.toLatin1().data(),
pk_details,
(PolkitCheckAuthorizationFlags)(int)flags,
d->m_checkAuthorizationCancellable,
d->checkAuthorizationCallback, this);
if (pk_details) {
g_object_unref(pk_details);
}
}
void Authority::checkAuthorization(const QString &actionId, const Subject &subject, AuthorizationFlags flags)
{
checkAuthorizationWithDetails(actionId, subject, flags, DetailsMap());
}
void Authority::Private::checkAuthorizationCallback(GObject *object, GAsyncResult *result, gpointer user_data)
{
Authority *authority = (Authority *) user_data;
Q_ASSERT(authority != nullptr);
GError *error = nullptr;
PolkitAuthorizationResult *pkResult = polkit_authority_check_authorization_finish((PolkitAuthority *) object, result, &error);
if (error != nullptr) {
// We don't want to set error if this is cancellation of some action
if (error->code != 1) {
authority->d->setError(E_CheckFailed, error->message);
}
g_error_free(error);
return;
}
if (pkResult != nullptr) {
Q_EMIT authority->checkAuthorizationFinished(polkitResultToResult(pkResult));
g_object_unref(pkResult);
} else {
authority->d->setError(E_UnknownResult);
}
}
void Authority::checkAuthorizationCancel()
{
if (!g_cancellable_is_cancelled(d->m_checkAuthorizationCancellable)) {
g_cancellable_cancel(d->m_checkAuthorizationCancellable);
}
}
ActionDescription::List Authority::enumerateActionsSync()
{
if (Authority::instance()->hasError()) {
return ActionDescription::List();
}
GError *error = nullptr;
GList *glist = polkit_authority_enumerate_actions_sync(d->pkAuthority,
nullptr,
&error);
if (error != nullptr) {
d->setError(E_EnumFailed, error->message);
g_error_free(error);
return ActionDescription::List();
}
return actionsToListAndFree(glist);
}
void Authority::enumerateActions()
{
if (Authority::instance()->hasError()) {
return;
}
polkit_authority_enumerate_actions(d->pkAuthority,
d->m_enumerateActionsCancellable,
d->enumerateActionsCallback,
Authority::instance());
}
void Authority::Private::enumerateActionsCallback(GObject *object, GAsyncResult *result, gpointer user_data)
{
Authority *authority = (Authority *) user_data;
Q_ASSERT(authority != nullptr);
GError *error = nullptr;
GList *list = polkit_authority_enumerate_actions_finish((PolkitAuthority *) object, result, &error);
if (error != nullptr) {
// We don't want to set error if this is cancellation of some action
if (error->code != 1) {
authority->d->setError(E_EnumFailed, error->message);
}
g_error_free(error);
return;
}
Q_EMIT authority->enumerateActionsFinished(actionsToListAndFree(list));
}
void Authority::enumerateActionsCancel()
{
if (!g_cancellable_is_cancelled(d->m_enumerateActionsCancellable)) {
g_cancellable_cancel(d->m_enumerateActionsCancellable);
}
}
bool Authority::registerAuthenticationAgentSync(const Subject &subject, const QString &locale, const QString &objectPath)
{
if (Authority::instance()->hasError()) {
return false;
}
gboolean result;
GError *error = nullptr;
if (!subject.isValid()) {
d->setError(E_WrongSubject);
return false;
}
result = polkit_authority_register_authentication_agent_sync(d->pkAuthority,
subject.subject(), locale.toLatin1().data(),
objectPath.toLatin1().data(), nullptr, &error);
if (error) {
d->setError(E_RegisterFailed, error->message);
g_error_free(error);
return false;
}
return result;
}
void Authority::registerAuthenticationAgent(const Subject &subject, const QString &locale, const QString &objectPath)
{
if (Authority::instance()->hasError()) {
return;
}
if (!subject.isValid()) {
d->setError(E_WrongSubject);
return;
}
polkit_authority_register_authentication_agent(d->pkAuthority,
subject.subject(),
locale.toLatin1().data(),
objectPath.toLatin1().data(),
d->m_registerAuthenticationAgentCancellable,
d->registerAuthenticationAgentCallback,
this);
}
void Authority::Private::registerAuthenticationAgentCallback(GObject *object, GAsyncResult *result, gpointer user_data)
{
Authority *authority = (Authority *) user_data;
Q_ASSERT(authority != nullptr);
GError *error = nullptr;
bool res = polkit_authority_register_authentication_agent_finish((PolkitAuthority *) object, result, &error);
if (error != nullptr) {
// We don't want to set error if this is cancellation of some action
if (error->code != 1) {
authority->d->setError(E_EnumFailed , error->message);
}
g_error_free(error);
return;
}
Q_EMIT authority->registerAuthenticationAgentFinished(res);
}
void Authority::registerAuthenticationAgentCancel()
{
if (!g_cancellable_is_cancelled(d->m_registerAuthenticationAgentCancellable)) {
g_cancellable_cancel(d->m_registerAuthenticationAgentCancellable);
}
}
bool Authority::unregisterAuthenticationAgentSync(const Subject &subject, const QString &objectPath)
{
if (d->pkAuthority) {
return false;
}
if (!subject.isValid()) {
d->setError(E_WrongSubject);
return false;
}
GError *error = nullptr;
bool result = polkit_authority_unregister_authentication_agent_sync(d->pkAuthority,
subject.subject(),
objectPath.toUtf8().data(),
nullptr,
&error);
if (error != nullptr) {
d->setError(E_UnregisterFailed, error->message);
g_error_free(error);
return false;
}
return result;
}
void Authority::unregisterAuthenticationAgent(const Subject &subject, const QString &objectPath)
{
if (Authority::instance()->hasError()) {
return;
}
if (!subject.isValid()) {
d->setError(E_WrongSubject);
return;
}
polkit_authority_unregister_authentication_agent(d->pkAuthority,
subject.subject(),
objectPath.toUtf8().data(),
d->m_unregisterAuthenticationAgentCancellable,
d->unregisterAuthenticationAgentCallback,
this);
}
void Authority::Private::unregisterAuthenticationAgentCallback(GObject *object, GAsyncResult *result, gpointer user_data)
{
Authority *authority = (Authority *) user_data;
Q_ASSERT(authority);
GError *error = nullptr;
bool res = polkit_authority_unregister_authentication_agent_finish((PolkitAuthority *) object, result, &error);
if (error != nullptr) {
// We don't want to set error if this is cancellation of some action
if (error->code != 1) {
authority->d->setError(E_UnregisterFailed, error->message);
}
g_error_free(error);
return;
}
Q_EMIT authority->unregisterAuthenticationAgentFinished(res);
}
void Authority::unregisterAuthenticationAgentCancel()
{
if (!g_cancellable_is_cancelled(d->m_unregisterAuthenticationAgentCancellable)) {
g_cancellable_cancel(d->m_unregisterAuthenticationAgentCancellable);
}
}
bool Authority::authenticationAgentResponseSync(const QString &cookie, const Identity &identity)
{
if (Authority::instance()->hasError()) {
return false;
}
if (cookie.isEmpty() || !identity.isValid()) {
d->setError(E_CookieOrIdentityEmpty);
return false;
}
GError *error = nullptr;
bool result = polkit_authority_authentication_agent_response_sync(d->pkAuthority,
cookie.toUtf8().data(),
identity.identity(),
nullptr,
&error);
if (error != nullptr) {
d->setError(E_AgentResponseFailed, error->message);
g_error_free(error);
return false;
}
return result;
}
void Authority::authenticationAgentResponse(const QString &cookie, const Identity &identity)
{
if (Authority::instance()->hasError()) {
return;
}
if (cookie.isEmpty() || !identity.isValid()) {
d->setError(E_CookieOrIdentityEmpty);
return;
}
polkit_authority_authentication_agent_response(d->pkAuthority,
cookie.toUtf8().data(),
identity.identity(),
d->m_authenticationAgentResponseCancellable,
d->authenticationAgentResponseCallback,
this);
}
void Authority::Private::authenticationAgentResponseCallback(GObject *object, GAsyncResult *result, gpointer user_data)
{
Authority *authority = (Authority *) user_data;
Q_ASSERT(authority);
GError *error = nullptr;
bool res = polkit_authority_authentication_agent_response_finish((PolkitAuthority *) object, result, &error);
if (error != nullptr) {
// We don't want to set error if this is cancellation of some action
if (error->code != 1) {
authority->d->setError(E_AgentResponseFailed, error->message);
}
g_error_free(error);
return;
}
Q_EMIT authority->authenticationAgentResponseFinished(res);
}
void Authority::authenticationAgentResponseCancel()
{
if (!g_cancellable_is_cancelled(d->m_authenticationAgentResponseCancellable)) {
g_cancellable_cancel(d->m_authenticationAgentResponseCancellable);
}
}
TemporaryAuthorization::List Authority::enumerateTemporaryAuthorizationsSync(const Subject &subject)
{
TemporaryAuthorization::List result;
GError *error = nullptr;
GList *glist = polkit_authority_enumerate_temporary_authorizations_sync(d->pkAuthority,
subject.subject(),
nullptr,
&error);
if (error != nullptr) {
d->setError(E_EnumFailed, error->message);
g_error_free(error);
return result;
}
GList *glist2;
for (glist2 = glist; glist2 != nullptr; glist2 = g_list_next(glist2)) {
result.append(TemporaryAuthorization((PolkitTemporaryAuthorization *) glist2->data));
}
g_list_free(glist);
return result;
}
void Authority::Private::enumerateTemporaryAuthorizationsCallback(GObject *object, GAsyncResult *result, gpointer user_data)
{
Authority *authority = (Authority *) user_data;
Q_ASSERT(authority);
GError *error = nullptr;
GList *glist = polkit_authority_enumerate_temporary_authorizations_finish((PolkitAuthority *) object, result, &error);
if (error != nullptr) {
// We don't want to set error if this is cancellation of some action
if (error->code != 1) {
authority->d->setError(E_EnumFailed, error->message);
}
g_error_free(error);
return;
}
TemporaryAuthorization::List res;
GList *glist2;
for (glist2 = glist; glist2 != nullptr; glist2 = g_list_next(glist2)) {
res.append(TemporaryAuthorization((PolkitTemporaryAuthorization *) glist2->data));
}
g_list_free(glist);
Q_EMIT authority->enumerateTemporaryAuthorizationsFinished(res);
}
void Authority::enumerateTemporaryAuthorizationsCancel()
{
if (!g_cancellable_is_cancelled(d->m_enumerateTemporaryAuthorizationsCancellable)) {
g_cancellable_cancel(d->m_enumerateTemporaryAuthorizationsCancellable);
}
}
bool Authority::revokeTemporaryAuthorizationsSync(const Subject &subject)
{
bool result;
if (Authority::instance()->hasError()) {
return false;
}
GError *error = nullptr;
result = polkit_authority_revoke_temporary_authorizations_sync(d->pkAuthority,
subject.subject(),
nullptr,
&error);
if (error != nullptr) {
d->setError(E_RevokeFailed, error->message);
g_error_free(error);
return false;
}
return result;
}
void Authority::revokeTemporaryAuthorizations(const Subject &subject)
{
if (Authority::instance()->hasError()) {
return;
}
polkit_authority_revoke_temporary_authorizations(d->pkAuthority,
subject.subject(),
d->m_revokeTemporaryAuthorizationsCancellable,
d->revokeTemporaryAuthorizationsCallback,
this);
}
void Authority::Private::revokeTemporaryAuthorizationsCallback(GObject *object, GAsyncResult *result, gpointer user_data)
{
Authority *authority = (Authority *) user_data;
Q_ASSERT(authority != nullptr);
GError *error = nullptr;
bool res = polkit_authority_revoke_temporary_authorizations_finish((PolkitAuthority *) object, result, &error);
if (error != nullptr) {
// We don't want to set error if this is cancellation of some action
if (error->code != 1) {
authority->d->setError(E_RevokeFailed, error->message);
}
g_error_free(error);
return;
}
Q_EMIT authority->revokeTemporaryAuthorizationsFinished(res);
}
void Authority::revokeTemporaryAuthorizationsCancel()
{
if (!g_cancellable_is_cancelled(d->m_revokeTemporaryAuthorizationsCancellable)) {
g_cancellable_cancel(d->m_revokeTemporaryAuthorizationsCancellable);
}
}
bool Authority::revokeTemporaryAuthorizationSync(const QString &id)
{
bool result;
if (Authority::instance()->hasError()) {
return false;
}
GError *error = nullptr;
result = polkit_authority_revoke_temporary_authorization_by_id_sync(d->pkAuthority,
id.toUtf8().data(),
nullptr,
&error);
if (error != nullptr) {
d->setError(E_RevokeFailed, error->message);
g_error_free(error);
return false;
}
return result;
}
void Authority::revokeTemporaryAuthorization(const QString &id)
{
if (Authority::instance()->hasError()) {
return;
}
polkit_authority_revoke_temporary_authorization_by_id(d->pkAuthority,
id.toUtf8().data(),
d->m_revokeTemporaryAuthorizationCancellable,
d->revokeTemporaryAuthorizationCallback,
this);
}
void Authority::Private::revokeTemporaryAuthorizationCallback(GObject *object, GAsyncResult *result, gpointer user_data)
{
Authority *authority = (Authority *) user_data;
Q_ASSERT(authority != nullptr);
GError *error = nullptr;
bool res = polkit_authority_revoke_temporary_authorization_by_id_finish((PolkitAuthority *) object, result, &error);
if (error != nullptr) {
// We don't want to set error if this is cancellation of some action
if (error->code != 1) {
authority->d->setError(E_RevokeFailed, error->message);
}
g_error_free(error);
return;
}
Q_EMIT authority->revokeTemporaryAuthorizationFinished(res);
}
void Authority::revokeTemporaryAuthorizationCancel()
{
if (!g_cancellable_is_cancelled(d->m_revokeTemporaryAuthorizationCancellable)) {
g_cancellable_cancel(d->m_revokeTemporaryAuthorizationCancellable);
}
}
}
#include "moc_polkitqt1-authority.cpp"
@@ -0,0 +1,550 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_AUTHORITY_H
#define POLKITQT1_AUTHORITY_H
#include "polkitqt1-core-export.h"
#include "polkitqt1-identity.h"
#include "polkitqt1-subject.h"
#include "polkitqt1-temporaryauthorization.h"
#include "polkitqt1-actiondescription.h"
#include <QObject>
#include <QMetaType>
#include <QStringList>
typedef struct _PolkitAuthority PolkitAuthority;
/**
* \namespace PolkitQt1 PolkitQt
*
* \brief Namespace wrapping Polkit-Qt classes
*
* This namespace wraps all Polkit-Qt classes.
*/
namespace PolkitQt1
{
typedef QMap<QString, QString> DetailsMap;
/**
* \class Authority polkitqt1-authority.h Authority
* \author Daniel Nicoletti <dantti85-pk@yahoo.com.br>
* \author Dario Freddi <drf@kde.org>
* \author Jaroslav Reznik <jreznik@redhat.com>
*
* \brief Convenience class for Qt/KDE applications
*
* This class is a singleton that provides makes easy the usage
* of PolKitAuthority. It emits configChanged()
* whenever PolicyKit files change (e.g. the PolicyKit.conf
* or .policy files) or when ConsoleKit reports activities changes.
*
* \note This class is a singleton, its constructor is private.
* Call Authority::instance() to get an instance of the Authority object.
* Do not delete Authority::instance(), cleanup will be done automatically.
*/
class POLKITQT1_CORE_EXPORT Authority : public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Authority)
public:
enum Result {
/** Result unknown */
Unknown = 0x00,
/** The subject is authorized for the specified action */
Yes = 0x01,
/** The subject is not authorized for the specified action */
No = 0x02,
/** The subject is authorized if more information is provided */
Challenge = 0x03
};
Q_ENUM(Result)
enum AuthorizationFlag {
/** No flags set **/
None = 0x00,
/** If the subject can obtain the authorization through authentication,
* and an authentication agent is available, then attempt to do so.
*
* Note, this means that the method used for checking authorization is likely
* to block for a long time. **/
AllowUserInteraction = 0x01
};
Q_DECLARE_FLAGS(AuthorizationFlags, AuthorizationFlag)
/** Error codes for the authority class */
enum ErrorCode {
/** No error occurred **/
E_None = 0x00,
/** Authority cannot be obtained **/
E_GetAuthority = 0x01,
/** Authority check failed **/
E_CheckFailed = 0x02,
/** Wrong or empty subject was given **/
E_WrongSubject = 0x03,
/** Action returned unknown result **/
E_UnknownResult = 0x04,
/** Enumerating actions failed **/
E_EnumFailed = 0x05,
/** Registration of authentication agent failed **/
E_RegisterFailed = 0x06,
/** Unregistration of authentication agent failed **/
E_UnregisterFailed = 0x07,
/** Cookie or polkitqt1-identity.handled to the action is empty **/
E_CookieOrIdentityEmpty = 0x08,
/** Response of auth agent failed **/
E_AgentResponseFailed = 0x09,
/** Revoke temporary authorizations failed **/
E_RevokeFailed = 0x0A
};
Q_ENUM(ErrorCode)
/**
* \brief Returns the instance of Authority
*
* Returns the current instance of Authority. Call this function whenever
* you need to access the Authority class.
*
* \note Authority is a singleton. Memory is handled by polkit-qt, so you just
* need to call this function to get a working instance of Authority.
* Don't delete the object after having used it.
*
* \param authority use this if you want to set an explicit PolkitAuthority. If you
* don't know what this implies, simply ignore the parameter. In case
* you want to use it, be sure of streaming it the first time you call
* this function, otherwise it will have no effect.
*
* \return The current authority instance
*/
static Authority *instance(PolkitAuthority *authority = nullptr);
~Authority() override;
/**
* You should always call this method after every action. No action will be allowed
* if the object is in error state. Use clearError() to clear the error message.
*
* \see lastError
* \see clearError
*
* \return \c true if an error occurred, \c false if the library is ready
*/
bool hasError() const;
/**
* \return the code of last error
*/
ErrorCode lastError() const;
/**
* Get detail information about error that occurred.
*
* \return detail message
*/
const QString errorDetails() const;
/**
* Use this method to clear the error message.
*/
void clearError();
/**
* Returns the current instance of PolkitAuthority. If you are handling
* it through Polkit-qt (which is quite likely, since you are calling
* this function), DO NOT use any PolicyKit API's specific method that
* modifies the instance on it, unless you're completely aware of what you're doing and
* of the possible consequencies. Use this instance only to gather information.
*
* \return the current PolkitAuthority instance
*/
PolkitAuthority *polkitAuthority() const;
/**
* This function should be used by mechanisms (e.g.: helper applications).
* It returns the action should be carried out, so if the caller was
* actually authorized to perform it. The result is in form of a Result, so that
* you can have more control over the whole process, and detect an eventual error.
* Most of the times you simply want to check if the result is == to \c Result::Yes,
* if you don't have specific needs.
*
* It is CRITICAL that you call this function
* and check what it returns before doing anything in your helper, since otherwise
* you could be actually performing an action from an unknown or unauthorized caller.
*
* When operation is finished, signal checkAuthorizationFinish is emitted
* with result of authorization check in its parameter.
*
* \see checkAuthorizationSync Synchronous version of this method.
* \see checkAuthorizationFinished Signal that is emitted when this method finishes.
* \see checkAuthorizationCancel Use it to cancel execution of this method.
*
* \param actionId the Id of the action in question
* \param subject subject that the action is authorized for (e.g. unix process)
* \param flags flags that influences the authorization checking
*/
void checkAuthorization(const QString &actionId, const Subject &subject,
AuthorizationFlags flags);
/**
* This function does the same as checkAuthorization(const QString&, const
* Subject&, AuthorizationFlags), but also accepts a
* DetailsMap parameter. This map can contain key/value pairs that, for
* example, are used to expand placeholders in polkit authentication
* messages that are formatted like "Authentication required to access
* $(device)". For this example, when a key "device" exists in the map,
* the "$(device)" will be replaced by the corresponding value in the map.
*
* \see checkAuthorization(const QString&, const Subject&, AuthorizationFlags) Base version of this method.
*/
// TODO: merge with checkAuthorization when we decide to break binary compatibility probably in Plasma 6
void checkAuthorizationWithDetails(
const QString &actionId, const Subject &subject,
AuthorizationFlags flags, const DetailsMap &details);
/**
* Synchronous version of the checkAuthorization method.
*
* \param actionId the Id of the action in question
* \param subject subject that the action is authorized for (e.g. unix process)
* \param flags flags that influences the authorization checking
*
* \see checkAuthorization Asynchronous version of this method.
*/
Result checkAuthorizationSync(const QString &actionId, const Subject &subject,
AuthorizationFlags flags);
/**
* This function does the same as checkAuthorizationSync(const QString&,
* const Subject&, AuthorizationFlags), but also accepts a DetailsMap
* parameter.
*
* \see checkAuthorization(const QString&, const Subject&, AuthorizationFlags, const DetailsMap&) for a description of the details parameter.
*
* \see checkAuthorizationSync(const QString&, const Subject, AuthorizationFlags) Base version of this method.
*/
Result checkAuthorizationSyncWithDetails(const QString &actionId, const Subject &subject,
AuthorizationFlags flags, const DetailsMap &details);
/**
* This method can be used to cancel last authorization check.
*/
void checkAuthorizationCancel();
/**
* Asynchronously retrieves all registered actions.
*
* When operation is finished, signal checkAuthorizationFinish is emitted
* with result of authorization check in its parameter.
*
* \see enumerateActionsSync Synchronous version of this method.
* \see enumerateActionsFinished Signal that is emitted when this method finishes.
* \see enumerateActionsCancel Use it to cancel execution of this method.
*/
void enumerateActions();
/**
* Synchronously retrieves all registered actions.
*
* \see enumerateActions Asynchronous version of this method.
*
* \return a list of Action IDs
*/
ActionDescription::List enumerateActionsSync();
/**
* This method can be used to cancel enumeration of actions
*/
void enumerateActionsCancel();
/**
* Registers an authentication agent.
*
* \see registerAuthenticationAgentSync Synchronous version of this method.
* \see registerAuthenticationAgentFinished Signal that is emitted when this method finishes.
* \see registerAuthenticationAgentCancel Use it to cancel execution of this method.
*
* \param subject caller subject
* \param locale the locale of the authentication agent
* \param objectPath the object path for the authentication agent
*/
void registerAuthenticationAgent(const Subject &subject, const QString &locale,
const QString &objectPath);
/**
* Registers an authentication agent.
*
* \see registerAuthenticationAgent Asynchronous version of this method.
*
* \param subject caller subject
* \param locale the locale of the authentication agent
* \param objectPath the object path for the authentication agent
*
* \return \c true if the Authentication agent has been successfully registered
* \c false if the Authentication agent registration failed
*/
bool registerAuthenticationAgentSync(const Subject &subject, const QString &locale,
const QString &objectPath);
/**
* This method can be used to cancel the registration of the authentication agent.
*/
void registerAuthenticationAgentCancel();
/**
* Unregisters an Authentication agent.
*
* \see unregisterAuthenticationAgentSync Synchronous version of this method.
* \see unregisterAuthenticationAgentFinished Signal that is emitted when this method finishes.
* \see unregisterAuthenticationAgentCancel Use it to cancel execution of this method.
*
* \param subject caller subject
* \param objectPath the object path for the Authentication agent
*
* \return \c true if the Authentication agent has been successfully unregistered
* \c false if the Authentication agent unregistration failed
*/
void unregisterAuthenticationAgent(const Subject &subject, const QString &objectPath);
/**
* Unregisters an Authentication agent.
*
* \see unregisterAuthenticationAgent Asynchronous version of this method.
*
* \param subject caller subject
* \param objectPath the object path for the Authentication agent
*
* \return \c true if the Authentication agent has been successfully unregistered
* \c false if the Authentication agent unregistration failed
*/
bool unregisterAuthenticationAgentSync(const Subject &subject, const QString &objectPath);
/**
* This method can be used to cancel the unregistration of the authentication agent.
*/
void unregisterAuthenticationAgentCancel();
/**
* Provide response that \p identity successfully authenticated for the authentication request identified by \p cookie.
*
* \see authenticationAgentResponseSync Synchronous version of this method.
* \see authenticationAgentResponseFinished Signal that is emitted when this method finishes.
* \see authenticationAgentResponseCancel Use it to cancel execution of this method.
*
* \param cookie The cookie passed to the authentication agent from the authority.
* \param identity The identity that was authenticated.
*/
void authenticationAgentResponse(const QString &cookie, const Identity &identity);
/**
* Provide response that \p identity successfully authenticated for the authentication request identified by \p cookie.
*
* \see authenticationAgentResponse Asynchronous version of this method.
*
* \param cookie The cookie passed to the authentication agent from the authority.
* \param identity The identity that was authenticated.
*
* \return \c true if authority acknowledged the call, \c false if error is set.
*
*/
bool authenticationAgentResponseSync(const QString& cookie, const PolkitQt1::Identity& identity);
/**
* This method can be used to cancel the authenticationAgentResponseAsync method.
*/
void authenticationAgentResponseCancel();
/**
* Retrieves all temporary action that applies to \p subject.
*
* \see enumerateTemporaryAuthorizationsSync Synchronous version of this method.
* \see enumerateTemporaryAuthorizationsFinished Signal that is emitted when this method finishes.
* \see enumerateTemporaryAuthorizationsCancel Use it to cancel execution of this method.
*
* \param subject the subject to get temporary authorizations for
*
*/
void enumerateTemporaryAuthorizations(const Subject &subject);
/**
* Retrieves all temporary action that applies to \p subject
*
* \see enumerateTemporaryAuthorizations Asynchronous version of this method.
*
* \param subject the subject to get temporary authorizations for
*
* \note Free all TemporaryAuthorization objects using \p delete operator.
*
* \return List of all temporary authorizations
*/
TemporaryAuthorization::List enumerateTemporaryAuthorizationsSync(const Subject &subject);
/**
* This method can be used to cancel the enumerateTemporaryAuthorizationsAsync method.
*/
void enumerateTemporaryAuthorizationsCancel();
/**
* Revokes all temporary authorizations that applies to \p subject
*
* \see revokeTemporaryAuthorizationsSync Synchronous version of this method.
* \see revokeTemporaryAuthorizationsFinished Signal that is emitted when this method finishes.
* \see revokeTemporaryAuthorizationsCancel Use it to cancel execution of this method.
* \param subject the subject to revoke temporary authorizations from
*/
void revokeTemporaryAuthorizations(const Subject &subject);
/**
* Revokes all temporary authorizations that applies to \p subject
*
* \see revokeTemporaryAuthorizations Asynchronous version of this method.
*
* \param subject the subject to revoke temporary authorizations from
*
* \return \c true if all temporary authorization were revoked
* \c false if the revoking failed
*/
bool revokeTemporaryAuthorizationsSync(const Subject &subject);
/**
* This method can be used to cancel the method revokeTemporaryAuthorizationsAsync.
*/
void revokeTemporaryAuthorizationsCancel();
/**
* Revokes temporary authorization by \p id
*
* \see revokeTemporaryAuthorizationSync Synchronous version of this method.
* \see revokeTemporaryAuthorizationFinished Signal that is emitted when this method finishes.
* \see revokeTemporaryAuthorizationCancel Use it to cancel execution of this method.
*
* \param id the identifier of the temporary authorization
*/
void revokeTemporaryAuthorization(const QString &id);
/**
* Revokes temporary authorization by \p id
*
* \see revokeTemporaryAuthorization Asynchronous version of this method.
*
* \param id the identifier of the temporary authorization
*
* \return \c true if the temporary authorization was revoked
* \c false if the revoking failed
*/
bool revokeTemporaryAuthorizationSync(const QString &id);
/**
* This method can be used to cancel the method revokeTemporaryAuthorizationAsync.
*/
void revokeTemporaryAuthorizationCancel();
Q_SIGNALS:
/**
* This signal will be emitted when a configuration
* file gets changed (e.g. /etc/PolicyKit/PolicyKit.conf or
* .policy files).
* Connect to this signal if you want to track down
* actions.
*/
void configChanged();
/**
* This signal is emitted when ConsoleKit configuration
* changes. This might happen when a session becomes active
* or inactive.
*
* If you want to track your actions directly you should
* connect to this signal, as this might change the return value
* PolicyKit will give you.
*
* \note If you use Action you'll probably prefer to
* use the dataChanged() signal to track Action changes.
*/
void consoleKitDBChanged();
/**
* This signal is emitted when asynchronous method checkAuthorization finishes.
*
* The argument is the result of authorization.
*/
void checkAuthorizationFinished(PolkitQt1::Authority::Result);
/**
* This signal is emitted when asynchronous method enumerateActions finishes.
*
* The argument is the list of all Action IDs.
*/
void enumerateActionsFinished(PolkitQt1::ActionDescription::List);
/**
* This signal is emitted when asynchronous method registerAuthenticationAgent finishes.
*
* The argument is \c true if the Authentication agent has been successfully registered
* \c false if the Authentication agent registration failed
*/
void registerAuthenticationAgentFinished(bool);
/**
* This signal is emitted when asynchronous method unregisterAuthenticationAgent finishes.
*
* The argument is \c true if the Authentication agent has been successfully unregistered
* \c false if the Authentication agent unregistration failed
*/
void unregisterAuthenticationAgentFinished(bool);
/**
* This signal is emitted when asynchronous method authenticationAgentResponse finishes.
*
* The argument is \c true if authority acknowledged the call, \c false if error is set.
*/
void authenticationAgentResponseFinished(bool);
/**
* This signal is emitted when asynchronous method enumerateTemporaryAuthorizations finishes.
*
* The argument is list of all temporary authorizations.
*
* \note Free all TemporaryAuthorization objects using \p delete operator.
*/
void enumerateTemporaryAuthorizationsFinished(PolkitQt1::TemporaryAuthorization::List);
/**
* This signal is emitted when asynchronous method revokeTemporaryAuthorizations finishes.
*
* The argument is \c true if all temporary authorizations were revoked
* \c false if the revoking failed
*/
void revokeTemporaryAuthorizationsFinished(bool);
/**
* This signal is emitted when asynchronous method revokeTemporaryAuthorization finishes.
* \return \c true if the temporary authorization was revoked
* \c false if the revoking failed
*/
void revokeTemporaryAuthorizationFinished(bool);
private:
explicit Authority(PolkitAuthority *context, QObject *parent = nullptr);
class Private;
friend class Private;
Private * const d;
Q_PRIVATE_SLOT(d, void dbusFilter(const QDBusMessage &message))
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Authority::AuthorizationFlags)
}
#endif
@@ -0,0 +1,94 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-details.h"
#include <QStringList>
#include <polkit/polkit.h>
namespace PolkitQt1
{
class Q_DECL_HIDDEN Details::Data : public QSharedData
{
public:
Data() {}
Data(const Data &other)
: QSharedData(other)
, polkitDetails(other.polkitDetails)
{
if (polkitDetails != nullptr) {
g_object_ref(polkitDetails);
}
}
~Data()
{
if (polkitDetails != nullptr) {
g_object_unref(polkitDetails);
}
}
PolkitDetails *polkitDetails;
};
Details::Details()
: d(new Data)
{
d->polkitDetails = polkit_details_new();
}
Details::Details(PolkitDetails *pkDetails)
: d(new Data)
{
d->polkitDetails = pkDetails;
if (d->polkitDetails != nullptr) {
g_object_ref(d->polkitDetails);
}
}
Details::~Details()
{
}
Details::Details(const Details &other) = default;
Details& Details::operator=(const PolkitQt1::Details& other)
{
d = other.d;
return *this;
}
QString Details::lookup(const QString &key) const
{
const gchar *result = polkit_details_lookup(d->polkitDetails, key.toUtf8().data());
if (result != nullptr) {
return QString::fromUtf8(result);
} else {
return QString();
}
}
void Details::insert(const QString &key, const QString &value)
{
polkit_details_insert(d->polkitDetails, key.toUtf8().data(), value.toUtf8().data());
}
QStringList Details::keys() const
{
gchar **result = polkit_details_get_keys(d->polkitDetails);
QStringList list;
int len = g_strv_length(result);
for (int i = 0; i < len; i++) {
list.append(QString::fromUtf8(result[i]));
}
g_strfreev(result);
return list;
}
}
@@ -0,0 +1,89 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_DETAILS_H
#define POLKITQT1_DETAILS_H
#include "polkitqt1-core-export.h"
#include <QObject>
#include <QSharedData>
typedef struct _PolkitDetails PolkitDetails;
/**
* \namespace PolkitQt1 PolkitQt
*
* \brief Namespace wrapping Polkit-Qt classes
*
* This namespace wraps all Polkit-Qt classes.
*/
namespace PolkitQt1
{
/**
* \class Details polkitqt1-details.h Details
* \author Radek Novacek <rnovacek@redhat.com>
*
* \brief Class used for passing details around.
*/
class POLKITQT1_CORE_EXPORT Details
{
public:
/**
* Creates a new Details object
*/
Details();
/**
* Creates Details object from PolkitDetails
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param pkDetails PolkitDetails object
*/
explicit Details(PolkitDetails *pkDetails);
/**
* Copy constructor.
*/
Details(const Details &other);
~Details();
Details &operator=(const Details &other);
/**
* Get the value for \p key
*
* \param key A key
* \return Value of the key \p key, otherwise empty QString.
*/
QString lookup(const QString &key) const;
/**
* Inserts key \p key with value \p value.
*
* \param key A key.
* \param value A value.
*/
void insert(const QString &key, const QString &value);
/**
* Gets a list of all keys.
*
* \return List of all keys.
*/
QStringList keys() const;
private:
class Data;
QExplicitlySharedDataPointer< Data > d;
};
}
#endif // DETAILS_H
@@ -0,0 +1,212 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Lukas Tinkl <ltinkl@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-identity.h"
#include <polkit/polkit.h>
#include <QDebug>
namespace PolkitQt1
{
class Q_DECL_HIDDEN Identity::Data : public QSharedData
{
public:
Data() : identity(nullptr) {}
Data(const Data& other)
: QSharedData(other)
, identity(other.identity)
{
if (identity) {
g_object_ref(identity);
}
}
~Data()
{
if (identity) {
g_object_unref(identity);
}
}
PolkitIdentity *identity;
};
Identity::Identity()
: d(new Data)
{
}
Identity::Identity(PolkitIdentity *polkitIdentity)
: d(new Data)
{
d->identity = polkitIdentity;
if (d->identity) {
g_object_ref(d->identity);
}
}
Identity::Identity(const PolkitQt1::Identity& other)
: d(other.d)
{
}
Identity::~Identity()
{
}
Identity& Identity::operator=(const PolkitQt1::Identity& other)
{
d = other.d;
return *this;
}
bool Identity::isValid() const
{
return d->identity != nullptr;
}
PolkitIdentity *Identity::identity() const
{
return d->identity;
}
void Identity::setIdentity(PolkitIdentity *identity)
{
if (d->identity == identity) {
return;
}
if (d->identity) {
g_object_unref(d->identity);
}
d->identity = identity;
if (d->identity) {
g_object_ref(d->identity);
}
}
QString Identity::toString() const
{
Q_ASSERT(d->identity);
return QString::fromUtf8(polkit_identity_to_string(d->identity));
}
Identity Identity::fromString(const QString &string)
{
GError *error = nullptr;
PolkitIdentity *pkIdentity = polkit_identity_from_string(string.toUtf8().data(), &error);
if (error != nullptr) {
qWarning() << QString("Cannot create Identity from string: %1").arg(error->message);
return Identity();
}
return Identity(pkIdentity);
}
UnixGroupIdentity Identity::toUnixGroupIdentity()
{
UnixGroupIdentity *ugid = static_cast< UnixGroupIdentity* >(this);
if (!ugid) {
return UnixGroupIdentity();
}
return *ugid;
}
UnixUserIdentity Identity::toUnixUserIdentity()
{
UnixUserIdentity *uuid = static_cast< UnixUserIdentity* >(this);
if (!uuid) {
return UnixUserIdentity();
}
return *uuid;
}
UnixUserIdentity::UnixUserIdentity(const QString &name)
: Identity()
{
GError *error = nullptr;
setIdentity(polkit_unix_user_new_for_name(name.toUtf8().data(), &error));
if (error != nullptr) {
qWarning() << QString("Cannot create UnixUserIdentity: %1").arg(error->message);
setIdentity(nullptr);
}
}
UnixUserIdentity::UnixUserIdentity(uid_t uid)
: Identity()
{
setIdentity(polkit_unix_user_new(uid));
}
UnixUserIdentity::UnixUserIdentity(PolkitUnixUser *pkUnixUser)
: Identity((PolkitIdentity *)pkUnixUser)
{
}
UnixUserIdentity::UnixUserIdentity()
: Identity()
{
}
uid_t UnixUserIdentity::uid() const
{
return polkit_unix_user_get_uid((PolkitUnixUser *) identity());
}
void UnixUserIdentity::setUid(uid_t uid)
{
polkit_unix_user_set_uid((PolkitUnixUser *) identity(), uid);
}
UnixGroupIdentity::UnixGroupIdentity(const QString &name)
: Identity()
{
GError *error = nullptr;
setIdentity(polkit_unix_group_new_for_name(name.toUtf8().data(), &error));
if (error != nullptr) {
qWarning() << QString("Cannot create UnixGroupIdentity: %1").arg(error->message);
setIdentity(nullptr);
}
}
UnixGroupIdentity::UnixGroupIdentity(gid_t gid)
: Identity()
{
setIdentity(polkit_unix_group_new(gid));
}
UnixGroupIdentity::UnixGroupIdentity(PolkitUnixGroup *pkUnixGroup)
: Identity((PolkitIdentity *) pkUnixGroup)
{
}
UnixGroupIdentity::UnixGroupIdentity()
: Identity()
{
}
gid_t UnixGroupIdentity::gid() const
{
return polkit_unix_group_get_gid((PolkitUnixGroup *) identity());
}
void UnixGroupIdentity::setGid(gid_t gid)
{
polkit_unix_group_set_gid((PolkitUnixGroup *) identity(), gid);
}
}
@@ -0,0 +1,198 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Lukas Tinkl <ltinkl@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_IDENTITY_H
#define POLKITQT1_IDENTITY_H
#include "polkitqt1-core-export.h"
#include <unistd.h>
#include <QObject>
#include <QSharedData>
typedef struct _PolkitIdentity PolkitIdentity;
typedef struct _PolkitUnixUser PolkitUnixUser;
typedef struct _PolkitUnixGroup PolkitUnixGroup;
/**
* \namespace PolkitQt1 PolkitQt
*
* \brief Namespace wrapping Polkit-Qt classes
*
* This namespace wraps all Polkit-Qt classes.
*/
namespace PolkitQt1
{
class UnixUserIdentity;
class UnixGroupIdentity;
/**
* \class Identity polkitqt1-identity.h Identity
* \author Lukas Tinkl <ltinkl@redhat.com>
*
* This class encapsulates the PolkitIdentity interface.
*
* \brief Abstract class representing identities
*
* \see UnixGroup
* \see UnixUser
*/
class POLKITQT1_CORE_EXPORT Identity
{
public:
typedef QList< Identity > List;
Identity();
explicit Identity(PolkitIdentity *polkitIdentity);
Identity(const Identity &other);
~Identity();
Identity &operator=(const Identity &other);
bool isValid() const;
/**
* Serialization of object to the string
*
* \return Serialized Identity object
*/
QString toString() const;
/**
* Creates the Identity object from string representation
*
* \param string string representation of the object
*
* \return Pointer to new Identity instance
*/
static Identity fromString(const QString &string);
UnixUserIdentity toUnixUserIdentity();
UnixGroupIdentity toUnixGroupIdentity();
/**
* Gets PolkitIdentity object.
*
* \warning It shouldn't be used directly unless you are completely aware of what are you doing
*
* \return Pointer to PolkitIdentity instance
*/
PolkitIdentity *identity() const;
protected:
void setIdentity(PolkitIdentity *identity);
private:
class Data;
QExplicitlySharedDataPointer< Data > d;
};
/**
* \class UnixUserIdentity polkitqt1-identity.h Identity
*
* An object representing a user identity on a UNIX system.
*
* \brief UNIX user identity
* \sa Identity
*/
class POLKITQT1_CORE_EXPORT UnixUserIdentity : public Identity
{
public:
UnixUserIdentity();
/**
* Creates UnixUser object by UID of the user
*
* \param uid user id
*/
explicit UnixUserIdentity(uid_t uid);
/**
* Creates UnixUser object by unix name of the user
*
* \param name Unix name
*/
explicit UnixUserIdentity(const QString &name);
/**
* Creates UnixUser object from PolkitUnixUser object
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param pkUnixUser The PolkitUnixUser object
*/
explicit UnixUserIdentity(PolkitUnixUser *pkUnixUser);
/**
* Gets an user id
*
* \return user id
*/
uid_t uid() const;
/**
* Sets the id of user
*
* \param uid user id
*/
void setUid(uid_t uid);
};
/**
* \class UnixGroupIdentity polkitqt1-identity.h Identity
*
* An object representing a group identity on a UNIX system.
*
* \brief UNIX group identity
* \sa Identity
*/
class POLKITQT1_CORE_EXPORT UnixGroupIdentity : public Identity
{
public:
UnixGroupIdentity();
/**
* Creates UnixGroup object by GID of the group
*
* \param gid group id
*/
explicit UnixGroupIdentity(gid_t gid);
/**
* Creates UnixGroup object by unix name of the group
*
* \param name group name
*/
explicit UnixGroupIdentity(const QString &name);
/**
* Creates UnixGroup object from PolkitUnixGroup object
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param pkUnixGroup The PolkitUnixGroup object
*/
explicit UnixGroupIdentity(PolkitUnixGroup *pkUnixGroup);
/**
* Gets a group id
*
* \return group id
*/
gid_t gid() const;
/**
* Sets the id of group
*
* \param gid group id
*/
void setGid(gid_t gid);
};
}
#endif // POLKIT_QT_IDENTITY_H
@@ -0,0 +1,213 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-subject.h"
#include "polkitqt1-identity.h"
#include "polkitqt1-config.h"
#include <QDebug>
#include <polkit/polkit.h>
namespace PolkitQt1
{
class Q_DECL_HIDDEN Subject::Data : public QSharedData
{
public:
Data()
: QSharedData()
, subject(nullptr)
{}
Data(const Data& other) = delete;
~Data()
{
if (subject) {
g_object_unref(subject);
}
}
PolkitSubject *subject;
};
Subject::Subject()
: d(new Data)
{
}
Subject::Subject(PolkitSubject *subject)
: d(new Data)
{
d->subject = subject;
if (d->subject != nullptr) {
g_object_ref(d->subject);
}
}
Subject::Subject(const PolkitQt1::Subject& other)
: d(other.d)
{
}
Subject& Subject::operator=(const PolkitQt1::Subject& other)
{
d = other.d;
return *this;
}
Subject::~Subject()
{
}
bool Subject::isValid() const
{
return d->subject != nullptr;
}
PolkitSubject *Subject::subject() const
{
return d->subject;
}
void Subject::setSubject(PolkitSubject *subject)
{
if (d->subject != nullptr) {
g_object_unref(d->subject);
}
d->subject = subject;
}
QString Subject::toString() const
{
Q_ASSERT(d->subject);
return QString::fromUtf8(polkit_subject_to_string(d->subject));
}
Subject Subject::fromString(const QString &string)
{
Subject subject;
GError *error = nullptr;
subject.d->subject = polkit_subject_from_string(string.toUtf8().data(), &error);
if (error != nullptr) {
qWarning() << QString("Cannot create Subject from string: %1").arg(error->message);
return {};
}
return subject;
}
Subject Subject::fromSubject(PolkitSubject *subject)
{
return Subject{subject};
}
UnixProcessSubject::UnixProcessSubject(qint64 pid)
: Subject()
{
setSubject(polkit_unix_process_new_for_owner(pid, 0, -1));
}
UnixProcessSubject::UnixProcessSubject(qint64 pid, quint64 startTime)
: Subject()
{
setSubject(polkit_unix_process_new_for_owner(pid, startTime, -1));
}
UnixProcessSubject::UnixProcessSubject(PolkitUnixProcess *pkUnixProcess)
: Subject((PolkitSubject *) pkUnixProcess)
{
}
qint64 UnixProcessSubject::pid() const
{
return polkit_unix_process_get_pid((PolkitUnixProcess *) subject());
}
qint64 UnixProcessSubject::startTime() const
{
return polkit_unix_process_get_start_time((PolkitUnixProcess *) subject());
}
qint64 UnixProcessSubject::uid() const
{
return polkit_unix_process_get_uid((PolkitUnixProcess *) subject());
}
void UnixProcessSubject::setPid(qint64 pid)
{
polkit_unix_process_set_pid((PolkitUnixProcess *) subject(), pid);
}
// ----- SystemBusName
SystemBusNameSubject::SystemBusNameSubject(const QString &name)
: Subject()
{
setSubject(polkit_system_bus_name_new(name.toUtf8().data()));
}
SystemBusNameSubject::SystemBusNameSubject(PolkitSystemBusName *pkSystemBusName)
: Subject((PolkitSubject *) pkSystemBusName)
{
}
QString SystemBusNameSubject::name() const
{
return QString::fromUtf8(polkit_system_bus_name_get_name((PolkitSystemBusName *) subject()));
}
void SystemBusNameSubject::setName(const QString &name)
{
polkit_system_bus_name_set_name((PolkitSystemBusName *) subject(), name.toUtf8().data());
}
UnixUserIdentity SystemBusNameSubject::user()
{
#if HAVE_POLKIT_SYSTEM_BUS_NAME_GET_USER_SYNC
return UnixUserIdentity(polkit_system_bus_name_get_user_sync((PolkitSystemBusName *) subject(), nullptr, nullptr));
#else
qWarning("Polkit is too old, returning invalid user from SystemBusNameSubject::user()!");
return UnixUserIdentity();
#endif
}
// ----- SystemSession
UnixSessionSubject::UnixSessionSubject(const QString &sessionId)
: Subject()
{
setSubject(polkit_unix_session_new(sessionId.toUtf8().data()));
}
UnixSessionSubject::UnixSessionSubject(qint64 pid)
: Subject()
{
GError *error = nullptr;
setSubject(polkit_unix_session_new_for_process_sync(pid, nullptr, &error));
if (error != nullptr) {
qWarning() << QString("Cannot create unix session: %1").arg(error->message);
setSubject(nullptr);
}
}
UnixSessionSubject::UnixSessionSubject(PolkitSystemBusName *pkUnixSession)
: Subject((PolkitSubject *) pkUnixSession)
{
}
QString UnixSessionSubject::sessionId() const
{
return QString::fromUtf8(polkit_unix_session_get_session_id((PolkitUnixSession *) subject()));
}
void UnixSessionSubject::setSessionId(const QString &sessionId)
{
polkit_unix_session_set_session_id((PolkitUnixSession *) subject(), sessionId.toUtf8().data());
}
}
@@ -0,0 +1,276 @@
/*
This file is part of the PolKit1-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_SUBJECT_H
#define POLKITQT1_SUBJECT_H
#include "polkitqt1-core-export.h"
#include <QObject>
#include <QSharedData>
typedef struct _PolkitSubject PolkitSubject;
typedef struct _PolkitUnixProcess PolkitUnixProcess;
typedef struct _PolkitSystemBusName PolkitSystemBusName;
/**
* \namespace PolkitQt1 PolkitQt
*
* \brief Namespace wrapping PolicyKit-Qt classes
*
* This namespace wraps all PolicyKit-Qt classes.
*/
namespace PolkitQt1
{
class UnixUserIdentity;
/**
* \class Subject polkitqt1-subject.h Subject
* \author Jaroslav Reznik <jreznik@redhat.com>
*
* \brief This class represents PolicyKit subjects
*
* This class encapsulates the PolkitSubject interface.
*
* \see UnixProcess
* \see SystemBusName
* \see UnixSession
*/
class POLKITQT1_CORE_EXPORT Subject
{
public:
Subject();
Subject(const Subject &other);
~Subject();
Subject &operator=(const Subject &other);
bool isValid() const;
/**
* Serialization of object to the string
*
* \return Serialized Subject object
*/
QString toString() const;
/**
* Creates the Subject object from string reprezentation
*
* \param string string reprezentation of the object
*
* \return Pointer to new Subject instance
*/
static Subject fromString(const QString &string);
/**
* Creates the Subject object
*
* \param subject string reprezentation of the object
*
* \return A new Subject instance
*/
static Subject fromSubject(PolkitSubject *subject);
/**
* Gets PolkitSubject object.
*
* \warning It shouldn't be used directly unless you are completely aware of what are you doing
*
* \return Pointer to PolkitSubject instance
*/
PolkitSubject *subject() const;
protected:
explicit Subject(PolkitSubject *subject);
void setSubject(PolkitSubject *subject);
private:
class Data;
QExplicitlySharedDataPointer< Data > d;
};
/**
* \class UnixProcessSubject polkitqt1-subject.h Subject
* \author Jaroslav Reznik <jreznik@redhat.com>
*
* \brief A class for representing a UNIX process.
*
* To uniquely identify processes, both the process
* id and the start time of the process (a monotonic
* increasing value representing the time since the
* kernel was started) is used.
*
* \sa Subject
*/
class POLKITQT1_CORE_EXPORT UnixProcessSubject : public Subject
{
public:
/**
* Subject constructor, takes one parameter - PID. The start time
* of process will be looked automatically.
*
* \param pid An Unix process PID.
*/
explicit UnixProcessSubject(qint64 pid);
/**
* Subject constructor, takes two parameters - PID and start time.
*
* \param pid An Unix process PID.
* \param startTime An Unix process start time.
*/
UnixProcessSubject(qint64 pid, quint64 startTime);
/**
* Subject constructor, it creates UnixProcess object from PolkitUnixProcess object
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param process PolkitUnixProcess object
*/
explicit UnixProcessSubject(PolkitUnixProcess *process);
/**
* Returns Unix process PID.
*
* \return A PID of associated Unix process.
*/
qint64 pid() const;
/**
* Returns Unix process start time.
*
* \return A start time of associated Unix process.
*/
qint64 startTime() const;
/**
* Returns Unix process UID.
*
* \return A UID of associated Unix process.
*/
qint64 uid() const;
/**
* Sets Unix process PID.
*
* \param pid An Unix process PID.
*/
void setPid(qint64 pid);
};
/**
* \class SystemBusNameSubject polkitqt1-subject.h Subject
* \author Jaroslav Reznik <jreznik@redhat.com>
*
* \brief A class for representing a process owning a unique name on the system bus.
*
* \sa Subject
*/
class POLKITQT1_CORE_EXPORT SystemBusNameSubject : public Subject
{
public:
/**
* Subject constructor, takes one parameter - system bus name.
*
* \param name A unique system bus name.
*/
explicit SystemBusNameSubject(const QString &name);
/**
* Subject constructor, it creates SystemBusName object from PolkitSystemBusName object
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param pkSystemBusName PolkitSystemBusName object
*/
explicit SystemBusNameSubject(PolkitSystemBusName *pkSystemBusName);
/**
* Returns system bus name.
*
* \return A unique system bus name.
*/
QString name() const;
/**
* Sets system bus name.
*
* \param name System bus name.
*/
void setName(const QString &name);
/**
* Returns the UnixUserIdentity for this subject.
*
* \note This can be an invalid UnixUserIdentity so be sure to check before using it
*
* \since 0.113
**/
UnixUserIdentity user();
};
/**
* \class UnixSessionSubject polkitqt1-subject.h Subject
* \author Jaroslav Reznik <jreznik@redhat.com>
*
* \brief A class for representing unix session.
*
* The session id is an opaque string obtained from
* ConsoleKit.
*
* \sa Subject
*/
class POLKITQT1_CORE_EXPORT UnixSessionSubject : public Subject
{
public:
/**
* Subject constructor, takes one parameter - session id.
*
* \param sessionId The session id.
*/
explicit UnixSessionSubject(const QString &sessionId);
/**
* Subject constructor, takes one parameter - pid of process.
*
* Synchronous!
*
* \param pid The session's process pid.
*/
explicit UnixSessionSubject(qint64 pid);
/**
* Subject constructor, it creates UnixSession object from PolkitUnixSession object
*
* \warning Use this only if you are completely aware of what are you doing!
*
* \param pkUnixSession PolkitUnixSession object
*/
explicit UnixSessionSubject(PolkitSystemBusName *pkUnixSession);
/**
* Returns session id.
*
* \return A session id.
*/
QString sessionId() const;
/**
* Sets session id.
*
* \param sessionId A session id.
*/
void setSessionId(const QString &sessionId);
};
}
#endif
@@ -0,0 +1,103 @@
/*
This file is part of the PolKit1-qt project
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-temporaryauthorization.h"
#include "polkitqt1-authority.h"
#include <polkit/polkit.h>
namespace PolkitQt1
{
class Q_DECL_HIDDEN TemporaryAuthorization::Data : public QSharedData
{
public:
Data() {}
Data(const Data& other)
: QSharedData(other)
, id(other.id)
, actionId(other.actionId)
, subject(other.subject)
, timeObtained(other.timeObtained)
, timeExpires(other.timeExpires)
{
}
~Data() {}
QString id;
QString actionId;
Subject subject;
QDateTime timeObtained;
QDateTime timeExpires;
};
TemporaryAuthorization::TemporaryAuthorization(PolkitTemporaryAuthorization *pkTemporaryAuthorization)
: d(new Data)
{
d->id = QString::fromUtf8(polkit_temporary_authorization_get_id(pkTemporaryAuthorization));
d->actionId = QString::fromUtf8(polkit_temporary_authorization_get_action_id(pkTemporaryAuthorization));
d->subject = Subject::fromSubject(polkit_temporary_authorization_get_subject(pkTemporaryAuthorization));
d->timeObtained = QDateTime::fromSecsSinceEpoch(polkit_temporary_authorization_get_time_obtained(pkTemporaryAuthorization));
d->timeExpires = QDateTime::fromSecsSinceEpoch(polkit_temporary_authorization_get_time_expires(pkTemporaryAuthorization));
g_object_unref(pkTemporaryAuthorization);
}
TemporaryAuthorization::TemporaryAuthorization(const PolkitQt1::TemporaryAuthorization& other)
: d(other.d)
{
}
TemporaryAuthorization::TemporaryAuthorization()
: d(new Data)
{
}
TemporaryAuthorization& TemporaryAuthorization::operator=(const PolkitQt1::TemporaryAuthorization& other)
{
d = other.d;
return *this;
}
TemporaryAuthorization::~TemporaryAuthorization()
{
}
QString TemporaryAuthorization::id() const
{
return d->id;
}
QString TemporaryAuthorization::actionId() const
{
return d->actionId;
}
Subject TemporaryAuthorization::subject() const
{
//qFatal(polkit_subject_to_string(polkit_temporary_authorization_get_subject(d->temporaryAuthorization)));
return d->subject;//Subject::fromString(polkit_subject_to_string(d->subject));
}
QDateTime TemporaryAuthorization::obtainedAt() const
{
return d->timeObtained;
}
QDateTime TemporaryAuthorization::expirationTime() const
{
return d->timeExpires;
}
bool TemporaryAuthorization::revoke()
{
Authority::instance()->revokeTemporaryAuthorization(id());
return true;
}
}
@@ -0,0 +1,111 @@
/*
This file is part of the PolKit1-qt project
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_TEMPORARYAUTHORIZATION_H
#define POLKITQT1_TEMPORARYAUTHORIZATION_H
#include "polkitqt1-subject.h"
#include <QObject>
#include <QDateTime>
#include <QMetaType>
#include <QSharedData>
typedef struct _PolkitTemporaryAuthorization PolkitTemporaryAuthorization;
/**
* \namespace PolkitQt1 PolkitQt
*
* \brief Namespace wrapping PolicyKit-Qt classes
*
* This namespace wraps all PolicyKit-Qt classes.
*/
namespace PolkitQt1
{
/**
* \class TemporaryAuthorization polkitqt1-temporaryauthorization.h TemporaryAuthorization
* \author Radek Novacek <rnovacek@redhat.com>
*
* \brief This class represents PolicyKit temporary authorization
*
* This class encapsulates the PolkitTemporaryAuthorization interface.
*/
class POLKITQT1_CORE_EXPORT TemporaryAuthorization
{
public:
typedef QList< TemporaryAuthorization > List;
TemporaryAuthorization();
/**
* Creates TemporaryAuthorization object from PolkitTemporaryAuthorization
*
* \warning It shouldn't be used directly unless you are completely aware of what are you doing
*
* \param pkTemporaryAuthorization PolkitTemporaryAuthorization object
* \param parent
*/
explicit TemporaryAuthorization(PolkitTemporaryAuthorization *pkTemporaryAuthorization);
TemporaryAuthorization(const TemporaryAuthorization &other);
~TemporaryAuthorization();
TemporaryAuthorization &operator=(const TemporaryAuthorization &other);
/**
* \brief Gets the identifier for the authorization.
*
* This identifier can be user by the revokeTemporaryAuthorization function
*
* \return Unique identifier for the authorization
*/
QString id() const;
/**
* \brief Gets the identifier of the action that authorization is for
*
* \return String that identifies the action
*/
QString actionId() const;
/**
* \brief Gets the subject that authorization is for
*
* \return A Subject.
*/
Subject subject() const;
/**
* \brief Gets the time when authorization was obtained
*
* \return Time of obtaining the authorization
*/
QDateTime obtainedAt() const;
/**
* \brief Gets the time when authorizaton will expire
*
* \return Time of expiration
*/
QDateTime expirationTime() const;
/**
* \brief Revoke temporary authorization
*
* \return \c true Authorization has been revoked
* \c false Revoking authorization failed
*/
bool revoke();
private:
class Data;
QSharedDataPointer< Data > d;
};
}
Q_DECLARE_METATYPE(PolkitQt1::TemporaryAuthorization::List)
#endif // TEMPORARYAUTHORIZATION_H
@@ -0,0 +1,63 @@
install(FILES org.qt.policykit.examples.policy DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/polkit-1/actions/)
add_executable(${POLKITQT-1_EXAMPLE})
target_sources(${POLKITQT-1_EXAMPLE} PRIVATE
main.cpp
PkExample.cpp
icons/icons.qrc
)
target_link_libraries(${POLKITQT-1_EXAMPLE}
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::DBus
Qt${QT_MAJOR_VERSION}::Widgets
${POLKITQT-1_GUI_PCNAME}
${POLKITQT-1_CORE_PCNAME}
)
#--------Helper Application
# This macro is defined in FindPolkitQt.cmake
macro(dbus_add_activation_system_service _sources)
foreach (_i ${_sources})
get_filename_component(_service_file ${_i} ABSOLUTE)
string(REGEX REPLACE "\\.service.*$" ".service" _output_file ${_i})
set(_target ${CMAKE_CURRENT_BINARY_DIR}/${_output_file})
configure_file(${_service_file} ${_target})
install(FILES ${_target} DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/dbus-1/system-services )
#install(FILES ${_target} DESTINATION ${_install_dir})
endforeach (_i ${ARGN})
endmacro(dbus_add_activation_system_service _sources)
add_executable(${POLKITQT-1_EXAMPLE_HELPER})
qt_add_dbus_adaptor(polkit_example_helper_dbus_SRCS
org.qt.policykit.examples.xml
PkExampleHelper.h
PkExampleHelper
)
target_sources(${POLKITQT-1_EXAMPLE_HELPER} PRIVATE
PkExampleHelper.cpp
mainHelper.cpp
${polkit_example_helper_dbus_SRCS}
)
# see our helper is pretty small :D
target_link_libraries(${POLKITQT-1_EXAMPLE_HELPER}
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::Xml
Qt${QT_MAJOR_VERSION}::DBus
${POLKITQT-1_GUI_PCNAME}
)
install(TARGETS ${POLKITQT-1_EXAMPLE_HELPER} RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
dbus_add_activation_system_service(org.qt.policykit.examples.service.in)
install(FILES org.qt.policykit.examples.conf DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/dbus-1/system.d)
add_subdirectory(agent)
@@ -0,0 +1,227 @@
// This is an example not a library
/*
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-FileCopyrightText: 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "PkExample.h"
#include <polkitqt1-gui-actionbutton.h>
#include <polkitqt1-gui-actionbuttons.h>
#include <polkitqt1-authority.h>
#include <QDebug>
#include <QDBusMessage>
#include <QDBusConnection>
using namespace PolkitQt1;
using namespace PolkitQt1::Gui;
PkExample::PkExample(QMainWindow *parent)
: QMainWindow(parent)
{
setupUi(this);
ActionButton *bt;
// Here we create an ActionButton that is a subclass of Action
// always pass a QAbstractButton pointer and action id
// You can change the action id later if you want
bt = new ActionButton(kickPB, "org.qt.policykit.examples.kick", this);
// Here we are setting the text and icon to all four states
// an action might have
bt->setText("Kick!");
bt->setIcon(QPixmap(":/Icons/custom-no.png"));
// By using set{Yes|No|Auth}Enabled you can set the states
// when the button is enabled
bt->setEnabled(true, Action::No);
// As ActionButton is also an Action we cast it to add to menu
menuActions->addAction(qobject_cast<Action *>(bt));
toolBar->addAction(qobject_cast<Action *>(bt));
// this signal is emitted when the user click on the action,
// it will only happen if it was inserted in a QMenu or a QToolBar
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
// This signal was propagated from the QAbstractButton just for
// convenience in this case we don't have any benefit but the code
// look cleaner
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
// this is the Action activated signal, it is always emitted whenever
// someone click and get authorized to do the action
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
bt = new ActionButton(cryPB, "org.qt.policykit.examples.cry", this);
bt->setText("Cry!");
bt->setIcon(QPixmap(":/Icons/custom-yes.png"));
menuActions->addAction(qobject_cast<Action *>(bt));
toolBar->addAction(qobject_cast<Action *>(bt));
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
bt = new ActionButton(bleedPB, "org.qt.policykit.examples.bleed", this);
bt->setText("Bleed!");
bt->setIcon(QPixmap(":/Icons/action-locked-default.png"));
menuActions->addAction(qobject_cast<Action *>(bt));
toolBar->addAction(qobject_cast<Action *>(bt));
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
// This action is more customized
bt = new ActionButton(playPB, "org.qt.policykit.examples.play", this);
bt->setText("Play!");
bt->setVisible(true, Action::No | Action::Auth | Action::Yes);
bt->setEnabled(true, Action::No | Action::Auth | Action::Yes);
// here we set the behavior of PolKitResul = No
bt->setText("Can't play!", Action::No);
bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No);
bt->setToolTip("If your admin wasn't annoying, you could do this", Action::No);
// here we set the behavior of PolKitResul = Auth
bt->setText("Play?", Action::Auth);
bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth);
bt->setToolTip("Only card carrying tweakers can do this!", Action::Auth);
// here we set the behavior of PolKitResul = Yes
bt->setText("Play!", Action::Yes);
bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes);
bt->setToolTip("Go ahead, play!", Action::Yes);
menuActions->addAction(qobject_cast<Action *>(bt));
toolBar->addAction(qobject_cast<Action *>(bt));
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
bt = new ActionButton(deletePB, "org.qt.policykit.examples.delete", this);
bt->setText("Delete!");
bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No);
bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth);
bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes);
menuActions->addAction(qobject_cast<Action *>(bt));
toolBar->addAction(qobject_cast<Action *>(bt));
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
bt = new ActionButton(listenPB, "org.qt.policykit.examples.listen", this);
bt->setText("Listen!");
bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No);
bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth);
bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes);
menuActions->addAction(qobject_cast<Action *>(bt));
toolBar->addAction(qobject_cast<Action *>(bt));
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
bt = new ActionButton(setPB, "org.qt.policykit.examples.set", this);
bt->setText("Set!");
bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No);
bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth);
bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes);
menuActions->addAction(qobject_cast<Action *>(bt));
toolBar->addAction(qobject_cast<Action *>(bt));
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
bt = new ActionButton(shoutPB, "org.qt.policykit.examples.shout", this);
bt->setIcon(QPixmap(":/Icons/custom-no.png"), Action::No);
bt->setIcon(QPixmap(":/Icons/action-locked-default.png"), Action::Auth);
bt->setIcon(QPixmap(":/Icons/custom-yes.png"), Action::Yes);
bt->setText("Can't shout!", Action::No);
bt->setText("Shout?", Action::Auth);
bt->setText("Shout!", Action::Yes);
menuActions->addAction(qobject_cast<Action *>(bt));
toolBar->addAction(qobject_cast<Action *>(bt));
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(actionActivated()));
// test configChanged
}
PkExample::~PkExample()
{
}
void PkExample::activateAction()
{
// Here we cast the sender() to an Action and call activate()
// on it.
// Be careful in doing the same for ActionButton won't work as expected
// as action->activate() is calling Action::activate() and
// not ActionButton::activate which are different.
// You can cast then to ActionButton but be careful
// an Action casted to ActionButton may crash you app
Action *action = qobject_cast<Action *>(sender());
// calling activate with winId() makes the auth dialog
// be correct parented with your application.
action->activate();
}
void PkExample::actionActivated()
{
// This slot is called whenever an action is allowed
// here you will do your dirt job by calling a helper application
// that might erase your hardrive ;)
Action *action = qobject_cast<Action *>(sender());
// this is our Special Action that after allowed will call the helper
if (action->is("org.qt.policykit.examples.set")) {
qDebug() << "toggled for: org.qt.policykit.examples.set";
QDBusMessage message;
message = QDBusMessage::createMethodCall("org.qt.policykit.examples",
"/",
"org.qt.policykit.examples",
QLatin1String("set"));
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(setCB->currentText());
message.setArguments(argumentList);
// notice the systemBus here..
QDBusMessage reply = QDBusConnection::systemBus().call(message);
if (reply.type() == QDBusMessage::ReplyMessage
&& reply.arguments().size() == 1) {
// the reply can be anything, here we receive a bool
QListWidgetItem *item;
if (reply.arguments().first().toBool())
item = new QListWidgetItem(QPixmap(":/Icons/custom-yes.png"),
QString("Implicit authorization for shout has been set to %0")
.arg(setCB->currentText()));
else
item = new QListWidgetItem(QPixmap(":/Icons/custom-no.png"),
QString("Can't change the implicit authorization. Denied."));
actionList->addItem(item);
qDebug() << reply.arguments().first().toString();
} else if (reply.type() == QDBusMessage::MethodCallMessage) {
qWarning() << "Message did not receive a reply (timeout by message bus)";
}
return;
}
// As debug message says we are pretending to be the mechanism for the
// following action, here you will actually call your DBus helper that
// will run as root (setuid is not needed, see DBus docs).
// In the helper application you will issue checkAuthorizationSync,
// passing the action id and the caller pid (which DBus will tell you).
qDebug() << "pretending to be the mechanism for action:" << action->actionId();
Authority::Result result;
UnixProcessSubject subject(static_cast<uint>(QCoreApplication::applicationPid()));
result = Authority::instance()->checkAuthorizationSync(action->actionId(), subject,
Authority::AllowUserInteraction);
if (result == Authority::Yes) {
// in the helper you will do the action
qDebug() << "caller is authorized to do:" << action->actionId();
QListWidgetItem *item = new QListWidgetItem(QPixmap(":/Icons/custom-yes.png"), action->actionId());
actionList->addItem(item);
} else {
// OR return false to notify the caller that the action is not authorized.
qDebug() << "caller is NOT authorized to do:" << action->actionId();
QListWidgetItem *item = new QListWidgetItem(QIcon(":/Icons/custom-no.png"), action->actionId());
actionList->addItem(item);
}
}
@@ -0,0 +1,28 @@
// This is an example not a library
/*
SPDX-FileCopyrightText: 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PKEXAMPLE_H
#define PKEXAMPLE_H
#include "ui_PkExample.h"
class PkExample : public QMainWindow, Ui::PkExample
{
Q_OBJECT
public:
PkExample(QMainWindow *parent = nullptr);
~PkExample() override;
private Q_SLOTS:
void activateAction();
void actionActivated();
};
#endif
@@ -0,0 +1,234 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PkExample</class>
<widget class="QMainWindow" name="PkExample">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>PolicyKit-qt example</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QGridLayout" name="gridLayout" columnstretch="3,1">
<item row="0" column="0">
<widget class="QLabel" name="kickL">
<property name="text">
<string>Making the helper &lt;b&gt;Kick&lt;/b&gt; is not allowed. Action cannot be triggered.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="kickPB">
<property name="text">
<string>Kick!</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="cryL">
<property name="text">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Making the helper &lt;span style=&quot; font-weight:600;&quot;&gt;Cry&lt;/span&gt; is always allowed. Action can be triggered without authentication.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="cryPB">
<property name="text">
<string>Cry!</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="bleedL">
<property name="text">
<string>Making the helper &lt;b&gt;Bleed&lt;/b&gt; requires the user to authenticate. This is a one-shot authorization.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="bleedPB">
<property name="text">
<string>Bleed!</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="playL">
<property name="text">
<string>Making the helper &lt;b&gt;Play&lt;/b&gt; requires a system administrator to authenticate. This is a one-shot authorization.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="playPB">
<property name="text">
<string>Play!</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="listenL">
<property name="text">
<string>Making the helper &lt;b&gt;Listen&lt;/b&gt; requires the user to authenticate. The authorization will be kept for a brief period.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="listenPB">
<property name="text">
<string>Listen!</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="deleteL">
<property name="text">
<string>Making the helper &lt;b&gt;Delete&lt;/b&gt; requires a system administrator to authenticate. The authorization will be kept for a brief period.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="deletePB">
<property name="text">
<string>Delete!</string>
</property>
</widget>
</item>
<item row="6" column="0" rowspan="2">
<widget class="QLabel" name="deleteL_2">
<property name="text">
<string>&lt;b&gt;Set&lt;/b&gt; is special action. It sets the permissions for the &lt;b&gt;Shout&lt;/b&gt; action by actually using the helper application to change the implicit authorization.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="setCB">
<item>
<property name="text">
<string>no</string>
</property>
</item>
<item>
<property name="text">
<string>yes</string>
</property>
</item>
<item>
<property name="text">
<string>auth_self</string>
</property>
</item>
<item>
<property name="text">
<string>auth_admin</string>
</property>
</item>
<item>
<property name="text">
<string>auth_self_keep</string>
</property>
</item>
<item>
<property name="text">
<string>auth_admin_keep</string>
</property>
</item>
</widget>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="setPB">
<property name="text">
<string>Set!</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="deleteL_3">
<property name="text">
<string>The implicit authorization for the &lt;b&gt;Shout&lt;/b&gt; action is set by the &lt;b&gt;Set&lt;/b&gt; action. You can watch how different options can change behaviour of this action.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QPushButton" name="shoutPB">
<property name="text">
<string>Shout!</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="actionList"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuActions">
<property name="title">
<string>Actions</string>
</property>
</widget>
<addaction name="menuActions"/>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextUnderIcon</enum>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,97 @@
// This is an example not a library
/*
SPDX-FileCopyrightText: 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "PkExampleHelper.h"
#include "examplesadaptor.h"
#include <polkitqt1-authority.h>
#include <QDBusConnection>
#include <QTimer>
#include <QDebug>
#include <QDomDocument>
#define MINUTE 60000
using namespace PolkitQt1;
PkExampleHelper::PkExampleHelper(int &argc, char **argv)
: QCoreApplication(argc, argv)
{
qDebug() << "Creating Helper";
(void) new ExamplesAdaptor(this);
// Register the DBus service
if (!QDBusConnection::systemBus().registerService("org.qt.policykit.examples")) {
qDebug() << QDBusConnection::systemBus().lastError().message();;
QTimer::singleShot(0, this, SLOT(quit()));
return;
}
if (!QDBusConnection::systemBus().registerObject("/", this)) {
qDebug() << "unable to register service interface to dbus";
QTimer::singleShot(0, this, SLOT(quit()));
return;
}
// Normally you will set a timeout so your application can
// free some resources of the poor client machine ;)
QTimer::singleShot(MINUTE, this, SLOT(quit()));
}
PkExampleHelper::~PkExampleHelper()
{
qDebug() << "Destroying Helper";
}
bool PkExampleHelper::set(const QString &action)
{
qDebug() << "PkExampleHelper::set" << action;
// message().service() is the service name of the caller
// We can check if the caller is authorized to the following action
Authority::Result result;
SystemBusNameSubject subject(message().service());
result = Authority::instance()->checkAuthorizationSync("org.qt.policykit.examples.set",
subject , Authority::AllowUserInteraction);
if (result == Authority::Yes) {
qDebug() << message().service() << QString("Implicit authorization set to") << action;
// Caller is authorized so we can perform the action
return setValue(action);
} else {
qDebug() << message().service() << QString("Can't set the implicit authorization");
// Caller is not authorized so the action can't be performed
return false;
}
}
bool PkExampleHelper::setValue(const QString &action)
{
// This action must be authorized first. It will set the implicit
// authorization for the Shout action by editing the .policy file
QDomDocument doc = QDomDocument("policy");
QFile file("/usr/share/polkit-1/actions/org.qt.policykit.examples.policy");
if (!file.open(QIODevice::ReadOnly))
return false;
doc.setContent(&file);
file.close();
QDomElement el = doc.firstChildElement("policyconfig").
firstChildElement("action");
while (!el.isNull() && el.attribute("id", QString()) != "org.qt.policykit.examples.shout") {
el = el.nextSiblingElement("action");
}
el = el.firstChildElement("defaults");
el = el.firstChildElement("allow_active");
if (el.isNull())
return false;
el.firstChild().toText().setData(action);
if (!file.open(QIODevice::WriteOnly))
return false;
QTextStream stream(&file);
doc.save(stream, 2);
file.close();
return true;
}
@@ -0,0 +1,29 @@
// This is an example not a library
/*
SPDX-FileCopyrightText: 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PKEXAMPLE_HELPER_H
#define PKEXAMPLE_HELPER_H
#include <QDBusContext>
#include <QCoreApplication>
class PkExampleHelper : public QCoreApplication, protected QDBusContext
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.qt.policykit.examples")
public:
PkExampleHelper(int &argc, char **argv);
~PkExampleHelper() override;
public Q_SLOTS:
bool set(const QString &action);
bool setValue(const QString &action);
};
#endif
@@ -0,0 +1,16 @@
add_executable(${POLKITQT-1_AGENT_EXAMPLE})
target_sources(${POLKITQT-1_AGENT_EXAMPLE} PRIVATE
main.cpp
pkagentexample.cpp
klistener.cpp
)
target_link_libraries(${POLKITQT-1_AGENT_EXAMPLE}
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::Widgets
${POLKITQT-1_AGENT_PCNAME}
${POLKITQT-1_CORE_PCNAME}
PkgConfig::POLKIT_AGENT
PkgConfig::GOBJECT
)
@@ -0,0 +1,88 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include <QDebug>
#include <QInputDialog>
#include "klistener.h"
#include <polkitqt1-agent-session.h>
using namespace PolkitQt1::Agent;
KListener::KListener(QObject *parent)
: Listener(parent)
{
qDebug() << "Registering KDE listener";
}
// README: this is just testing code...
void KListener::initiateAuthentication(const QString &actionId,
const QString &message,
const QString &iconName,
const PolkitQt1::Details &details,
const QString &cookie,
const PolkitQt1::Identity::List &identities,
AsyncResult *result)
{
qDebug() << "initiateAuthentication for " << actionId << " with message " << message;
qDebug() << "iconName " << iconName;
qDebug() << details.keys();
qDebug() << "cookie" << cookie;
Q_FOREACH (const PolkitQt1::Identity &identity, identities) {
qDebug() << identity.toString();
Session *session;
session = new Session(identity, cookie, result);
connect(session, SIGNAL(request(QString,bool)), this, SLOT(request(QString,bool)));
connect(session, SIGNAL(completed(bool)), this, SLOT(completed(bool)));
connect(session, SIGNAL(showError(QString)), this, SLOT(showError(QString)));
connect(session, SIGNAL(showInfo(QString)), this, SLOT(showInfo(QString)));
session->initiate();
}
}
bool KListener::initiateAuthenticationFinish()
{
qDebug() << "initiateAuthenticationFinish()";
return true;
}
void KListener::cancelAuthentication()
{
qDebug() << "Cancelling authentication";
}
void KListener::request(const QString &request, bool echo)
{
qDebug() << "Request: " << request;
Session *session = (Session *)sender();
session->setResponse("");
}
void KListener::completed(bool gainedAuthorization)
{
qDebug() << "Completed: " << gainedAuthorization;
Session *session = (Session *)sender();
session->result()->setCompleted();
// This slot is invoked from the Session::completed signal (emitted in Session::Private::completed).
// Use deleteLater() to defer Session destruction; synchronous delete inside the signal callback would be unsafe.
session->deleteLater();
}
void KListener::showError(const QString &text)
{
qDebug() << "Error: " << text;
}
void KListener::showInfo(const QString &text)
{
qDebug() << "Info: " << text;
}
@@ -0,0 +1,43 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKIT_QT_AGENT_KDE_LISTENER_H
#define POLKIT_QT_AGENT_KDE_LISTENER_H
#include <QObject>
#include <QString>
#include <polkitqt1-agent-listener.h>
#include <polkitqt1-identity.h>
#include <polkitqt1-details.h>
#include <polkitqt1-agent-session.h>
class KListener : public PolkitQt1::Agent::Listener
{
Q_OBJECT
Q_DISABLE_COPY(KListener)
public:
KListener(QObject *parent = nullptr);
~KListener() override {};
public Q_SLOTS:
void initiateAuthentication(const QString &actionId,
const QString &message,
const QString &iconName,
const PolkitQt1::Details &details,
const QString &cookie,
const PolkitQt1::Identity::List &identities,
PolkitQt1::Agent::AsyncResult *result) override;
bool initiateAuthenticationFinish() override;
void cancelAuthentication() override;
void request(const QString &request, bool echo);
void completed(bool gainedAuthorization);
void showError(const QString &text);
void showInfo(const QString &text);
};
#endif
@@ -0,0 +1,17 @@
/*
SPDX-FileCopyrightText: 2009 Jaroslav Reznik
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <QApplication>
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE 1
#include "pkagentexample.h"
int main(int argc, char *argv[])
{
PkAgentExample example(argc, argv);
return example.exec();
}
@@ -0,0 +1,15 @@
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE 1
#include <polkitagent/polkitagent.h>
#include "pkagentexample.h"
#include <glib-object.h>
#include <QDebug>
#include <polkitqt1-subject.h>
PkAgentExample::PkAgentExample(int &argc, char **argv)
: QCoreApplication(argc, argv)
{
PolkitQt1::UnixSessionSubject session(getpid());
m_listener.registerListener(session, "/org/kde/PolicyKit1/AuthenticationAgent");
}
@@ -0,0 +1,28 @@
// This is an example not a library
/*
SPDX-FileCopyrightText: 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Radek Novacek <rnovacek@redhat.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PKAGENTEXAMPLE_H
#define PKAGENTEXAMPLE_H
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE 1
#include <QCoreApplication>
#include "klistener.h"
class PkAgentExample : public QCoreApplication
{
Q_OBJECT
public:
PkAgentExample(int &argc, char **argv);
~PkAgentExample() override {};
private:
KListener m_listener;
};
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,9 @@
<RCC>
<qresource prefix="Icons" >
<file>action-locked-default.png</file>
<file>action-locked.png</file>
<file>action-unlocked.png</file>
<file>custom-no.png</file>
<file>custom-yes.png</file>
</qresource>
</RCC>
@@ -0,0 +1,18 @@
// This is an example not a library
/*
SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <QApplication>
#include "PkExample.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
PkExample example;
example.show();
return app.exec();
}
@@ -0,0 +1,14 @@
// This is an example not a library
/*
SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "PkExampleHelper.h"
int main(int argc, char *argv[])
{
PkExampleHelper example(argc, argv);
return example.exec();
}
@@ -0,0 +1,20 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- This configuration file specifies the required security policies
for the PolicyKit examples to work. -->
<!-- Only user root can own the PackageKit service -->
<policy user="root">
<allow own="org.qt.policykit.examples"/>
</policy>
<!-- Allow anyone to call into the service - we'll reject callers using PolicyKit -->
<policy context="default">
<allow send_destination="org.qt.policykit.examples"/>
</policy>
</busconfig>
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
<vendor>KDE</vendor>
<vendor_url>http://www.kde.org</vendor_url>
<action id="org.qt.policykit.examples.kick">
<description>Kick</description>
<message>Prevents PolicyKit-Qt example from kicking</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>no</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.cry">
<description>Cry</description>
<message>Prevents PolicyKit-Qt example from crying</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.bleed">
<description>Bleed</description>
<message>Prevents PolicyKit-Qt example from bleeding</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_self</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.play">
<description>Play</description>
<message>Prevents PolicyKit-Qt example from playing</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.listen">
<description>Listen</description>
<message>Prevents PolicyKit-Qt example from listening</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_self_keep</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.delete">
<description>Delete</description>
<message>Prevents PolicyKit-Qt example from deleting</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.set">
<description>Push</description>
<message>Prevents PolicyKit-Qt example from setting permissions for the shout action</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.shout">
<description>Shout</description>
<message>Prevents PolicyKit-Qt example from shouting</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
<annotate key="org.qt.policykit.examples.shout">foo</annotate>
</action>
</policyconfig>
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
<vendor>KDE</vendor>
<vendor_url>http://www.kde.org</vendor_url>
<action id="org.qt.policykit.examples.kick">
<description>Kick</description>
<message>Prevents PolicyKit-Qt example from kicking</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>no</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.cry">
<description>Cry</description>
<message>Prevents PolicyKit-Qt example from crying</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.play">
<description>Play</description>
<message>Prevents PolicyKit-Qt example from playing</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_self</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.bleed">
<description>Bleed</description>
<message>Prevents PolicyKit-Qt example from bleeding</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.listen">
<description>Listen</description>
<message>Prevents PolicyKit-Qt example from listening</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_self_keep</allow_active>
</defaults>
</action>
<action id="org.qt.policykit.examples.delete">
<description>Delete</description>
<message>Prevents PolicyKit-Qt example from deleting</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<!--
<action id="org.qt.policykit.examples.shout">
<description>Shout</description>
<message>Prevents PolicyKit-Qt example from shouting</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
<annotate key="org.qt.policykit.examples.shout">foo</annotate>
</action>
<action id="org.qt.policykit.examples.push">
<description>Push</description>
<message>Prevents PolicyKit-Qt example from pushing</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
<annotate key="org.qt.policykit.examples.push">bar</annotate>
</action>
<action id="org.qt.policykit.examples.blow-up">
<description>Blow Up</description>
<message>Prevents PolicyKit-Qt example from blowing up</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
<annotate key="org.qt.policykit.examples.blow-up">booo</annotate>
</action>
-->
</policyconfig>
@@ -0,0 +1,5 @@
[D-BUS Service]
Name=org.qt.policykit.examples
Exec=@BIN_INSTALL_DIR@/@POLKITQT-1_EXAMPLE_HELPER@
User=root
@@ -0,0 +1,11 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.qt.policykit.examples">
<method name="set" >
<!-- IN: system user -->
<arg direction="in" type="s" name="user" />
<!-- OUT: whether the user gained the authorization -->
<arg direction="out" type="b" name="shadow_line" />
</method>
</interface>
</node>
@@ -0,0 +1,38 @@
add_library(${POLKITQT-1_GUI_PCNAME} SHARED)
add_library(${POLKITQT-1_CAMEL_NAME}::Gui ALIAS ${POLKITQT-1_GUI_PCNAME})
target_sources(${POLKITQT-1_GUI_PCNAME} PRIVATE
polkitqt1-gui-action.cpp
polkitqt1-gui-actionbutton.cpp
polkitqt1-gui-actionbuttons.cpp
)
generate_export_header(${POLKITQT-1_CORE_PCNAME}
BASE_NAME polkitqt1-gui
EXPORT_FILE_NAME polkitqt1-gui-export.h
)
target_link_libraries(${POLKITQT-1_GUI_PCNAME}
PUBLIC
${POLKITQT-1_CORE_PCNAME}
Qt${QT_MAJOR_VERSION}::Widgets
PRIVATE
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::DBus
)
set_target_properties(${POLKITQT-1_GUI_PCNAME} PROPERTIES VERSION ${POLKITQT-1_LIBRARY_VERSION}
SOVERSION ${POLKITQT-1_ABI_VERSION}
DEFINE_SYMBOL MAKE_POLKITQT1_LIB
EXPORT_NAME Gui)
target_include_directories(${POLKITQT-1_GUI_PCNAME}
INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/${POLKITQT-1_INCLUDE_PATH}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
)
install(TARGETS ${POLKITQT-1_GUI_PCNAME} EXPORT ${POLKITQT-1_CAMEL_NAME}Export ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION bin)
@@ -0,0 +1,502 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-FileCopyrightText: 2009 Jaroslav Reznik <jreznik@redhat.com>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-gui-action.h"
#include "polkitqt1-authority.h"
#include "polkitqt1-subject.h"
#include <QCoreApplication>
namespace PolkitQt1
{
namespace Gui
{
/**
* \internal
*/
class Q_DECL_HIDDEN Action::Private
{
public:
Private(Action *p);
Action *parent;
QString actionId;
Authority::Result pkResult;
qint64 targetPID;
void updateAction();
bool computePkResult();
void configChanged();
bool initiallyChecked;
// states data
bool selfBlockedVisible;
bool selfBlockedEnabled;
QString selfBlockedText;
QString selfBlockedWhatsThis;
QString selfBlockedToolTip;
QIcon selfBlockedIcon;
bool noVisible;
bool noEnabled;
QString noText;
QString noWhatsThis;
QString noToolTip;
QIcon noIcon;
bool authVisible;
bool authEnabled;
QString authText;
QString authWhatsThis;
QString authToolTip;
QIcon authIcon;
bool yesVisible;
bool yesEnabled;
QString yesText;
QString yesWhatsThis;
QString yesToolTip;
QIcon yesIcon;
};
Action::Private::Private(Action *p)
: parent(p)
, targetPID(getpid())
{
initiallyChecked = false;
// Set the default values
selfBlockedVisible = true;
selfBlockedEnabled = false;
noVisible = true;
noEnabled = false;
authVisible = true;
authEnabled = true;
yesVisible = true;
yesEnabled = true;
}
Action::Action(const QString &actionId, QObject *parent)
: QAction(parent)
, d(new Private(this))
{
// this must be called AFTER the values initialization
setPolkitAction(actionId);
// track the config changes to update the action
connect(Authority::instance(), SIGNAL(configChanged()),
this, SLOT(configChanged()));
// for now we call config changed..
connect(Authority::instance(), SIGNAL(consoleKitDBChanged()),
this, SLOT(configChanged()));
}
Action::~Action()
{
delete d;
}
bool Action::activate()
{
switch (d->pkResult) {
case Authority::Yes:
case Authority::Challenge:
// just Q_EMIT the 'activated' signal
Q_EMIT authorized();
return true;
break;
default:
case Authority::No:
if (d->noEnabled) {
/* If PolicyKit says no... and we got here.. it means
* that the user set the property "no-enabled" to
* TRUE..
*
* Hence, they probably have a good reason for doing
* this so do let the 'activate' signal propagate..
*/
Q_EMIT authorized();
return true;
}
break;
}
return false;
}
void Action::setChecked(bool checked)
{
// We store this as initiallyChecked
// to be able to undo changes in case the auth fails
d->initiallyChecked = checked;
QAction::setChecked(checked);
}
void Action::Private::updateAction()
{
if (Authority::instance()->hasError()) {
return;
}
switch (pkResult) {
default:
case Authority::Unknown:
case Authority::No:
qobject_cast<QAction *>(parent)->setVisible(noVisible);
qobject_cast<QAction *>(parent)->setEnabled(noEnabled);
qobject_cast<QAction *>(parent)->setText(noText);
if (!noWhatsThis.isNull()) {
qobject_cast<QAction *>(parent)->setWhatsThis(noWhatsThis);
}
if (!noToolTip.isNull()) {
qobject_cast<QAction *>(parent)->setToolTip(noToolTip);
}
qobject_cast<QAction *>(parent)->setIcon(noIcon);
break;
case Authority::Challenge:
qobject_cast<QAction *>(parent)->setVisible(authVisible);
qobject_cast<QAction *>(parent)->setEnabled(authEnabled);
qobject_cast<QAction *>(parent)->setText(authText);
if (!authWhatsThis.isNull()) {
qobject_cast<QAction *>(parent)->setWhatsThis(authWhatsThis);
}
if (!authToolTip.isNull()) {
qobject_cast<QAction *>(parent)->setToolTip(authToolTip);
}
qobject_cast<QAction *>(parent)->setIcon(authIcon);
break;
case Authority::Yes:
qobject_cast<QAction *>(parent)->setVisible(yesVisible);
qobject_cast<QAction *>(parent)->setEnabled(yesEnabled);
qobject_cast<QAction *>(parent)->setText(yesText);
if (!yesWhatsThis.isNull()) {
qobject_cast<QAction *>(parent)->setWhatsThis(yesWhatsThis);
}
if (!yesToolTip.isNull()) {
qobject_cast<QAction *>(parent)->setToolTip(yesToolTip);
}
qobject_cast<QAction *>(parent)->setIcon(yesIcon);
if (parent->isCheckable()) {
qobject_cast<QAction *>(parent)->setChecked(!initiallyChecked);
}
break;
}
Q_EMIT parent->dataChanged();
}
void Action::Private::configChanged()
{
bool result_changed;
result_changed = computePkResult();
if (result_changed) {
updateAction();
}
}
bool Action::Private::computePkResult()
{
Authority::Result old_result;
UnixProcessSubject subject(parent->targetPID());
old_result = pkResult;
pkResult = Authority::Unknown;
pkResult = Authority::instance()->checkAuthorizationSync(actionId, subject, Authority::None);
return old_result != pkResult;
}
qint64 Action::targetPID() const
{
if (d->targetPID != 0) {
return d->targetPID;
} else {
return QCoreApplication::applicationPid();
}
}
void Action::setTargetPID(qint64 pid)
{
d->targetPID = pid;
d->computePkResult();
d->updateAction();
}
bool Action::isAllowed() const
{
return d->pkResult == Authority::Yes;
}
bool Action::is(const QString &other) const
{
return d->actionId == other;
}
void Action::revoke()
{
/*TODO: implement it? no negative authorizations available, no authorization db*/
}
void Action::setText(const QString &text, States states)
{
if (states & All) {
d->selfBlockedText = text;
d->noText = text;
d->authText = text;
d->yesText = text;
} else if (states & Auth) {
d->authText = text;
} else if (states & No) {
d->noText = text;
} else if (states & SelfBlocked) {
d->selfBlockedText = text;
} else if (states & Yes) {
d->yesText = text;
}
d->updateAction();
}
QString Action::text(Action::State state) const
{
switch (state) {
case Yes:
return d->yesText;
case No:
return d->noText;
case Auth:
return d->authText;
case SelfBlocked:
return d->selfBlockedText;
case None:
return QAction::text();
default:
return QString();
}
}
void Action::setToolTip(const QString &toolTip, States states)
{
if (states & All) {
d->selfBlockedToolTip = toolTip;
d->noToolTip = toolTip;
d->authToolTip = toolTip;
d->yesToolTip = toolTip;
} else if (states & Auth) {
d->authToolTip = toolTip;
} else if (states & No) {
d->noToolTip = toolTip;
} else if (states & SelfBlocked) {
d->selfBlockedToolTip = toolTip;
} else if (states & Yes) {
d->yesToolTip = toolTip;
}
d->updateAction();
}
QString Action::toolTip(Action::State state) const
{
switch (state) {
case Yes:
return d->yesToolTip;
case No:
return d->noToolTip;
case Auth:
return d->authToolTip;
case SelfBlocked:
return d->selfBlockedToolTip;
case None:
return QAction::toolTip();
default:
return QString();
}
}
void Action::setWhatsThis(const QString &whatsThis, States states)
{
if (states & All) {
d->selfBlockedWhatsThis = whatsThis;
d->noWhatsThis = whatsThis;
d->authWhatsThis = whatsThis;
d->yesWhatsThis = whatsThis;
} else if (states & Auth) {
d->authWhatsThis = whatsThis;
} else if (states & No) {
d->noWhatsThis = whatsThis;
} else if (states & SelfBlocked) {
d->selfBlockedWhatsThis = whatsThis;
} else if (states & Yes) {
d->yesWhatsThis = whatsThis;
}
d->updateAction();
}
QString Action::whatsThis(Action::State state) const
{
switch (state) {
case Yes:
return d->yesWhatsThis;
case No:
return d->noWhatsThis;
case Auth:
return d->authWhatsThis;
case SelfBlocked:
return d->selfBlockedWhatsThis;
case None:
return QAction::whatsThis();
default:
return QString();
}
}
void Action::setIcon(const QIcon &icon, States states)
{
if (states & All) {
d->selfBlockedIcon = icon;
d->noIcon = icon;
d->authIcon = icon;
d->yesIcon = icon;
} else if (states & Auth) {
d->authIcon = icon;
} else if (states & No) {
d->noIcon = icon;
} else if (states & SelfBlocked) {
d->selfBlockedIcon = icon;
} else if (states & Yes) {
d->yesIcon = icon;
}
d->updateAction();
}
QIcon Action::icon(Action::State state) const
{
switch (state) {
case Yes:
return d->yesIcon;
case No:
return d->noIcon;
case Auth:
return d->authIcon;
case SelfBlocked:
return d->selfBlockedIcon;
case None:
return QAction::icon();
default:
return QIcon();
}
}
void Action::setEnabled(bool enabled, States states)
{
if (states & All) {
d->selfBlockedEnabled = enabled;
d->noEnabled = enabled;
d->authEnabled = enabled;
d->yesEnabled = enabled;
} else if (states & Auth) {
d->authEnabled = enabled;
} else if (states & No) {
d->noEnabled = enabled;
} else if (states & SelfBlocked) {
d->selfBlockedEnabled = enabled;
} else if (states & Yes) {
d->yesEnabled = enabled;
}
d->updateAction();
}
bool Action::isEnabled(Action::State state) const
{
switch (state) {
case Yes:
return d->yesEnabled;
case No:
return d->noEnabled;
case Auth:
return d->authEnabled;
case SelfBlocked:
return d->selfBlockedEnabled;
case None:
return QAction::isEnabled();
default:
return false;
}
}
void Action::setVisible(bool visible, States states)
{
if (states & All) {
d->selfBlockedVisible = visible;
d->noVisible = visible;
d->authVisible = visible;
d->yesVisible = visible;
} else if (states & Auth) {
d->authVisible = visible;
} else if (states & No) {
d->noVisible = visible;
} else if (states & SelfBlocked) {
d->selfBlockedVisible = visible;
} else if (states & Yes) {
d->yesVisible = visible;
}
d->updateAction();
}
bool Action::isVisible(Action::State state) const
{
switch (state) {
case Yes:
return d->yesVisible;
case No:
return d->noVisible;
case Auth:
return d->authVisible;
case SelfBlocked:
return d->selfBlockedVisible;
case None:
return QAction::isVisible();
default:
return false;
}
}
void Action::setPolkitAction(const QString &actionId)
{
//TODO:
d->actionId = actionId;
d->computePkResult();
d->updateAction();
}
//--------------------------------------------------
QString Action::actionId() const
{
return d->actionId;
}
}
}
#include "moc_polkitqt1-gui-action.cpp"
@@ -0,0 +1,291 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_GUI_ACTION_H
#define POLKITQT1_GUI_ACTION_H
#include "polkitqt1-gui-export.h"
#include <QAction>
namespace PolkitQt1
{
namespace Gui
{
/**
* \class Action polkitqt1-gui-action.h Action
* \author Daniel Nicoletti <dantti85-pk@yahoo.com.br>
* \author Dario Freddi <drf@kde.org>
*
* \brief Class used to manage actions
*
* This class is an interface around PolicyKit Actions.
* By using this class, you are able to track the result of a
* given action.
*
* Most of the times, you would want to use this class combined
* with a QAbstractButton. In this case, you can use the more
* comfortable ActionButton class that manages button's properties
* update for you.
*
* \see ActionButton
*/
class POLKITQT1_GUI_EXPORT Action : public QAction
{
Q_OBJECT
Q_DISABLE_COPY(Action)
public:
enum State {
None = 0,
SelfBlocked = 1,
Yes = 2,
No = 4,
Auth = 8,
// Future usage = 16,
// Future usage = 32,
// Future usage = 64,
// Future usage = 128,
// Future usage = 256,
All = 512
};
Q_DECLARE_FLAGS(States, State)
/**
* Constructs a new Action item
*
* \param actionId the PolicyKit action Id (e.g.: org.freedesktop.policykit.read)
* \param parent the object parent
*/
explicit Action(const QString &actionId = QString(), QObject *parent = nullptr);
~Action() override;
Q_SIGNALS:
/**
* Emitted when the PolicyKit result (PolKitResult)
* for the given action or the internal data changes
* (i.e. the user called one of the set methods).
* You should connect to this signal if you want
* to track these changes.
*/
void dataChanged();
/**
* Emitted when using this class as a proxy
* for a given action, It's only emitted if the
* activate() slot is called and the auth permits
* the action
*
* \see activate()
*/
void authorized();
public Q_SLOTS:
/**
* Use this slot if you want to activate
* the action. authorized() will be emitted
* if the action gets authorized.
*
* \return \c true if the caller can do the action
*
* \see authorized()
*/
bool activate();
/**
* Defines the checked state. The opposite state will
* trigger authentication for this actions. For example, if
* you set this to \c true, when the action's checked state
* will become \c false, the authentication will be triggered.
*
* \param checked the new checked state
*/
void setChecked(bool checked);
/**
* This method can be used to revoke the authorization
* obtained for this action.
*/
void revoke();
public:
/**
* Changes the action being tracked
*
* \param actionId The new action ID
*/
void setPolkitAction(const QString &actionId);
/**
* Returns the current action ID.
*
* \return The action ID
*
*/
QString actionId() const;
/**
* Sets the text for the current action. This will
* be shown only in the states specified in the \c states parameter.
* \param text the new text for the action
* \param states the states of the Polkit action on which the setting
* will be applied
*/
void setText(const QString &text, States states = All);
/**
* Sets the tooltip for the current action. This will
* be shown only in the states specified in the \c states parameter.
* \param toolTip the new tooltip for the action
* \param states the states of the Polkit action on which the setting
* will be applied
*/
void setToolTip(const QString &toolTip, States states = All);
/**
* Sets the whatsthis for the current action. This will
* be shown only in the states specified in the \c states parameter.
* \param whatsThis the new whatsthis for the action
* \param states the states of the Polkit action on which the setting
* will be applied
*/
void setWhatsThis(const QString &whatsThis, States states = All);
/**
* Sets the icon for the current action. This will
* be shown only in the states specified in the \c states parameter.
* \note You need to pass a QIcon here. You can easily
* create one from a Pixmap, or pass a KIcon
* \param icon the new icon for the action
* \param states the states of the Polkit action on which the setting
* will be applied
*/
void setIcon(const QIcon &icon, States states = All);
/**
* Sets whether the current action is visible or not. This will
* be applied only in the states specified in the \c states parameter.
* \param visible visibility of the action
* \param states the states of the Polkit action on which the setting
* will be applied
*/
void setVisible(bool visible, States states = All);
/**
* Sets whether the current action is enabled or not. This will
* be shown only in the states specified in the \c states parameter.
* \param enabled whether the Action will be enabled or not
* \param states the states of the Polkit action on which the setting
* will be applied
*/
void setEnabled(bool enabled, States states = All);
/**
* This function sets the process id of the target that
* should receive the authorization. Set this to 0 to set
* the current process as the target.
*
* \param pid The target process id; 0 if it is the current process
*/
void setTargetPID(qint64 pid);
/**
* Gets the text of the action when it is in the specified state
*
* \note Passing None will return the current value
* \param state The state to be checked
* \returns The text shown when the action is in the specified state
*/
QString text(State state = None) const;
/**
* Gets the tooltip of the action when it is in the specified state
*
* \note Passing None will return the current value
* \param state The state to be checked
* \returns The tooltip shown when the action is in the specified state
*/
QString toolTip(State state = None) const;
/**
* Gets the whatsThis of the action when it is in the specified state
*
* \param state The state to be checked
* \returns The whatsThis shown when the action is in the specified state
*/
QString whatsThis(State state = None) const;
/**
* Gets the icon of the action when it is in the specified state
*
* \note Passing None will return the current value
* \param state The state to be checked
* \returns The icon shown when the action is in the specified state
*/
QIcon icon(State state = None) const;
/**
* Gets whether the action is visible or not when it is in the specified state
*
* \note Passing None will return the current value
* \param state The state to be checked
* \returns Whether the action is visible or not in the specified state
*/
bool isVisible(State state = None) const;
/**
* Gets whether the action is enabled or not when it is in the specified state
*
* \note Passing None will return the current value
* \param state The state to be checked
* \returns Whether the action is enabled or not in the specified state
*/
bool isEnabled(State state = None) const;
/**
* \see setTargetPID
*/
qint64 targetPID() const;
/**
* This method can be used to check the if the current action
* can be performed (i.e. PolKitResult is YES).
* \note This method does not call the authentication dialog, use
* activate() instead
* \return \c true if the action can be performed
*/
bool isAllowed() const;
/**
* This method compares a PolicyKit action Id with the
* current one of the object.
*
* \see actionId()
*
* \param actionId the action Id to compare
*
* \return \c true if the actionId is the same as this object's one
*/
bool is(const QString &actionId) const;
private:
class Private;
Private * const d;
Q_PRIVATE_SLOT(d, void configChanged())
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Action::States)
}
}
#endif
@@ -0,0 +1,153 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-gui-actionbutton.h"
#include "polkitqt1-gui-actionbutton_p.h"
namespace PolkitQt1
{
namespace Gui
{
ActionButton::ActionButton(QAbstractButton *button, const QString &actionId, QObject *parent)
: Action(actionId, parent)
, d_ptr(new ActionButtonPrivate(QList<QAbstractButton *>() << button))
{
d_ptr->q_ptr = this;
setButton(button);
connect(this, SIGNAL(dataChanged()), SLOT(updateButton()));
}
ActionButton::ActionButton(ActionButtonPrivate &dd, const QString &actionId, QObject *parent)
: Action(actionId, parent)
, d_ptr(&dd)
{
d_ptr->q_ptr = this;
connect(this, SIGNAL(dataChanged()), SLOT(updateButton()));
}
ActionButton::~ActionButton()
{
delete d_ptr;
}
void ActionButtonPrivate::updateButton()
{
Q_Q(ActionButton);
Q_FOREACH(QAbstractButton *ent, buttons) {
ent->setVisible(q->isVisible());
ent->setEnabled(q->isEnabled());
ent->setText(q->text());
if (!q->toolTip().isNull()) {
ent->setToolTip(q->toolTip());
}
if (!q->whatsThis().isNull()) {
ent->setWhatsThis(q->whatsThis());
}
ent->setIcon(q->icon());
// if the item cannot do the action anymore
// lets revert to the initial state
if (ent->isCheckable()) {
ent->setChecked(q->isChecked());
}
}
}
bool ActionButton::activate()
{
Q_D(ActionButton);
bool tg = false;
Q_FOREACH(QAbstractButton *ent, d->buttons) {
if (ent->isCheckable()) {
// we set the current Action state
ent->setChecked(isChecked());
// toggle the action cause we are not directly connected there..
tg = true;
}
}
if (tg) {
toggle();
}
return Action::activate();
}
void ActionButton::setButton(QAbstractButton *button)
{
Q_D(ActionButton);
// First, let's clear the list
Q_FOREACH(QAbstractButton *ent, d->buttons) {
d->removeButton(ent);
}
// And then add it
d->addButton(button);
}
void ActionButtonPrivate::addButton(QAbstractButton *button)
{
Q_Q(ActionButton);
buttons.append(button);
QObject::connect(button, SIGNAL(clicked(bool)), q, SLOT(streamClicked(bool)));
QObject::connect(q, SIGNAL(toggled(bool)), button, SLOT(toggle()));
if (q->isCheckable()) {
// the button should follow our first buttons
button->setCheckable(true);
} else if (button->isCheckable()) {
// if we are not checkable BUT the button
// is (eg a QCheckBox) we should set all buttons to
// checkable.
Q_FOREACH(QAbstractButton *ent, buttons) {
ent->setCheckable(true);
}
// set the checkable state of Action to store the initial state
q->setCheckable(true);
}
// call this after m_activateOnCheck receives the value
updateButton();
}
void ActionButtonPrivate::removeButton(QAbstractButton *button)
{
Q_Q(ActionButton);
if (buttons.contains(button)) {
QObject::disconnect(button, SIGNAL(clicked(bool)), q, SLOT(streamClicked(bool)));
QObject::disconnect(q, SIGNAL(toggled(bool)), button, SLOT(toggle()));
buttons.removeOne(button);
}
}
QAbstractButton *ActionButton::button() const
{
Q_D(const ActionButton);
return d->buttons.first();
}
void ActionButtonPrivate::streamClicked(bool c)
{
Q_Q(ActionButton);
Q_EMIT q->clicked(qobject_cast<QAbstractButton *>(q->sender()), c);
}
}
}
#include "moc_polkitqt1-gui-actionbutton.cpp"
@@ -0,0 +1,131 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_GUI_ACTIONBUTTON_H
#define POLKITQT1_GUI_ACTIONBUTTON_H
#include "polkitqt1-gui-action.h"
class QAbstractButton;
namespace PolkitQt1
{
namespace Gui
{
class ActionButtonPrivate;
/**
* \class ActionButton polkitqt1-gui-actionbutton.h ActionButton
* \author Daniel Nicoletti <dantti85-pk@yahoo.com.br>
* \author Dario Freddi <drf@kde.org>
*
* \brief Class used to hold and update a QAbstractButton
*
* This class allows you to associate QAbstractButtons
* (i.e. QPushButton) to a PolicyKit Action. It will update the
* button properties according to the PolicyKit Action automatically.
*
* \note You should connect the activated() signal to receive
* a notification when the user clicked the button and gets
* permission to perform the given action. If you set 'noEnabled'
* to \c true it will be emitted when PolKitResult is NO.
*/
class POLKITQT1_GUI_EXPORT ActionButton : public Action
{
Q_OBJECT
Q_DECLARE_PRIVATE(ActionButton)
Q_DISABLE_COPY(ActionButton)
public:
/**
* Constructs a new ActionButton. You need to pass this
* constructor an existing QAbstractButton, whose properties
* will be modified according to the underlying Action
* object. As ActionButton inherits from Action, you can
* define your button's behavior right through this wrapper.
*
* \see Action
*
* \param button the QAbstractButton to associate to this ActionButton
* \param actionId the action Id to create the underlying Action
* \param parent the parent object
*/
explicit ActionButton(QAbstractButton *button, const QString &actionId = QString(), QObject *parent = nullptr);
~ActionButton() override;
/**
* Sets the button associated to the underlying action.
*
* \note If you are calling this function, you're probably
* changing the button the action is referring to. If this
* is the case, please note that Polkit-Qt does not handle
* the previous button's memory, so you should take care of
* deleting it yourself (if needed). You can retrieve it by
* using button()
*
* \see button
*
* \param button the new button associated with the underlying action
*/
void setButton(QAbstractButton *button);
/**
* Returns the current button
*
* \return the button currently associated with the underlying action
*/
QAbstractButton *button() const;
public Q_SLOTS:
/**
* Connect clicked() signals to this slot. This should be
* manually done, as in some cases we might want
* to manually call this. Calling this will emit authorized().
*
* \note This slot is reentrant which is likely to only be a problem
* if you are creating an interface to setup PolicyKit policies.
* \note If you have a checkbox, connect to its' clicked() signal
* to avoid an infinite loop as this function internally calls setChecked().
* You can always use the clicked(bool) signal in this class to
* connect to here.
* \warning if you use this class take care to not call Action::activate
* otherwise your checkable buttons won't be properly updated.
*/
bool activate();
Q_SIGNALS:
/**
* Emitted when the abstract button clicked(bool) signal
* is emitted. This allows you to use qobject_cast<ActionButton *>(sender())
* in a slot connected to this signal and call activate() on it.
*
* \note you will normally want to connect this signal
* to the activate slot.
*
* \param button the button that has been clicked
* \param checked the checked state, if applicable. Otherwise \c false
*
*/
void clicked(QAbstractButton *button, bool checked = false);
protected:
ActionButton(ActionButtonPrivate &dd, const QString &actionId, QObject *parent = nullptr);
ActionButtonPrivate * const d_ptr;
private:
Q_PRIVATE_SLOT(d_func(), void updateButton())
Q_PRIVATE_SLOT(d_func(), void streamClicked(bool))
};
}
}
#endif
@@ -0,0 +1,37 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_GUI_ACTIONBUTTON_P_H
#define POLKITQT1_GUI_ACTIONBUTTON_P_H
#include <polkitqt1-gui-actionbutton.h>
#include <QList>
#include <QAbstractButton>
/**
* \internal
*/
class PolkitQt1::Gui::ActionButtonPrivate
{
public:
ActionButtonPrivate(const QList<QAbstractButton *> &b)
: buttons(b) {}
virtual ~ActionButtonPrivate() {}
void addButton(QAbstractButton *button);
void removeButton(QAbstractButton *button);
void updateButton();
void streamClicked(bool);
Q_DECLARE_PUBLIC(ActionButton)
ActionButton *q_ptr;
QList<QAbstractButton *> buttons;
};
#endif /* ACTIONBUTTON_P_H */
@@ -0,0 +1,58 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "polkitqt1-gui-actionbuttons.h"
#include "polkitqt1-gui-actionbuttons_p.h"
namespace PolkitQt1
{
namespace Gui
{
ActionButtons::ActionButtons(const QList<QAbstractButton *> &buttons, const QString &actionId, QObject *parent)
: ActionButton(*new ActionButtonsPrivate(buttons), actionId, parent)
{
setButtons(buttons);
}
ActionButtons::~ActionButtons()
{
}
void ActionButtons::setButtons(const QList<QAbstractButton *> &buttons)
{
Q_FOREACH(QAbstractButton *ent, buttons) {
addButton(ent);
}
}
QList<QAbstractButton *> ActionButtons::buttons() const
{
Q_D(const ActionButtons);
return d->buttons;
}
void ActionButtons::addButton(QAbstractButton *button)
{
Q_D(ActionButtons);
d->addButton(button);
}
void ActionButtons::removeButton(QAbstractButton *button)
{
Q_D(ActionButtons);
d->removeButton(button);
}
}
}
@@ -0,0 +1,101 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_GUI_ACTIONBUTTONS_H
#define POLKITQT1_GUI_ACTIONBUTTONS_H
#include "polkitqt1-gui-actionbutton.h"
namespace PolkitQt1
{
namespace Gui
{
class ActionButtonsPrivate;
/**
* \class ActionButtons polkitqt1-gui-actionbuttons.h ActionButtons
* \author Dario Freddi <drf@kde.org>
*
* \brief Class used to hold and update a list of QAbstractButtons
*
* This class is a convenience wrapper around ActionButton that lets
* you associate an undefined number of QAbstractButtons with a single
* action. Every button will be updated accordingly upon action's properties
* changes.
*
* \see ActionButton
*/
class ActionButtons : public ActionButton
{
Q_OBJECT
Q_DECLARE_PRIVATE(ActionButtons)
Q_DISABLE_COPY(ActionButtons)
public:
/**
* Constructs a new ActionButton. You need to pass this
* constructor an existing list of QAbstractButtons, whose properties
* will be modified according to the underlying Action
* object. As ActionButtons inherits from Action, you can
* define your buttons' behavior right through this wrapper.
*
* \see Action
*
* \param buttons the QAbstractButton to associate to this ActionButton
* \param actionId the action Id to create the underlying Action
* \param parent the parent object
*/
explicit ActionButtons(const QList<QAbstractButton *> &buttons, const QString &actionId = QString(), QObject *parent = nullptr);
~ActionButtons() override;
/**
* Sets a list of buttons associated to the underlying action.
*
* \note If you are calling this function, you're probably
* changing the buttons list the action is referring to. If this
* is the case, please note that Polkit-Qt does not handle
* the previous buttons' memory, so you should take care of
* deleting them yourself (if needed). You can retrieve it by
* using buttons()
*
* \see buttons
*
* \param buttons the new buttons associated with the underlying action
*/
void setButtons(const QList<QAbstractButton *> &buttons);
/**
* Returns the current buttons list
*
* \return the buttons currently associated with the underlying action
*/
QList<QAbstractButton *> buttons() const;
/**
* Adds a button to the current button list. The button's properties
* will be updated according to the action upon adding.
*
* \param button the button to add
*/
void addButton(QAbstractButton *button);
/**
* Removes a button from the current list. Please note that Polkit-Qt
* does not handle the removed button's memory, so you should take care of
* deleting it yourself (if needed).
*
* \param button the button to remove
*/
void removeButton(QAbstractButton *button);
};
}
}
#endif
@@ -0,0 +1,23 @@
/*
This file is part of the Polkit-qt project
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef POLKITQT1_GUI_ACTIONBUTTONS_P_H
#define POLKITQT1_GUI_ACTIONBUTTONS_P_H
#include "polkitqt1-gui-actionbutton_p.h"
/**
* \internal
*/
class PolkitQt1::Gui::ActionButtonsPrivate : public ActionButtonPrivate
{
public:
ActionButtonsPrivate(const QList<QAbstractButton *> &b)
: ActionButtonPrivate(b) {}
};
#endif /* ACTIONBUTTONS_P_H */
@@ -0,0 +1 @@
#include "../polkitqt1-actiondescription.h"
@@ -0,0 +1 @@
#include "../../polkitqt1-agent-listener.h"
@@ -0,0 +1 @@
#include "../../polkitqt1-agent-session.h"
@@ -0,0 +1 @@
#include "../polkitqt1-authority.h"
@@ -0,0 +1 @@
#include "../polkitqt1-details.h"
@@ -0,0 +1 @@
#include "../../polkitqt1-gui-action.h"
@@ -0,0 +1 @@
#include "../../polkitqt1-gui-actionbutton.h"
@@ -0,0 +1 @@
#include "../../polkitqt1-gui-actionbuttons.h"
@@ -0,0 +1 @@
#include "../polkitqt1-identity.h"
@@ -0,0 +1 @@
#include "../polkitqt1-subject.h"
@@ -0,0 +1 @@
#include "../polkitqt1-temporaryauthorization.h"
@@ -0,0 +1,21 @@
fancyname: PolkitQt-1
description: Qt wrapper around polkit-1
platforms:
- name: Linux
# - name: FreeBSD
# - name: Windows
# - name: MacOSX
# - name: Android
release: true
public_lib: true
public_source_dirs:
- core
- gui
- agent
libraries:
- cmake: "PolkitQt5-1::Core"
- cmake: "PolkitQt5-1::Gui"
- cmake: "PolkitQt5-1::Agent"
cmakename: PolkitQt-1
irc: kde-devel
mailinglist: kde-core-devel
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API
Version: @POLKITQT-1_VERSION_STRING@
Requires: @POLKITQT-1_CORE_PCNAME@ @POLKITQT-1_GUI_PCNAME@ @POLKITQT-1_AGENT_PCNAME@
Libs: -L${libdir} -l@POLKITQT-1_CORE_PCNAME@ -l@POLKITQT-1_GUI_PCNAME@ -l@POLKITQT-1_AGENT_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_AGENT_PCNAME@
Description: Convenience library for using polkit Agent with a Qt-styled API
Version: @POLKITQT-1_VERSION_STRING@
Requires: QtCore QtGui
Libs: -L${libdir} -l@POLKITQT-1_AGENT_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_CORE_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API, non-GUI classes
Version: @POLKITQT-1_VERSION_STRING@
Requires: QtCore
Libs: -L${libdir} -l@POLKITQT-1_CORE_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_GUI_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API, GUI classes
Version: @POLKITQT-1_VERSION_STRING@
Requires: QtCore QtGui @POLKITQT-1_CORE_PCNAME@
Libs: -L${libdir} -l@POLKITQT-1_GUI_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API
Version: @POLKITQT-1_VERSION_STRING@
Requires: @POLKITQT-1_CORE_PCNAME@ @POLKITQT-1_GUI_PCNAME@ @POLKITQT-1_AGENT_PCNAME@
Libs: -L${libdir} -l@POLKITQT-1_CORE_PCNAME@ -l@POLKITQT-1_GUI_PCNAME@ -l@POLKITQT-1_AGENT_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_AGENT_PCNAME@
Description: Convenience library for using polkit Agent with a Qt-styled API
Version: @POLKITQT-1_VERSION_STRING@
Requires: Qt@QT_MAJOR_VERSION@Core Qt@QT_MAJOR_VERSION@Gui
Libs: -L${libdir} -l@POLKITQT-1_AGENT_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_CORE_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API, non-GUI classes
Version: @POLKITQT-1_VERSION_STRING@
Requires: Qt@QT_MAJOR_VERSION@Core
Libs: -L${libdir} -l@POLKITQT-1_CORE_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_GUI_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API, GUI classes
Version: @POLKITQT-1_VERSION_STRING@
Requires: Qt@QT_MAJOR_VERSION@Core Qt@QT_MAJOR_VERSION@Gui @POLKITQT-1_CORE_PCNAME@
Libs: -L${libdir} -l@POLKITQT-1_GUI_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API
Version: @POLKITQT-1_VERSION_STRING@
Requires: @POLKITQT-1_CORE_PCNAME@ @POLKITQT-1_GUI_PCNAME@ @POLKITQT-1_AGENT_PCNAME@
Libs: -L${libdir} -l@POLKITQT-1_CORE_PCNAME@ -l@POLKITQT-1_GUI_PCNAME@ -l@POLKITQT-1_AGENT_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_AGENT_PCNAME@
Description: Convenience library for using polkit Agent with a Qt-styled API
Version: @POLKITQT-1_VERSION_STRING@
Requires: Qt@QT_MAJOR_VERSION@Core Qt@QT_MAJOR_VERSION@Gui
Libs: -L${libdir} -l@POLKITQT-1_AGENT_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_CORE_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API, non-GUI classes
Version: @POLKITQT-1_VERSION_STRING@
Requires: Qt@QT_MAJOR_VERSION@Core
Libs: -L${libdir} -l@POLKITQT-1_CORE_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@POLKITQT-1_INCLUDE_PATH@
Name: @POLKITQT-1_GUI_PCNAME@
Description: Convenience library for using polkit with a Qt-styled API, GUI classes
Version: @POLKITQT-1_VERSION_STRING@
Requires: Qt@QT_MAJOR_VERSION@Core Qt@QT_MAJOR_VERSION@Gui @POLKITQT-1_CORE_PCNAME@
Libs: -L${libdir} -l@POLKITQT-1_GUI_PCNAME@
Cflags: -I${includedir}
@@ -0,0 +1 @@
#cmakedefine01 HAVE_POLKIT_SYSTEM_BUS_NAME_GET_USER_SYNC
@@ -0,0 +1,53 @@
/*
SPDX-FileCopyrightText: 2007 Sebastian Trueg <trueg@kde.org>
SPDX-FileCopyrightText: 2009 Dario Freddi <drf@kde.org>
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#ifndef _POLKITQT1_VERSION_H_
#define _POLKITQT1_VERSION_H_
/// @brief PolkitQt-1 version as string at compile time.
#define POLKITQT1_VERSION_STRING "${POLKITQT-1_VERSION_STRING}"
/// @brief The major PolkitQt-1 version number at compile time
#define POLKITQT1_VERSION_MAJOR ${POLKITQT-1_VERSION_MAJOR}
/// @brief The minor PolkitQt-1 version number at compile time
#define POLKITQT1_VERSION_MINOR ${POLKITQT-1_VERSION_MINOR}
/// @brief The PolkitQt-1 patch version number at compile time
#define POLKITQT1_VERSION_PATCH ${POLKITQT-1_VERSION_PATCH}
/**
* \brief Create a unique number from the major, minor and release number of a %PolkitQt-1 version
*
* This function can be used for preprocessing.
*/
#define POLKITQT1_MAKE_VERSION( a,b,c ) (((a) << 16) | ((b) << 8) | (c))
/**
* \brief %PolkitQt-1 Version as a unique number at compile time
*
* This macro calculates the %PolkitQt-1 version into a number. It is mainly used
* through POLKITQT1_IS_VERSION in preprocessing.
*/
#define POLKITQT1_VERSION \
POLKITQT1_MAKE_VERSION(POLKITQT1_VERSION_MAJOR,POLKITQT1_VERSION_MINOR,POLKITQT1_VERSION_PATCH)
/**
* \brief Check if the %PolkitQt-1 version matches a certain version or is higher
*
* This macro is typically used to compile conditionally a part of code:
* \code
* #if POLKITQT1_IS_VERSION(2,1)
* // Code for PolkitQt-1 2.1
* #else
* // Code for PolkitQt-1 2.0
* #endif
* \endcode
*/
#define POLKITQT1_IS_VERSION(a,b,c) ( POLKITQT1_VERSION >= POLKITQT1_MAKE_VERSION(a,b,c) )
#endif
@@ -0,0 +1,16 @@
enable_testing()
add_executable(polkit-qt-test
test.cpp
)
target_link_libraries(polkit-qt-test
Qt${QT_MAJOR_VERSION}::Core
Qt${QT_MAJOR_VERSION}::DBus
Qt${QT_MAJOR_VERSION}::Test
Qt${QT_MAJOR_VERSION}::Widgets
${POLKITQT-1_CORE_PCNAME}
${POLKITQT-1_AGENT_PCNAME}
)
add_test(BaseTest ${CMAKE_CURRENT_BINARY_DIR}/polkit-qt-test)
@@ -0,0 +1,237 @@
#include "test.h"
#include <polkitqt1-authority.h>
#include <polkitqt1-agent-session.h>
#include <polkitqt1-details.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QSignalSpy>
using namespace PolkitQt1;
using namespace PolkitQt1::Agent;
void wait()
{
for (int i = 0; i < 100; i++) {
usleep(100);
QCoreApplication::processEvents();
}
}
void TestAuth::test_Auth_checkAuthorization()
{
// This needs the file org.qt.policykit.examples.policy from examples to be installed
UnixProcessSubject process(QCoreApplication::applicationPid());
Authority::Result result;
// Check if this method returns good authorization results
Authority *authority = Authority::instance();
result = authority->checkAuthorizationSync("org.qt.policykit.examples.kick", process, Authority::None);
QCOMPARE(result, Authority::No);
QVERIFY(!authority->hasError());
result = authority->checkAuthorizationSync("org.qt.policykit.examples.cry", process, Authority::None);
QCOMPARE(result, Authority::Yes);
QVERIFY(!authority->hasError());
result = authority->checkAuthorizationSync("org.qt.policykit.examples.bleed", process, Authority::None);
QCOMPARE(result, Authority::Challenge);
QVERIFY(!authority->hasError());
// Now we try async methods
QSignalSpy spy(authority, SIGNAL(checkAuthorizationFinished(PolkitQt1::Authority::Result)));
// Call asynchronous checkAuthorization
authority->checkAuthorization("org.qt.policykit.examples.kick", process, Authority::None);
// Give the polkit time to obtain the result and emit the signal with it
wait();
// Test if the signal was emitted
QCOMPARE(spy.count(), 1);
// Test the result
result = spy.takeFirst()[0].value<PolkitQt1::Authority::Result>();
QCOMPARE(result, Authority::No);
QVERIFY(!authority->hasError());
spy.clear();
// Let's test the cancellability
authority->checkAuthorization("org.qt.policykit.examples.kick", process, Authority::None);
authority->checkAuthorizationCancel();
// Wait and check if the signal arrieved
wait();
QCOMPARE(spy.count(), 0);
// Check if it can cancel user authentication dialog
authority->checkAuthorization("org.qt.policykit.examples.bleed", process, Authority::AllowUserInteraction);
// Show it for second
sleep(1);
// And now kill it
authority->checkAuthorizationCancel();
QVERIFY(!authority->hasError());
// But how to test if it was successful?
qWarning() << "You should see an authentication dialog for a short period.";
}
void TestAuth::test_Auth_enumerateActions()
{
// This needs the file org.qt.policykit.examples.policy from examples to be installed
ActionDescription::List list = Authority::instance()->enumerateActionsSync();
QVERIFY(!Authority::instance()->hasError());
// Check whether enumerateAction returns at least example actions
int count = 0;
Q_FOREACH(const ActionDescription &ad, list) {
if ((ad.actionId() == "org.qt.policykit.examples.kick") ||
(ad.actionId() == "org.qt.policykit.examples.cry") ||
(ad.actionId() == "org.qt.policykit.examples.bleed"))
count++;
}
QCOMPARE(count, 3);
// Test asynchronous version as well
list.clear();
count = 0;
QSignalSpy spy(Authority::instance(), SIGNAL(enumerateActionsFinished(PolkitQt1::ActionDescription::List)));
Authority::instance()->enumerateActions();
wait();
QCOMPARE(spy.count(), 1);
list = spy.takeFirst()[0].value<PolkitQt1::ActionDescription::List>();
QVERIFY(!Authority::instance()->hasError());
Q_FOREACH(const ActionDescription &ad, list) {
if ((ad.actionId() == "org.qt.policykit.examples.kick") ||
(ad.actionId() == "org.qt.policykit.examples.cry") ||
(ad.actionId() == "org.qt.policykit.examples.bleed"))
count++;
}
QCOMPARE(count, 3);
// Test cancelling the enumeration
spy.clear();
Authority::instance()->enumerateActions();
Authority::instance()->enumerateActionsCancel();
wait();
QCOMPARE(spy.count(), 0);
QVERIFY(!Authority::instance()->hasError());
}
void TestAuth::test_Identity()
{
// Get real name and id of current user and group
struct passwd *userinfo = getpwuid(getuid());
QString userName = userinfo->pw_name;
unsigned int userId = userinfo->pw_uid;
unsigned int groupId = userinfo->pw_gid;
// Try to create UnixUser from username
UnixUserIdentity user(userName);
QVERIFY(user.identity());
// Create generic Identity from UnixUser via string representation
Identity id = Identity::fromString(user.toString());
// Compare obtained uid with real uid
QCOMPARE(id.toUnixUserIdentity().uid(), userId);
// Create generic Identity from UnixGroup via string representation
UnixGroupIdentity group(groupId);
QVERIFY(group.identity());
id = Identity::fromString(group.toString());
QCOMPARE(id.toUnixGroupIdentity().gid(), groupId);
// Test setting gid to another value
group.setGid(9999U);
id = Identity::fromString(group.toString());
QCOMPARE(id.toUnixGroupIdentity().gid(), 9999U);
}
void TestAuth::test_Authority()
{
Authority *authority = Authority::instance();
QVERIFY(authority);
QVERIFY(!authority->hasError());
// Verify emitting of the signals
QSignalSpy spy(authority, SIGNAL(consoleKitDBChanged()));
QDBusMessage msg = QDBusMessage::createMethodCall("org.freedesktop.ConsoleKit",
"/org/freedesktop/ConsoleKit/Manager",
"org.freedesktop.ConsoleKit.Manager",
"OpenSession");
QDBusMessage reply = QDBusConnection::systemBus().call(msg);
QString cookie;
cookie = reply.arguments()[0].value<QString>();
msg = QDBusMessage::createMethodCall("org.freedesktop.ConsoleKit",
"/org/freedesktop/ConsoleKit/Manager",
"org.freedesktop.ConsoleKit.Manager",
"CloseSession");
msg.setArguments(QList<QVariant> () << cookie);
QDBusConnection::systemBus().call(msg);
// FIXME: Emitting consoleKitDBChanged is not working now
qWarning() << "Emitting consoleKitDBChanged is not working now, test will be skipped";
//QVERIFY(spy.count() > 0);
QVERIFY(!authority->hasError());
// configChanged signal from authority requires changing some policy files
// and it would require user interaction (typing the password)
// so this is not covered by this test
}
void TestAuth::test_Subject()
{
// Get pid of this application
qint64 pid = QCoreApplication::applicationPid();
// Create unix process for it
UnixProcessSubject *process = new UnixProcessSubject(pid);
// Test if pid doesn't differ
QCOMPARE(process->pid(), pid);
// Serialize and deserialize subject
//Subject *subject = Subject::fromString(process->toString());
// and try it
//QCOMPARE(((UnixProcess *) subject)->pid(), pid);
delete process;
}
void TestAuth::test_Session()
{
/*
UnixUser user(getuid());
Session *session = new Session(&user, "/org/freedesktop/ConsoleKit/Session2");
QSignalSpy spy_completed(session, SIGNAL(completed(bool)));
QSignalSpy spy_request(session, SIGNAL(request(QString,bool)));
QSignalSpy spy_error(session, SIGNAL(showError(QString)));
QSignalSpy spy_info(session, SIGNAL(showInfo(QString)));
session->initiate();
session->response("aaa");
// Canceling should emit the "completed" signal
session->cancel();
QCOMPARE(spy_completed.count(), 1);
//UnixProcess *process = new UnixProcess(QCoreApplication::applicationPid());
//Authority::instance()->checkAuthorization("org.qt.policykit.examples.kick", process, Authority::None);
qDebug() << "COMPLETED:" << spy_completed.count();
qDebug() << "REQUEST:" << spy_request.count();
qDebug() << "ERROR:" << spy_error.count();
qDebug() << "INFO:" << spy_info.count();
*/
}
void TestAuth::test_Details()
{
Details details;
details.insert("1", "aaa");
details.insert("2", "bbb");
details.insert("3", "ccc");
details.insert("4", "ddd");
QCOMPARE(details.lookup("1"), QString("aaa"));
QCOMPARE(details.lookup("2"), QString("bbb"));
QCOMPARE(details.lookup("3"), QString("ccc"));
QCOMPARE(details.lookup("4"), QString("ddd"));
QList<QString> list = details.keys();
QVERIFY(list.contains("1"));
QVERIFY(list.contains("2"));
QVERIFY(list.contains("3"));
QVERIFY(list.contains("4"));
}
QTEST_MAIN(TestAuth)

Some files were not shown because too many files have changed in this diff Show More