MythTV master
v2myth.cpp
Go to the documentation of this file.
1// Qt
2#include <QDir>
3#include <QFileInfo>
4#include <QCryptographicHash>
5#include <QHostAddress>
6#include <QUdpSocket>
7#include <QNetworkRequest>
8
9// MythTV
10#include "libmythbase/mythconfig.h"
11#include "libmythbase/dbutil.h"
17#include "libmythbase/mythdb.h"
21#include "libmythbase/mythversion.h"
24#include "libmythtv/tv_rec.h"
25
26// MythBackend
27#include "scheduler.h"
28#include "v2databaseInfo.h"
29#include "v2myth.h"
30#include "v2serviceUtil.h"
31#include "v2versionInfo.h"
32#include "v2wolInfo.h"
33
34#if CONFIG_SYSTEMD_NOTIFY
35#include <systemd/sd-daemon.h>
36static inline void api_sd_notify(const char *str) { sd_notify(0, str); };
37#else
38static inline void api_sd_notify(const char */*str*/) {};
39#endif
40
41// This will be initialised in a thread safe manner on first use
43 (MYTH_HANDLE, V2Myth::staticMetaObject, &V2Myth::RegisterCustomTypes))
44
46{
47 qRegisterMetaType<V2ConnectionInfo*>("V2ConnectionInfo");
48 qRegisterMetaType<V2VersionInfo*>("V2VersionInfo");
49 qRegisterMetaType<V2DatabaseInfo*>("V2DatabaseInfo");
50 qRegisterMetaType<V2WOLInfo*>("V2WOLInfo");
51 qRegisterMetaType<V2StorageGroupDirList*>("V2StorageGroupDirList");
52 qRegisterMetaType<V2StorageGroupDir*>("V2StorageGroupDir");
53 qRegisterMetaType<V2TimeZoneInfo*>("V2TimeZoneInfo");
54 qRegisterMetaType<V2LogMessage*>("V2LogMessage");
55 qRegisterMetaType<V2LogMessageList*>("V2LogMessageList");
56 qRegisterMetaType<V2LabelValue*>("V2LabelValue");
57 qRegisterMetaType<V2Frontend*>("V2Frontend");
58 qRegisterMetaType<V2FrontendList*>("V2FrontendList");
59 qRegisterMetaType<V2SettingList*>("V2SettingList");
60 qRegisterMetaType<V2BackendInfo*>("V2BackendInfo");
61 qRegisterMetaType<V2EnvInfo*>("V2EnvInfo");
62 qRegisterMetaType<V2LogInfo*>("V2LogInfo");
63 qRegisterMetaType<V2BuildInfo*>("V2BuildInfo");
64}
65
66
68 : MythHTTPService(s_service)
69{
70}
71
73//
75
77{
78 QString sSecurityPin = gCoreContext->GetSetting( "SecurityPin", "");
79
80 if ( sSecurityPin.isEmpty() )
81 throw( QString( "No Security Pin assigned. Run mythtv-setup to set one." ));
82 //SB: UPnPResult_HumanInterventionRequired,
83
84 if ((sSecurityPin != "0000" ) && ( sPin != sSecurityPin ))
85 throw( QString( "Not Authorized" ));
86 //SB: UPnPResult_ActionNotAuthorized );
87
88 DatabaseParams params = GetMythDB()->GetDatabaseParams();
89
90 // ----------------------------------------------------------------------
91 // Check for DBHostName of "localhost" and change to public name or IP
92 // ----------------------------------------------------------------------
93
94 QString sServerIP = gCoreContext->GetBackendServerIP();
95 //QString sPeerIP = pRequest->GetPeerAddress();
96
97 if ((params.m_dbHostName.compare("localhost",Qt::CaseInsensitive)==0
98 || params.m_dbHostName == "127.0.0.1"
99 || params.m_dbHostName == "::1")
100 && !sServerIP.isEmpty()) // &&
101 //(sServerIP != sPeerIP ))
102 {
103 params.m_dbHostName = sServerIP;
104 }
105
106 // If dbHostName is an IPV6 address with scope,
107 // remove the scope. Unescaped % signs are an
108 // xml violation
109 QString dbHostName(params.m_dbHostName);
110 QHostAddress addr;
111 if (addr.setAddress(dbHostName))
112 {
113 addr.setScopeId(QString());
114 dbHostName = addr.toString();
115 }
116 // ----------------------------------------------------------------------
117 // Create and populate a ConnectionInfo object
118 // ----------------------------------------------------------------------
119
120 auto *pInfo = new V2ConnectionInfo();
121 V2DatabaseInfo *pDatabase = pInfo->Database();
122 V2WOLInfo *pWOL = pInfo->WOL();
123 V2VersionInfo *pVersion = pInfo->Version();
124
125 pDatabase->setHost ( dbHostName );
126 pDatabase->setPing ( params.m_dbHostPing );
127 pDatabase->setPort ( params.m_dbPort );
128 pDatabase->setUserName ( params.m_dbUserName );
129 pDatabase->setPassword ( params.m_dbPassword );
130 pDatabase->setName ( params.m_dbName );
131 pDatabase->setType ( params.m_dbType );
132 pDatabase->setLocalEnabled ( params.m_localEnabled );
133 pDatabase->setLocalHostName( params.m_localHostName );
134
135 pWOL->setEnabled ( params.m_wolEnabled );
136 pWOL->setReconnect ( params.m_wolReconnect.count() );
137 pWOL->setRetry ( params.m_wolRetry );
138 pWOL->setCommand ( params.m_wolCommand );
139
140 pVersion->setVersion ( GetMythSourceVersion());
141 pVersion->setBranch ( GetMythSourcePath() );
142 pVersion->setProtocol ( MYTH_PROTO_VERSION );
143 pVersion->setBinary ( MYTH_BINARY_VERSION );
144 pVersion->setSchema ( MYTH_DATABASE_VERSION );
145
146 // ----------------------------------------------------------------------
147 // Return the pointer... caller is responsible to delete it!!!
148 // ----------------------------------------------------------------------
149
150 return pInfo;
151}
152
154//
156bool V2Myth::SetConnectionInfo(const QString &Host, const QString &UserName, const QString &Password, const QString &Name, int Port, bool DoTest)
157{
158 bool bResult = false;
159
160 QString db("mythconverg");
161 int port = 3306;
162
163 if (!Name.isEmpty())
164 db = Name;
165
166 if (Port != 0)
167 port = Port;
168
169 if (DoTest && !TestDatabase(Host, UserName, Password, db, port))
170 throw( QString( "Database test failed. Not saving database connection information." ));
171
172 DatabaseParams dbparms;
173 dbparms.m_dbName = db;
174 dbparms.m_dbUserName = UserName;
175 dbparms.m_dbPassword = Password;
176 dbparms.m_dbHostName = Host;
177 dbparms.m_dbPort = port;
178
179 // Just use some sane defaults for these values
180 dbparms.m_wolEnabled = false;
181 dbparms.m_wolReconnect = 1s;
182 dbparms.m_wolRetry = 3;
183 dbparms.m_wolCommand = QString();
184
185 bResult = GetMythDB()->SaveDatabaseParams(dbparms, false);
186
187 return bResult;
188}
189
191//
193
195{
196 if (!gCoreContext)
197 throw( QString( "No MythCoreContext in GetHostName." ));
198
199 return gCoreContext->GetHostName();
200}
201
203//
205
206QStringList V2Myth::GetHosts( )
207{
209
210 if (!query.isConnected())
211 throw( QString( "Database not open while trying to load list of hosts" ));
212
213 query.prepare(
214 "SELECT DISTINCTROW hostname "
215 "FROM settings "
216 "WHERE (not isNull( hostname ))");
217
218 if (!query.exec())
219 {
220 MythDB::DBError("MythAPI::GetHosts()", query);
221
222 throw( QString( "Database Error executing query." ));
223 }
224
225 // ----------------------------------------------------------------------
226 // return the results of the query
227 // ----------------------------------------------------------------------
228
229 QStringList oList;
230
231 while (query.next())
232 oList.append( query.value(0).toString() );
233
234 return oList;
235}
236
238//
240
241QStringList V2Myth::GetKeys()
242{
244
245 if (!query.isConnected())
246 throw( QString("Database not open while trying to load settings"));
247
248 query.prepare("SELECT DISTINCTROW value FROM settings;" );
249
250 if (!query.exec())
251 {
252 MythDB::DBError("MythAPI::GetKeys()", query);
253
254 throw( QString( "Database Error executing query." ));
255 }
256
257 // ----------------------------------------------------------------------
258 // return the results of the query
259 // ----------------------------------------------------------------------
260
261 QStringList oResults;
262
263 //pResults->setObjectName( "KeyList" );
264
265 while (query.next())
266 oResults.append( query.value(0).toString() );
267
268 return oResults;
269}
270
272// DirListing gets a list of subdirectories
274
275QStringList V2Myth::GetDirListing ( const QString &DirName, bool Files)
276{
277 QDir directory(DirName);
278 QDir::Filters filts = QDir::AllDirs|QDir::NoDotAndDotDot;
279 if (Files)
280 filts = QDir::Files;
281 else
282 filts = QDir::AllDirs|QDir::NoDotAndDotDot;
283 return directory.entryList(filts, QDir::Name);
284}
285
286
288//
291 const QString &sHostName )
292{
294
295 if (!query.isConnected())
296 throw( QString("Database not open while trying to list "
297 "Storage Group Dirs"));
298
299 if (!sGroupName.isEmpty() && !sHostName.isEmpty())
300 {
301 query.prepare("SELECT id, groupname, hostname, dirname "
302 "FROM storagegroup "
303 "WHERE groupname = :GROUP AND hostname = :HOST "
304 "ORDER BY groupname, hostname, dirname" );
305 query.bindValue(":HOST", sHostName);
306 query.bindValue(":GROUP", sGroupName);
307 }
308 else if (!sHostName.isEmpty())
309 {
310 query.prepare("SELECT id, groupname, hostname, dirname "
311 "FROM storagegroup "
312 "WHERE hostname = :HOST "
313 "ORDER BY groupname, hostname, dirname" );
314 query.bindValue(":HOST", sHostName);
315 }
316 else if (!sGroupName.isEmpty())
317 {
318 query.prepare("SELECT id, groupname, hostname, dirname "
319 "FROM storagegroup "
320 "WHERE groupname = :GROUP "
321 "ORDER BY groupname, hostname, dirname" );
322 query.bindValue(":GROUP", sGroupName);
323 }
324 else
325 {
326 query.prepare("SELECT id, groupname, hostname, dirname "
327 "FROM storagegroup "
328 "ORDER BY groupname, hostname, dirname" );
329 }
330
331 if (!query.exec())
332 {
333 MythDB::DBError("MythAPI::GetStorageGroupDirs()", query);
334
335 throw( QString( "Database Error executing query." ));
336 }
337
338 // ----------------------------------------------------------------------
339 // return the results of the query plus R/W and size information
340 // ----------------------------------------------------------------------
341
342 auto* pList = new V2StorageGroupDirList();
343
344 while (query.next())
345 {
346 V2StorageGroupDir *pStorageGroupDir = pList->AddNewStorageGroupDir();
347 QFileInfo fi(query.value(3).toString());
348 auto fsInfo = FileSystemInfo(QString(), query.value(3).toString());
349
350 pStorageGroupDir->setId ( query.value(0).toInt() );
351 pStorageGroupDir->setGroupName ( query.value(1).toString() );
352 pStorageGroupDir->setHostName ( query.value(2).toString() );
353 pStorageGroupDir->setDirName ( query.value(3).toString() );
354 pStorageGroupDir->setDirRead ( fi.isReadable() );
355 pStorageGroupDir->setDirWrite ( fi.isWritable() );
356 pStorageGroupDir->setKiBFree ( fsInfo.getFreeSpace() );
357 }
358
359 return pList;
360}
361
363//
365
366bool V2Myth::AddStorageGroupDir( const QString &sGroupName,
367 const QString &sDirName,
368 const QString &sHostName )
369{
371
372 if (!query.isConnected())
373 throw( QString("Database not open while trying to add Storage Group "
374 "dir"));
375
376 if (sGroupName.isEmpty())
377 throw ( QString( "Storage Group Required" ));
378
379 if (sDirName.isEmpty())
380 throw ( QString( "Directory Name Required" ));
381
382 if (sHostName.isEmpty())
383 throw ( QString( "HostName Required" ));
384
385 query.prepare("SELECT COUNT(*) "
386 "FROM storagegroup "
387 "WHERE groupname = :GROUPNAME "
388 "AND dirname = :DIRNAME "
389 "AND hostname = :HOSTNAME;");
390 query.bindValue(":GROUPNAME", sGroupName );
391 query.bindValue(":DIRNAME" , sDirName );
392 query.bindValue(":HOSTNAME" , sHostName );
393 if (!query.exec())
394 {
395 MythDB::DBError("MythAPI::AddStorageGroupDir()", query);
396
397 throw( QString( "Database Error executing query." ));
398 }
399
400 if (query.next())
401 {
402 if (query.value(0).toInt() > 0)
403 return false;
404 }
405
406 query.prepare("INSERT storagegroup "
407 "( groupname, dirname, hostname ) "
408 "VALUES "
409 "( :GROUPNAME, :DIRNAME, :HOSTNAME );");
410 query.bindValue(":GROUPNAME", sGroupName );
411 query.bindValue(":DIRNAME" , sDirName );
412 query.bindValue(":HOSTNAME" , sHostName );
413
414 if (!query.exec())
415 {
416 MythDB::DBError("MythAPI::AddStorageGroupDir()", query);
417
418 throw( QString( "Database Error executing query." ));
419 }
420
421 return true;
422}
423
425//
427
428bool V2Myth::RemoveStorageGroupDir( const QString &sGroupName,
429 const QString &sDirName,
430 const QString &sHostName )
431{
433
434 if (!query.isConnected())
435 throw( QString("Database not open while trying to remove Storage "
436 "Group dir"));
437
438 if (sGroupName.isEmpty())
439 throw ( QString( "Storage Group Required" ));
440
441 if (sDirName.isEmpty())
442 throw ( QString( "Directory Name Required" ));
443
444 if (sHostName.isEmpty())
445 throw ( QString( "HostName Required" ));
446
447 query.prepare("DELETE "
448 "FROM storagegroup "
449 "WHERE groupname = :GROUPNAME "
450 "AND dirname = :DIRNAME "
451 "AND hostname = :HOSTNAME;");
452 query.bindValue(":GROUPNAME", sGroupName );
453 query.bindValue(":DIRNAME" , sDirName );
454 query.bindValue(":HOSTNAME" , sHostName );
455 if (!query.exec())
456 {
457 MythDB::DBError("MythAPI::RemoveStorageGroupDir()", query);
458
459 throw( QString( "Database Error executing query." ));
460 }
461
462 return true;
463}
464
466//
468
470{
471 auto *pResults = new V2TimeZoneInfo();
472
473 pResults->setTimeZoneID( MythTZ::getTimeZoneID() );
474 pResults->setUTCOffset( MythTZ::calc_utc_offset() );
475 pResults->setCurrentDateTime( MythDate::current(true) );
476
477 return pResults;
478}
479
481//
483
484QString V2Myth::GetFormatDate(const QDateTime &Date, bool ShortDate)
485{
487 if (ShortDate)
489
490 return MythDate::toString(Date, dateFormat);
491}
492
494//
496
497QString V2Myth::GetFormatDateTime(const QDateTime &DateTime, bool ShortDate)
498{
500 if (ShortDate)
502
503 return MythDate::toString(DateTime, dateFormat);
504}
505
507//
509
510QString V2Myth::GetFormatTime(const QDateTime &Time)
511{
513}
514
516//
518
519QDateTime V2Myth::ParseISODateString(const QString& DateTime)
520{
521 auto dateTime = QDateTime::fromString(DateTime, Qt::ISODate);
522
523 if (!dateTime.isValid())
524 throw QString( "Unable to parse DateTime" );
525
526 return dateTime;
527}
528
530//
532
533V2LogMessageList* V2Myth::GetLogs( const QString &HostName,
534 const QString &Application,
535 int PID,
536 int TID,
537 const QString &Thread,
538 const QString &Filename,
539 int Line,
540 const QString &Function,
541 const QDateTime &FromTime,
542 const QDateTime &ToTime,
543 const QString &Level,
544 const QString &MsgContains )
545{
546 auto *pList = new V2LogMessageList();
547
549
550 // Get host name list
551 QString sql = "SELECT DISTINCT host FROM logging ORDER BY host ASC";
552 if (!query.exec(sql))
553 {
554 MythDB::DBError("Retrieving log host names", query);
555 delete pList;
556 throw( QString( "Database Error executing query." ));
557 }
558 while (query.next())
559 {
560 V2LabelValue *pLabelValue = pList->AddNewHostName();
561 QString availableHostName = query.value(0).toString();
562 pLabelValue->setValue ( availableHostName );
563 pLabelValue->setActive ( availableHostName == HostName );
564 pLabelValue->setSelected( availableHostName == HostName );
565 }
566 // Get application list
567 sql = "SELECT DISTINCT application FROM logging ORDER BY application ASC";
568 if (!query.exec(sql))
569 {
570 MythDB::DBError("Retrieving log applications", query);
571 delete pList;
572 throw( QString( "Database Error executing query." ));
573 }
574 while (query.next())
575 {
576 V2LabelValue *pLabelValue = pList->AddNewApplication();
577 QString availableApplication = query.value(0).toString();
578 pLabelValue->setValue ( availableApplication );
579 pLabelValue->setActive ( availableApplication == Application );
580 pLabelValue->setSelected( availableApplication == Application );
581 }
582
583 if (!HostName.isEmpty() && !Application.isEmpty())
584 {
585 // Get log messages
586 sql = "SELECT host, application, pid, tid, thread, filename, "
587 " line, function, msgtime, level, message "
588 " FROM logging "
589 " WHERE host = COALESCE(:HOSTNAME, host) "
590 " AND application = COALESCE(:APPLICATION, application) "
591 " AND pid = COALESCE(:PID, pid) "
592 " AND tid = COALESCE(:TID, tid) "
593 " AND thread = COALESCE(:THREAD, thread) "
594 " AND filename = COALESCE(:FILENAME, filename) "
595 " AND line = COALESCE(:LINE, line) "
596 " AND function = COALESCE(:FUNCTION, function) "
597 " AND msgtime >= COALESCE(:FROMTIME, msgtime) "
598 " AND msgtime <= COALESCE(:TOTIME, msgtime) "
599 " AND level <= COALESCE(:LEVEL, level) "
600 ;
601 if (!MsgContains.isEmpty())
602 {
603 sql.append(" AND message LIKE :MSGCONTAINS ");
604 }
605 sql.append(" ORDER BY msgtime ASC;");
606
607#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
608 QVariant ullNull = QVariant(QVariant::ULongLong);
609#else
610 QVariant ullNull = QVariant(QMetaType(QMetaType::ULongLong));
611#endif
612 query.prepare(sql);
613
614 query.bindValue(":HOSTNAME", (HostName.isEmpty()) ? QString() : HostName);
615 query.bindValue(":APPLICATION", (Application.isEmpty()) ? QString() :
616 Application);
617 query.bindValue(":PID", ( PID == 0 ) ? ullNull : (qint64)PID);
618 query.bindValue(":TID", ( TID == 0 ) ? ullNull : (qint64)TID);
619 query.bindValue(":THREAD", (Thread.isEmpty()) ? QString() : Thread);
620 query.bindValue(":FILENAME", (Filename.isEmpty()) ? QString() : Filename);
621 query.bindValue(":LINE", ( Line == 0 ) ? ullNull : (qint64)Line);
622 query.bindValue(":FUNCTION", (Function.isEmpty()) ? QString() : Function);
623 query.bindValue(":FROMTIME", (FromTime.isValid()) ? FromTime : QDateTime());
624 query.bindValue(":TOTIME", (ToTime.isValid()) ? ToTime : QDateTime());
625 query.bindValue(":LEVEL", (Level.isEmpty()) ? ullNull :
626 (qint64)logLevelGet(Level));
627
628 if (!MsgContains.isEmpty())
629 {
630 query.bindValue(":MSGCONTAINS", "%" + MsgContains + "%" );
631 }
632
633 if (!query.exec())
634 {
635 MythDB::DBError("Retrieving log messages", query);
636 delete pList;
637 throw( QString( "Database Error executing query." ));
638 }
639
640 while (query.next())
641 {
642 V2LogMessage *pLogMessage = pList->AddNewLogMessage();
643
644 pLogMessage->setHostName( query.value(0).toString() );
645 pLogMessage->setApplication( query.value(1).toString() );
646 pLogMessage->setPID( query.value(2).toInt() );
647 pLogMessage->setTID( query.value(3).toInt() );
648 pLogMessage->setThread( query.value(4).toString() );
649 pLogMessage->setFilename( query.value(5).toString() );
650 pLogMessage->setLine( query.value(6).toInt() );
651 pLogMessage->setFunction( query.value(7).toString() );
652 pLogMessage->setTime(MythDate::as_utc(query.value(8).toDateTime()));
653 pLogMessage->setLevel( logLevelGetName(
654 (LogLevel_t)query.value(9).toInt()) );
655 pLogMessage->setMessage( query.value(10).toString() );
656 }
657 }
658
659 return pList;
660}
661
663//
665
667{
668 auto *pList = new V2FrontendList();
669
670 FillFrontendList(pList->GetFrontends(), pList,
671 OnLine);
672 return pList;
673}
674
676//
678
679QString V2Myth::GetSetting( const QString &sHostName,
680 const QString &sKey,
681 const QString &sDefault )
682{
683 if (sKey.isEmpty())
684 throw( QString("Missing or empty Key (settings.value)") );
685
686 if (sHostName == "_GLOBAL_")
687 {
689
690 query.prepare("SELECT data FROM settings "
691 "WHERE value = :VALUE "
692 "AND (hostname IS NULL)" );
693
694 query.bindValue(":VALUE", sKey );
695
696 if (!query.exec())
697 {
698 MythDB::DBError("API Myth/GetSetting ", query);
699 throw( QString( "Database Error executing query." ));
700 }
701
702 return query.next() ? query.value(0).toString() : sDefault;
703 }
704
705 QString hostname = sHostName;
706
707 if (sHostName.isEmpty())
709
710 return gCoreContext->GetSettingOnHost(sKey, hostname, sDefault);
711}
712
714//
716
717V2SettingList* V2Myth::GetSettingList(const QString &sHostName)
718{
719
721
722 if (!query.isConnected())
723 {
724 throw( QString("Database not open while trying to load settings for host: %1")
725 .arg( sHostName ));
726 }
727
728 auto *pList = new V2SettingList();
729
730 pList->setHostName ( sHostName );
731
732 // ------------------------------------------------------------------
733 // Looking to return all Setting for supplied hostname
734 // ------------------------------------------------------------------
735
736 if (sHostName.isEmpty())
737 {
738 query.prepare("SELECT value, data FROM settings "
739 "WHERE (hostname IS NULL)" );
740 }
741 else
742 {
743 query.prepare("SELECT value, data FROM settings "
744 "WHERE (hostname = :HOSTNAME)" );
745
746 query.bindValue(":HOSTNAME", sHostName );
747 }
748
749 if (!query.exec())
750 {
751 // clean up unused object we created.
752
753 delete pList;
754
755 MythDB::DBError("MythAPI::GetSetting() w/o key ", query);
756 throw( QString( "Database Error executing query." ));
757 }
758
759 while (query.next())
760 pList->Settings().insert( query.value(0).toString(), query.value(1) );
761
762 return pList;
763}
764
766//
768
769bool V2Myth::PutSetting( const QString &sHostName,
770 const QString &sKey,
771 const QString &sValue )
772{
773 QString hostName = sHostName;
774
775 if (sKey.toLower() == "apiauthreqd")
776 {
777 QString authorization = MythHTTP::GetHeader(m_request->m_headers,
778 "authorization").trimmed();
779 if (authorization.isEmpty())
780 authorization = m_request->m_queries.value("authorization",{});
782 if (sessionManager->GetSession(authorization).GetUserName() != "admin")
783 throw QString ("Forbidden: PutSetting " + sKey);
784 }
785
786 if (hostName == "_GLOBAL_")
787 hostName = "";
788
789 if (!sKey.isEmpty())
790 {
791 return gCoreContext->SaveSettingOnHost( sKey, sValue, hostName );
792 }
793
794 throw ( QString( "Key Required" ));
795}
796
798//
800
801bool V2Myth::DeleteSetting( const QString &sHostName,
802 const QString &sKey)
803{
804 QString hostName = sHostName;
805
806 if (hostName == "_GLOBAL_")
807 hostName = "";
808
809 if (!sKey.isEmpty())
810 {
811 return gCoreContext->GetDB()->ClearSettingOnHost( sKey, hostName );
812 }
813
814 throw ( QString( "Key Required" ));
815}
816
817
819//
821
822bool V2Myth::TestDBSettings( const QString &sHostName,
823 const QString &sUserName,
824 const QString &sPassword,
825 const QString &sDBName,
826 int dbPort)
827{
828 bool bResult = false;
829
830 QString db("mythconverg");
831 int port = 3306;
832
833 if (!sDBName.isEmpty())
834 db = sDBName;
835
836 if (dbPort != 0)
837 port = dbPort;
838
839 bResult = TestDatabase(sHostName, sUserName, sPassword, db, port);
840
841 return bResult;
842}
843
845//
847
848bool V2Myth::SendMessage( const QString &sMessage,
849 const QString &sAddress,
850 int udpPort,
851 int Timeout)
852{
853 bool bResult = false;
854
855 if (sMessage.isEmpty())
856 return bResult;
857
858 if (Timeout < 0 || Timeout > 999)
859 Timeout = 0;
860
861 QString xmlMessage =
862 "<mythmessage version=\"1\">\n"
863 " <text>" + sMessage + "</text>\n"
864 " <timeout>" + QString::number(Timeout) + "</timeout>\n"
865 "</mythmessage>";
866
867 QHostAddress address = QHostAddress::Broadcast;
868 unsigned short port = 6948;
869
870 if (!sAddress.isEmpty())
871 address.setAddress(sAddress);
872
873 if (udpPort != 0)
874 port = udpPort;
875
876 auto *sock = new QUdpSocket();
877 QByteArray utf8 = xmlMessage.toUtf8();
878 int size = utf8.length();
879
880 if (sock->writeDatagram(utf8.constData(), size, address, port) < 0)
881 {
882 LOG(VB_GENERAL, LOG_ERR,
883 QString("Failed to send UDP/XML packet (Message: %1 "
884 "Address: %2 Port: %3")
885 .arg(sMessage, sAddress, QString::number(port)));
886 }
887 else
888 {
889 LOG(VB_GENERAL, LOG_DEBUG,
890 QString("UDP/XML packet sent! (Message: %1 Address: %2 Port: %3")
891 .arg(sMessage,
892 address.toString().toLocal8Bit(),
893 QString::number(port)));
894 bResult = true;
895 }
896
897 sock->deleteLater();
898
899 return bResult;
900}
901
902bool V2Myth::SendNotification( bool bError,
903 const QString &Type,
904 const QString &sMessage,
905 const QString &sOrigin,
906 const QString &sDescription,
907 const QString &sImage,
908 const QString &sExtra,
909 const QString &sProgressText,
910 float fProgress,
911 int Timeout,
912 bool bFullscreen,
913 uint Visibility,
915 const QString &sAddress,
916 int udpPort )
917{
918 bool bResult = false;
919
920 if (sMessage.isEmpty())
921 return bResult;
922
923 if (Timeout < 0 || Timeout > 999)
924 Timeout = -1;
925
926 QString xmlMessage =
927 "<mythnotification version=\"1\">\n"
928 " <text>" + sMessage + "</text>\n"
929 " <origin>" + (sOrigin.isNull() ? tr("MythServices") : sOrigin) + "</origin>\n"
930 " <description>" + sDescription + "</description>\n"
931 " <timeout>" + QString::number(Timeout) + "</timeout>\n"
932 " <image>" + sImage + "</image>\n"
933 " <extra>" + sExtra + "</extra>\n"
934 " <progress_text>" + sProgressText + "</progress_text>\n"
935 " <progress>" + QString::number(fProgress) + "</progress>\n"
936 " <fullscreen>" + (bFullscreen ? "true" : "false") + "</fullscreen>\n"
937 " <visibility>" + QString::number(Visibility) + "</visibility>\n"
938 " <priority>" + QString::number(Priority) + "</priority>\n"
939 " <type>" + (bError ? "error" : Type) + "</type>\n"
940 "</mythnotification>";
941
942 QHostAddress address = QHostAddress::Broadcast;
943 unsigned short port = 6948;
944
945 if (!sAddress.isEmpty())
946 address.setAddress(sAddress);
947
948 if (udpPort != 0)
949 port = udpPort;
950
951 auto *sock = new QUdpSocket();
952 QByteArray utf8 = xmlMessage.toUtf8();
953 int size = utf8.length();
954
955 if (sock->writeDatagram(utf8.constData(), size, address, port) < 0)
956 {
957 LOG(VB_GENERAL, LOG_ERR,
958 QString("Failed to send UDP/XML packet (Notification: %1 "
959 "Address: %2 Port: %3")
960 .arg(sMessage, sAddress, QString::number(port)));
961 }
962 else
963 {
964 LOG(VB_GENERAL, LOG_DEBUG,
965 QString("UDP/XML packet sent! (Notification: %1 Address: %2 Port: %3")
966 .arg(sMessage,
967 address.toString().toLocal8Bit(), QString::number(port)));
968 bResult = true;
969 }
970
971 sock->deleteLater();
972
973 return bResult;
974}
975
977//
979
981{
982 bool bResult = false;
983
984 DBUtil dbutil;
986 QString filename;
987
988 LOG(VB_GENERAL, LOG_NOTICE, "Performing API invoked DB Backup.");
989
990 status = DBUtil::BackupDB(filename);
991
992 if (status == kDB_Backup_Completed)
993 {
994 LOG(VB_GENERAL, LOG_NOTICE, "Database backup succeeded.");
995 bResult = true;
996 }
997 else
998 {
999 LOG(VB_GENERAL, LOG_ERR, "Database backup failed.");
1000 }
1001
1002 return bResult;
1003}
1004
1006//
1008
1009bool V2Myth::CheckDatabase( bool repair )
1010{
1011 LOG(VB_GENERAL, LOG_NOTICE, "Performing API invoked DB Check.");
1012
1013 bool bResult = DBUtil::CheckTables(repair);
1014
1015 if (bResult)
1016 LOG(VB_GENERAL, LOG_NOTICE, "Database check complete.");
1017 else
1018 LOG(VB_GENERAL, LOG_ERR, "Database check failed.");
1019
1020 return bResult;
1021}
1022
1024{
1025 auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
1026 if (scheduler == nullptr)
1027 return false;
1028 scheduler->DelayShutdown();
1029 LOG(VB_GENERAL, LOG_NOTICE, "Shutdown delayed 5 minutes for external application.");
1030 return true;
1031}
1032
1034//
1036
1038{
1040 LOG(VB_GENERAL, LOG_NOTICE, "Profile Submission...");
1041 profile.GenerateUUIDs();
1042 bool bResult = profile.SubmitProfile();
1043 if (bResult)
1044 LOG(VB_GENERAL, LOG_NOTICE, "Profile Submitted.");
1045
1046 return bResult;
1047}
1048
1050//
1052
1054{
1056 LOG(VB_GENERAL, LOG_NOTICE, "Profile Deletion...");
1057 profile.GenerateUUIDs();
1058 bool bResult = profile.DeleteProfile();
1059 if (bResult)
1060 LOG(VB_GENERAL, LOG_NOTICE, "Profile Deleted.");
1061
1062 return bResult;
1063}
1064
1066//
1068
1070{
1071 QString sProfileURL;
1072
1074 profile.GenerateUUIDs();
1075 sProfileURL = profile.GetProfileURL();
1076 LOG(VB_GENERAL, LOG_NOTICE, QString("ProfileURL: %1").arg(sProfileURL));
1077
1078 return sProfileURL;
1079}
1080
1082//
1084
1086{
1087 QString sProfileUpdate;
1088
1090 profile.GenerateUUIDs();
1091 QDateTime tUpdated;
1092 tUpdated = profile.GetLastUpdate();
1093 sProfileUpdate = tUpdated.toString(
1094 gCoreContext->GetSetting( "DateFormat", "MM.dd.yyyy"));
1095
1096 return sProfileUpdate;
1097}
1098
1100//
1102
1104{
1105 QString sProfileText;
1106
1108 sProfileText = HardwareProfile::GetHardwareProfile();
1109
1110 return sProfileText;
1111}
1112
1114//
1116
1118{
1119
1120 // ----------------------------------------------------------------------
1121 // Create and populate a Configuration object
1122 // ----------------------------------------------------------------------
1123
1124 auto *pInfo = new V2BackendInfo();
1125 V2BuildInfo *pBuild = pInfo->Build();
1126 V2EnvInfo *pEnv = pInfo->Env();
1127 V2LogInfo *pLog = pInfo->Log();
1128
1129 pBuild->setVersion ( GetMythSourceVersion());
1130 pBuild->setLibX264 ( CONFIG_LIBX264 );
1131 pBuild->setLibDNS_SD ( CONFIG_LIBDNS_SD );
1132 pEnv->setLANG ( qEnvironmentVariable("LANG") );
1133 pEnv->setLCALL ( qEnvironmentVariable("LC_ALL") );
1134 pEnv->setLCCTYPE ( qEnvironmentVariable("LC_CTYPE") );
1135 pEnv->setHOME ( qEnvironmentVariable("HOME") );
1136 pEnv->setHttpRootDir ( m_request->m_root );
1137 // USER for Linux systems, USERNAME for Windows
1138 pEnv->setUSER ( qEnvironmentVariable("USER",
1139 qEnvironmentVariable("USERNAME")) );
1140 pEnv->setMYTHCONFDIR ( qEnvironmentVariable("MYTHCONFDIR") );
1141 auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
1142 if (scheduler != nullptr)
1143 pEnv->setSchedulingEnabled(scheduler->QueryScheduling());
1144 pLog->setLogArgs ( logPropagateArgs );
1145 pEnv->setIsDatabaseIgnored(gCoreContext->GetDB()->IsDatabaseIgnored());
1146 pEnv->setDBTimezoneSupport(DBUtil::CheckTimeZoneSupport());
1147 QString webOnly;
1148 switch (s_WebOnlyStartup) {
1149 case kWebOnlyNone:
1150 webOnly = "NONE";
1151 break;
1152 case kWebOnlyDBSetup:
1153 webOnly = "DBSETUP";
1154 break;
1155 case kWebOnlyDBTimezone:
1156 webOnly = "DBTIMEZONE";
1157 break;
1159 webOnly = "WEBONLYPARM";
1160 break;
1161 case kWebOnlyIPAddress:
1162 webOnly = "IPADDRESS";
1163 break;
1165 webOnly = "SCHEMAUPDATE";
1166 break;
1167 }
1168 pEnv->setWebOnlyStartup (webOnly);
1169
1170 // ----------------------------------------------------------------------
1171 // Return the pointer... caller is responsible to delete it!!!
1172 // ----------------------------------------------------------------------
1173
1174 return pInfo;
1175
1176}
1177
1179//
1181
1182bool V2Myth::ManageDigestUser( const QString &sAction,
1183 const QString &sUserName,
1184 const QString &sPassword,
1185 const QString &sNewPassword)
1186{
1187
1188 DigestUserActions sessionAction = DIGEST_USER_ADD;
1189 QString loggedInUser;
1190
1191 QString authorization = MythHTTP::GetHeader(m_request->m_headers,
1192 "authorization").trimmed();
1193 if (authorization.isEmpty())
1194 authorization = m_request->m_queries.value("authorization",{});
1195
1197
1198 // if (!authorization.isEmpty())
1199 loggedInUser = sessionManager->GetSession(authorization).GetUserName();
1200
1201 if (sAction == "Add")
1202 {
1203 sessionAction = DIGEST_USER_ADD;
1204 }
1205 else if (sAction == "Remove")
1206 {
1207 sessionAction = DIGEST_USER_REMOVE;
1208 }
1209 else if (sAction == "ChangePassword")
1210 {
1211 sessionAction = DIGEST_USER_CHANGE_PW;
1212 if (sPassword.isEmpty() && loggedInUser != "admin" && !loggedInUser.isEmpty())
1213 {
1214 throw QString ("Forbidden: ManageDigestUser "
1215 + loggedInUser + " Old Password required");
1216 }
1217 }
1218 else
1219 {
1220 LOG(VB_GENERAL, LOG_ERR, QString("Action must be Add, Remove or "
1221 "ChangePassword, not '%1'")
1222 .arg(sAction));
1223 return false;
1224 }
1225
1226 if (!loggedInUser.isEmpty()
1227 && loggedInUser != "admin" && loggedInUser != sUserName)
1228 {
1229 throw QString ("Forbidden: ManageDigestUser " + sessionManager->GetSession(authorization).GetUserName());
1230 }
1231
1232 return sessionManager->ManageDigestUser(sessionAction, sUserName,
1233 sPassword, sNewPassword);
1234 // sAdminPassword);
1235}
1236
1237// Login a user to the API Services. Return a session token if
1238// valid, empty string if not
1239
1240QString V2Myth::LoginUser ( const QString &UserName,
1241 const QString &Password,
1242 const QString &Client )
1243{
1245 QString client;
1246
1247 if (!HAS_PARAMv2("Client"))
1248 client = "webapi_" + gCoreContext->GetHostName();
1249 else
1250 client = Client + "_" + gCoreContext->GetHostName();
1251
1252 MythUserSession session = sessionManager->LoginUser(UserName, Password, client);
1253
1254 QString result = session.GetSessionToken();
1255 // Make sure in case of error that the return is an empty string
1256 // not the word "null"
1257 if (result.isEmpty())
1258 result = "";
1259 return result;
1260}
1261
1262QStringList V2Myth::GetUsers()
1263{
1265
1266 if (!query.isConnected())
1267 throw( QString( "Database not open while trying to load list of users" ));
1268
1269 query.prepare(
1270 "SELECT username "
1271 "FROM users ");
1272
1273 if (!query.exec())
1274 {
1275 MythDB::DBError("V2Myth::GetUsers()", query);
1276
1277 throw( QString( "Database Error executing query." ));
1278 }
1279
1280 // ----------------------------------------------------------------------
1281 // return the results of the query
1282 // ----------------------------------------------------------------------
1283
1284 QStringList oList;
1285
1286 while (query.next())
1287 oList.append( query.value(0).toString() );
1288
1289 return oList;
1290}
1291
1293//
1295
1296bool V2Myth::ManageUrlProtection( const QString &sServices,
1297 const QString &sAdminPassword )
1298{
1299 LOG(VB_GENERAL, LOG_WARNING, QString("ManageUrlProtection is deprecated."
1300 "Protection unavailable in API V2."));
1301
1302 if (!MythSessionManager::IsValidUser("admin"))
1303 {
1304 LOG(VB_GENERAL, LOG_ERR, QString("Backend has no '%1' user!")
1305 .arg("admin"));
1306 return false;
1307 }
1308
1309 if (MythSessionManager::CreateDigest("admin", sAdminPassword) !=
1311 {
1312 LOG(VB_GENERAL, LOG_ERR, QString("Incorrect password for user: %1")
1313 .arg("admin"));
1314 return false;
1315 }
1316
1317 QStringList serviceList = sServices.split(",");
1318
1319 serviceList.removeDuplicates();
1320
1321 QStringList protectedURLs;
1322
1323 if (serviceList.size() == 1 && serviceList.first() == "All")
1324 {
1325 for (const QString& service : KnownServicesV2)
1326 protectedURLs << '/' + service;
1327 }
1328 else if (serviceList.size() == 1 && serviceList.first() == "None")
1329 {
1330 protectedURLs << "Unprotected";
1331 }
1332 else
1333 {
1334 for (const QString& service : std::as_const(serviceList))
1335 {
1336 if (KnownServicesV2.contains(service))
1337 protectedURLs << '/' + service;
1338 else
1339 LOG(VB_GENERAL, LOG_ERR, QString("Invalid service name: '%1'")
1340 .arg(service));
1341 }
1342 }
1343
1344 if (protectedURLs.isEmpty())
1345 {
1346 LOG(VB_GENERAL, LOG_ERR, "No valid Services were found");
1347 return false;
1348 }
1349
1350 return gCoreContext->SaveSettingOnHost("HTTP/Protected/Urls",
1351 protectedURLs.join(';'), "");
1352}
1353
1354bool V2Myth::ManageScheduler ( bool Enable, bool Disable )
1355{
1356 auto *scheduler = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
1357 if (scheduler == nullptr)
1358 throw QString("Scheduler is null");
1359 // One and only one of enable and disable must be supplied
1360 if (Enable == Disable)
1361 return false;
1362 if (Enable)
1363 {
1364 scheduler->EnableScheduling();
1365 }
1366 else
1367 {
1368 scheduler->DisableScheduling();
1369 api_sd_notify("STATUS=Scheduling disabled via Services API/Web App.");
1370 }
1371 // Stop EIT scanning
1372 for (auto * tvrec : std::as_const(TVRec::s_inputs))
1373 tvrec->EnableActiveScan(Enable);
1374 return true;
1375}
1376
1377bool V2Myth::Shutdown ( int Retcode, bool Restart, bool WebOnly )
1378{
1379 if (Retcode < 0 || Retcode > 255)
1380 return false;
1381 if (Restart)
1382 {
1383 if (WebOnly)
1384 {
1385 // Retcode 259 is a special value to signal to mythbackend to restart
1386 // in --webonly mode
1387 Retcode = 259;
1388 }
1389 else
1390 {
1391 // Retcode 258 is a special value to signal to mythbackend to restart
1392 // in normal mode
1393 Retcode = 258;
1394 }
1395
1396 }
1397 QCoreApplication::exit(Retcode);
1398 return true;
1399}
1400
1401QString V2Myth::Proxy ( const QString &urlString)
1402{
1403 QUrl url(urlString);
1404
1405 QByteArray data;
1406
1407 auto *req = new QNetworkRequest(url);
1408 req->setHeader(QNetworkRequest::ContentTypeHeader, QString("application/x-www-form-urlencoded"));
1409
1410 if (GetMythDownloadManager()->post(req, &data))
1411 {
1412 return {data};
1413 }
1414
1415 return {};
1416}
Aggregates database and DBMS utility functions.
Definition: dbutil.h:31
static MythDBBackupStatus BackupDB(QString &filename, bool disableRotation=false)
Requests a backup of the database.
Definition: dbutil.cpp:190
static bool CheckTables(bool repair=false, const QString &options="QUICK")
Checks database tables.
Definition: dbutil.cpp:279
static bool CheckTimeZoneSupport(void)
Check if MySQL has working timz zone support.
Definition: dbutil.cpp:869
Structure containing the basic Database parameters.
Definition: mythdbparams.h:11
QString m_dbName
database name
Definition: mythdbparams.h:26
QString m_dbPassword
DB password.
Definition: mythdbparams.h:25
std::chrono::seconds m_wolReconnect
seconds to wait for reconnect
Definition: mythdbparams.h:34
QString m_localHostName
name used for loading/saving settings
Definition: mythdbparams.h:30
bool m_localEnabled
true if localHostName is not default
Definition: mythdbparams.h:29
bool m_dbHostPing
No longer used.
Definition: mythdbparams.h:22
QString m_dbUserName
DB user name.
Definition: mythdbparams.h:24
QString m_dbType
database type (MySQL, Postgres, etc.)
Definition: mythdbparams.h:27
QString m_wolCommand
command to use for wake-on-lan
Definition: mythdbparams.h:36
bool m_wolEnabled
true if wake-on-lan params are used
Definition: mythdbparams.h:33
int m_dbPort
database port
Definition: mythdbparams.h:23
int m_wolRetry
times to retry to reconnect
Definition: mythdbparams.h:35
QString m_dbHostName
database server
Definition: mythdbparams.h:21
static QString GetHardwareProfile(void)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:838
QVariant value(int i) const
Definition: mythdbcon.h:204
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:137
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:889
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:813
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
MythDB * GetDB(void)
QString GetHostName(void)
MythScheduler * GetScheduler(void)
MythSessionManager * GetSessionManager(void)
QString GetSetting(const QString &key, const QString &defaultval="")
bool SaveSettingOnHost(const QString &key, const QString &newValue, const QString &host)
QString GetSettingOnHost(const QString &key, const QString &host, const QString &defaultval="")
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
bool HAS_PARAMv2(const QString &p)
HTTPRequest2 m_request
static QString GetHeader(const HTTPHeaders &Headers, const QString &Value, const QString &Default="")
We use digest authentication because it protects the password over unprotected networks.
Definition: mythsession.h:106
static bool IsValidUser(const QString &username)
Check if the given user exists but not whether there is a valid session open for them!
static QString GetPasswordDigest(const QString &username)
Load the password digest for comparison in the HTTP Auth code.
MythUserSession GetSession(const QString &sessionToken)
Load the session details and return.
static QByteArray CreateDigest(const QString &username, const QString &password)
Generate a digest string.
bool ManageDigestUser(DigestUserActions action, const QString &username, const QString &password, const QString &newPassword)
Manage digest user entries.
MythUserSession LoginUser(const QString &username, const QByteArray &digest, const QString &client="")
Login user by digest.
QString GetSessionToken(void) const
Definition: mythsession.h:45
QString GetUserName(void) const
Definition: mythsession.h:42
Contains Packet Identifier numeric values.
Definition: mpegtables.h:207
void DelayShutdown()
Definition: scheduler.cpp:3104
static QMap< uint, TVRec * > s_inputs
Definition: tv_rec.h:435
static QStringList GetKeys()
Definition: v2myth.cpp:241
static V2TimeZoneInfo * GetTimeZone()
Definition: v2myth.cpp:469
static bool RemoveStorageGroupDir(const QString &GroupName, const QString &DirName, const QString &HostName)
Definition: v2myth.cpp:428
static V2SettingList * GetSettingList(const QString &HostName)
Definition: v2myth.cpp:717
bool PutSetting(const QString &HostName, const QString &Key, const QString &Value)
Definition: v2myth.cpp:769
static bool AddStorageGroupDir(const QString &GroupName, const QString &DirName, const QString &HostName)
Definition: v2myth.cpp:366
static bool SendNotification(bool Error, const QString &Type, const QString &Message, const QString &Origin, const QString &Description, const QString &Image, const QString &Extra, const QString &ProgressText, float Progress, int Timeout, bool Fullscreen, uint Visibility, uint Priority, const QString &Address, int udpPort)
Definition: v2myth.cpp:902
static bool DelayShutdown(void)
Definition: v2myth.cpp:1023
static bool TestDBSettings(const QString &HostName, const QString &UserName, const QString &Password, const QString &DBName, int dbPort)
Definition: v2myth.cpp:822
static void RegisterCustomTypes()
static WebOnlyStartup s_WebOnlyStartup
Definition: v2myth.h:68
static V2LogMessageList * GetLogs(const QString &HostName, const QString &Application, int PID, int TID, const QString &Thread, const QString &Filename, int Line, const QString &Function, const QDateTime &FromTime, const QDateTime &ToTime, const QString &Level, const QString &MsgContains)
Definition: v2myth.cpp:533
static QString GetHostName()
Definition: v2myth.cpp:194
static QString GetSetting(const QString &HostName, const QString &Key, const QString &Default)
Definition: v2myth.cpp:679
QString LoginUser(const QString &UserName, const QString &Password, const QString &Client)
Definition: v2myth.cpp:1240
static bool BackupDatabase(void)
Definition: v2myth.cpp:980
static bool SendMessage(const QString &Message, const QString &Address, int udpPort, int Timeout)
Definition: v2myth.cpp:848
static bool ProfileSubmit(void)
Definition: v2myth.cpp:1037
static bool CheckDatabase(bool Repair)
Definition: v2myth.cpp:1009
static V2FrontendList * GetFrontends(bool OnLine)
Definition: v2myth.cpp:666
static V2StorageGroupDirList * GetStorageGroupDirs(const QString &GroupName, const QString &HostName)
Definition: v2myth.cpp:290
static QStringList GetUsers(void)
Definition: v2myth.cpp:1262
static QString ProfileText(void)
Definition: v2myth.cpp:1103
bool ManageDigestUser(const QString &Action, const QString &UserName, const QString &Password, const QString &NewPassword)
Definition: v2myth.cpp:1182
V2Myth()
Definition: v2myth.cpp:67
static QString GetFormatTime(const QDateTime &Time)
Definition: v2myth.cpp:510
@ kWebOnlyNone
Definition: v2myth.h:61
@ kWebOnlyIPAddress
Definition: v2myth.h:65
@ kWebOnlyDBTimezone
Definition: v2myth.h:63
@ kWebOnlyWebOnlyParm
Definition: v2myth.h:64
@ kWebOnlySchemaUpdate
Definition: v2myth.h:66
@ kWebOnlyDBSetup
Definition: v2myth.h:62
V2BackendInfo * GetBackendInfo(void)
Definition: v2myth.cpp:1117
static bool SetConnectionInfo(const QString &Host, const QString &UserName, const QString &Password, const QString &Name, int Port, bool DoTest)
Definition: v2myth.cpp:156
static QString Proxy(const QString &Url)
Definition: v2myth.cpp:1401
static QStringList GetDirListing(const QString &DirName, bool Files)
Definition: v2myth.cpp:275
static bool ProfileDelete(void)
Definition: v2myth.cpp:1053
static bool DeleteSetting(const QString &HostName, const QString &Key)
Definition: v2myth.cpp:801
static bool ManageUrlProtection(const QString &Services, const QString &AdminPassword)
Definition: v2myth.cpp:1296
static QStringList GetHosts()
Definition: v2myth.cpp:206
static bool Shutdown(int Retcode, bool Restart, bool WebOnly)
Definition: v2myth.cpp:1377
static QString GetFormatDate(const QDateTime &Date, bool ShortDate)
Definition: v2myth.cpp:484
static bool ManageScheduler(bool Enable, bool Disable)
Definition: v2myth.cpp:1354
static QDateTime ParseISODateString(const QString &DateTime)
Definition: v2myth.cpp:519
static QString ProfileUpdated(void)
Definition: v2myth.cpp:1085
static QString GetFormatDateTime(const QDateTime &DateTime, bool ShortDate)
Definition: v2myth.cpp:497
static QString ProfileURL(void)
Definition: v2myth.cpp:1069
static V2ConnectionInfo * GetConnectionInfo(const QString &Pin)
Definition: v2myth.cpp:76
unsigned int uint
Definition: compat.h:60
MythDBBackupStatus
Definition: dbutil.h:10
@ kDB_Backup_Unknown
Definition: dbutil.h:11
@ kDB_Backup_Completed
Definition: dbutil.h:13
static StandardSetting * Password(bool enabled)
Setting for changing password.
QString logPropagateArgs
Definition: logging.cpp:86
QString logLevelGetName(LogLevel_t level)
Map a log level enumerated value back to the name.
Definition: logging.cpp:786
LogLevel_t logLevelGet(const QString &level)
Map a log level name back to the enumerated value.
Definition: logging.cpp:764
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythDB * GetMythDB(void)
Definition: mythdb.cpp:50
bool TestDatabase(const QString &dbHostName, const QString &dbUserName, QString dbPassword, QString dbName, int dbPort)
Definition: mythdbcon.cpp:42
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DigestUserActions
Definition: mythsession.h:13
@ DIGEST_USER_ADD
Definition: mythsession.h:14
@ DIGEST_USER_CHANGE_PW
Definition: mythsession.h:16
@ DIGEST_USER_REMOVE
Definition: mythsession.h:15
const char * GetMythSourceVersion()
Definition: mythversion.cpp:7
const char * GetMythSourcePath()
Definition: mythversion.cpp:12
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
Definition: mythdate.cpp:28
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
@ kDateTimeFull
Default local time.
Definition: mythdate.h:23
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:26
@ kDateFull
Default local time.
Definition: mythdate.h:19
@ kDateTimeShort
Default local time.
Definition: mythdate.h:24
@ ISODate
Default UTC.
Definition: mythdate.h:17
@ kTime
Default local time.
Definition: mythdate.h:22
@ kDateShort
Default local time.
Definition: mythdate.h:20
@ kAutoYear
Add year only if different from current year.
Definition: mythdate.h:28
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
int calc_utc_offset(void)
QString getTimeZoneID(void)
Returns the zoneinfo time zone ID or as much time zone information as possible.
string hostname
Definition: caa.py:17
static void api_sd_notify(const char *)
Definition: v2myth.cpp:38
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(MYTH_HANDLE, V2Myth::staticMetaObject, &V2Myth::RegisterCustomTypes)) void V2Myth
Definition: v2myth.cpp:42
#define MYTH_HANDLE
Definition: v2myth.h:17
void FillFrontendList(QVariantList &list, QObject *parent, bool OnLine)
const QStringList KnownServicesV2
Definition: v2serviceUtil.h:36