|
MythTV
0.26-pre
|
00001 #include <map> 00002 00003 #include "mythcontext.h" 00004 #include "mythmainwindow.h" 00005 #include "mythscreenstack.h" 00006 #include "mythdialogbox.h" 00007 00008 #include "parentalcontrols.h" 00009 00010 namespace 00011 { 00012 ParentalLevel::Level boundedParentalLevel(ParentalLevel::Level pl) 00013 { 00014 if (pl < ParentalLevel::plNone) 00015 return ParentalLevel::plNone; 00016 else if (pl > ParentalLevel::plHigh) 00017 return ParentalLevel::plHigh; 00018 00019 return pl; 00020 } 00021 00022 ParentalLevel::Level nextParentalLevel(ParentalLevel::Level cpl) 00023 { 00024 ParentalLevel::Level rpl(cpl); 00025 switch (cpl) 00026 { 00027 case ParentalLevel::plNone: 00028 { rpl = ParentalLevel::plLowest; break; } 00029 case ParentalLevel::plLowest: { rpl = ParentalLevel::plLow; break; } 00030 case ParentalLevel::plLow: { rpl = ParentalLevel::plMedium; break; } 00031 case ParentalLevel::plMedium: 00032 { rpl = ParentalLevel::plHigh; break; } 00033 case ParentalLevel::plHigh: { rpl = ParentalLevel::plHigh; break; } 00034 } 00035 00036 return boundedParentalLevel(rpl); 00037 } 00038 00039 ParentalLevel::Level prevParentalLevel(ParentalLevel::Level cpl) 00040 { 00041 ParentalLevel::Level rpl(cpl); 00042 switch (cpl) 00043 { 00044 case ParentalLevel::plNone: { rpl = ParentalLevel::plNone; break; } 00045 case ParentalLevel::plLowest: 00046 { rpl = ParentalLevel::plLowest; break; } 00047 case ParentalLevel::plLow: { rpl = ParentalLevel::plLowest; break; } 00048 case ParentalLevel::plMedium: { rpl = ParentalLevel::plLow; break; } 00049 case ParentalLevel::plHigh: 00050 { rpl = ParentalLevel::plMedium; break; } 00051 } 00052 00053 return boundedParentalLevel(rpl); 00054 } 00055 00056 ParentalLevel::Level toParentalLevel(int pl) 00057 { 00058 return boundedParentalLevel(static_cast<ParentalLevel::Level>(pl)); 00059 } 00060 } 00061 00062 ParentalLevel::ParentalLevel(Level pl) : m_level(pl), 00063 m_hitlimit(false) 00064 { 00065 } 00066 00067 ParentalLevel::ParentalLevel(int pl) : m_hitlimit(false) 00068 { 00069 m_level = toParentalLevel(pl); 00070 } 00071 00072 ParentalLevel::ParentalLevel(const ParentalLevel &rhs) : m_hitlimit(false) 00073 { 00074 *this = rhs; 00075 } 00076 00077 ParentalLevel &ParentalLevel::operator=(const ParentalLevel &rhs) 00078 { 00079 if (&rhs != this) 00080 { 00081 m_level = rhs.m_level; 00082 } 00083 00084 return *this; 00085 } 00086 00087 ParentalLevel &ParentalLevel::operator=(Level pl) 00088 { 00089 m_level = boundedParentalLevel(pl); 00090 return *this; 00091 } 00092 00093 ParentalLevel &ParentalLevel::operator++() 00094 { 00095 Level last = m_level; 00096 m_level = nextParentalLevel(m_level); 00097 if (m_level == last) 00098 m_hitlimit = true; 00099 return *this; 00100 } 00101 00102 ParentalLevel &ParentalLevel::operator+=(int amount) 00103 { 00104 m_level = toParentalLevel(m_level + amount); 00105 return *this; 00106 } 00107 00108 ParentalLevel &ParentalLevel::operator--() 00109 { 00110 Level prev = m_level; 00111 m_level = prevParentalLevel(m_level); 00112 if (m_level == prev) 00113 m_hitlimit = true; 00114 return *this; 00115 } 00116 00117 ParentalLevel &ParentalLevel::operator-=(int amount) 00118 { 00119 m_level = toParentalLevel(m_level - amount); 00120 return *this; 00121 } 00122 00123 ParentalLevel::Level ParentalLevel::GetLevel() const 00124 { 00125 return m_level; 00126 } 00127 00128 bool operator!=(const ParentalLevel &lhs, const ParentalLevel &rhs) 00129 { 00130 return lhs.GetLevel() != rhs.GetLevel(); 00131 } 00132 00133 bool operator==(const ParentalLevel &lhs, const ParentalLevel &rhs) 00134 { 00135 return lhs.GetLevel() == rhs.GetLevel(); 00136 } 00137 00138 bool operator<(const ParentalLevel &lhs, const ParentalLevel &rhs) 00139 { 00140 return lhs.GetLevel() < rhs.GetLevel(); 00141 } 00142 00143 bool operator>(const ParentalLevel &lhs, const ParentalLevel &rhs) 00144 { 00145 return lhs.GetLevel() > rhs.GetLevel(); 00146 } 00147 00148 bool operator<=(const ParentalLevel &lhs, const ParentalLevel &rhs) 00149 { 00150 return lhs.GetLevel() <= rhs.GetLevel(); 00151 } 00152 00153 bool operator>=(const ParentalLevel &lhs, const ParentalLevel &rhs) 00154 { 00155 return lhs.GetLevel() >= rhs.GetLevel(); 00156 } 00157 00158 namespace 00159 { 00160 class PasswordManager 00161 { 00162 private: 00163 typedef std::map<ParentalLevel::Level, QString> pws; 00164 00165 public: 00166 void Add(ParentalLevel::Level level, const QString &password) 00167 { 00168 m_passwords.insert(pws::value_type(level, password)); 00169 } 00170 00171 QStringList AtOrAbove(ParentalLevel::Level level) 00172 { 00173 QStringList ret; 00174 for (ParentalLevel i = level; 00175 i <= ParentalLevel::plHigh && i.good(); ++i) 00176 { 00177 pws::const_iterator p = m_passwords.find(i.GetLevel()); 00178 if (p != m_passwords.end() && p->second.length()) 00179 ret.push_back(p->second); 00180 } 00181 00182 return ret; 00183 } 00184 00185 QString FirstAtOrBelow(ParentalLevel::Level level) 00186 { 00187 QString ret; 00188 for (ParentalLevel i = level; 00189 i >= ParentalLevel::plLow && i.good(); --i) 00190 { 00191 pws::const_iterator p = m_passwords.find(i.GetLevel()); 00192 if (p != m_passwords.end() && p->second.length()) 00193 { 00194 ret = p->second; 00195 break; 00196 } 00197 } 00198 00199 return ret; 00200 } 00201 00202 private: 00203 pws m_passwords; 00204 }; 00205 } 00206 00207 class ParentalLevelChangeCheckerPrivate : public QObject 00208 { 00209 Q_OBJECT 00210 00211 public: 00212 ParentalLevelChangeCheckerPrivate(QObject *lparent) : QObject(lparent) 00213 { 00214 m_pm.Add(ParentalLevel::plHigh, 00215 gCoreContext->GetSetting("VideoAdminPassword")); 00216 m_pm.Add(ParentalLevel::plMedium, 00217 gCoreContext->GetSetting("VideoAdminPasswordThree")); 00218 m_pm.Add(ParentalLevel::plLow, 00219 gCoreContext->GetSetting("VideoAdminPasswordTwo")); 00220 00221 m_passwordOK = false; 00222 } 00223 00224 void Check(ParentalLevel::Level fromLevel, ParentalLevel::Level toLevel) 00225 { 00226 m_fromLevel = fromLevel; 00227 m_toLevel = toLevel; 00228 if (DoCheck()) 00229 { 00230 emit SigDone(true, toLevel); 00231 } 00232 } 00233 00234 signals: 00235 void SigDone(bool passwordValid, ParentalLevel::Level toLevel); 00236 00237 private: 00238 // returns true if no completion is required 00239 bool DoCheck() 00240 { 00241 ParentalLevel which_level(m_toLevel); 00242 00243 // No password for level 1 and you can always switch down from your 00244 // current level. 00245 if (which_level == ParentalLevel::plLowest || 00246 which_level <= ParentalLevel(m_fromLevel)) 00247 return true; 00248 00249 // If there isn't a password at the current level, and 00250 // none of the levels below, we are done. 00251 // The assumption is that if you password protected lower levels, 00252 // and a higher level does not have a password it is something 00253 // you've overlooked (rather than intended). 00254 if (!m_pm.FirstAtOrBelow(which_level.GetLevel()).length()) 00255 return true; 00256 00257 // See if we recently (and successfully) asked for a password 00258 QString last_time_stamp = gCoreContext->GetSetting("VideoPasswordTime"); 00259 int last_parent_lvl = gCoreContext->GetNumSetting("VideoPasswordLevel", 00260 -1); 00261 00262 if (!last_time_stamp.length() || last_parent_lvl == -1) 00263 { 00264 LOG(VB_GENERAL, LOG_ERR, 00265 QString("%1: Could not read password/pin time " 00266 "stamp. This is only an issue if it " 00267 "happens repeatedly.").arg(__FILE__)); 00268 } 00269 else 00270 { 00271 QDateTime curr_time = QDateTime::currentDateTime(); 00272 QDateTime last_time = 00273 QDateTime::fromString(last_time_stamp, Qt::ISODate); 00274 00275 if (ParentalLevel(last_parent_lvl) >= which_level && 00276 last_time.secsTo(curr_time) < 120) 00277 { 00278 // Two minute window 00279 last_time_stamp = curr_time.toString(Qt::ISODate); 00280 gCoreContext->SaveSetting("VideoPasswordTime", last_time_stamp); 00281 return true; 00282 } 00283 } 00284 00285 m_validPasswords = m_pm.AtOrAbove(which_level.GetLevel()); 00286 00287 // If there isn't a password for this level or higher levels, treat 00288 // the next lower password as valid. This is only done so people 00289 // cannot lock themselves out of the setup. 00290 if (!m_validPasswords.size()) 00291 { 00292 QString pw = m_pm.FirstAtOrBelow(which_level.GetLevel()); 00293 if (pw.length()) 00294 m_validPasswords.push_back(pw); 00295 } 00296 00297 // There are no suitable passwords. 00298 if (!m_validPasswords.size()) 00299 return true; 00300 00301 // If we got here, there is a password, and there's no backing down. 00302 m_passwordOK = false; 00303 MythScreenStack *popupStack = 00304 GetMythMainWindow()->GetStack("popup stack"); 00305 00306 MythTextInputDialog *pwd = 00307 new MythTextInputDialog(popupStack, 00308 QObject::tr("Parental PIN:"), FilterNone, true); 00309 00310 connect(pwd, SIGNAL(haveResult(QString)), 00311 SLOT(OnPasswordEntered(QString))); 00312 connect(pwd, SIGNAL(Exiting()), SLOT(OnPasswordExit())); 00313 00314 if (pwd->Create()) 00315 popupStack->AddScreen(pwd, false); 00316 00317 return false; 00318 } 00319 00320 private slots: 00321 void OnPasswordEntered(QString password) 00322 { 00323 m_passwordOK = false; 00324 00325 for (QStringList::iterator p = m_validPasswords.begin(); 00326 p != m_validPasswords.end(); ++p) 00327 { 00328 if (password == *p) 00329 { 00330 m_passwordOK = true; 00331 QString time_stamp = 00332 QDateTime::currentDateTime().toString(Qt::ISODate); 00333 00334 gCoreContext->SaveSetting("VideoPasswordTime", time_stamp); 00335 gCoreContext->SaveSetting("VideoPasswordLevel", m_toLevel); 00336 00337 break; 00338 } 00339 } 00340 } 00341 00342 void OnPasswordExit() 00343 { 00344 emit SigDone(m_passwordOK, m_passwordOK ? m_toLevel : m_fromLevel); 00345 } 00346 00347 private: 00348 bool m_passwordOK; 00349 ParentalLevel::Level m_fromLevel; 00350 ParentalLevel::Level m_toLevel; 00351 PasswordManager m_pm; 00352 QStringList m_validPasswords; 00353 }; 00354 00355 ParentalLevelChangeChecker::ParentalLevelChangeChecker() 00356 { 00357 m_private = new ParentalLevelChangeCheckerPrivate(this); 00358 connect(m_private, SIGNAL(SigDone(bool, ParentalLevel::Level)), 00359 SLOT(OnResultReady(bool, ParentalLevel::Level))); 00360 } 00361 00362 void ParentalLevelChangeChecker::Check(ParentalLevel::Level fromLevel, 00363 ParentalLevel::Level toLevel) 00364 { 00365 m_private->Check(fromLevel, toLevel); 00366 } 00367 00368 void ParentalLevelChangeChecker::OnResultReady(bool passwordValid, 00369 ParentalLevel::Level newLevel) 00370 { 00371 emit SigResultReady(passwordValid, newLevel); 00372 } 00373 00374 #include "parentalcontrols.moc"
1.7.6.1