MythTV  0.26-pre
httpconfig.cpp
Go to the documentation of this file.
00001 // Qt headers
00002 #include <QByteArray>
00003 #include <QDir>
00004 #include <QFileInfo>
00005 #include <QTextStream>
00006 #include <QUrl>
00007 
00008 // MythTV headers
00009 #include "httpconfig.h"
00010 #include "backendutil.h"
00011 #include "mythcontext.h"
00012 #include "mythdb.h"
00013 #include "mythdirs.h"
00014 #include "storagegroup.h"
00015 #include "mythdownloadmanager.h"
00016 #include "mythcoreutil.h"
00017 
00018 HttpConfig::HttpConfig() : HttpServerExtension("HttpConfig", QString())
00019 {
00020 }
00021 
00022 HttpConfig::~HttpConfig()
00023 {
00024 }
00025 
00026 QStringList HttpConfig::GetBasePaths()
00027 {
00028     QStringList paths;
00029     paths << "/Config";
00030     paths << "/Config/Database";
00031     paths << "/Config/General";
00032     return paths;
00033 }
00034 
00035 bool HttpConfig::ProcessRequest(HTTPRequest *request)
00036 {
00037     if (!request)
00038         return false;
00039 
00040     LOG(VB_UPNP, LOG_INFO,
00041         QString("HttpConfig::ProcessRequest(): m_sBaseURL: '%1',"
00042                 "m_sMethod: '%2'")
00043             .arg(request->m_sBaseUrl).arg(request->m_sMethod));
00044     if (!request->m_sBaseUrl.startsWith("/Config"))
00045     {
00046         return false;
00047     }
00048 
00049     bool handled = false;
00050     if (request->m_sMethod == "Save")
00051     {
00052         {
00053             // DISABLE HTML SETUP SAVING
00054             // DISABLE HTML SETUP SAVING
00055             QTextStream os(&request->m_response);
00056             os << "<html>\r\n"
00057                   "  <head>\r\n"
00058                   "    <title>Saving is Disabled</title>\r\n"
00059                   "  </head>\r\n"
00060                   "  <body>\r\n"
00061                   "    <b>Saving is Disabled</b><br>\r\n"
00062                   "  </body>\r\n"
00063                   "</html>\r\n";
00064 
00065             request->m_eResponseType = ResponseTypeHTML;
00066             request->m_mapRespHeaders[ "Cache-Control" ] =
00067                 "no-cache=\"Ext\", max-age = 0";
00068 
00069             return true;
00070             // DISABLE HTML SETUP SAVING
00071             // DISABLE HTML SETUP SAVING
00072         }
00073 
00074         // FIXME, this is always false, what's it for
00075         if (request->m_sBaseUrl.right(7) == "config" &&
00076             !database_settings.empty())
00077         {
00078             QString checkResult;
00079             PrintHeader(request->m_response, "/Config/Database");
00080             check_settings(database_settings, request->m_mapParams,
00081                            checkResult);
00082             load_settings(database_settings, "");
00083             PrintSettings(request->m_response, database_settings);
00084             PrintFooter(request->m_response);
00085             handled = true;
00086         }
00087         else
00088         {
00089             bool okToSave = false;
00090             QString checkResult;
00091             QString fn = GetShareDir() + "backend-config/";
00092 
00093             if (request->m_sBaseUrl == "/Config/Database")
00094             {
00095                 if (check_settings(database_settings, request->m_mapParams,
00096                                    checkResult))
00097                     okToSave = true;
00098             }
00099             else if (request->m_sBaseUrl == "/Config/General")
00100             {
00101                 if (check_settings(general_settings, request->m_mapParams,
00102                                    checkResult))
00103                     okToSave = true;
00104             }
00105 
00106             if (okToSave)
00107                 LOG(VB_UPNP, LOG_INFO, "HTTP method 'Save' called, but not handled");
00108 #if 0
00109             QTextStream os(&request->m_response);
00110             os << "<html><body><h3>The Save function for this screen is "
00111                << "not hooked up yet</h3><dl>";
00112             QStringMap::const_iterator it = request->m_mapParams.begin();
00113             for (; it!=request->m_mapParams.end(); ++it)
00114             {
00115                 if (it.key() == "__group__")
00116                     continue;
00117 
00118                 os << "<dt>"<<it.key()<<"</dt><dd>"
00119                                     <<*it<<"</dd>\r\n";
00120             }
00121             os << "</dl></body></html>";
00122             handled = true;
00123 #else
00124             QTextStream os(&request->m_response);
00125             os << checkResult;
00126             request->m_eResponseType     = ResponseTypeOther;
00127             request->m_sResponseTypeText = "application/json";
00128             request->m_mapRespHeaders[ "Cache-Control" ] =
00129                 "no-cache=\"Ext\", max-age = 0";
00130 
00131             return true;
00132 #endif
00133         }
00134     }
00135     else if (request->m_sMethod == "Settings")
00136     {
00137         QString result = "{ \"Error\": \"Unknown Settings List\" }";
00138         QString fn = GetShareDir() + "backend-config/";
00139 
00140         if (request->m_sBaseUrl == "/Config/Database")
00141         {
00142             fn += "config_backend_database.xml";
00143             parse_settings(database_settings, fn);
00144             result = StringMapToJSON(
00145                 GetSettingsMap(database_settings, gCoreContext->GetHostName()));
00146         }
00147         else if (request->m_sBaseUrl == "/Config/General")
00148         {
00149             fn += "config_backend_general.xml";
00150             parse_settings(general_settings, fn);
00151             result = StringMapToJSON(
00152                 GetSettingsMap(general_settings, gCoreContext->GetHostName()));
00153         }
00154 
00155         QTextStream os(&request->m_response);
00156         os << result;
00157         request->m_eResponseType     = ResponseTypeOther;
00158         request->m_sResponseTypeText = "application/json";
00159         request->m_mapRespHeaders[ "Cache-Control" ] =
00160             "no-cache=\"Ext\", max-age = 0";
00161 
00162         return true;
00163     }
00164     else if (request->m_sMethod == "XML")
00165     {
00166         QString fn = GetShareDir() + "backend-config/";
00167 
00168         if (request->m_sBaseUrl == "/Config/Database")
00169             fn += "config_backend_database.xml";
00170         else if (request->m_sBaseUrl == "/Config/General")
00171             fn += "config_backend_general.xml";
00172 
00173         request->FormatFileResponse(fn);
00174         return true;
00175     }
00176     else if ((request->m_sMethod == "InstallPackage") &&
00177              (request->m_mapParams.contains("package")))
00178     {
00179         QString package = QUrl::fromPercentEncoding(request->m_mapParams["package"].toUtf8());
00180         QString url = QString("http://www.mythtv.org/ftp/3rdParty/%1").arg(package);
00181         StorageGroup tmpGroup("Temp", gCoreContext->GetHostName());
00182         QString tmpFile = tmpGroup.GetFirstDir(true) + "package.zip";
00183         StorageGroup destGroup("3rdParty", gCoreContext->GetHostName());
00184         QString outDir = destGroup.GetFirstDir();
00185 
00186         QString result = "false";
00187         if ((GetMythDownloadManager()->download(url, tmpFile)) &&
00188             (extractZIP(tmpFile, outDir)))
00189         {
00190             result = "true";
00191         }
00192 
00193         QTextStream os(&request->m_response);
00194         os << StringListToJSON("Result", QStringList(result));
00195 
00196         request->m_eResponseType     = ResponseTypeOther;
00197         request->m_sResponseTypeText = "application/json";
00198         request->m_mapRespHeaders[ "Cache-Control" ] =
00199             "no-cache=\"Ext\", max-age = 0";
00200 
00201         return true;
00202     }
00203     else if ((request->m_sMethod == "FileBrowser") &&
00204              (request->m_mapParams.contains("dir")))
00205     {
00206         QString startingDir = QUrl::fromPercentEncoding(request->m_mapParams["dir"].toUtf8());
00207         if (startingDir.startsWith("myth://"))
00208         {
00209             QUrl qurl(startingDir);
00210             QString dir;
00211 
00212             QString host = qurl.host();
00213             int port = qurl.port();
00214 
00215             dir = qurl.path();
00216 
00217             QString storageGroup = qurl.userName();
00218 
00219             StorageGroup sgroup(storageGroup);
00220             QStringList entries = sgroup.GetFileInfoList(dir);
00221 
00222             if ((entries.size() == 1) &&
00223                 (entries[0].startsWith("sgdir::")))
00224             {
00225                 QStringList parts = entries[0].split("::");
00226                 entries = sgroup.GetFileInfoList(parts[1]);
00227             }
00228 
00229             if (entries.size())
00230             {
00231                 QTextStream os(&request->m_response);
00232                 os << "<ul class=\"jqueryFileTree\" style=\"display: none;\">\r\n";
00233 
00234                 for (QStringList::iterator it = entries.begin();
00235                      it != entries.end(); ++it)
00236                 {
00237                     QString entry = *it;
00238                     QStringList parts = entry.split("::");
00239                     QFileInfo fi(parts[1]);
00240                     if (dir == "/")
00241                         dir = "";
00242                     QString path =
00243                             gCoreContext->GenMythURL(host,
00244                                                      port,
00245                                                      dir + parts[1],
00246                                                      storageGroup);
00247                     if (entry.startsWith("sgdir::"))
00248                     {
00249                         os << "    <li class=\"directory collapsed\"><a href=\"#\" rel=\""
00250                            << path << "/\">" << parts[1] << "</a></li>\r\n";
00251                     }
00252                     else if (entry.startsWith("dir::"))
00253                     {
00254                         os << "    <li class=\"directory collapsed\"><a href=\"#\" rel=\""
00255                            << path << "/\">" << fi.fileName() << "</a></li>\r\n";
00256                     }
00257                     else if (entry.startsWith("file::"))
00258                     {
00259                         os << "    <li class=\"file ext_" << fi.suffix() << "\"><a href=\"#\" rel=\""
00260                            << parts[3] << "\">" << fi.fileName() << "</a></li>\r\n";
00261                     }
00262                 }
00263                 os << "</ul>\r\n";
00264 
00265                 handled = true;
00266             }
00267         } else {
00268             QDir dir(startingDir);
00269             if (dir.exists())
00270             {
00271                 QTextStream os(&request->m_response);
00272                 os << "<ul class=\"jqueryFileTree\" style=\"display: none;\">\r\n";
00273 
00274                 QFileInfoList infoList = dir.entryInfoList();
00275                 for (QFileInfoList::iterator it  = infoList.begin();
00276                                              it != infoList.end();
00277                                            ++it )
00278                 {
00279                     QFileInfo &fi = *it;
00280                     if (!fi.isDir())
00281                         continue;
00282                     if (fi.fileName().startsWith("."))
00283                         continue;
00284 
00285                     os << "    <li class=\"directory collapsed\"><a href=\"#\" rel=\""
00286                        << fi.absoluteFilePath() << "/\">" << fi.fileName() << "</a></li>\r\n";
00287                 }
00288 
00289                 bool dirsOnly = true;
00290                 if (request->m_mapParams.contains("dirsOnly"))
00291                     dirsOnly = request->m_mapParams["dirsOnly"].toInt();
00292 
00293                 if (!dirsOnly)
00294                 {
00295                     for (QFileInfoList::iterator it  = infoList.begin();
00296                                                  it != infoList.end();
00297                                                ++it )
00298                     {
00299                         QFileInfo &fi = *it;
00300                         if (fi.isDir())
00301                             continue;
00302                         if (fi.fileName().startsWith("."))
00303                             continue;
00304 
00305                         os << "    <li class=\"file ext_" << fi.suffix() << "\"><a href=\"#\" rel=\""
00306                            << fi.absoluteFilePath() << "\">" << fi.fileName() << "</a></li>\r\n";
00307                     }
00308                 }
00309                 os << "</ul>\r\n";
00310 
00311                 handled = true;
00312             }
00313         }
00314     }
00315     else if ((request->m_sMethod == "GetValueList") &&
00316              (request->m_mapParams.contains("List")))
00317     {
00318         QString key = request->m_mapParams["List"];
00319         QStringList sList = GetSettingValueList(key);
00320         QTextStream os(&request->m_response);
00321         os << StringListToJSON(key, sList);
00322 
00323         request->m_eResponseType     = ResponseTypeOther;
00324         request->m_sResponseTypeText = "application/json";
00325         request->m_mapRespHeaders[ "Cache-Control" ] =
00326             "no-cache=\"Ext\", max-age = 0";
00327 
00328         return true;
00329     }
00330     else if ((request->m_sMethod == "Database") || (NULL == gContext))
00331     {
00332         QString fn = GetShareDir() + "backend-config/"
00333             "config_backend_database.xml";
00334         QString group;
00335         QString form("/Config/Database/Save");
00336 
00337         if (request->m_mapParams.contains("__group__"))
00338             group = request->m_mapParams["__group__"];
00339 
00340         if (group.isEmpty())
00341             PrintHeader(request->m_response, form);
00342         else
00343             OpenForm(request->m_response, form, group);
00344 
00345         parse_settings(general_settings, fn, group);
00346         load_settings(general_settings, gCoreContext->GetHostName());
00347         PrintSettings(request->m_response, general_settings);
00348 
00349         if (group.isEmpty())
00350             PrintFooter(request->m_response);
00351         else
00352             CloseForm(request->m_response, group);
00353 
00354         handled = true;
00355     }
00356     else if (request->m_sMethod == "General")
00357     {
00358         QString fn = GetShareDir() + "backend-config/"
00359             "config_backend_general.xml";
00360         QString group;
00361         QString form("/Config/General/Save");
00362 
00363         if (request->m_mapParams.contains("__group__"))
00364             group = request->m_mapParams["__group__"];
00365 
00366         if (group.isEmpty())
00367             PrintHeader(request->m_response, form);
00368         else
00369             OpenForm(request->m_response, form, group);
00370 
00371         parse_settings(general_settings, fn, group);
00372         load_settings(general_settings, gCoreContext->GetHostName());
00373         PrintSettings(request->m_response, general_settings);
00374 
00375         if (group.isEmpty())
00376             PrintFooter(request->m_response);
00377         else
00378             CloseForm(request->m_response, group);
00379 
00380         handled = true;
00381     }
00382 
00383     if (handled)
00384     {
00385         request->m_eResponseType = ResponseTypeHTML;
00386         request->m_mapRespHeaders[ "Cache-Control" ] =
00387             "no-cache=\"Ext\", max-age = 0";
00388     }
00389 
00390     return handled;
00391 }
00392 
00393 void HttpConfig::PrintHeader(QBuffer &buffer, const QString &form,
00394                              const QString &group)
00395 {
00396     QTextStream os(&buffer);
00397 
00398     os.setCodec("UTF-8");
00399 
00400     os << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
00401        << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n"
00402        << "<html xmlns=\"http://www.w3.org/1999/xhtml\""
00403        << " xml:lang=\"en\" lang=\"en\">\r\n"
00404        << "<head>\r\n"
00405        << "  <meta http-equiv=\"Content-Type\"\r\n"
00406        << "        content=\"text/html; charset=UTF-8\" />\r\n"
00407        << "  <link rel=\"stylesheet\" href=\"/setup/css/Config.css\" type=\"text/css\">\r\n"
00408        << "  <title>MythTV Config</title>"
00409        << "</head>\r\n"
00410        << "<body>\r\n\r\n"
00411        << "<div class=\"config\">\r\n"
00412        << "  <h1 class=\"config\">MythTV Configuration</h1>\r\n";
00413 
00414     OpenForm(buffer, form, group);
00415 }
00416 
00417 void HttpConfig::OpenForm(QBuffer &buffer, const QString &form,
00418                           const QString &group)
00419 {
00420     QTextStream os(&buffer);
00421 
00422     os.setCodec("UTF-8");
00423 
00424     os << "  <form id=\"config_form_" << group << "\">\r\n"
00425        << "    <input type=\"hidden\" id=\"__config_form_action__\" value=\"" << form << "\" />\r\n"
00426        << "    <input type=\"hidden\" id=\"__group__\" value=\"" << group << "\" />\r\n";
00427 }
00428 
00429 void HttpConfig::CloseForm(QBuffer &buffer, const QString &group)
00430 {
00431     QTextStream os(&buffer);
00432 
00433 //    os << "    <div class=\"config_form_submit\"\r\n"
00434 //       << "         id=\"config_form_submit\">\r\n";
00435     os << "      <input type=\"button\" value=\"Save Changes\" onClick=\"javascript:submitConfigForm('" << group << "')\" />\r\n"
00436 //       << "    </div>\r\n"
00437        << "  </form>\r\n";
00438 }
00439 
00440 void HttpConfig::PrintFooter(QBuffer &buffer, const QString &group)
00441 {
00442     CloseForm(buffer, group);
00443 
00444     QTextStream os(&buffer);
00445 
00446     os << "</div>\r\n"
00447        << "</body>\r\n"
00448        << "</html>\r\n";
00449 }
00450 
00451 void HttpConfig::PrintSettings(QBuffer &buffer, const MythSettingList &settings)
00452 {
00453     QTextStream os(&buffer);
00454 
00455     MythSettingList::const_iterator it = settings.begin();
00456     for (; it != settings.end(); ++it)
00457         os << (*it)->ToHTML(1);
00458 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends