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