Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ qrc_resources.cpp
repoeditor/.qtc_clangd/**
repoeditor/bin/**
repoeditor/build/**
result
result/**
sudo/*.o
sudo/moc*.*
sudo/octopi-sudo
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,21 @@ $ make
$ sudo make install
```

### Steps to build Octopi source code (Nix)

For development in a clean, isolated environment without installing dependencies system-wide, you can use Nix. This requires [Nix with flakes enabled](https://nixos.wiki/wiki/Flakes).

```
$ cd octopi
$ nix develop # or use direnv
$ mkdir -p build && cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release
$ make -j$(nproc)
$ ./octopi
```

The Nix environment provides all dependencies (`qt6`, `cmake`, `vala`, etc.) and builds `alpm_octopi_utils` and `qt-sudo` automatically. You can then follow the standard CMake or qmake build instructions above. The environment sets `OCTOPI_ALLOWED_PATHS` to allow running from the build directory.

### To run Octopi

```
Expand Down
3 changes: 2 additions & 1 deletion cachecleaner/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <QLocale>
#include <QLibraryInfo>
#include <QtGui>
#include <QStandardPaths>

int main( int argc, char *argv[] )
{
Expand Down Expand Up @@ -70,7 +71,7 @@ int main( int argc, char *argv[] )
return (-4);
}

if (!QFile::exists(ctn_OCTOPISUDO))
if (QStandardPaths::findExecutable(QStringLiteral("qt-sudo")).isEmpty())
{
qDebug() << "Aborting cache-cleaner as 'octopi-sudo' binary could not be found! [" << ctn_OCTOPISUDO << "]";
return (-5);
Expand Down
61 changes: 61 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

89 changes: 89 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
# Maintenance: Run 'nix flake update' to update nixpkgs. For alpm_octopi_utils and qt-sudo,
# check GitHub for new commits/tags and update rev + sha256 (get hash from error output).
description = "Octopi Nix development environment";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = {
self,
nixpkgs,
flake-utils,
}:
flake-utils.lib.eachDefaultSystem (
system: let
pkgs = nixpkgs.legacyPackages.${system};

alpm_octopi_utils = pkgs.stdenv.mkDerivation {
pname = "alpm_octopi_utils";
version = "unstable-2024-12-27";

src = pkgs.fetchFromGitHub {
owner = "aarnt";
repo = "alpm_octopi_utils";
rev = "0ed2a8bd6b869f40683cf7a79727dc64d7da274e";
sha256 = "sha256-TxjXtdhp2BqkGDVYnyhQ5mccU0MDndFfAZMuBQRVf1c=";
};

nativeBuildInputs = with pkgs; [cmake vala pkg-config];
buildInputs = with pkgs; [pacman glib libarchive];
};

qt-sudo = pkgs.stdenv.mkDerivation {
pname = "qt-sudo";
version = "2.2.0";

src = pkgs.fetchFromGitHub {
owner = "aarnt";
repo = "qt-sudo";
rev = "v2.2.0";
sha256 = "sha256-bvRQEOHMnmAr95ecHkVD0JWGiCMTCx51ncMwrS3/wu0=";
};

nativeBuildInputs = with pkgs; [qt6.wrapQtAppsHook qt6.qmake qt6.qttools];
buildInputs = with pkgs; [qt6.qtbase];

postConfigure = ''
substituteInPlace Makefile \
--replace-quiet "${pkgs.qt6.qtbase}/bin/lrelease" "${pkgs.qt6.qttools}/bin/lrelease"
'';
};
in {
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
alpm_octopi_utils
cmake
gcc
git
glib
gnumake
libarchive
lxqt.qtermwidget
pacman
pipewire
pkg-config
qt-sudo
qt6.qmake
qt6.qt5compat
qt6.qtbase
qt6.qtmultimedia
qt6.qttools
qt6.wrapQtAppsHook
sudo
vala
];

shellHook = ''
export OCTOPI_ALLOWED_PATHS="/usr/bin:$PWD/build"
export LD_LIBRARY_PATH="${pkgs.pipewire}/lib:$LD_LIBRARY_PATH"
'';

QT_QPA_PLATFORM_PLUGIN_PATH = "${pkgs.qt6.qtbase}/${pkgs.qt6.qtbase.qtPluginPrefix}";
QT_PLUGIN_PATH = "${pkgs.qt6.qtbase}/${pkgs.qt6.qtbase.qtPluginPrefix}";
};
}
);
}
3 changes: 2 additions & 1 deletion notifier/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <QtGui>
#include <QMessageBox>
#include <QDebug>
#include <QStandardPaths>

#define NO_GTK_STYLE

Expand Down Expand Up @@ -65,7 +66,7 @@ int main(int argc, char *argv[])
return (-3);
}

if (!QFile::exists(ctn_OCTOPISUDO))
if (QStandardPaths::findExecutable(QStringLiteral("qt-sudo")).isEmpty())
{
qDebug() << "Aborting notifier as 'qt-sudo' binary could not be found! [" << ctn_OCTOPISUDO << "]";
return (-4);
Expand Down
3 changes: 2 additions & 1 deletion repoeditor/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <QLocale>
#include <QLibraryInfo>
#include <QtGui>
#include <QStandardPaths>

int main( int argc, char *argv[] )
{
Expand Down Expand Up @@ -62,7 +63,7 @@ int main( int argc, char *argv[] )
return (-2);
}

if (!QFile::exists(ctn_OCTOPISUDO))
if (QStandardPaths::findExecutable(QStringLiteral("qt-sudo")).isEmpty())
{
qDebug() << "Aborting Repository Editor as 'octopi-sudo' binary could not be found! [" << ctn_OCTOPISUDO << "]";
return (-3);
Expand Down
2 changes: 1 addition & 1 deletion src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ const int ctn_RUN_IN_TERMINAL(328);
const QString ctn_NO_SU_COMMAND(QStringLiteral("none"));
const QString ctn_ROOT_SH(QStringLiteral("/bin/sh -c "));

const QString ctn_OCTOPISUDO(QStringLiteral("/usr/local/bin/qt-sudo"));
const QString ctn_OCTOPISUDO(QStringLiteral("qt-sudo"));
const QString ctn_OCTOPISUDO_PARAMS(QStringLiteral("-d"));

const QString ctn_KDE_DESKTOP(QStringLiteral("kwin"));
Expand Down
3 changes: 2 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "QtSolutions/qtsingleapplication.h"
#include <QtGui>
#include <QMessageBox>
#include <QStandardPaths>

int main(int argc, char *argv[])
{
Expand All @@ -42,7 +43,7 @@ int main(int argc, char *argv[])
return (-2);
}

if (!QFile::exists(ctn_OCTOPISUDO))
if (QStandardPaths::findExecutable(QStringLiteral("qt-sudo")).isEmpty())
{
qDebug() << "Aborting octopi as 'qt-sudo' binary could not be found! [" << ctn_OCTOPISUDO << "]";
return (-3);
Expand Down
35 changes: 28 additions & 7 deletions src/unixcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <QtNetwork>
#include <QFileInfo>
#include <QtGlobal>
#include <QStandardPaths>

/*
* Collection of methods to execute many Unix commands
Expand Down Expand Up @@ -701,14 +702,19 @@ bool UnixCommand::doInternetPingTest()
}

/*
* Checks if the given executable is available somewhere in the system
* Finds the given executable in PATH
*/
QString UnixCommand::findExecutable(const QString& exeName)
{
return QStandardPaths::findExecutable(exeName);
}

