summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastien Braun2010-10-07 22:54:10 +0200
committerSebastien Braun2010-10-07 22:54:10 +0200
commite61097b8881bc7e72a5499816cb1199ea274a3ca (patch)
treebcfa9f3fe3f43af02845bc21367de395b248600c
parentMake behaviour on lookup failures configurable (diff)
downloadpvs-e61097b8881bc7e72a5499816cb1199ea274a3ca.tar.gz
pvs-e61097b8881bc7e72a5499816cb1199ea274a3ca.tar.xz
pvs-e61097b8881bc7e72a5499816cb1199ea274a3ca.zip
Rework template meta-magic
- No more implicit dependency on Boost.MPL - Better documentation for template magic - Move input handler policies to handler definitions where they belong - Separate out event descriptions from handlers
-rw-r--r--src/gui/frame.cpp18
-rw-r--r--src/input/CMakeLists.txt5
-rw-r--r--src/input/allowLocalOrPrivileged.cpp21
-rw-r--r--src/input/detail/Makefile.autogen8
-rw-r--r--src/input/detail/gen/gen_policyChain.cpp68
-rw-r--r--src/input/detail/gen/gen_typeList.cpp115
-rw-r--r--src/input/detail/policyChain.h78
-rw-r--r--src/input/detail/policyChain_autogen.h8
-rw-r--r--src/input/detail/systemTraits.h94
-rw-r--r--src/input/detail/typeList.h76
-rw-r--r--src/input/detail/typeList_autogen.h60
-rw-r--r--src/input/inputEvent.cpp32
-rw-r--r--src/input/inputEvent.h49
-rw-r--r--src/input/inputEventHandler.cpp21
-rw-r--r--src/input/inputEventHandler.h407
-rw-r--r--src/input/inputHandlerChain.h49
-rw-r--r--src/input/inputHandlerChains.h25
-rw-r--r--src/input/killX11Handler.cpp2
-rw-r--r--src/input/killX11Handler.h14
-rw-r--r--src/input/magicSysRqHandler.cpp2
-rw-r--r--src/input/magicSysRqHandler.h52
-rw-r--r--src/input/privilegedHandlerForwarder.cpp4
-rw-r--r--src/input/privilegedHandlerForwarder.h6
-rw-r--r--src/input/privilegedInputHandlerChain.cpp30
-rw-r--r--src/input/pvsPrivInputHandler.cpp3
-rw-r--r--src/input/pvsPrivInputHandler.h4
-rw-r--r--src/input/rebootSystemHandler.cpp2
-rw-r--r--src/input/rebootSystemHandler.h10
-rw-r--r--src/input/sayHelloHandler.cpp2
-rw-r--r--src/input/sayHelloHandler.h11
-rw-r--r--src/input/unprivilegedInputHandlerChain.cpp30
-rw-r--r--src/input/x11FakeKeyboardHandler.cpp4
-rw-r--r--src/input/x11FakeKeyboardHandler.h8
-rw-r--r--src/input/x11FakeMouseHandler.cpp4
-rw-r--r--src/input/x11FakeMouseHandler.h14
-rwxr-xr-xsrc/pvs.cpp7
-rwxr-xr-xsrc/pvs.h4
37 files changed, 968 insertions, 379 deletions
diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp
index 1b80c3d..12ce6b5 100644
--- a/src/gui/frame.cpp
+++ b/src/gui/frame.cpp
@@ -19,7 +19,6 @@
*/
#include <src/input/inputEvent.h>
-#include <src/input/inputHandlerChain.h>
#include "frame.h"
#include <src/gui/mainWindow.h>
#include <iostream>
@@ -434,19 +433,18 @@ void Frame::sendInputEvent(InputEvent const& evt)
{
QString str;
eventToString(evt, str);
- std::string evtStr = evt.toString();
PVSMsg msg(PVSCOMMAND, "INPUTEVENT", str);
if(_remoteControlEnabled)
{
if(_remoteControlToAll)
{
- ConsoleLog writeLine(QString("sendInputEvent(%1) to one").arg(evtStr.c_str()));
+ ConsoleLog writeLine(QString("sendInputEvent(%1) to one").arg(evt.toString()));
PVSConnectionManager::getManager()->getServer()->sendToAll(msg);
}
else
{
- ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evtStr.c_str()));
+ ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evt.toString()));
_cFrame->getConnection()->sendMessage(msg);
}
}
@@ -592,14 +590,14 @@ void Frame::showSpecialEventMenu()
{
qDebug("Trying to show menu...");
QMenu* menu = new QMenu(this);
- QList<SpecialInputEventDescription> specialEvents = privileged_handler_chain::describe();
- QList<SpecialInputEventDescription>::iterator iter;
+ QList<SpecialInputEventDescription> specialEvents = SpecialInputEventDescription::describeSpecialEvents();
+ QListIterator<SpecialInputEventDescription> iter(specialEvents);
int i;
- for(i = 0, iter = specialEvents.begin();
- iter != specialEvents.end();
- iter++, i++)
+ for(i = 0;
+ iter.hasNext();
+ i++)
{
- QAction* act = menu->addAction((*iter).descriptionString);
+ QAction* act = menu->addAction(iter.next().description);
act->setData(i);
}
QAction* selected = menu->exec(QCursor::pos());
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
index 20fd531..689fd39 100644
--- a/src/input/CMakeLists.txt
+++ b/src/input/CMakeLists.txt
@@ -2,6 +2,8 @@ include(${QT_USE_FILE})
set(pvsinput_SRCS
inputEvent.cpp
+ unprivilegedInputHandlerChain.cpp
+ inputEventHandler.cpp
)
if(UNIX)
@@ -23,7 +25,8 @@ if(UNIX)
killX11Handler.cpp
magicSysRqHandler.cpp
sayHelloHandler.cpp
- inputEventHandler.cpp
+ privilegedInputHandlerChain.cpp
+ allowLocalOrPrivileged.cpp
)
set(pvsprivinputd_MOC_HDRS
diff --git a/src/input/allowLocalOrPrivileged.cpp b/src/input/allowLocalOrPrivileged.cpp
new file mode 100644
index 0000000..ba456dc
--- /dev/null
+++ b/src/input/allowLocalOrPrivileged.cpp
@@ -0,0 +1,21 @@
+/*
+ * inputHandlerSecurityPolicies.cpp
+ *
+ * Created on: Oct 7, 2010
+ * Author: brs
+ */
+
+#include "inputEventHandler.h"
+#include "pvsCheckPrivileges.h"
+
+bool input_policy::AllowLocalOrPrivileged::allow(InputEventContext const* ctx)
+{
+ if(ctx)
+ {
+ if(PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_LOCAL, ctx))
+ return true;
+ if(PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::USER_PRIVILEGED, ctx))
+ return true;
+ }
+ return false;
+}
diff --git a/src/input/detail/Makefile.autogen b/src/input/detail/Makefile.autogen
new file mode 100644
index 0000000..6d0bfb3
--- /dev/null
+++ b/src/input/detail/Makefile.autogen
@@ -0,0 +1,8 @@
+all : policyChain_autogen.h typeList_autogen.h
+.PHONY : all
+
+policyChain_autogen.h : gen/gen_policyChain
+ gen/gen_policyChain > policyChain_autogen.h
+
+typeList_autogen.h : gen/gen_typeList
+ gen/gen_typeList > typeList_autogen.h
diff --git a/src/input/detail/gen/gen_policyChain.cpp b/src/input/detail/gen/gen_policyChain.cpp
new file mode 100644
index 0000000..3e375ec
--- /dev/null
+++ b/src/input/detail/gen/gen_policyChain.cpp
@@ -0,0 +1,68 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/gen/gen_policyChain.cpp:
+ # - generate the input_policy::detail::PolicyChain class
+ # --------------------------------------------------------------------------
+ */
+
+#include <iostream>
+
+using namespace std;
+
+#define NUM_POLICIES 8
+
+int main(int, char**)
+{
+ int i;
+
+ cout << "template<typename BaseCase";
+ for(i = 0; i < NUM_POLICIES; i++)
+ {
+ cout << ", typename P" << i;
+ }
+ cout << ">\nstruct PolicyChain :\npublic P0::template apply_<PolicyChain<BaseCase";
+ for(i = 1; i < NUM_POLICIES; i++)
+ {
+ cout << ", P" << i;
+ }
+ cout << ", void> >\n";
+ cout << "{};\n";
+
+ // Base case:
+ cout << "template<typename BaseCase>\n";
+ cout << "struct PolicyChain<BaseCase";
+ for(i = 0; i < NUM_POLICIES; i++)
+ {
+ cout << ", void";
+ }
+ cout << "> : public BaseCase {};\n";
+
+ // We need the following in macros:
+ cout << "#define _autogen_POLICY_TEMPLATE_PARAMS ";
+ for(i = 0; i < NUM_POLICIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "typename P" << i;
+ }
+
+ cout << "\n#define _autogen_POLICY_TEMPLATE_ARGS ";
+ for(i = 0; i < NUM_POLICIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "P" << i;
+ }
+ cout << "\n";
+
+ return 0;
+}
diff --git a/src/input/detail/gen/gen_typeList.cpp b/src/input/detail/gen/gen_typeList.cpp
new file mode 100644
index 0000000..e092b80
--- /dev/null
+++ b/src/input/detail/gen/gen_typeList.cpp
@@ -0,0 +1,115 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/gen/gen_policyChain.cpp:
+ # - generate the input_policy::detail::TypeList class
+ # --------------------------------------------------------------------------
+ */
+
+#include <iostream>
+
+using namespace std;
+
+#define NUM_MAX_ENTRIES 16
+
+int main(int, char**)
+{
+ int i;
+
+ cout << "template<";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "typename T" << i << " = void";
+ }
+ cout << ">\nstruct TypeList {\n";
+ cout << "typedef T0 head;\n";
+ cout << "typedef TypeList<";
+ for(i = 1; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i > 1)
+ cout << ", ";
+ cout << "T" << i;
+ }
+ cout << ", void > tail;\n";
+ cout << "};\n";
+
+ // Contains:
+ cout << "template<typename Needle, typename Haystack>\n"
+ "struct Contains { static const int index = -1; static const bool value = false; };\n";
+
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ int j;
+
+ cout << "template<typename Needle";
+ for(j = 0; j < NUM_MAX_ENTRIES; j++)
+ {
+ if(j == i)
+ continue;
+ cout << ", typename T" << j;
+ }
+ cout << ">\nstruct Contains<Needle, TypeList<";
+ for(j = 0; j < NUM_MAX_ENTRIES; j++)
+ {
+ if(j)
+ cout << ", ";
+ if(j == i)
+ cout << "Needle";
+ else
+ cout << "T" << j;
+ }
+ cout << "> >\n{ static const int index = " << i << "; static const bool value = true; };\n";
+ }
+
+ // Empty List:
+ cout << "typedef TypeList<";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "void";
+ }
+ cout << " > EmptyList;\n";
+
+ // Macros:
+ cout << "#define IMPLICIT_TYPE_LIST_PARAMS(prefix) ";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "typename prefix##" << i << " = void";
+ }
+ cout << "\n";
+
+ cout << "#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) ";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "typename prefix##" << i;
+ }
+ cout << "\n";
+
+ cout << "#define IMPLICIT_TYPE_LIST_ARGS(prefix) ";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "prefix##" << i;
+ }
+ cout << "\n";
+
+ cout << "#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList<IMPLICIT_TYPE_LIST_ARGS(prefix) >\n";
+
+ return 0;
+}
diff --git a/src/input/detail/policyChain.h b/src/input/detail/policyChain.h
new file mode 100644
index 0000000..ae01ff2
--- /dev/null
+++ b/src/input/detail/policyChain.h
@@ -0,0 +1,78 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/policyChain.h:
+ # - Tie together the different bits of policy information a handler may
+ # give us
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef POLICYCHAIN_H_
+#define POLICYCHAIN_H_
+
+#include "typeList.h"
+
+namespace input_policy
+{
+namespace detail
+{
+
+template<typename BaseCase, typename PolicyList>
+struct PolicyChain : public PolicyList::head::template apply_<PolicyChain<BaseCase, typename PolicyList::tail> >
+{
+};
+
+template<typename BaseCase>
+struct PolicyChain<BaseCase, EmptyList> : public BaseCase
+{
+private:
+ struct This_Should_Not_Work;
+public:
+ static const int test_value = sizeof(This_Should_Not_Work);
+};
+
+}
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Macros that enable specification of policies:
+// A policy is declared like this:
+// template< PARAM1, PARAM2, ... >
+// BEGIN_POLICY_CLASS(MyPolicy) {
+// static const int field1 = 2;
+// ...
+// } END_POLICY_CLASS(MyPolicy);
+/////////////////////////////////////////////////////////////////////////
+#define BEGIN_POLICY_CLASS(policyName) \
+ struct policyName { \
+ template<typename NextPolicy> \
+ struct apply_ : public NextPolicy
+#define END_POLICY_CLASS \
+ ; };
+
+/////////////////////////////////////////////////////////////////////////
+// A macro that enables us to use a template parameter list
+// in a class using a policy, like this:
+//
+// template<POLICY_PARAMS>
+// struct MyPolicyBasedClass
+// {
+// typedef USE_POLICY(baseCase) policy_type;
+// };
+//
+// now, the following type is valid:
+// MyPolicyBasedClass<Policy1, Policy2>
+/////////////////////////////////////////////////////////////////////////
+#define POLICY_PARAMS IMPLICIT_TYPE_LIST_PARAMS(Policy)
+#define POLICY_PARAMS_LIST IMPLICIT_TYPE_LIST(Policy)
+#define USE_POLICY(baseCase) ::input_policy::detail::PolicyChain<baseCase, POLICY_PARAMS_LIST>
+
+#endif /* POLICYCHAIN_H_ */
diff --git a/src/input/detail/policyChain_autogen.h b/src/input/detail/policyChain_autogen.h
new file mode 100644
index 0000000..d9503b8
--- /dev/null
+++ b/src/input/detail/policyChain_autogen.h
@@ -0,0 +1,8 @@
+template<typename BaseCase, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
+struct PolicyChain :
+public P0::template apply_<PolicyChain<BaseCase, P1, P2, P3, P4, P5, P6, P7, void> >
+{};
+template<typename BaseCase>
+struct PolicyChain<BaseCase, void, void, void, void, void, void, void, void> : public BaseCase {};
+#define _autogen_POLICY_TEMPLATE_PARAMS typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7
+#define _autogen_POLICY_TEMPLATE_ARGS P0, P1, P2, P3, P4, P5, P6, P7
diff --git a/src/input/detail/systemTraits.h b/src/input/detail/systemTraits.h
new file mode 100644
index 0000000..7f5582f
--- /dev/null
+++ b/src/input/detail/systemTraits.h
@@ -0,0 +1,94 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/systemTraits.h:
+ # - Define system traits and provide a way to match against them
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef SYSTEMTRAITS_H_
+#define SYSTEMTRAITS_H_
+
+#include "typeList.h"
+
+#define DEFINE_SYSTEM_TRAIT(name) struct name;
+#define BEGIN_SYSTEM_TRAITS typedef TypeList<
+#define END_SYSTEM_TRAITS > SystemTraits;
+
+namespace input_policy
+{
+
+// Trait names are externally visible.
+DEFINE_SYSTEM_TRAIT(UnixLike)
+DEFINE_SYSTEM_TRAIT(LinuxSystem)
+DEFINE_SYSTEM_TRAIT(X11GUI)
+DEFINE_SYSTEM_TRAIT(ConsoleKitSupported)
+
+namespace detail
+{
+BEGIN_SYSTEM_TRAITS
+#ifdef __linux
+UnixLike,
+LinuxSystem,
+X11GUI,
+ConsoleKitSupported
+#endif
+END_SYSTEM_TRAITS
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Boolean logic as applied to system traits
+/////////////////////////////////////////////////////////////////////////
+template<IMPLICIT_TYPE_LIST_PARAMS(T)>
+struct AllOf;
+
+template<IMPLICIT_TYPE_LIST_PARAMS(T)>
+struct AnyOf;
+
+namespace detail
+{
+/////////////////////////////////////////////////////////////////////////
+// Does the list of system traits match what we have given?
+/////////////////////////////////////////////////////////////////////////
+template<typename Needles, typename Haystack>
+struct Matches
+{
+ // if Needles is neither AnyOf<...> nor AllOf<...>
+ // then we need to know if the Haystack contains it:
+ static const bool value = Contains<Needles, Haystack>::value;
+};
+
+template<typename Haystack>
+struct MatchesPredicate
+{
+ template<typename Needle>
+ struct apply
+ {
+ static const bool value = Matches<Needle, Haystack>::value;
+ };
+};
+
+template<IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(T), typename Haystack>
+struct Matches<AnyOf<IMPLICIT_TYPE_LIST_ARGS(T)>, Haystack>
+{
+ static const bool value = ForAnyInTypeList<MatchesPredicate<Haystack>, IMPLICIT_TYPE_LIST(T)>::value;
+};
+
+template<IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(T), typename Haystack>
+struct Matches<AllOf<IMPLICIT_TYPE_LIST_ARGS(T)>, Haystack>
+{
+ static const bool value = ForAllInTypeList<MatchesPredicate<Haystack>, IMPLICIT_TYPE_LIST(T)>::value;
+};
+}
+
+}
+
+#endif /* SYSTEMTRAITS_H_ */
diff --git a/src/input/detail/typeList.h b/src/input/detail/typeList.h
new file mode 100644
index 0000000..5b915a9
--- /dev/null
+++ b/src/input/detail/typeList.h
@@ -0,0 +1,76 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/typeList.h:
+ # - Compile-time metaprogramming facilities: Type Lists and Member Check
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef TYPELIST_H_
+#define TYPELIST_H_
+
+namespace input_policy
+{
+namespace detail
+{
+
+/////////////////////////////////////////////////////////////////////////
+// TypeList, Contains, EmptyList:
+// This class is autogenerated by gen/gen_typeList.cpp
+/////////////////////////////////////////////////////////////////////////
+#include "typeList_autogen.h"
+
+/////////////////////////////////////////////////////////////////////////
+// Type-level functions that do not need to be autogenerated as they
+// do not depend on the maximum number of entries:
+//
+// ForAnyInTypeList<Predicate, List>::value == true
+// if there is any entry E in List for which
+// Predicate::apply<E>::value == true
+/////////////////////////////////////////////////////////////////////////
+template<typename Predicate, typename List>
+struct ForAnyInTypeList
+{
+ static const bool value =
+ Predicate::template apply<typename List::head>::value ||
+ ForAnyInTypeList<Predicate, typename List::tail>::value;
+};
+
+template<typename Predicate>
+struct ForAnyInTypeList<Predicate, EmptyList>
+{
+ static const bool value = false;
+};
+
+/////////////////////////////////////////////////////////////////////////
+// ForAllInTypeList<Predicate, List>::value == true
+// if there is not any entry E in List for which
+// Predicate::apply<E>::value == false
+/////////////////////////////////////////////////////////////////////////
+template<typename Predicate, typename List>
+struct ForAllInTypeList
+{
+ static const bool value =
+ Predicate::template apply<typename List::head>::value &&
+ ForAllInTypeList<Predicate, typename List::tail>::value;
+};
+
+template<typename Predicate>
+struct ForAllInTypeList<Predicate, EmptyList>
+{
+ static const bool value = true;
+};
+
+}
+
+}
+
+#endif /* TYPELIST_H_ */
diff --git a/src/input/detail/typeList_autogen.h b/src/input/detail/typeList_autogen.h
new file mode 100644
index 0000000..0f8fdd4
--- /dev/null
+++ b/src/input/detail/typeList_autogen.h
@@ -0,0 +1,60 @@
+template<typename T0 = void, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void, typename T13 = void, typename T14 = void, typename T15 = void>
+struct TypeList {
+typedef T0 head;
+typedef TypeList<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void > tail;
+};
+template<typename Needle, typename Haystack>
+struct Contains { static const int index = -1; static const bool value = false; };
+template<typename Needle, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<Needle, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 0; static const bool value = true; };
+template<typename Needle, typename T0, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, Needle, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 1; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, Needle, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 2; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, Needle, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 3; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, Needle, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 4; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, Needle, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 5; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, Needle, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 6; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, Needle, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 7; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, Needle, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 8; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, Needle, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 9; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Needle, T11, T12, T13, T14, T15> >
+{ static const int index = 10; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, Needle, T12, T13, T14, T15> >
+{ static const int index = 11; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, Needle, T13, T14, T15> >
+{ static const int index = 12; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, Needle, T14, T15> >
+{ static const int index = 13; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, Needle, T15> >
+{ static const int index = 14; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, Needle> >
+{ static const int index = 15; static const bool value = true; };
+typedef TypeList<void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void > EmptyList;
+#define IMPLICIT_TYPE_LIST_PARAMS(prefix) typename prefix##0 = void, typename prefix##1 = void, typename prefix##2 = void, typename prefix##3 = void, typename prefix##4 = void, typename prefix##5 = void, typename prefix##6 = void, typename prefix##7 = void, typename prefix##8 = void, typename prefix##9 = void, typename prefix##10 = void, typename prefix##11 = void, typename prefix##12 = void, typename prefix##13 = void, typename prefix##14 = void, typename prefix##15 = void
+#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) typename prefix##0, typename prefix##1, typename prefix##2, typename prefix##3, typename prefix##4, typename prefix##5, typename prefix##6, typename prefix##7, typename prefix##8, typename prefix##9, typename prefix##10, typename prefix##11, typename prefix##12, typename prefix##13, typename prefix##14, typename prefix##15
+#define IMPLICIT_TYPE_LIST_ARGS(prefix) prefix##0, prefix##1, prefix##2, prefix##3, prefix##4, prefix##5, prefix##6, prefix##7, prefix##8, prefix##9, prefix##10, prefix##11, prefix##12, prefix##13, prefix##14, prefix##15
+#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList<IMPLICIT_TYPE_LIST_ARGS(prefix) >
diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp
index 9b69a3a..f5abf43 100644
--- a/src/input/inputEvent.cpp
+++ b/src/input/inputEvent.cpp
@@ -7,6 +7,7 @@
#include <QBuffer>
#include <QByteArray>
+#include <QCoreApplication>
#include <QDataStream>
#include <QKeyEvent>
#include <QMouseEvent>
@@ -97,3 +98,34 @@ InputEvent InputEvent::keyboardRelease(int key, int mods)
return InputEvent(ET_KEY, EC_RELEASE, value);
}
+#define describe(list, description, type, code, value) \
+ list.append(SpecialInputEventDescription(InputEvent::type, InputEvent::code, value, QCoreApplication::translate("InputEvent", description)))
+
+QList<SpecialInputEventDescription> SpecialInputEventDescription::describeSpecialEvents()
+{
+ QList<SpecialInputEventDescription> list;
+ describe(list, "Say Hello", ET_SPECIAL, EC_SAY_HELLO, 0);
+ describe(list, "Reboot", ET_SPECIAL, EC_REBOOT, 0);
+ describe(list, "Kill X Server", ET_SPECIAL, EC_KILL_X, 0);
+ describe(list, "Reboot immediately", ET_SPECIAL, EC_SYSRQ, 'b');
+ describe(list, "Power off immediately", ET_SPECIAL, EC_SYSRQ, 'o');
+ describe(list, "Crash System", ET_SPECIAL, EC_SYSRQ, 'c');
+ describe(list, "Turn off raw keyboard mode", ET_SPECIAL, EC_SYSRQ, 'r');
+ describe(list, "Send SIGTERM to all", ET_SPECIAL, EC_SYSRQ, 'e');
+ describe(list, "Send SIGKILL to all", ET_SPECIAL, EC_SYSRQ, 'i');
+ describe(list, "Kill all on this terminal", ET_SPECIAL, EC_SYSRQ, 'k');
+ describe(list, "Activate OOM killer", ET_SPECIAL, EC_SYSRQ, 'f');
+ describe(list, "Make real-time tasks niceable", ET_SPECIAL, EC_SYSRQ, 'n');
+ describe(list, "Force-thaw filesystems", ET_SPECIAL, EC_SYSRQ, 'j');
+ describe(list, "Sync all mounted filesystems", ET_SPECIAL, EC_SYSRQ, 's');
+ describe(list, "Remount all readonly", ET_SPECIAL, EC_SYSRQ, 'u');
+ describe(list, "Show all held locks", ET_SPECIAL, EC_SYSRQ, 'd');
+ describe(list, "Show stack traces", ET_SPECIAL, EC_SYSRQ, 'l');
+ describe(list, "Dump memory info", ET_SPECIAL, EC_SYSRQ, 'm');
+ describe(list, "Dump registers and flags", ET_SPECIAL, EC_SYSRQ, 'p');
+ describe(list, "Dump timers and clockevents", ET_SPECIAL, EC_SYSRQ, 'q');
+ describe(list, "Dump task list", ET_SPECIAL, EC_SYSRQ, 't');
+ describe(list, "Dump uninterruptible tasks", ET_SPECIAL, EC_SYSRQ, 'w');
+ describe(list, "Dump ftrace buffer", ET_SPECIAL, EC_SYSRQ, 'z');
+ return list;
+}
diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h
index 7a64bfc..2f557ce 100644
--- a/src/input/inputEvent.h
+++ b/src/input/inputEvent.h
@@ -18,9 +18,7 @@
#define INPUTEVENT_H_
#include <cassert>
-#include <string>
-#include <sstream>
-#include <stdint.h>
+#include <QString>
#ifndef __linux
# error "This will only run on a Linux system. Porting is required for other systems."
@@ -46,8 +44,13 @@ private:
// InputEvents are immutable. Prohibit assignment:
InputEvent& operator=(InputEvent const&); // There intentionally is no implementation.
+
public:
- InputEvent(uint16_t type, uint16_t code, uint32_t value) : type_(type), code_(code), value_(value)
+ InputEvent(uint16_t type, uint16_t code, uint32_t value = 0) : type_(type), code_(code), value_(value)
+ {
+ }
+
+ InputEvent(InputEvent const& other) : type_(other.type_), code_(other.code_), value_(other.value_)
{
}
@@ -158,7 +161,7 @@ public:
return (value_ & 0xffff);
}
- static std::string typeToString(uint16_t type)
+ static QString typeToString(uint16_t type)
{
switch(type)
{
@@ -171,13 +174,11 @@ public:
case ET_SPECIAL:
return "SPECIAL";
default:
- std::ostringstream s;
- s << std::hex << type;
- return s.str();
+ return QString::number(type, 16);
}
}
- static std::string codeToString(uint16_t code)
+ static QString codeToString(uint16_t code)
{
switch(code)
{
@@ -192,17 +193,13 @@ public:
case EC_KILL_X:
return "KILL_X";
default:
- std::ostringstream s;
- s << std::hex << code;
- return s.str();
+ return QString::number(code, 16);
}
}
- std::string toString() const
+ QString toString() const
{
- std::ostringstream s;
- s << typeToString(type_) << ':' << codeToString(code_) << ':' << std::hex << value_;
- return s.str();
+ return QString("%1:%2:%3").arg(typeToString(type_)).arg(codeToString(code_)).arg(value_, 16);
}
uint32_t qt_keysym() const
@@ -216,4 +213,24 @@ public:
}
};
+struct SpecialInputEventDescription
+{
+ SpecialInputEventDescription(uint16_t type, uint16_t code, uint32_t value, QString const& description_)
+ : type(type), code(code), value(value), description(description_)
+ {
+ }
+
+ uint16_t type;
+ uint16_t code;
+ uint32_t value;
+ QString description;
+
+ InputEvent toEvent() const
+ {
+ return InputEvent(type, code, value);
+ }
+
+ static QList<SpecialInputEventDescription> describeSpecialEvents();
+};
+
#endif /* INPUTEVENT_H_ */
diff --git a/src/input/inputEventHandler.cpp b/src/input/inputEventHandler.cpp
index c16c358..5298aed 100644
--- a/src/input/inputEventHandler.cpp
+++ b/src/input/inputEventHandler.cpp
@@ -17,20 +17,17 @@
#include "inputEventHandler.h"
#include "pvsCheckPrivileges.h"
-bool policy::allowPrivilegedUser(InputEvent const& evt, InputEventContext const* ctx)
+InputEventHandlerBase::HandlerStatus InputEventHandlerBase::handle(InputEvent const& evt, InputEventContext const* ctx)
{
- if(ctx)
- return PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_UNKNOWN, PVSCheckPrivileges::USER_PRIVILEGED,
- ctx);
- else
- return false;
+ if(!isApplicable(evt, ctx))
+ return HANDLER_NOT_APPLICABLE;
+ if(!allow(evt, ctx))
+ return HANDLER_NOT_ALLOWED;
+ doHandle(evt, ctx);
+ return HANDLER_MATCHED;
}
-bool policy::allowPhysicalSeat(InputEvent const& evt, InputEventContext const* ctx)
+bool input_policy::AllowEverybody::allow(InputEventContext const*)
{
- if(ctx)
- return PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_LOCAL, PVSCheckPrivileges::USER_UNKNOWN,
- ctx);
- else
- return false;
+ return true;
}
diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h
index 52e3338..5b03a90 100644
--- a/src/input/inputEventHandler.h
+++ b/src/input/inputEventHandler.h
@@ -22,274 +22,283 @@
#include <QList>
#include <QString>
#include <QCoreApplication>
-#include <boost/mpl/contains.hpp>
-#include <boost/mpl/if.hpp>
-#include <boost/mpl/vector.hpp>
#include <src/input/inputEvent.h>
+#include "detail/policyChain.h"
+#include "detail/systemTraits.h"
-#define HANDLER_TYPE_DONT_CARE 0xffff
-#define HANDLER_CODE_DONT_CARE 0xffff
-#define HANDLER_VALUE_DONT_CARE 0xffffffff
-
-class InputEventContext
-{
-public:
- virtual pid_t getSenderPid() const = 0;
- virtual uid_t getSenderUid() const = 0;
- virtual gid_t getSenderGid() const = 0;
-};
-
-struct SpecialInputEventDescription
+struct InputEventContext
{
- SpecialInputEventDescription(QString const& d, quint16 t, quint16 c, quint32 v = 0)
- : descriptionString(d), evtType(t), evtCode(c), evtValue(v)
+ InputEventContext()
{
+ hasBeenDenied = false;
}
- QString descriptionString;
- quint16 evtType;
- quint16 evtCode;
- quint32 evtValue;
+ virtual pid_t getSenderPid() const = 0;
+ virtual uid_t getSenderUid() const = 0;
+ virtual gid_t getSenderGid() const = 0;
- InputEvent toEvent() const
- {
- return InputEvent(evtType, evtCode, evtValue);
- }
+ mutable bool hasBeenDenied;
};
-template<quint16 Type = HANDLER_TYPE_DONT_CARE,
- quint16 Code = HANDLER_CODE_DONT_CARE,
- quint32 Value = HANDLER_VALUE_DONT_CARE>
-class DefaultInputEventHandler {
-protected:
- static QString tr(char const* string)
- {
- return QCoreApplication::translate("InputEventHandler", string);
- }
-
-public:
- virtual bool matches(InputEvent const& evt, InputEventContext const*) {
- if(Type != HANDLER_TYPE_DONT_CARE) {
- if(evt.type() != Type)
- return false;
- }
- if(Code != HANDLER_CODE_DONT_CARE) {
- if(evt.code() != Code)
- return false;
- }
- if(Value != HANDLER_VALUE_DONT_CARE) {
- if(evt.value() != Value)
- return false;
- }
- return true;
- }
+namespace input_policy
+{
- virtual void initialize()
+/////////////////////////////////////////////////////////////////////////
+// Policy:
+// Modifies the behaviour of an input handler class.
+//
+// There are several kinds of policy:
+// - Security Policy (When to allow a certain action)
+// - System Requirements (When to enable a certain handler)
+// - Applicability (When to consider a certain handler)
+//
+// Policies are tied together using the detail::PolicyChain class.
+/////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////
+// Security Policy:
+// At the moment there are two security policies:
+// 1. If the user is on a local seat, allow. If the user is privileged,
+// allow. Else deny.
+// 2. Allow everybody.
+// Additional security policies can be added by following the example
+// set by AllowLocalOrPrivileged
+/////////////////////////////////////////////////////////////////////////
+template<typename PolicyImpl>
+BEGIN_POLICY_CLASS(Security)
+{
+ bool allow(InputEventContext const* context)
{
+ return PolicyImpl::allow(context);
}
+}
+END_POLICY_CLASS
- virtual void handle(InputEvent const& evt, InputEventContext const*) = 0;
-
- static void describeInto(QList<SpecialInputEventDescription>& description)
- {
- }
+struct AllowLocalOrPrivileged
+{
+ static bool allow(InputEventContext const*);
};
-namespace policy {
-
-enum SecurityFlags {
- SEC_FREE_FOR_ALL,
- SEC_PHYSICAL_OR_PRIVILEGED
+struct AllowEverybody
+{
+ static bool allow(InputEventContext const*);
};
-bool allowPhysicalSeat(InputEvent const& evt, InputEventContext const* ctx);
-bool allowPrivilegedUser(InputEvent const& evt, InputEventContext const* ctx);
+typedef Security<AllowEverybody> Unprivileged;
-struct SecurityAllowAny
+/////////////////////////////////////////////////////////////////////////
+// System Requirements:
+// At the moment, this is trivial, as PVS only runs on Linux. But,
+// as porting efforts are already underway, we include the necessary
+// machinery anyway.
+/////////////////////////////////////////////////////////////////////////
+template<typename SystemTrait>
+BEGIN_POLICY_CLASS(Require)
{
- bool allow(InputEvent const& evt, InputEventContext const* ctx)
- {
- return true;
- }
+ static const bool areSystemRequirementsFulfilled =
+ NextPolicy::areSystemRequirementsFulfilled &&
+ detail::Matches<SystemTrait, detail::SystemTraits>::value;
+}
+END_POLICY_CLASS
+
+/////////////////////////////////////////////////////////////////////////
+// System Requirements:
+// At the moment, this is trivial, as PVS only runs on Linux. But,
+// as porting efforts are already underway, we include the necessary
+// machinery anyway.
+/////////////////////////////////////////////////////////////////////////
+enum {
+ HANDLER_CODE_DONT_CARE = 0xffff,
+ HANDLER_VALUE_DONT_CARE = 0xffffffff
};
-struct SecurityAllowPhysicalOrPrivileged
+struct T;
+
+template<unsigned short EventType,
+ unsigned short EventCode = HANDLER_CODE_DONT_CARE,
+ unsigned int EventValue = HANDLER_VALUE_DONT_CARE>
+BEGIN_POLICY_CLASS(Match)
{
- bool allow(InputEvent const& evt, InputEventContext const* ctx)
+ bool isApplicable(InputEvent const& evt)
{
- if(allowPhysicalSeat(evt, ctx))
- return true;
- else if(allowPrivilegedUser(evt, ctx))
- return true;
- return false;
+ if(evt.type() != EventType)
+ return NextPolicy::isApplicable(evt);
+ if(EventCode != HANDLER_CODE_DONT_CARE && evt.code() != EventCode)
+ return NextPolicy::isApplicable(evt);
+ if(EventValue != HANDLER_VALUE_DONT_CARE && evt.value() != EventValue)
+ return NextPolicy::isApplicable(evt);
+ return true;
}
};
+END_POLICY_CLASS
-struct UnixLike;
-struct Linux;
-struct Windows;
-
-#if defined(__linux)
-typedef boost::mpl::vector2<UnixLike,Linux>::type Systems;
-#elif defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
-typedef boost::mpl::vector1<Windows>::type Systems;
-#else
-# error "Porting is needed!"
-#endif
-
-struct SystemEnabled;
-struct SystemDisabled;
-
-template<typename System>
-struct RequireSystem
-{
- typedef typename boost::mpl::contains<Systems, System>::type enabled_type;
- static const bool enabled = enabled_type::value;
-};
-
-struct RequireNoSystem
+namespace detail
{
- typedef boost::mpl::bool_<true>::type enabled_type;
- static const bool enabled = enabled_type::value;
-};
-}
-
-template<bool Enabled, typename Delegate, typename SecurityPolicy>
-class HandlerHelper
+/////////////////////////////////////////////////////////////////////////
+// Base case: If no policies are given:
+/////////////////////////////////////////////////////////////////////////
+struct InputEventHandlerPolicyBase
{
-public:
- bool handle(InputEvent const& evt, InputEventContext const* context = 0) {
- if(!securityPolicy.allow(evt, context))
- {
- std::string evtStr = evt.toString();
- qWarning("Input Event %s has been denied by security policy", evtStr.c_str());
- return true;
- }
- if(delegate.matches(evt, context)) {
- delegate.handle(evt, context);
- return true;
- } else {
- return false;
- }
- }
+ // The default security policy applies
+ typedef AllowLocalOrPrivileged DefaultSecurityPolicyImpl;
- void initialize()
+ bool allow(InputEventContext const* context)
{
- delegate.initialize();
+ return DefaultSecurityPolicyImpl::allow(context);
}
- static void describeInto(QList<SpecialInputEventDescription>& list)
- {
- Delegate::describeInto(list);
- }
+ // A handler that does not specify requirements works
+ // everywhere
+ static const bool areSystemRequirementsFulfilled = true;
-private:
- Delegate delegate;
- SecurityPolicy securityPolicy;
-};
-
-template<typename Delegate, typename SecurityPolicy>
-class HandlerHelper<false, Delegate, SecurityPolicy>
-{
-public:
- bool handle(InputEvent const& evt, InputEventContext const* context = 0) {
+ // Generate an error when no match policy is given.
+ bool isApplicable(InputEvent const&)
+ {
return false;
}
+ // If any policy implementation needs an initialization hook:
+ // Don't forget to call NextPolicy::initialize() in your
+ // implementation!
void initialize()
{
}
-
- static void describeInto(QList<SpecialInputEventDescription>&)
- {
- }
};
-template<typename Delegate, typename SystemPolicy = policy::RequireNoSystem, typename SecurityPolicy = void>
-struct Handler : public HandlerHelper<SystemPolicy::enabled, Delegate, SecurityPolicy>
-{
-};
+}
+}
-template<typename DefaultSecurityPolicy, typename HandlerType>
-struct ApplyDefaultSecurityPolicy
+/////////////////////////////////////////////////////////////////////////
+// We want a nice non-generic base so we can make a list of polymorphic
+// handlers.
+//
+// The actual handler class need to provide doHandle and can override
+// allow and isApplicable.
+/////////////////////////////////////////////////////////////////////////
+/* interface */ class InputEventHandlerBase
{
- typedef HandlerType type;
-};
+public:
+ enum HandlerStatus
+ {
+ HANDLER_MATCHED,
+ HANDLER_NOT_ALLOWED,
+ HANDLER_NOT_APPLICABLE
+ };
-template<typename DefaultSecurityPolicy, typename Delegate, typename SystemPolicy>
-struct ApplyDefaultSecurityPolicy<DefaultSecurityPolicy, Handler<Delegate, SystemPolicy, void> >
-{
- typedef Handler<Delegate, SystemPolicy, DefaultSecurityPolicy> type;
+ virtual void initialize() = 0;
+ HandlerStatus handle(InputEvent const& evt, InputEventContext const* context = 0);
+
+protected:
+ virtual bool allow(InputEvent const& event, InputEventContext const* context = 0) = 0;
+ virtual bool isApplicable(InputEvent const& event, InputEventContext const* context = 0) = 0;
+ virtual void doHandle(InputEvent const& event, InputEventContext const* context = 0) = 0;
};
-template<typename DefaultSecurityPolicy, typename Begin, typename End>
-struct InputEventHandlerChainHelper
+/////////////////////////////////////////////////////////////////////////
+// Now that the machinery is in place, we can finally define what it
+// is like to be an input event handler:
+/////////////////////////////////////////////////////////////////////////
+template<POLICY_PARAMS>
+class InputEventHandler : public InputEventHandlerBase
{
-private:
- typedef typename boost::mpl::next<Begin>::type next_iterator_type;
- typedef InputEventHandlerChainHelper<DefaultSecurityPolicy, next_iterator_type, End> next_in_chain;
-
- typedef typename boost::mpl::deref<Begin>::type handler_entry_type;
- typedef typename ApplyDefaultSecurityPolicy<DefaultSecurityPolicy, handler_entry_type>::type handler_type;
-
- handler_type _handler;
- next_in_chain _next;
+protected:
+ typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type;
+ policy_type policy;
public:
- void handle(InputEvent const& evt, InputEventContext const* context = 0) {
- if(!_handler.handle(evt, context)) {
- _next.handle(evt, context);
- }
+ void initialize()
+ {
+ policy.initialize();
}
- void initialize() {
- _handler.initialize();
- _next.initialize();
- }
+ // Export this so the handler chain can decide whether to include this handler
+ static const bool areSystemRequirementsFulfilled = policy_type::areSystemRequirementsFulfilled;
+
+protected:
+
+ typedef InputEventHandler super;
- static void describeInto(QList<SpecialInputEventDescription>& list)
+ // allow and isApplicable are actually provided by Policy. If the
+ // handler class wishes to override any of them, the policy implementation
+ // can be called by means of super.
+ bool allow(InputEvent const&, InputEventContext const* context = 0)
{
- handler_type::describeInto(list);
- next_in_chain::describeInto(list);
+ return policy.allow(context);
}
- static QList<SpecialInputEventDescription> describe()
+ bool isApplicable(InputEvent const& event, InputEventContext const* = 0)
{
- QList<SpecialInputEventDescription> list;
- describeInto(list);
- return list;
+ return policy.isApplicable(event);
}
};
-template<typename DefaultSecurityPolicy, typename End>
-struct InputEventHandlerChainHelper<DefaultSecurityPolicy, End, End>
+/////////////////////////////////////////////////////////////////////////
+// And we can chain input handlers together:
+/////////////////////////////////////////////////////////////////////////
+class InputEventHandlerChain
{
- void handle(InputEvent const&, InputEventContext const* context = 0) {
- // do nothing
- }
+private:
+ QList<InputEventHandlerBase*> handlers;
+
+ /////////////////////////////////////////////////////////////////////////
+ // We need to statically dispatch on a static member of HandlerType.
+ // Unfortunately, we cannot specialize member functions of a template.
+ // So, we need to make this a class with a static non-template member.
+ /////////////////////////////////////////////////////////////////////////
+ template<bool Applicable, typename HandlerType>
+ struct ConditionallyAppend
+ {
+ static void doIt(InputEventHandlerChain* chain)
+ {
+ chain->handlers.append(new HandlerType);
+ }
+ };
- void initialize() {
- // do nothing
- }
+ template<typename HandlerType>
+ struct ConditionallyAppend<false, HandlerType>
+ {
+ static void doIt(InputEventHandlerChain*)
+ {
+ }
+ };
- static void describeInto(QList<SpecialInputEventDescription>&)
+public:
+ // Add an event handler to the chain. The argument is only for
+ // compilers which cannot handle template member functions
+ // correctly.
+ template<typename HandlerType>
+ InputEventHandlerChain& add(HandlerType const* = 0)
{
- // do nothing
+ ConditionallyAppend<HandlerType::areSystemRequirementsFulfilled, HandlerType>::doIt(this);
+ return *this;
}
- static QList<SpecialInputEventDescription> describe()
+ void initialize()
{
- return QList<SpecialInputEventDescription>();
+ QListIterator<InputEventHandlerBase*> i(handlers);
+ while(i.hasNext())
+ {
+ i.next()->initialize();
+ }
}
-};
-template<typename DefaultSecurityPolicy, typename Collection>
-struct InputEventHandlerChain :
- public InputEventHandlerChainHelper<DefaultSecurityPolicy,
- typename boost::mpl::begin<Collection>::type,
- typename boost::mpl::end<Collection>::type>
-{
+ void handle(InputEvent const& event, InputEventContext const* context = 0)
+ {
+ QListIterator<InputEventHandlerBase*> i(handlers);
+ while(i.hasNext())
+ {
+ switch(i.next()->handle(event, context))
+ {
+ case InputEventHandlerBase::HANDLER_MATCHED:
+ break;
+ case InputEventHandlerBase::HANDLER_NOT_ALLOWED:
+ context->hasBeenDenied = true;
+ case InputEventHandlerBase::HANDLER_NOT_APPLICABLE:
+ continue;
+ }
+ }
+ }
};
#endif /* INPUTEVENTHANDLER_H_ */
diff --git a/src/input/inputHandlerChain.h b/src/input/inputHandlerChain.h
deleted file mode 100644
index 3c9446c..0000000
--- a/src/input/inputHandlerChain.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
- #
- # This program is free software distributed under the GPL version 2.
- # See http://openslx.org/COPYING
- #
- # If you have any feedback please consult http://openslx.org/feedback and
- # send your suggestions, praise, or complaints to feedback@openslx.org
- #
- # General information about OpenSLX can be found at http://openslx.org/
- # --------------------------------------------------------------------------
- # inputHandlerChain.h:
- # - Definition of the input handler chain
- # --------------------------------------------------------------------------
- */
-
-#ifndef INPUTHANDLERCHAIN_H_
-#define INPUTHANDLERCHAIN_H_
-
-#include <boost/mpl/list.hpp>
-#include "inputEventHandler.h"
-
-#include "x11FakeKeyboardHandler.h"
-#include "x11FakeMouseHandler.h"
-#include "privilegedHandlerForwarder.h"
-#include "rebootSystemHandler.h"
-#include "sayHelloHandler.h"
-#include "killX11Handler.h"
-#include "magicSysRqHandler.h"
-
-typedef boost::mpl::list<
- Handler<X11FakeKeyboardHandler, policy::RequireSystem<policy::UnixLike> >,
- Handler<X11FakeMouseButtonHandler, policy::RequireSystem<policy::UnixLike> >,
- Handler<X11FakeMouseMovementHandler, policy::RequireSystem<policy::UnixLike> >,
- Handler<PrivilegedHandlerForwarder>
->::type unprivileged_handler_list;
-
-typedef InputEventHandlerChain<policy::SecurityAllowAny, unprivileged_handler_list> unprivileged_handler_chain;
-
-typedef boost::mpl::list<
- Handler<SayHelloHandler, policy::RequireNoSystem, policy::SecurityAllowAny >,
- Handler<KillX11Handler, policy::RequireSystem<policy::Linux> >,
- Handler<RebootLinuxSystemHandler, policy::RequireSystem<policy::Linux> >,
- Handler<MagicSysRqHandler, policy::RequireSystem<policy::Linux> >
->::type privileged_handler_list;
-
-typedef InputEventHandlerChain<policy::SecurityAllowPhysicalOrPrivileged, privileged_handler_list> privileged_handler_chain;
-
-#endif /* INPUTHANDLERCHAIN_H_ */
diff --git a/src/input/inputHandlerChains.h b/src/input/inputHandlerChains.h
new file mode 100644
index 0000000..a91e605
--- /dev/null
+++ b/src/input/inputHandlerChains.h
@@ -0,0 +1,25 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputHandlerChains.h:
+ # - Definition of the input handler chains - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef INPUTHANDLERCHAIN_H_
+#define INPUTHANDLERCHAIN_H_
+
+#include "inputEventHandler.h"
+
+InputEventHandlerChain makeUnprivilegedInputEventHandlerChain();
+InputEventHandlerChain makePrivilegedInputEventHandlerChain();
+
+#endif /* INPUTHANDLERCHAIN_H_ */
diff --git a/src/input/killX11Handler.cpp b/src/input/killX11Handler.cpp
index 7ac75a1..572656e 100644
--- a/src/input/killX11Handler.cpp
+++ b/src/input/killX11Handler.cpp
@@ -25,7 +25,7 @@
using namespace std;
-void KillX11Handler::handle(InputEvent const&, InputEventContext const* ctx)
+void KillX11Handler::doHandle(InputEvent const&, InputEventContext const* ctx)
{
// Find out which display device is used:
QString displayDevice = PVSCheckPrivileges::instance()->getX11DisplayDevice(ctx);
diff --git a/src/input/killX11Handler.h b/src/input/killX11Handler.h
index 2f3ef44..8c0d655 100644
--- a/src/input/killX11Handler.h
+++ b/src/input/killX11Handler.h
@@ -20,15 +20,15 @@
#include <QCoreApplication>
#include "inputEventHandler.h"
-class KillX11Handler : public DefaultInputEventHandler<InputEvent::ET_SPECIAL, InputEvent::EC_KILL_X>
+class KillX11Handler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_SPECIAL, InputEvent::EC_KILL_X>,
+ input_policy::Require<input_policy::AllOf<
+ input_policy::UnixLike,
+ input_policy::X11GUI,
+ input_policy::ConsoleKitSupported> > >
{
public:
- void handle(InputEvent const&, InputEventContext const*);
-
- static void describeInto(QList<SpecialInputEventDescription>& list)
- {
- list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Kill X Server")), InputEvent::ET_SPECIAL, InputEvent::EC_KILL_X);
- }
+ void doHandle(InputEvent const&, InputEventContext const*);
};
#endif /* KILLX11HANDLER_H_ */
diff --git a/src/input/magicSysRqHandler.cpp b/src/input/magicSysRqHandler.cpp
index 108bfca..7c38216 100644
--- a/src/input/magicSysRqHandler.cpp
+++ b/src/input/magicSysRqHandler.cpp
@@ -17,7 +17,7 @@
#include <QFile>
#include "magicSysRqHandler.h"
-void MagicSysRqHandler::handle(InputEvent const& evt, InputEventContext const*)
+void MagicSysRqHandler::doHandle(InputEvent const& evt, InputEventContext const*)
{
QFile trigger("/proc/sysrq-trigger");
trigger.open(QIODevice::WriteOnly);
diff --git a/src/input/magicSysRqHandler.h b/src/input/magicSysRqHandler.h
index 563d091..ba02997 100644
--- a/src/input/magicSysRqHandler.h
+++ b/src/input/magicSysRqHandler.h
@@ -19,54 +19,16 @@
#include "inputEventHandler.h"
-class MagicSysRqHandler : public DefaultInputEventHandler<InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ>
+class MagicSysRqHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ>,
+ input_policy::Require<input_policy::LinuxSystem> >
{
public:
- void handle(InputEvent const& evt, InputEventContext const* ctx);
+ void doHandle(InputEvent const& evt, InputEventContext const* ctx);
- static void describeInto(QList<SpecialInputEventDescription>& list)
- {
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Reboot immediately"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'b');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Crash system"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'c');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Show all held logs"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'd');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Send SIGTERM to all"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'e');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Activate OOM killer"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'f');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Send SIGKILL to all"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'i');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Force thaw filesystems"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'j');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Kill all on terminal"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'k');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Show stack traces"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'l');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump memory info"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'm');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Make real-time tasks niceable"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'n');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Power off immediately"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'o');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump registers and flags"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'p');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump timers and clockevents"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'q');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Turn off raw keyboard mode"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'r');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Sync all mounted filesystems"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 's');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump task list"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 't');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Remount all read-only"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'u');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump uninterruptible tasks"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'w');
- list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump ftrace buffer"),
- InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'z');
- }
+// static void describeInto(QList<SpecialInputEventDescription>& list)
+// {
+// }
};
#endif /* MAGICSYSRQHANDLER_H_ */
diff --git a/src/input/privilegedHandlerForwarder.cpp b/src/input/privilegedHandlerForwarder.cpp
index 3c0b3bd..17c4ab1 100644
--- a/src/input/privilegedHandlerForwarder.cpp
+++ b/src/input/privilegedHandlerForwarder.cpp
@@ -45,9 +45,9 @@ void PrivilegedHandlerForwarder::initialize()
}
}
-void PrivilegedHandlerForwarder::handle(InputEvent const& evt, InputEventContext const*)
+void PrivilegedHandlerForwarder::doHandle(InputEvent const& evt, InputEventContext const*)
{
- qDebug("Trying to handle %s in PrivilegedHandlerForwarder", evt.toString().c_str());
+ qDebug("Trying to handle %s in PrivilegedHandlerForwarder", evt.toString().toLocal8Bit().constData());
if(_socket < 0)
{
initialize();
diff --git a/src/input/privilegedHandlerForwarder.h b/src/input/privilegedHandlerForwarder.h
index 37e8f24..f5a6cc3 100644
--- a/src/input/privilegedHandlerForwarder.h
+++ b/src/input/privilegedHandlerForwarder.h
@@ -19,10 +19,12 @@
#include "inputEventHandler.h"
-class PrivilegedHandlerForwarder : public DefaultInputEventHandler<InputEvent::ET_SPECIAL>
+class PrivilegedHandlerForwarder : public InputEventHandler<
+ input_policy::Require<input_policy::UnixLike>,
+ input_policy::Unprivileged>
{
public:
- void handle(InputEvent const& evt, InputEventContext const* = 0);
+ void doHandle(InputEvent const& evt, InputEventContext const* = 0);
void initialize();
private:
diff --git a/src/input/privilegedInputHandlerChain.cpp b/src/input/privilegedInputHandlerChain.cpp
new file mode 100644
index 0000000..5764728
--- /dev/null
+++ b/src/input/privilegedInputHandlerChain.cpp
@@ -0,0 +1,30 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # privilegedInputHandlerChain.cpp
+ # - Definition of the input handler chains - implementation for privileged
+ # chain
+ # --------------------------------------------------------------------------
+ */
+
+#include "rebootSystemHandler.h"
+#include "sayHelloHandler.h"
+#include "killX11Handler.h"
+#include "magicSysRqHandler.h"
+#include "inputHandlerChains.h"
+
+InputEventHandlerChain makePrivilegedInputEventHandlerChain()
+{
+ return InputEventHandlerChain().add<RebootLinuxSystemHandler>()
+ .add<SayHelloHandler>()
+ .add<KillX11Handler>()
+ .add<MagicSysRqHandler>();
+}
diff --git a/src/input/pvsPrivInputHandler.cpp b/src/input/pvsPrivInputHandler.cpp
index 70ed1bc..bfa60ce 100644
--- a/src/input/pvsPrivInputHandler.cpp
+++ b/src/input/pvsPrivInputHandler.cpp
@@ -21,7 +21,7 @@
#include <QtDebug>
#include <QSocketNotifier>
#include "inputEvent.h"
-#include "inputEventHandler.h"
+#include "inputHandlerChains.h"
#include "pvsPrivInputSocket.h"
#include "pvsPrivInputHandler.h"
@@ -63,6 +63,7 @@ PVSPrivInputHandler::PVSPrivInputHandler(int fd, QObject* parent) :
_notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
_notifier->setEnabled(true);
connect(_notifier, SIGNAL(activated(int)), this, SLOT(canRead()));
+ _handlerChain = makePrivilegedInputEventHandlerChain();
}
PVSPrivInputHandler::~PVSPrivInputHandler()
diff --git a/src/input/pvsPrivInputHandler.h b/src/input/pvsPrivInputHandler.h
index 9980cdf..e82787b 100644
--- a/src/input/pvsPrivInputHandler.h
+++ b/src/input/pvsPrivInputHandler.h
@@ -20,7 +20,7 @@
#include <QObject>
#include <QHash>
#include <QPointer>
-#include "inputHandlerChain.h"
+#include "inputEventHandler.h"
class QSocketNotifier;
@@ -39,7 +39,7 @@ private:
QByteArray _messageAssembly;
int _bytes;
int _fd;
- privileged_handler_chain _handlerChain;
+ InputEventHandlerChain _handlerChain;
};
#endif /* PVSPRIVINPUTHANDLER_H_ */
diff --git a/src/input/rebootSystemHandler.cpp b/src/input/rebootSystemHandler.cpp
index b5b8f8a..6c5c63a 100644
--- a/src/input/rebootSystemHandler.cpp
+++ b/src/input/rebootSystemHandler.cpp
@@ -22,7 +22,7 @@
using namespace std;
-void RebootLinuxSystemHandler::handle(InputEvent const& evt, InputEventContext const* ctx)
+void RebootLinuxSystemHandler::doHandle(InputEvent const& evt, InputEventContext const* ctx)
{
// Rebooting a linux system is particulary easy:
if(kill(1, SIGINT) < 0)
diff --git a/src/input/rebootSystemHandler.h b/src/input/rebootSystemHandler.h
index 34fa8ae..4920452 100644
--- a/src/input/rebootSystemHandler.h
+++ b/src/input/rebootSystemHandler.h
@@ -20,15 +20,11 @@
#include <QCoreApplication>
#include "inputEventHandler.h"
-class RebootLinuxSystemHandler : public DefaultInputEventHandler<InputEvent::ET_SPECIAL, InputEvent::EC_REBOOT>
+class RebootLinuxSystemHandler : public InputEventHandler<
+ input_policy::Require<input_policy::LinuxSystem> >
{
public:
- void handle(InputEvent const&, InputEventContext const*);
-
- static void describeInto(QList<SpecialInputEventDescription>& list)
- {
- list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Reboot")), InputEvent::ET_SPECIAL, InputEvent::EC_REBOOT);
- }
+ void doHandle(InputEvent const&, InputEventContext const*);
};
#endif /* REBOOTSYSTEMHANDLER_H_ */
diff --git a/src/input/sayHelloHandler.cpp b/src/input/sayHelloHandler.cpp
index fc6f668..712963d 100644
--- a/src/input/sayHelloHandler.cpp
+++ b/src/input/sayHelloHandler.cpp
@@ -19,7 +19,7 @@
using namespace std;
-void SayHelloHandler::handle(InputEvent const&, InputEventContext const* ctx)
+void SayHelloHandler::doHandle(InputEvent const&, InputEventContext const* ctx)
{
cerr << "I'm right here! You sent this message from pid " << ctx->getSenderPid() << " as user " << ctx->getSenderUid() << " with gid " << ctx->getSenderGid() << endl;
}
diff --git a/src/input/sayHelloHandler.h b/src/input/sayHelloHandler.h
index b0d4c7e..00463ca 100644
--- a/src/input/sayHelloHandler.h
+++ b/src/input/sayHelloHandler.h
@@ -20,15 +20,12 @@
#include <QCoreApplication>
#include "inputEventHandler.h"
-class SayHelloHandler : public DefaultInputEventHandler<InputEvent::ET_SPECIAL, InputEvent::EC_SAY_HELLO>
+class SayHelloHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_SPECIAL, InputEvent::EC_SAY_HELLO>,
+ input_policy::Security<input_policy::AllowEverybody> >
{
public:
- void handle(InputEvent const&, InputEventContext const*);
-
- static void describeInto(QList<SpecialInputEventDescription>& list)
- {
- list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Say Hello")), InputEvent::ET_SPECIAL, InputEvent::EC_SAY_HELLO);
- }
+ void doHandle(InputEvent const&, InputEventContext const*);
};
#endif /* SAYHELLOHANDLER_CPP_ */
diff --git a/src/input/unprivilegedInputHandlerChain.cpp b/src/input/unprivilegedInputHandlerChain.cpp
new file mode 100644
index 0000000..fbbc770
--- /dev/null
+++ b/src/input/unprivilegedInputHandlerChain.cpp
@@ -0,0 +1,30 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # privilegedInputHandlerChain.cpp
+ # - Definition of the input handler chains - implementation for
+ # unprivileged chain
+ # --------------------------------------------------------------------------
+ */
+
+#include "x11FakeKeyboardHandler.h"
+#include "x11FakeMouseHandler.h"
+#include "privilegedHandlerForwarder.h"
+#include "inputHandlerChains.h"
+
+InputEventHandlerChain makeUnprivilegedInputEventHandlerChain()
+{
+ return InputEventHandlerChain().add<X11FakeKeyboardHandler>()
+ .add<X11FakeMouseButtonHandler>()
+ .add<X11FakeKeyboardHandler>()
+ .add<PrivilegedHandlerForwarder>();
+}
+
diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp
index 0c32b66..eab4498 100644
--- a/src/input/x11FakeKeyboardHandler.cpp
+++ b/src/input/x11FakeKeyboardHandler.cpp
@@ -807,7 +807,7 @@ void X11FakeKeyboardHandler::initialize()
current_modifiers = 0;
}
-void X11FakeKeyboardHandler::handle(InputEvent const& evt, InputEventContext const*)
+void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext const*)
{
Display* dpy = X11InputUtils::display();
@@ -818,7 +818,7 @@ void X11FakeKeyboardHandler::handle(InputEvent const& evt, InputEventContext con
switch(evt.qt_keysym())
{
case Qt::Key_Backtab:
- handle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab));
+ doHandle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab));
break;
default:
ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qt_keysym(), 8, 16));
diff --git a/src/input/x11FakeKeyboardHandler.h b/src/input/x11FakeKeyboardHandler.h
index 3dde7cc..6c18dce 100644
--- a/src/input/x11FakeKeyboardHandler.h
+++ b/src/input/x11FakeKeyboardHandler.h
@@ -19,10 +19,14 @@
#include "inputEventHandler.h"
-class X11FakeKeyboardHandler : public DefaultInputEventHandler<InputEvent::ET_KEY>
+class X11FakeKeyboardHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_KEY, InputEvent::EC_PRESS>,
+ input_policy::Match<InputEvent::ET_KEY, InputEvent::EC_RELEASE>,
+ input_policy::Require<input_policy::X11GUI>,
+ input_policy::Unprivileged>
{
public:
- void handle(InputEvent const&, InputEventContext const* = 0);
+ void doHandle(InputEvent const&, InputEventContext const* = 0);
void initialize();
};
diff --git a/src/input/x11FakeMouseHandler.cpp b/src/input/x11FakeMouseHandler.cpp
index 58415d5..605fe2c 100644
--- a/src/input/x11FakeMouseHandler.cpp
+++ b/src/input/x11FakeMouseHandler.cpp
@@ -19,7 +19,7 @@
#include <X11/extensions/XTest.h>
#include "x11InputUtils.h"
-void X11FakeMouseButtonHandler::handle(InputEvent const& evt, InputEventContext const*)
+void X11FakeMouseButtonHandler::doHandle(InputEvent const& evt, InputEventContext const*)
{
quint16 pressedButton = evt.pressedButton();
@@ -42,7 +42,7 @@ void X11FakeMouseButtonHandler::handle(InputEvent const& evt, InputEventContext
XFlush(dpy);
}
-void X11FakeMouseMovementHandler::handle(InputEvent const& evt, InputEventContext const*)
+void X11FakeMouseMovementHandler::doHandle(InputEvent const& evt, InputEventContext const*)
{
ConsoleLog writeLine(QString("Received mouse motion event (%1,%2)").arg(evt.xCoord()).arg(evt.yCoord()));
Display* dpy = X11InputUtils::display();
diff --git a/src/input/x11FakeMouseHandler.h b/src/input/x11FakeMouseHandler.h
index 0e32256..8ff8df4 100644
--- a/src/input/x11FakeMouseHandler.h
+++ b/src/input/x11FakeMouseHandler.h
@@ -19,16 +19,22 @@
#include "inputEventHandler.h"
-class X11FakeMouseButtonHandler : public DefaultInputEventHandler<InputEvent::ET_BUTTON>
+class X11FakeMouseButtonHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_POINTER>,
+ input_policy::Require<input_policy::X11GUI>,
+ input_policy::Unprivileged>
{
public:
- void handle(InputEvent const&, InputEventContext const* = 0);
+ void doHandle(InputEvent const&, InputEventContext const* = 0);
};
-class X11FakeMouseMovementHandler : public DefaultInputEventHandler<InputEvent::ET_POINTER>
+class X11FakeMouseMovementHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_POINTER>,
+ input_policy::Require<input_policy::X11GUI>,
+ input_policy::Unprivileged>
{
public:
- void handle(InputEvent const&, InputEventContext const* = 0);
+ void doHandle(InputEvent const&, InputEventContext const* = 0);
};
#endif /* X11FAKEMOUSEHANDLER_H_ */
diff --git a/src/pvs.cpp b/src/pvs.cpp
index eda63f5..96a92ea 100755
--- a/src/pvs.cpp
+++ b/src/pvs.cpp
@@ -20,7 +20,7 @@
#include "src/net/pvsServiceDiscovery.h"
#include "src/net/pvsDiscoveredServer.h"
#include "src/input/inputEvent.h"
-#include "src/input/inputHandlerChain.h"
+#include "src/input/inputHandlerChains.h"
#include "src/input/x11InputUtils.h"
#include "src/net/mcast/McastConfiguration.h"
#include "src/net/pvsOutgoingMulticastTransfer.h"
@@ -751,14 +751,15 @@ bool PVS::createMulticastTransfer(QString const& objectPath, quint64& transferID
void PVS::handleInputEvent(InputEvent const& evt)
{
- std::string s = evt.toString();
- ConsoleLog writeLine(QString("Received input event: %1").arg(s.c_str()));
+ QString s = evt.toString();
+ ConsoleLog writeLine(QString("Received input event: %1").arg(s.toLocal8Bit().constData()));
_inputEventHandlers.handle(evt);
}
void PVS::initializeInputEventHandling()
{
X11InputUtils::setDisplay(X11Info::display());
+ _inputEventHandlers = makeUnprivilegedInputEventHandlerChain();
_inputEventHandlers.initialize();
}
diff --git a/src/pvs.h b/src/pvs.h
index c18e9a3..902fbe7 100755
--- a/src/pvs.h
+++ b/src/pvs.h
@@ -26,7 +26,7 @@
#include "src/version.h"
#include "src/util/consoleLogger.h"
#include "src/util/clientGUIUtils.h"
-#include "src/input/inputHandlerChain.h"
+#include "src/input/inputEventHandler.h"
class PVSServiceDiscovery;
class PVSDiscoveredServer;
@@ -168,7 +168,7 @@ private:
int _timerLockDelay;
// input event handling:
- unprivileged_handler_chain _inputEventHandlers;
+ InputEventHandlerChain _inputEventHandlers;
void handleInputEvent(InputEvent const& evt);
void initializeInputEventHandling();