MythTV  master
parentalcontrols.cpp
Go to the documentation of this file.
1 #include <map>
2 
4 #include "libmythbase/mythdate.h"
9 
10 #include "parentalcontrols.h"
11 
12 namespace
13 {
15  {
16  if (pl < ParentalLevel::plNone)
17  return ParentalLevel::plNone;
18  if (pl > ParentalLevel::plHigh)
19  return ParentalLevel::plHigh;
20 
21  return pl;
22  }
23 
25  {
26  ParentalLevel::Level rpl(cpl);
27  switch (cpl)
28  {
30  rpl = ParentalLevel::plLowest; break;
32  rpl = ParentalLevel::plLow; break;
34  rpl = ParentalLevel::plMedium; break;
37  rpl = ParentalLevel::plHigh; break;
38  }
39 
40  return boundedParentalLevel(rpl);
41  }
42 
44  {
45  ParentalLevel::Level rpl(cpl);
46  switch (cpl)
47  {
49  rpl = ParentalLevel::plNone; break;
52  rpl = ParentalLevel::plLowest; break;
54  rpl = ParentalLevel::plLow; break;
56  rpl = ParentalLevel::plMedium; break;
57  }
58 
59  return boundedParentalLevel(rpl);
60  }
61 
63  {
64  return boundedParentalLevel(static_cast<ParentalLevel::Level>(pl));
65  }
66 }
67 
69 {
70 }
71 
73  : m_level(toParentalLevel(pl))
74 {
75 }
76 
78 {
79  *this = rhs;
80 }
81 
83 {
84  if (&rhs != this)
85  {
86  m_level = rhs.m_level;
87  m_hitlimit = rhs.m_hitlimit;
88  }
89 
90  return *this;
91 }
92 
94 {
96  return *this;
97 }
98 
100 {
101  Level last = m_level;
103  if (m_level == last)
104  m_hitlimit = true;
105  return *this;
106 }
107 
109 {
110  m_level = toParentalLevel(m_level + amount);
111  return *this;
112 }
113 
115 {
116  Level prev = m_level;
118  if (m_level == prev)
119  m_hitlimit = true;
120  return *this;
121 }
122 
124 {
125  m_level = toParentalLevel(m_level - amount);
126  return *this;
127 }
128 
130 {
131  return m_level;
132 }
133 
134 bool operator!=(const ParentalLevel &lhs, const ParentalLevel &rhs)
135 {
136  return lhs.GetLevel() != rhs.GetLevel();
137 }
138 
139 bool operator==(const ParentalLevel &lhs, const ParentalLevel &rhs)
140 {
141  return lhs.GetLevel() == rhs.GetLevel();
142 }
143 
144 bool operator<(const ParentalLevel &lhs, const ParentalLevel &rhs)
145 {
146  return lhs.GetLevel() < rhs.GetLevel();
147 }
148 
149 bool operator>(const ParentalLevel &lhs, const ParentalLevel &rhs)
150 {
151  return lhs.GetLevel() > rhs.GetLevel();
152 }
153 
154 bool operator<=(const ParentalLevel &lhs, const ParentalLevel &rhs)
155 {
156  return lhs.GetLevel() <= rhs.GetLevel();
157 }
158 
159 bool operator>=(const ParentalLevel &lhs, const ParentalLevel &rhs)
160 {
161  return lhs.GetLevel() >= rhs.GetLevel();
162 }
163 
164 namespace
165 {
167  {
168  private:
169  using pws = std::map<ParentalLevel::Level, QString>;
170 
171  public:
172  void Add(ParentalLevel::Level level, const QString &password)
173  {
174  m_passwords.insert(pws::value_type(level, password));
175  }
176 
177  QStringList AtOrAbove(ParentalLevel::Level level)
178  {
179  QStringList ret;
180  for (ParentalLevel i = level;
181  i <= ParentalLevel::plHigh && i.good(); ++i)
182  {
183  auto p = m_passwords.find(i.GetLevel());
184  if (p != m_passwords.end() && !p->second.isEmpty())
185  ret.push_back(p->second);
186  }
187 
188  return ret;
189  }
190 
192  {
193  QString ret;
194  for (ParentalLevel i = level;
195  i >= ParentalLevel::plLow && i.good(); --i)
196  {
197  auto p = m_passwords.find(i.GetLevel());
198  if (p != m_passwords.end() && !p->second.isEmpty())
199  {
200  ret = p->second;
201  break;
202  }
203  }
204 
205  return ret;
206  }
207 
208  private:
210  };
211 }
212 
213 class ParentalLevelChangeCheckerPrivate : public QObject
214 {
215  Q_OBJECT
216 
217  public:
218  explicit ParentalLevelChangeCheckerPrivate(QObject *lparent)
219  : QObject(lparent)
220  {
222  gCoreContext->GetSetting("VideoAdminPassword"));
224  gCoreContext->GetSetting("VideoAdminPasswordThree"));
226  gCoreContext->GetSetting("VideoAdminPasswordTwo"));
227  }
228 
230  {
231  m_fromLevel = fromLevel;
232  m_toLevel = toLevel;
233  if (DoCheck())
234  {
235  emit SigDone(true, toLevel);
236  }
237  }
238 
239  signals:
240  // NOLINTNEXTLINE(readability-inconsistent-declaration-parameter-name)
241  void SigDone(bool passwordValid, ParentalLevel::Level toLevel);
242 
243  private:
244  // returns true if no completion is required
245  bool DoCheck()
246  {
247  ParentalLevel which_level(m_toLevel);
248 
249  // No password for level 1 and you can always switch down from your
250  // current level.
251  if (which_level == ParentalLevel::plLowest ||
252  which_level <= ParentalLevel(m_fromLevel))
253  return true;
254 
255  // If there isn't a password at the current level, and
256  // none of the levels below, we are done.
257  // The assumption is that if you password protected lower levels,
258  // and a higher level does not have a password it is something
259  // you've overlooked (rather than intended).
260  if (m_pm.FirstAtOrBelow(which_level.GetLevel()).isEmpty())
261  return true;
262 
263  // See if we recently (and successfully) asked for a password
264  QString last_time_stamp = gCoreContext->GetSetting("VideoPasswordTime");
265  int last_parent_lvl = gCoreContext->GetNumSetting("VideoPasswordLevel",
266  -1);
267 
268  if (last_time_stamp.isEmpty() || last_parent_lvl == -1)
269  {
270  LOG(VB_GENERAL, LOG_ERR,
271  QString("%1: Could not read password/pin time "
272  "stamp. This is only an issue if it "
273  "happens repeatedly.").arg(__FILE__));
274  }
275  else
276  {
277  QDateTime curr_time = MythDate::current();
278  QDateTime last_time = MythDate::fromString(last_time_stamp);
279 
280  if (ParentalLevel(last_parent_lvl) >= which_level &&
281  last_time.secsTo(curr_time) < 120)
282  {
283  // Two minute window
284  last_time_stamp = curr_time.toString(Qt::ISODate);
285  gCoreContext->SaveSetting("VideoPasswordTime", last_time_stamp);
286  return true;
287  }
288  }
289 
290  m_validPasswords = m_pm.AtOrAbove(which_level.GetLevel());
291 
292  // If there isn't a password for this level or higher levels, treat
293  // the next lower password as valid. This is only done so people
294  // cannot lock themselves out of the setup.
295  if (m_validPasswords.empty())
296  {
297  QString pw = m_pm.FirstAtOrBelow(which_level.GetLevel());
298  if (!pw.isEmpty())
299  m_validPasswords.push_back(pw);
300  }
301 
302  // There are no suitable passwords.
303  if (m_validPasswords.empty())
304  return true;
305 
306  // If we got here, there is a password, and there's no backing down.
307  m_passwordOK = false;
308  MythScreenStack *popupStack =
309  GetMythMainWindow()->GetStack("popup stack");
310 
311  auto *pwd = new MythTextInputDialog(popupStack,
312  tr("Parental PIN:"), FilterNone, true);
313 
314  connect(pwd, &MythTextInputDialog::haveResult,
317 
318  if (pwd->Create())
319  popupStack->AddScreen(pwd, false);
320 
321  return false;
322  }
323 
324  private slots:
325  void OnPasswordEntered(const QString& password)
326  {
327  m_passwordOK = false;
328 
329  for (const auto& valid_pwd : std::as_const(m_validPasswords))
330  {
331  if (password != valid_pwd)
332  continue;
333 
334  m_passwordOK = true;
335  QString time_stamp = MythDate::current_iso_string();
336 
337  gCoreContext->SaveSetting("VideoPasswordTime", time_stamp);
338  gCoreContext->SaveSetting("VideoPasswordLevel", m_toLevel);
339 
340  return;
341  }
342  }
343 
345  {
347  }
348 
349  private:
350  bool m_passwordOK {false};
353  PasswordManager m_pm;
354  QStringList m_validPasswords;
355 };
356 
358  : m_private(new ParentalLevelChangeCheckerPrivate(this))
359 {
362 }
363 
365  ParentalLevel::Level toLevel)
366 {
367  m_private->Check(fromLevel, toLevel);
368 }
369 
371  ParentalLevel::Level newLevel)
372 {
373  emit SigResultReady(passwordValid, newLevel);
374 }
375 
376 #include "parentalcontrols.moc"
anonymous_namespace{parentalcontrols.cpp}::toParentalLevel
ParentalLevel::Level toParentalLevel(int pl)
Definition: parentalcontrols.cpp:62
operator==
bool operator==(const ParentalLevel &lhs, const ParentalLevel &rhs)
Definition: parentalcontrols.cpp:139
anonymous_namespace{parentalcontrols.cpp}::PasswordManager::Add
void Add(ParentalLevel::Level level, const QString &password)
Definition: parentalcontrols.cpp:172
parentalcontrols.h
mythscreenstack.h
operator>
bool operator>(const ParentalLevel &lhs, const ParentalLevel &rhs)
Definition: parentalcontrols.cpp:149
anonymous_namespace{parentalcontrols.cpp}::PasswordManager::pws
std::map< ParentalLevel::Level, QString > pws
Definition: parentalcontrols.cpp:169
anonymous_namespace{parentalcontrols.cpp}::prevParentalLevel
ParentalLevel::Level prevParentalLevel(ParentalLevel::Level cpl)
Definition: parentalcontrols.cpp:43
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
ParentalLevelChangeCheckerPrivate::m_pm
PasswordManager m_pm
Definition: parentalcontrols.cpp:353
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
ParentalLevelChangeCheckerPrivate::SigDone
void SigDone(bool passwordValid, ParentalLevel::Level toLevel)
ParentalLevel::m_level
Level m_level
Definition: parentalcontrols.h:33
ParentalLevelChangeCheckerPrivate::ParentalLevelChangeCheckerPrivate
ParentalLevelChangeCheckerPrivate(QObject *lparent)
Definition: parentalcontrols.cpp:218
ParentalLevelChangeChecker::m_private
class ParentalLevelChangeCheckerPrivate * m_private
Definition: parentalcontrols.h:60
MythTextInputDialog::haveResult
void haveResult(QString)
ParentalLevelChangeCheckerPrivate::Check
void Check(ParentalLevel::Level fromLevel, ParentalLevel::Level toLevel)
Definition: parentalcontrols.cpp:229
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
operator>=
bool operator>=(const ParentalLevel &lhs, const ParentalLevel &rhs)
Definition: parentalcontrols.cpp:159
anonymous_namespace{parentalcontrols.cpp}::PasswordManager::m_passwords
pws m_passwords
Definition: parentalcontrols.cpp:209
ParentalLevelChangeCheckerPrivate::DoCheck
bool DoCheck()
Definition: parentalcontrols.cpp:245
ParentalLevelChangeChecker::ParentalLevelChangeChecker
ParentalLevelChangeChecker()
Definition: parentalcontrols.cpp:357
ParentalLevel::plLowest
@ plLowest
Definition: parentalcontrols.h:13
mythdate.h
mythlogging.h
operator!=
bool operator!=(const ParentalLevel &lhs, const ParentalLevel &rhs)
Definition: parentalcontrols.cpp:134
hardwareprofile.config.p
p
Definition: config.py:33
ParentalLevel::plLow
@ plLow
Definition: parentalcontrols.h:13
ParentalLevelChangeCheckerPrivate::OnPasswordExit
void OnPasswordExit()
Definition: parentalcontrols.cpp:344
ParentalLevelChangeCheckerPrivate
Definition: parentalcontrols.cpp:213
anonymous_namespace{parentalcontrols.cpp}::PasswordManager::FirstAtOrBelow
QString FirstAtOrBelow(ParentalLevel::Level level)
Definition: parentalcontrols.cpp:191
ParentalLevel::ParentalLevel
ParentalLevel(Level pl)
Definition: parentalcontrols.cpp:68
ParentalLevel::operator=
ParentalLevel & operator=(const ParentalLevel &rhs)
Definition: parentalcontrols.cpp:82
ParentalLevelChangeCheckerPrivate::m_passwordOK
bool m_passwordOK
Definition: parentalcontrols.cpp:350
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
operator<=
bool operator<=(const ParentalLevel &lhs, const ParentalLevel &rhs)
Definition: parentalcontrols.cpp:154
ParentalLevel::plMedium
@ plMedium
Definition: parentalcontrols.h:13
ParentalLevelChangeChecker::SigResultReady
void SigResultReady(bool passwordValid, ParentalLevel::Level newLevel)
FilterNone
@ FilterNone
Definition: mythuitextedit.h:21
ParentalLevel::plNone
@ plNone
Definition: parentalcontrols.h:13
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:919
anonymous_namespace{parentalcontrols.cpp}::boundedParentalLevel
ParentalLevel::Level boundedParentalLevel(ParentalLevel::Level pl)
Definition: parentalcontrols.cpp:14
anonymous_namespace{parentalcontrols.cpp}::nextParentalLevel
ParentalLevel::Level nextParentalLevel(ParentalLevel::Level cpl)
Definition: parentalcontrols.cpp:24
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
operator<
bool operator<(const ParentalLevel &lhs, const ParentalLevel &rhs)
Definition: parentalcontrols.cpp:144
anonymous_namespace{parentalcontrols.cpp}::PasswordManager
Definition: parentalcontrols.cpp:166
ParentalLevel::plHigh
@ plHigh
Definition: parentalcontrols.h:14
anonymous_namespace{parentalcontrols.cpp}::PasswordManager::AtOrAbove
QStringList AtOrAbove(ParentalLevel::Level level)
Definition: parentalcontrols.cpp:177
ParentalLevelChangeChecker::Check
void Check(ParentalLevel::Level fromLevel, ParentalLevel::Level toLevel)
Definition: parentalcontrols.cpp:364
mythcorecontext.h
ParentalLevelChangeChecker::OnResultReady
void OnResultReady(bool passwordValid, ParentalLevel::Level newLevel)
Definition: parentalcontrols.cpp:370
ParentalLevel
Definition: parentalcontrols.h:9
ParentalLevel::operator+=
ParentalLevel & operator+=(int amount)
Definition: parentalcontrols.cpp:108
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
ParentalLevelChangeCheckerPrivate::m_validPasswords
QStringList m_validPasswords
Definition: parentalcontrols.cpp:354
MythDate::current_iso_string
QString current_iso_string(bool stripped)
Returns current Date and Time in UTC as a string.
Definition: mythdate.cpp:23
ParentalLevel::m_hitlimit
bool m_hitlimit
Definition: parentalcontrols.h:34
MythScreenType::Exiting
void Exiting()
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:322
ParentalLevel::operator-=
ParentalLevel & operator-=(int amount)
Definition: parentalcontrols.cpp:123
ParentalLevel::Level
Level
Definition: parentalcontrols.h:12
MythTextInputDialog
Dialog prompting the user to enter a text string.
Definition: mythdialogbox.h:313
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:888
ParentalLevelChangeCheckerPrivate::m_toLevel
ParentalLevel::Level m_toLevel
Definition: parentalcontrols.cpp:352
ParentalLevel::operator--
ParentalLevel & operator--()
Definition: parentalcontrols.cpp:114
mythmainwindow.h
ParentalLevelChangeCheckerPrivate::m_fromLevel
ParentalLevel::Level m_fromLevel
Definition: parentalcontrols.cpp:351
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
ParentalLevel::GetLevel
Level GetLevel() const
Definition: parentalcontrols.cpp:129
ParentalLevelChangeCheckerPrivate::OnPasswordEntered
void OnPasswordEntered(const QString &password)
Definition: parentalcontrols.cpp:325
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:905
ParentalLevel::operator++
ParentalLevel & operator++()
Definition: parentalcontrols.cpp:99