/*
* Checks if the given executable is available
*/
bool UnixCommand::hasTheExecutable(const QString& exeName)
{
if (exeName == ctn_OCTOPISUDO)
return (QFile::exists(ctn_OCTOPISUDO));
else
return (QFile::exists(QStringLiteral("/usr/bin/") + exeName));
return !findExecutable(exeName).isEmpty();
}

/*
Expand Down Expand Up @@ -1180,10 +1186,13 @@ bool UnixCommand::isAppRunning(const QString &appName, bool justOneInstance)
}

/*
* Checks if Octopi/Octopi-notifier, cache-cleaner, etc is being executed from /usr/bin
* Checks if Octopi/Octopi-notifier, cache-cleaner, etc is being executed from allowed paths
* Allowed paths can be configured via OCTOPI_ALLOWED_PATHS environment variable (colon-separated)
* Default: /usr/bin only (security: only system-installed binaries are trusted)
* Development: set OCTOPI_ALLOWED_PATHS=/usr/bin:/path/to/your/build to allow running from build dir
*/
bool UnixCommand::isOctoToolRunning(const QString &octoToolName)
{
{
char exePath[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", exePath, sizeof(exePath));
if (count == -1)
Expand All @@ -1195,6 +1204,18 @@ bool UnixCommand::isOctoToolRunning(const QString &octoToolName)
QString path = QString::fromUtf8(exePath, count);
QFileInfo fi(path);

QByteArray allowedPathsEnv = qgetenv("OCTOPI_ALLOWED_PATHS");
if (!allowedPathsEnv.isEmpty())
{
QStringList allowedPaths = QString::fromUtf8(allowedPathsEnv).split(QLatin1Char(':'), Qt::SkipEmptyParts);
for (const QString &allowedPath : allowedPaths)
{
if (fi.absoluteFilePath() == allowedPath + QLatin1Char('/') + octoToolName)
return true;
}
return false;
}

return (fi.absoluteFilePath() == QLatin1String("/usr/bin/") + octoToolName);
}

Expand Down
1 change: 1 addition & 0 deletions src/unixcommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class UnixCommand : public QObject{
static bool doInternetPingTest();
static bool isTextFile(QString fileName); //fileName is Path + Name

static QString findExecutable( const QString& exeName );
static bool hasTheExecutable( const QString& exeName );
static bool isAppRunning(const QString &appName, bool justOneInstance = false);

Expand Down
21 changes: 12 additions & 9 deletions src/wmhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <QApplication>
#include <QProcess>
#include <QMessageBox>
#include <QStandardPaths>
#include <QFile>

/*
* This class is a helper to abstract some Desktop Environments services for Octopi.
Expand Down Expand Up @@ -226,7 +228,8 @@ QString WMHelper::getXFCEEditor()
*/
QString WMHelper::getOctopiSudoCommand()
{
QString result = ctn_OCTOPISUDO;
QString result = UnixCommand::findExecutable(ctn_OCTOPISUDO);
result += QStringLiteral(" ");
result += ctn_OCTOPISUDO_PARAMS;

return result;
Expand All @@ -237,27 +240,27 @@ QString WMHelper::getOctopiSudoCommand()
*/
QString WMHelper::getSUCommand()
{
QString result(ctn_NO_SU_COMMAND);
QString qtSudoPath = UnixCommand::findExecutable(ctn_OCTOPISUDO);

if (QFile::exists(ctn_OCTOPISUDO)){
result = ctn_OCTOPISUDO;
if (!qtSudoPath.isEmpty() && QFile::exists(qtSudoPath)){
return qtSudoPath;
}

return result;
return ctn_NO_SU_COMMAND;
}

/*
* The generic SU get method. It retrieves the SU tool name you have installed in your system!
*/
QString WMHelper::getSUTool()
{
QString result(QLatin1String(""));
QString qtSudoPath = UnixCommand::findExecutable(ctn_OCTOPISUDO);

if (QFile::exists(ctn_OCTOPISUDO)){
return ctn_OCTOPISUDO;
if (!qtSudoPath.isEmpty() && QFile::exists(qtSudoPath)){
return qtSudoPath;
}

return result;
return QLatin1String("");
}

/*
Expand Down