「Qtの基礎 - 管理者権限」の版間の差分
47行目: | 47行目: | ||
<br> | <br> | ||
<u>次に、<code>cmake</code>コマンド、または、パッケージ管理システムからインストールした<code>qmake-qt5</code>を使用して、Qtプロジェクトをビルドする必要がある。</u><br> | <u>次に、<code>cmake</code>コマンド、または、パッケージ管理システムからインストールした<code>qmake-qt5</code>を使用して、Qtプロジェクトをビルドする必要がある。</u><br> | ||
qmake-qt5 | # qmakeコマンドを使用する場合 | ||
mkdir build && cd build | |||
qmake-qt5 <Qtプロジェクトファイル名>.pro または qmake <Qtプロジェクトファイル名>.pro | |||
make -j $(nproc) | |||
make install | |||
# cmakeコマンドを使用する場合 | |||
mkdir build && cd build | |||
cmake .. | |||
make -j $(nproc) | |||
make install | |||
<br><br> | |||
== PolKit-Qt-1を使用した開発例 == | |||
==== 開発例に挙げるソフトウェア ==== | |||
実行ファイルの画面にあるボタンを押下する時、任意のディレクトリにroot権限でテキストファイルを作成または書き込みするソフトウェアを例に挙げる。<br> | |||
<br> | |||
開発するプロジェクトを以下に示す。<br> | |||
* Sample | |||
*: 主となるGUIソフトウェア | |||
* SampleHelper | |||
*: 管理者権限でファイル操作を行うヘルパー実行ファイル | |||
* PolKitポリシーファイル | |||
*: ファイルの場所 : /usr/share/polkit-1/actions | |||
*: .policy拡張子 | |||
*: ファイル名を、org.qt.policykit.examples.policyファイルとする。 | |||
* D-Busインターフェースファイル | |||
*: ファイルの場所 : /usr/share/dbus-1/interfaces | |||
*: .xml拡張子 | |||
*: ファイル名を、org.qt.policykit.examples.xmlファイルとする。 | |||
* D-Busポリシーファイル | |||
*: ファイルの場所 : | |||
*:: 優先順位 1 : /etc/dbus-1/system-local.conf (新規作成) | |||
*:: 優先順位 2 : /etc/dbus-1/system.d | |||
*:: 優先順位 3 : /usr/share/dbus-1/system.d | |||
*: .conf拡張子 | |||
*: ファイル名を、org.qt.policykit.examples.confファイルとする。 | |||
* D-Busサービスファイル(D-Busアクティベーションファイル) | |||
*: ファイルの場所 : /usr/share/dbus-1/system-services | |||
*: .service拡張子 | |||
*: ファイル名を、org.qt.policykit.examples.serviceファイルとする。 | |||
<br> | |||
==== ヘルパー実行ファイルの開発 ==== | |||
# SampleHelper.proファイル | |||
QT -= gui | |||
QT += core dbus | |||
CONFIG += c++17 | |||
CONFIG -= app_bundle | |||
# PolKit-Qt-1 Install directory | |||
isEmpty(polqt_dir) { | |||
polqt_dir = /usr | |||
} | |||
unix:!macx: LIBS += \ | |||
-L$${polqt_dir}/lib64 -lpolkit-qt5-core-1 \ | |||
-L$${polqt_dir}/lib64 -lpolkit-qt5-agent-1 \ | |||
-L$${polqt_dir}/lib64 -lpolkit-qt5-gui-1 | |||
INCLUDEPATH += \ | |||
$${polqt_dir}/include | |||
SOURCES += \ | |||
SampleHelper.cpp \ | |||
SamplesAdaptor.cpp \ | |||
main.cpp | |||
HEADERS += \ | |||
SampleHelper.h \ | |||
SamplesAdaptor.h | |||
# Config Install directory | |||
isEmpty(prefix) { | |||
prefix = $${PWD}/$${TARGET} | |||
} | |||
target.path = $${prefix} | |||
INSTALLS += target | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// main.cppファイル | |||
#include <QCoreApplication> | |||
#include "SampleHelper.h" | |||
int main(int argc, char *argv[]) | |||
{ | |||
QCoreApplication a(argc, argv); | |||
SampleHelper helper(argc, argv); | |||
return a.exec(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// SampleHelper.hファイル | |||
#ifndef SAMPLE_HELPER_H | |||
#define SAMPLE_HELPER_H | |||
#include <QDBusContext> | |||
#include <QDBusMessage> | |||
#include <QCoreApplication> | |||
class SampleHelper : public QCoreApplication, protected QDBusContext | |||
{ | |||
Q_OBJECT | |||
Q_CLASSINFO("D-Bus Interface", "org.qt.policykit.examples") | |||
public: | |||
SampleHelper(int &argc, char **argv); | |||
~SampleHelper() override; | |||
public Q_SLOTS: | |||
bool write(const QString &action); | |||
bool writeValue(const QString &action); | |||
}; | |||
#endif | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// SampleHelper.cppファイル | |||
#include "SampleHelper.h" | |||
#include "SamplesAdaptor.h" | |||
#include <polkit-qt5-1/polkitqt1-authority.h> | |||
#include <QDBusConnection> | |||
#include <QTimer> | |||
#include <QDebug> | |||
#include <QFile> | |||
#define MINUTE 60000 | |||
using namespace PolkitQt1; | |||
SampleHelper::SampleHelper(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())); | |||
} | |||
SampleHelper::~SampleHelper() | |||
{ | |||
qDebug() << "Destroying Helper"; | |||
} | |||
bool SampleHelper::write(const QString &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; | |||
PolkitQt1::SystemBusNameSubject subject(message().service()); | |||
result = Authority::instance()->checkAuthorizationSync("org.qt.policykit.examples.write", subject, Authority::AllowUserInteraction); | |||
if (result == Authority::Yes) | |||
{ // Caller is authorized so we can perform the action | |||
return writeValue(action); | |||
} | |||
else | |||
{ // Caller is not authorized so the action can't be performed | |||
return false; | |||
} | |||
} | |||
bool SampleHelper::writeValue(const QString &action) | |||
{ | |||
// This action must be authorized first. It will set the implicit authorization for the Shout action by editing the .policy file. | |||
QFileInfo FileInfo("/opt/sample.txt"); | |||
QFile File("/opt/sample.txt"); | |||
if(!File.open(QIODevice::WriteOnly)) | |||
{ | |||
QString strErrMsg = "File(" + FileInfo.fileName() + ") Open Error: " + File.errorString(); | |||
qDebug() << strErrMsg; | |||
return -1; | |||
} | |||
QTextStream OutStream(&File); | |||
OutStream << "foo bar"; | |||
File.close(); | |||
return true; | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
ここで、SamplesAdaptor.cppファイル、および、SamplesAdaptor.hファイルは、Qt Creator付属の<code>qdbusxml2cpp</code>コマンドを実行することにより自動生成される。<br> | |||
自動生成された上記の2つのファイルをインクルードすることにより、ヘルパー実行ファイルが完成する。<br> | |||
# mocファイルはインクルードしない場合 | |||
qdbusxml2cpp -a <自動生成するヘルパークラス名> -i <対象となるクラスを記述しているヘッダファイル> -l <対象となるクラス名> <D-Busインターフェースファイルのパス> | |||
例. qdbusxml2cpp -a SamplesAdaptor -i SampleHelper.h -l SampleHelper org.qt.policykit.examples.xml | |||
# mocファイルもインクルードする場合 | |||
qdbusxml2cpp -m -a <自動生成するヘルパークラス名> -i <対象となるクラスを記述しているヘッダファイル> -l <対象となるクラス名> <D-Busインターフェースファイルのパス> | |||
例. qdbusxml2cpp -m -a SamplesAdaptor -i SampleHelper.h -l SampleHelper org.qt.policykit.examples.xml | |||
<br> | |||
自動生成されたヘルパーファイルを、Qtプロジェクト等に追加する。<br> | |||
<br> | |||
最後に、<code>cmake</code>コマンド、または、パッケージ管理システムからインストールした<code>qmake-qt5</code>を使用して、Qtプロジェクトをビルドする。<br> | |||
# qmakeコマンドを使用する場合 | |||
mkdir build && cd build | |||
qmake-qt5 <ヘルパープロジェクトファイル名>.pro または qmake <ヘルパープロジェクトファイル名>.pro | |||
make -j $(nproc) | |||
make install | |||
# cmakeコマンドを使用する場合 | |||
mkdir build && cd build | |||
cmake .. | |||
make -j $(nproc) | make -j $(nproc) | ||
make install | make install |
2022年11月30日 (水) 01:52時点における版
概要
PolKit-Qt-1
PolKit-Qt-1のインストール
- パッケージ管理システムからインストールする場合
sudo zypper install libpolkit-qt5-1-devel
- ソースコードからインストールする場合
- PolKit-Qt-1のビルドに必要なライブラリをインストールする。
sudo zypper install pkg-config polkit-devel \
libQt5Core-devel libQt5Core-private-headers-devel libQt5Widgets-devel libQt5Widgets-private-headers-devel \
libQt5DBus-devel libQt5DBus-private-headers-devel libQt5Xml-devel
- PolKit-Qt-1のGithubまたは公式のGitLabにアクセスして、ソースコードをダウンロードする。
- ダウンロードしたファイルを解凍する。
tar xf polkit-qt-1-<バージョン>.tar.gz
cd polkit-qt-1-<バージョン>.tar.gz
- または、
git clone
コマンドを実行して、ソースコードをダウンロードする。 git clone https://invent.kde.org/libraries/polkit-qt-1.git
cd polkit-qt-1
- PolKit-Qt-1をインストールする。
cmake -DCMAKE_INSTALL_PREFIX=<PolKit-Qt-1のインストールディレクトリ> -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=TRUE \
-DSYSCONF_INSTALL_DIR=<PolKit-Qt-1のインストールディレクトリ> ..
make -j $(nproc)
make install
~/.profileファイル等に、環境変数を追記する。
vi ~/.profile
# ~/.profile export LD_LIBRARY_PATH="/<PolKit-Qt-1のインストールディレクトリ>/lib64:$LD_LIBRARY_PATH" export PKG_CONFIG_PATH="/<PolKit-Qt-1のインストールディレクトリ>/lib64/pkgconfig:${PKG_CONFIG_PATH}"
※注意
Qt Creator(Qt Creatorに付属しているQtライブラリ)とPolKit-Qt-1を使用してビルドした場合、生成された実行ファイルおよびライブラリはQt Creatorに付属しているQtライブラリを指すことになる。
つまり、Qt Creatorに付属しているQtライブラリを環境変数PKG_CONFIG_PATH
等に追加しなければ生成されたファイルが動作しないということである。
この動作を変更する場合(生成された実行ファイルおよびライブラリを/usrディレクトリにあるQtライブラリを指すようにする場合)は、
パッケージ管理システムから、少なくとも、Qt5Core、Qt5GUI、Qt5DBusをインストールする必要がある。
sudo zypper install libQt5Core-devel libQt5Gui-devel libQt5DBus-devel \ libqt5-qtbase-common-devel vulkan-devel vulkan-headers # 依存関係は自動的にインストールされる
次に、cmake
コマンド、または、パッケージ管理システムからインストールしたqmake-qt5
を使用して、Qtプロジェクトをビルドする必要がある。
# qmakeコマンドを使用する場合 mkdir build && cd build qmake-qt5 <Qtプロジェクトファイル名>.pro または qmake <Qtプロジェクトファイル名>.pro make -j $(nproc) make install # cmakeコマンドを使用する場合 mkdir build && cd build cmake .. make -j $(nproc) make install
PolKit-Qt-1を使用した開発例
開発例に挙げるソフトウェア
実行ファイルの画面にあるボタンを押下する時、任意のディレクトリにroot権限でテキストファイルを作成または書き込みするソフトウェアを例に挙げる。
開発するプロジェクトを以下に示す。
- Sample
- 主となるGUIソフトウェア
- SampleHelper
- 管理者権限でファイル操作を行うヘルパー実行ファイル
- PolKitポリシーファイル
- ファイルの場所 : /usr/share/polkit-1/actions
- .policy拡張子
- ファイル名を、org.qt.policykit.examples.policyファイルとする。
- D-Busインターフェースファイル
- ファイルの場所 : /usr/share/dbus-1/interfaces
- .xml拡張子
- ファイル名を、org.qt.policykit.examples.xmlファイルとする。
- D-Busポリシーファイル
- ファイルの場所 :
- 優先順位 1 : /etc/dbus-1/system-local.conf (新規作成)
- 優先順位 2 : /etc/dbus-1/system.d
- 優先順位 3 : /usr/share/dbus-1/system.d
- .conf拡張子
- ファイル名を、org.qt.policykit.examples.confファイルとする。
- ファイルの場所 :
- D-Busサービスファイル(D-Busアクティベーションファイル)
- ファイルの場所 : /usr/share/dbus-1/system-services
- .service拡張子
- ファイル名を、org.qt.policykit.examples.serviceファイルとする。
ヘルパー実行ファイルの開発
# SampleHelper.proファイル QT -= gui QT += core dbus CONFIG += c++17 CONFIG -= app_bundle # PolKit-Qt-1 Install directory isEmpty(polqt_dir) { polqt_dir = /usr } unix:!macx: LIBS += \ -L$${polqt_dir}/lib64 -lpolkit-qt5-core-1 \ -L$${polqt_dir}/lib64 -lpolkit-qt5-agent-1 \ -L$${polqt_dir}/lib64 -lpolkit-qt5-gui-1 INCLUDEPATH += \ $${polqt_dir}/include SOURCES += \ SampleHelper.cpp \ SamplesAdaptor.cpp \ main.cpp HEADERS += \ SampleHelper.h \ SamplesAdaptor.h # Config Install directory isEmpty(prefix) { prefix = $${PWD}/$${TARGET} } target.path = $${prefix} INSTALLS += target
// main.cppファイル
#include <QCoreApplication>
#include "SampleHelper.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
SampleHelper helper(argc, argv);
return a.exec();
}
// SampleHelper.hファイル
#ifndef SAMPLE_HELPER_H
#define SAMPLE_HELPER_H
#include <QDBusContext>
#include <QDBusMessage>
#include <QCoreApplication>
class SampleHelper : public QCoreApplication, protected QDBusContext
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.qt.policykit.examples")
public:
SampleHelper(int &argc, char **argv);
~SampleHelper() override;
public Q_SLOTS:
bool write(const QString &action);
bool writeValue(const QString &action);
};
#endif
// SampleHelper.cppファイル
#include "SampleHelper.h"
#include "SamplesAdaptor.h"
#include <polkit-qt5-1/polkitqt1-authority.h>
#include <QDBusConnection>
#include <QTimer>
#include <QDebug>
#include <QFile>
#define MINUTE 60000
using namespace PolkitQt1;
SampleHelper::SampleHelper(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()));
}
SampleHelper::~SampleHelper()
{
qDebug() << "Destroying Helper";
}
bool SampleHelper::write(const QString &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;
PolkitQt1::SystemBusNameSubject subject(message().service());
result = Authority::instance()->checkAuthorizationSync("org.qt.policykit.examples.write", subject, Authority::AllowUserInteraction);
if (result == Authority::Yes)
{ // Caller is authorized so we can perform the action
return writeValue(action);
}
else
{ // Caller is not authorized so the action can't be performed
return false;
}
}
bool SampleHelper::writeValue(const QString &action)
{
// This action must be authorized first. It will set the implicit authorization for the Shout action by editing the .policy file.
QFileInfo FileInfo("/opt/sample.txt");
QFile File("/opt/sample.txt");
if(!File.open(QIODevice::WriteOnly))
{
QString strErrMsg = "File(" + FileInfo.fileName() + ") Open Error: " + File.errorString();
qDebug() << strErrMsg;
return -1;
}
QTextStream OutStream(&File);
OutStream << "foo bar";
File.close();
return true;
}
ここで、SamplesAdaptor.cppファイル、および、SamplesAdaptor.hファイルは、Qt Creator付属のqdbusxml2cpp
コマンドを実行することにより自動生成される。
自動生成された上記の2つのファイルをインクルードすることにより、ヘルパー実行ファイルが完成する。
# mocファイルはインクルードしない場合 qdbusxml2cpp -a <自動生成するヘルパークラス名> -i <対象となるクラスを記述しているヘッダファイル> -l <対象となるクラス名> <D-Busインターフェースファイルのパス> 例. qdbusxml2cpp -a SamplesAdaptor -i SampleHelper.h -l SampleHelper org.qt.policykit.examples.xml # mocファイルもインクルードする場合 qdbusxml2cpp -m -a <自動生成するヘルパークラス名> -i <対象となるクラスを記述しているヘッダファイル> -l <対象となるクラス名> <D-Busインターフェースファイルのパス> 例. qdbusxml2cpp -m -a SamplesAdaptor -i SampleHelper.h -l SampleHelper org.qt.policykit.examples.xml
自動生成されたヘルパーファイルを、Qtプロジェクト等に追加する。
最後に、cmake
コマンド、または、パッケージ管理システムからインストールしたqmake-qt5
を使用して、Qtプロジェクトをビルドする。
# qmakeコマンドを使用する場合 mkdir build && cd build qmake-qt5 <ヘルパープロジェクトファイル名>.pro または qmake <ヘルパープロジェクトファイル名>.pro make -j $(nproc) make install # cmakeコマンドを使用する場合 mkdir build && cd build cmake .. make -j $(nproc) make install