summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Wieninger <cwieninger (at) gmx (dot) de>2009-09-08 19:50:00 +0200
committerChristian Wieninger <cwieninger (at) gmx (dot) de>2009-09-08 19:50:00 +0200
commit1a19a11081e56aff745ca0ba625187fabc54fb94 (patch)
tree4690ff63020d7762b1ffbac1dcc697e07989c07a
parent4cf240cb6faa33f1e51d1040ee6162f245525f8f (diff)
downloadvdr-plugin-live-1a19a11081e56aff745ca0ba625187fabc54fb94.tar.gz
vdr-plugin-live-1a19a11081e56aff745ca0ba625187fabc54fb94.tar.bz2
new files for user management
-rw-r--r--pages/edit_user.ecpp176
-rw-r--r--pages/users.ecpp80
-rw-r--r--users.cpp200
-rw-r--r--users.h69
4 files changed, 525 insertions, 0 deletions
diff --git a/pages/edit_user.ecpp b/pages/edit_user.ecpp
new file mode 100644
index 0000000..2ae510a
--- /dev/null
+++ b/pages/edit_user.ecpp
@@ -0,0 +1,176 @@
+<%pre>
+#include "exception.h"
+#include "tools.h"
+#include "users.h"
+#include "livefeatures.h"
+#include "setup.h"
+
+using namespace std;
+using namespace vdrlive;
+
+</%pre>
+<%args>
+ // input parameters
+ string userid;
+ // form parameters
+ string username;
+ string password;
+ bool ur_editsetup = false;
+ bool ur_addtimers = false;
+ bool ur_deltimers = false;
+ bool ur_delrecs = false;
+ bool ur_useremote = false;
+ bool ur_startreplay = false;
+ bool ur_switchchnl = false;
+ bool ur_addstimers = false;
+ bool ur_delstimers = false;
+</%args>
+<%session scope="global">
+bool logged_in(false);
+</%session>
+<%request scope="page">
+cUser* editUser;
+</%request>
+<%include>page_init.eh</%include>
+<%cpp>
+ if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
+
+#define CHECKIF(x) reply.out() << ( (x) ? "checked=\"checked\"" : "" );
+
+ editUser = NULL;
+
+ if (request.getMethod() == "POST") {
+ if (!userid.empty()) {
+ editUser = Users.GetByUserId( userid );
+ if ( editUser == 0 )
+ throw HtmlError( tr("Couldn't find user. Maybe you mistyped your request?") );
+ editUser->SetName(username);
+ if (password != std::string(editUser->GetPasswordLength(), '*'))
+ editUser->SetPassword(password);
+ }
+ else
+ {
+ if (Users.GetByUserName( username ))
+ throw HtmlError( tr("This user name is already in use!") );
+ editUser = new cUser(Users.GetNewId(), username, password);
+ Users.Add(editUser);
+ }
+ editUser->SetUserrights(0);
+ if (ur_editsetup) editUser->SetRight(UR_EDITSETUP);
+ if (ur_addtimers) editUser->SetRight(UR_EDITTIMERS);
+ if (ur_deltimers) editUser->SetRight(UR_DELTIMERS);
+ if (ur_delrecs) editUser->SetRight(UR_DELRECS);
+ if (ur_useremote) editUser->SetRight(UR_USEREMOTE);
+ if (ur_startreplay) editUser->SetRight(UR_STARTREPLAY);
+ if (ur_switchchnl) editUser->SetRight(UR_SWITCHCHNL);
+ if (ur_addstimers) editUser->SetRight(UR_EDITSTIMERS);
+ if (ur_delstimers) editUser->SetRight(UR_DELSTIMERS);
+
+ Users.Save();
+
+ return reply.redirect("users.html");
+ }
+
+ pageTitle = !userid.empty() ? tr("Edit user") : tr("New user");
+
+ if ( !userid.empty() ) {
+ cUser* User = Users.GetByUserId( userid );
+ if ( User == 0 )
+ throw HtmlError( tr("Couldn't find user. Maybe you mistyped your request?") );
+
+ username = User->Name();
+ password = std::string(User->GetPasswordLength(), '*');
+ ur_editsetup = User->HasRightTo(UR_EDITSETUP);
+ ur_addtimers = User->HasRightTo(UR_EDITTIMERS);
+ ur_deltimers = User->HasRightTo(UR_DELTIMERS);
+ ur_delrecs = User->HasRightTo(UR_DELRECS);
+ ur_useremote = User->HasRightTo(UR_USEREMOTE);
+ ur_startreplay = User->HasRightTo(UR_STARTREPLAY);
+ ur_switchchnl = User->HasRightTo(UR_SWITCHCHNL);
+ ur_addstimers = User->HasRightTo(UR_EDITSTIMERS);
+ ur_delstimers = User->HasRightTo(UR_DELSTIMERS);
+ editUser = User;
+ }
+ else
+ {
+ ur_editsetup = true;
+ ur_addtimers = true;
+ ur_deltimers = true;
+ ur_delrecs = true;
+ ur_useremote = true;
+ ur_startreplay = true;
+ ur_switchchnl = true;
+ ur_addstimers = true;
+ ur_delstimers = true;
+ }
+</%cpp>
+<& pageelems.doc_type &>
+<html>
+ <head>
+ <title>VDR Live - <$ pageTitle $></title>
+ <& pageelems.stylesheets &>
+ <& pageelems.ajax_js &>
+ </head>
+ <body>
+ <& pageelems.logo &>
+ <& menu active=("users") &>
+ <div class="inhalt">
+ <form method="post" name="edit_user" action="edit_user.ecpp">
+ <input type="hidden" name="userid" value="<$ userid $>"/>
+ <table class="formular" cellpadding="0" cellspacing="0">
+ <tr class="head">
+ <td class="toprow leftcol rightcol" colspan="2"><div class="boxheader"><div><div class="caption"><$ pageTitle $></div></div></div></td>
+ </tr>
+
+ <tr>
+ <td class="label leftcol"><div class="withmargin"><$ tr("Name" ) $>:</div></td>
+ <td class="rightcol"><input type="text" name="username" value="<$ username $>" size="80" /></td>
+ </tr>
+ <tr>
+ <td class="label leftcol"><div class="withmargin"><$ tr("Password" ) $>:</div></td>
+ <td class="rightcol"><input type="password" name="password" value="<$ password $>" size="80" /></td>
+ </tr>
+ <!-- user rights -->
+ <tr>
+ <td class="label leftcol"><div class="withmargin"><$ tr("User rights") $>:</div></td>
+ <td class="rightcol">
+ <input type="checkbox" name="ur_editsetup" value="1" <{ CHECKIF(ur_editsetup) }> />
+ <label for="ur_editsetup"><$ tr("Edit setup") $></label><br>
+ <input type="checkbox" name="ur_addtimers" value="1" <{ CHECKIF(ur_addtimers) }> />
+ <label for="ur_addtimers"><$ tr("Add or edit timers") $></label><br>
+ <input type="checkbox" name="ur_deltimers" value="1" <{ CHECKIF(ur_deltimers) }> />
+ <label for="ur_deltimers"><$ tr("Delete timers") $></label><br>
+ <input type="checkbox" name="ur_delrecs" value="1" <{ CHECKIF(ur_delrecs) }> />
+ <label for="ur_delrecs"><$ tr("Delete recordings") $></label><br>
+ <input type="checkbox" name="ur_useremote" value="1" <{ CHECKIF(ur_useremote) }> />
+ <label for="ur_useremote"><$ tr("Use remote menu") $></label><br>
+ <input type="checkbox" name="ur_startreplay" value="1" <{ CHECKIF(ur_startreplay) }> />
+ <label for="ur_startreplay"><$ tr("Start replay") $></label><br>
+ <input type="checkbox" name="ur_switchchnl" value="1" <{ CHECKIF(ur_switchchnl) }> />
+ <label for="ur_switchchnl"><$ tr("Switch channel") $></label><br>
+<%cpp>
+ if (LiveFeatures< features::epgsearch >().Recent()) {
+</%cpp>
+ <input type="checkbox" name="ur_addstimers" value="1" <{ CHECKIF(ur_addstimers) }> />
+ <label for="ur_addstimers"><$ tr("Add or edit search timers") $></label><br>
+ <input type="checkbox" name="ur_delstimers" value="1" <{ CHECKIF(ur_delstimers) }> />
+ <label for="ur_delstimers"><$ tr("Delete search timers") $></label><br>
+<%cpp>
+ }
+</%cpp>
+ </td>
+ </tr>
+ <tr>
+ <td class="buttonpanel leftcol rightcol bottomrow" colspan="2">
+ <div class="withmargin">
+ <button class="green" type="submit" name="save"><$ tr("Save") $></button>
+ <button type="button" class="red" onclick="history.back()"><$ tr("Cancel") $></button>
+ </div>
+ </td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ </body>
+</html>
+<%include>page_exit.eh</%include>
diff --git a/pages/users.ecpp b/pages/users.ecpp
new file mode 100644
index 0000000..f884e91
--- /dev/null
+++ b/pages/users.ecpp
@@ -0,0 +1,80 @@
+<%pre>
+#include <vdr/channels.h>
+#include <vdr/i18n.h>
+#include "users.h"
+#include "setup.h"
+
+using namespace vdrlive;
+using namespace std;
+
+</%pre>
+<%args>
+ // input parameters
+ string userid;
+ string action;
+</%args>
+<%session scope="global">
+bool logged_in(false);
+</%session>
+<%include>page_init.eh</%include>
+<%cpp>
+if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");
+</%cpp>
+<%cpp>
+ pageTitle = tr("Users");
+ if ( !userid.empty() ) {
+ if (action == "delete")
+ {
+ Users.Del(Users.GetByUserId( userid ));
+ Users.Save();
+ }
+ }
+</%cpp>
+<& pageelems.doc_type &>
+<html>
+ <head>
+ <title>VDR-Live - <$ pageTitle $></title>
+ <& pageelems.stylesheets &>
+ <& pageelems.ajax_js &>
+ </head>
+ <body>
+ <& pageelems.logo &>
+ <& menu active=("users") component=("users.user_actions")>
+ <div class="inhalt">
+ <table class="listing" cellspacing="0" cellpadding="0">
+ <tr class="head">
+ <td colspan="3">
+ <div class="boxheader"><div><div><$ pageTitle $></div></div></div>
+ </td>
+ </tr>
+ <tr class="description">
+ <td class="action leftcol"><div class="leftcol"><$ tr("Name") $></div></td>
+ <td class="rightcol" colspan="8"/>
+ </tr>
+<%cpp>
+ cUser* user = Users.First();
+ while (user)
+ {
+ bool bottom = (Users.Next(user) == NULL);
+ if (user)
+ {
+</%cpp>
+ <tr class="description">
+ <td class="action leftcol <? bottom ? "bottomrow" ?>"><div class="withmargin"><$ user->Name() $></div></td>
+ <td class="<? bottom ? "bottomrow" ?>"><a href="edit_user.html?userid=<$ user->Id() $>"><img src="<$ LiveSetup().GetThemedLink("img", "edit.png") $>" alt="" <& tooltip.hint text=(tr("Edit user")) &>></img></a></td>
+ <td class="action rightcol <? bottom ? "bottomrow" ?>"><a href="users.html?userid=<$ user->Id() $>&action=delete"><img src="<$ LiveSetup().GetThemedLink("img", "del.png") $>" alt="" <& tooltip.hint text=(tr("Delete user")) &>></img></a></td>
+ </tr>
+<%cpp>
+ }
+ user = Users.Next(user);
+ }
+</%cpp>
+ </table>
+ </div>
+ </body>
+</html>
+<%include>page_exit.eh</%include>
+
+<%def user_actions>
+<a href="edit_user.html"><$ tr("New user") $></a>
+</%def>
diff --git a/users.cpp b/users.cpp
new file mode 100644
index 0000000..d68ec1c
--- /dev/null
+++ b/users.cpp
@@ -0,0 +1,200 @@
+/*
+ * users.cpp: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ * $Id: users.cpp,v 1.0 2009/08/27 13:00:00 winni Exp $
+ */
+
+#include "users.h"
+#include <iostream>
+#include <sstream>
+#include "tools.h"
+#include "setup.h"
+
+namespace vdrlive {
+
+using namespace std;
+
+std::string cUsers::logged_in_user;
+
+// -- cUser -----------------------------------------------------------------
+cUser::cUser(int ID, const std::string& Name, const std::string& Password)
+ : m_ID(ID), m_Name(Name)
+{
+ SetPassword(Password);
+}
+
+void cUser::SetPassword(const std::string Password)
+{
+ ostringstream passwordStr;
+ passwordStr << Password.size() << "|" << MD5Hash(Password);
+ m_PasswordMD5 = passwordStr.str();
+}
+
+int cUser::GetPasswordLength() const
+{
+ // format is <length>:<md5-hash of password>
+ vector< string > parts = StringSplit( m_PasswordMD5, '|' );
+ return (parts.size() > 0) ? lexical_cast< int >( parts[0] ) : 0;
+}
+
+std::string const cUser::GetMD5HashPassword() const
+{
+ // format is <length>:<md5-hash of password>
+ vector< string > parts = StringSplit( m_PasswordMD5, '|' );
+ return (parts.size() > 1) ? parts[1] : "";
+}
+
+bool cUser::Parse(const char *s)
+{
+ char *line;
+ char *pos;
+ char *pos_next;
+ int parameter = 1;
+ int valuelen;
+#define MAXVALUELEN (10 * MaxFileName)
+
+ char value[MAXVALUELEN];
+
+ pos = line = strdup(s);
+ pos_next = pos + strlen(pos);
+ if (*pos_next == '\n') *pos_next = 0;
+ while (*pos) {
+ while (*pos == ' ') pos++;
+ if (*pos) {
+ if (*pos != ':') {
+ pos_next = strchr(pos, ':');
+ if (!pos_next)
+ pos_next = pos + strlen(pos);
+ valuelen = pos_next - pos + 1;
+ if (valuelen > MAXVALUELEN)
+ {
+ esyslog("entry '%s' is too long. Will be truncated!", pos);
+ valuelen = MAXVALUELEN;
+ }
+ strn0cpy(value, pos, valuelen);
+ pos = pos_next;
+
+ switch (parameter) {
+ case 1: m_ID = lexical_cast< int >(value);
+ break;
+ case 2: m_Name = value;
+ break;
+ case 3: m_PasswordMD5 = value;
+ break;
+ case 4:
+ m_Userrights = lexical_cast< int >(value);
+ break;
+ default:
+ break;
+ } //switch
+ }
+ parameter++;
+ }
+ if (*pos) pos++;
+ } //while
+
+ free(line);
+ return (parameter >= 4) ? true : false;
+}
+
+const char *cUser::ToText(void)
+{
+ char* buffer = NULL;
+ asprintf(&buffer, "%d:%s:%s:%d", m_ID, m_Name.c_str(), m_PasswordMD5.c_str(), m_Userrights);
+ return buffer;
+}
+
+bool cUser::Save(FILE *f)
+{
+ return fprintf(f, "%s\n", ToText()) > 0;
+}
+
+bool cUser::HasRightTo(eUserRights right)
+{
+ return ((m_Userrights & (1 << (right-1))) != 0);
+}
+
+bool cUser::CurrentUserHasRightTo(eUserRights right)
+{
+ if (!LiveSetup().UseAuth()) return true;
+ cUser* user = cUsers::GetByUserName(cUsers::logged_in_user);
+ return (cUsers::logged_in_user == LiveSetup().GetAdminLogin() || (user && (user->m_Userrights & (1 << (right-1))) != 0));
+}
+
+void cUser::SetRight(eUserRights right)
+{
+ isyslog("set right '%d' in '%d'", right, m_Userrights);
+ m_Userrights |= (1 << (right-1));
+ isyslog("now rights are '%d'", m_Userrights);
+}
+
+bool cUsers::Delete(const std::string& Name)
+{
+ cUser* user = Users.First();
+ while (user)
+ {
+ if (user->Name() == Name)
+ {
+ Users.Del(user);
+ Users.Save();
+ return true;
+ }
+ user = Users.Next(user);
+ }
+ return false;
+}
+
+cUser* cUsers::GetByUserId(const std::string& Id)
+{
+ cUser* user = Users.First();
+ while (user)
+ {
+ if (user->Id() == atoi(Id.c_str()))
+ return user;
+ user = Users.Next(user);
+ }
+ return NULL;
+}
+
+cUser* cUsers::GetByUserName(const std::string& Name)
+{
+ cUser* user = Users.First();
+ while (user)
+ {
+ if (user->Name() == Name)
+ return user;
+ user = Users.Next(user);
+ }
+ return NULL;
+}
+
+int cUsers::GetNewId()
+{
+ int iMaxId = -1;
+ cUser* user = Users.First();
+ while (user)
+ {
+ if (iMaxId < user->Id())
+ iMaxId = user->Id();
+ user = Users.Next(user);
+ }
+ return iMaxId + 1;
+}
+
+bool cUsers::ValidUserLogin(const std::string& login, const std::string& password)
+{
+ cUser* user = GetByUserName(login);
+ if (user && MD5Hash(password) == user->GetMD5HashPassword())
+ return true;
+ return false;
+}
+
+bool cUsers::ValidLogin(const std::string& login, const std::string& password)
+{
+ return ((login == LiveSetup().GetAdminLogin() && MD5Hash(password) == LiveSetup().GetMD5HashAdminPassword()) ||
+ ValidUserLogin(login, password));
+}
+
+}
diff --git a/users.h b/users.h
new file mode 100644
index 0000000..b845352
--- /dev/null
+++ b/users.h
@@ -0,0 +1,69 @@
+#ifndef VDR_LIVE_USERS_H
+#define VDR_LIVE_USERS_H
+
+#include <string>
+#include <vdr/plugin.h>
+#include <vdr/tools.h>
+#include <iostream>
+#include <sstream>
+
+namespace vdrlive {
+
+enum eUserRights
+{
+ UR_EDITSETUP=1,
+ UR_EDITTIMERS,
+ UR_DELTIMERS,
+ UR_DELRECS,
+ UR_USEREMOTE,
+ UR_STARTREPLAY,
+ UR_SWITCHCHNL,
+ UR_EDITSTIMERS,
+ UR_DELSTIMERS
+};
+
+// --- cUser --------------------------------------------------------
+class cUser : public cListObject {
+ int m_ID;
+ std::string m_Name;
+ std::string m_PasswordMD5;
+ int m_Userrights;
+public:
+ cUser() : m_ID(-1), m_Userrights(0) {}
+ cUser(int ID, const std::string& Name, const std::string& Password);
+ int Id() const { return m_ID; }
+ std::string Name() const { return m_Name; }
+ std::string PasswordMD5() const { return m_PasswordMD5; }
+ int Userrights() const { return m_Userrights; }
+ int GetPasswordLength() const;
+ std::string const GetMD5HashPassword() const;
+ void SetId(int Id) { m_ID = Id; }
+ void SetName(const std::string Name) { m_Name = Name; }
+ void SetPassword(const std::string Password);
+ void SetUserrights(int Userrights) { m_Userrights = Userrights; }
+ bool HasRightTo(eUserRights right);
+ static bool CurrentUserHasRightTo(eUserRights right);
+ void SetRight(eUserRights right);
+ bool Parse(const char *s);
+ const char *ToText(void);
+ bool Save(FILE *f);
+};
+
+// --- cUsers --------------------------------------------------------
+class cUsers : public cConfig<cUser> {
+ public:
+ bool ValidUserLogin(const std::string& login, const std::string& password);
+ bool ValidLogin(const std::string& login, const std::string& password);
+ bool Delete(const std::string& Name);
+ static cUser* GetByUserId(const std::string& Id);
+ static cUser* GetByUserName(const std::string& Name);
+ int GetNewId();
+
+ static std::string logged_in_user;
+};
+
+extern cUsers Users;
+
+}
+
+#endif