summaryrefslogtreecommitdiffstats
path: root/src/pwgui
diff options
context:
space:
mode:
authorSimon Rettberg2014-02-06 20:39:57 +0100
committerSimon Rettberg2014-02-06 20:39:57 +0100
commit909bab46a61d358d948c2784e48e3c144ade9c1a (patch)
treecbb4e9a9f659f5907371cfc66836ca9a0b23d6c8 /src/pwgui
parentRemove silly debug message boxes (diff)
downloadprintergui-909bab46a61d358d948c2784e48e3c144ade9c1a.tar.gz
printergui-909bab46a61d358d948c2784e48e3c144ade9c1a.tar.xz
printergui-909bab46a61d358d948c2784e48e3c144ade9c1a.zip
Lots of changes: Two binaries (selection/pw auth), qmake -> cmake, gitignore, more error handling
1. We now have two binaries: One pops up when the print job comes in so you can select the printer, duplex, copies, etc... The other one pops up when used as a backend and handles authentication by asking for username and password (WORK IN PROGRESS!). This is to better handle things like smb printing 2. We use cmake everywhere, and now that we want two binaries it made sense to switch. 3. Gitignore, well, what to say 4. Show an error message when calling ghostscript for grayscale conversion failed, insted of just doing nothing and not even closing the GUI. 5. Keep the printergui open for a few seconds after printing, but hide the window. Later we want to check in the password gui if the printergui is open to make sure we really should run, and maybe even exchange some information.
Diffstat (limited to 'src/pwgui')
-rw-r--r--src/pwgui/config.h5
-rw-r--r--src/pwgui/main.cpp135
-rw-r--r--src/pwgui/pwgui.cpp59
-rw-r--r--src/pwgui/pwgui.h31
-rw-r--r--src/pwgui/pwgui.ui145
5 files changed, 375 insertions, 0 deletions
diff --git a/src/pwgui/config.h b/src/pwgui/config.h
new file mode 100644
index 0000000..a06d9db
--- /dev/null
+++ b/src/pwgui/config.h
@@ -0,0 +1,5 @@
+// This is where pwgui will look for backends.
+// Works exactly like /usr/lib/cups/backend, but don't
+// use that as it would cause pwgui invoking itself again...
+#define BACKEND_PATH "/opt/openslx/cups/backend"
+
diff --git a/src/pwgui/main.cpp b/src/pwgui/main.cpp
new file mode 100644
index 0000000..d75f280
--- /dev/null
+++ b/src/pwgui/main.cpp
@@ -0,0 +1,135 @@
+#include "pwgui.h"
+#include "config.h"
+#include <QApplication>
+#include <cups/backend.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define NAMELEN 400
+#define BUFLEN 1000
+
+static int run_backend(char *backend, char *uri, char *jobid, char *user, char *title, char *copies, char *options, char *file, char *password);
+
+int main(int argc, char *argv[])
+{
+ char tmpfile[NAMELEN];
+ char device[NAMELEN];
+ char backend[NAMELEN];
+ int spoolres;
+
+ // Pretty much what smbspool does, but in a generalized way
+ if (argc > 2 && strstr(argv[0], ":/") == NULL && strstr(argv[1], ":/") != NULL) {
+ argv++;
+ argc--;
+ }
+
+ // First check parameter count
+ if (argc != 6 && argc != 7) {
+ fputs("ERROR: Invalid number of arguments passed.\n", stderr);
+ return CUPS_BACKEND_FAILED;
+ }
+
+ if (argc == 6) {
+ // Data comes from stdin, save...
+ snprintf(tmpfile, NAMELEN, "/tmp/print-%s-%d-%s-%d", argv[1], (int)time(NULL), argv[2], (int)getpid());
+ int fh = open(tmpfile, O_CREAT | O_WRONLY | O_TRUNC, 0600);
+ if (fh < 0) {
+ fprintf(stderr, "ERROR: Could not open %s for writing..\n", tmpfile);
+ return CUPS_BACKEND_FAILED;
+ }
+ char buffer[BUFLEN];
+ size_t bytes, ret;
+ while (!feof(stdin)) {
+ bytes = fread(buffer, BUFLEN, 1, stdin);
+ if (bytes == 0) break;
+ if ((ret = write(fh, buffer, bytes)) != bytes) {
+ fprintf(stderr, "ERROR: Could not write %d bytes to %s (wrote %d)\n", (int)bytes, tmpfile, (int)ret);
+ remove(tmpfile);
+ return CUPS_BACKEND_FAILED;
+ }
+ }
+ close(fh);
+ //
+ } else {
+ // File given, check if file exists
+ snprintf(tmpfile, NAMELEN, "%s", argv[6]);
+ int fh = open(tmpfile, O_RDONLY);
+ if (fh < 0) {
+ fprintf(stderr, "ERROR: Could not open %s for reading..\n", tmpfile);
+ return CUPS_BACKEND_FAILED;
+ }
+ close(fh);
+ //
+ }
+
+ // Determine device uri
+ char *env = getenv("DEVICE_URI");
+ if (env != NULL && strchr(env, ':') != NULL) {
+ snprintf(device, NAMELEN, "%s", env);
+ } else if (strstr(argv[0], ":/") != NULL) {
+ snprintf(device, NAMELEN, "%s", argv[0]);
+ } else {
+ fputs("ERROR: No device URI given.\n", stderr);
+ return CUPS_BACKEND_FAILED;
+ }
+
+ // Get backend from uri
+ char *colon = strchr(device, ':');
+ *colon = '\0';
+ snprintf(backend, NAMELEN, "%s/%s", BACKEND_PATH, device);
+ *colon = ':';
+ // Is valid?
+ if (access(backend, X_OK | R_OK) != 0) {
+ fprintf(stderr, "ERROR: Backend %s is not executable.\n", backend);
+ return CUPS_BACKEND_FAILED;
+ }
+
+ // Try right away with what we got
+ spoolres = run_backend(backend, device, argv[1], argv[2], argv[3], argv[4], argv[5], tmpfile, NULL);
+ if (spoolres == CUPS_BACKEND_OK) return spoolres; // Yay
+
+ // Dialog - TODO: Drop privileges here!
+ QApplication a(argc, argv);
+ PwGui w(NULL);
+ w.show();
+ return a.exec();
+ // TODO .....
+}
+
+static int run_backend(char *backend, char *uri, char *jobid, char *user, char *title, char *copies, char *options, char *file, char *password)
+{
+ pid_t pid = fork();
+ if (pid == 0) {
+ // Child
+ if (user != NULL) setenv("AUTH_USERNAME", user, 1);
+ if (password != NULL) setenv("AUTH_PASSWORD", password, 1);
+ char *args[8];
+ args[0] = uri;
+ args[1] = jobid;
+ args[2] = user;
+ args[3] = title;
+ args[4] = copies;
+ args[5] = options;
+ args[6] = file;
+ args[7] = NULL;
+ execv(backend, args);
+ exit(127);
+ return 127;
+ }
+
+ // Main - wait for it...
+ int status;
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status)) {
+ fprintf(stderr, "ERROR: Running backend %s failed!\n", backend);
+ return CUPS_BACKEND_FAILED;
+ }
+ return WEXITSTATUS(status);
+}
+
diff --git a/src/pwgui/pwgui.cpp b/src/pwgui/pwgui.cpp
new file mode 100644
index 0000000..31dd822
--- /dev/null
+++ b/src/pwgui/pwgui.cpp
@@ -0,0 +1,59 @@
+#include "pwgui.h"
+#include "ui_pwgui.h"
+#include <QMessageBox>
+#include <QTimer>
+#include <QDesktopWidget>
+
+// ____________________________________________________________________________
+PwGui::PwGui(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::PwGui) {
+ // Initialize UI
+ initializeUI();
+}
+
+// ____________________________________________________________________________
+PwGui::~PwGui() {
+ delete ui;
+}
+
+// ____________________________________________________________________________
+void PwGui::initializeUI() {
+ ui->setupUi(this);
+
+ /*
+ // Prefill username
+ if (this->user != NULL) {
+ ui->lineEditUser->setText(QString::fromUtf8(user));
+ }
+ */
+
+ // Protect password from being seen
+ ui->lineEditPass->setEchoMode(QLineEdit::Password);
+ ui->lineEditPass->setInputMethodHints(ui->lineEditPass->inputMethodHints() | Qt::ImhNoAutoUppercase);
+
+ /* Main Window properties */
+
+ // Disable close button
+ this->setWindowFlags((this->windowFlags() & ~Qt::WindowCloseButtonHint) | Qt::WindowStaysOnTopHint);
+ // center dialog on screen center
+ QRect desktopRect = QApplication::desktop()->screenGeometry(this);
+ this->move( desktopRect.width()/2-this->width()/2,
+ desktopRect.height()/2-this->height()/2);
+}
+
+/*
+void PwGui::on_buttonCancel_clicked() {
+ // Quit with code 1
+ QCoreApplication::instance()->exit(1);
+}
+*/
+
+// ____________________________________________________________________________
+void PwGui::on_checkStatusTimer() {
+ static int retries = 0;
+ if (++retries > 20) {
+ QCoreApplication::instance()->quit();
+ }
+}
+
diff --git a/src/pwgui/pwgui.h b/src/pwgui/pwgui.h
new file mode 100644
index 0000000..3e56ec8
--- /dev/null
+++ b/src/pwgui/pwgui.h
@@ -0,0 +1,31 @@
+#ifndef AUTHENTICATION_H
+#define AUTHENTICATION_H
+
+#include <QMainWindow>
+#include <QDebug>
+#include <QTimer>
+
+namespace Ui {
+class PwGui;
+}
+
+class QTimer;
+
+class PwGui : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit PwGui(QWidget *parent = 0);
+ ~PwGui();
+
+private slots:
+ void on_checkStatusTimer();
+
+private:
+ Ui::PwGui *ui;
+ void initializeUI();
+ QTimer* checkStatusTimer;
+};
+
+#endif // AUTHENTICATION_H
diff --git a/src/pwgui/pwgui.ui b/src/pwgui/pwgui.ui
new file mode 100644
index 0000000..236df30
--- /dev/null
+++ b/src/pwgui/pwgui.ui
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PwGui</class>
+ <widget class="QMainWindow" name="PwGui">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>310</width>
+ <height>160</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowTitle">
+ <string>Drucken - Authentifizierung</string>
+ </property>
+ <widget class="QWidget" name="verticalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>9</x>
+ <y>9</y>
+ <width>291</width>
+ <height>141</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Benutzername</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditUser">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Passwort</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEditPass">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="labelStatus">
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="text">
+ <string>Bitte Anmelden</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>