예제 #1
0
파일: DAVFile.cpp 프로젝트: Fury04/xbmc
bool CDAVFile::Execute(const CURL& url)
{
  CURL url2(url);
  ParseAndCorrectUrl(url2);

  CLog::Log(LOGDEBUG, "CDAVFile::Execute(%p) %s", (void*)this, m_url.c_str());

  ASSERT(!(!m_state->m_easyHandle ^ !m_state->m_multiHandle));
  if( m_state->m_easyHandle == NULL )
    g_curlInterface.easy_aquire(url2.GetProtocol().c_str(),
                                url2.GetHostName().c_str(),
                                &m_state->m_easyHandle,
                                &m_state->m_multiHandle);

  // setup common curl options
  SetCommonOptions(m_state);
  SetRequestHeaders(m_state);

  lastResponseCode = m_state->Connect(m_bufferSize);
  if( lastResponseCode < 0 || lastResponseCode >= 400)
    return false;

  char* efurl;
  if (CURLE_OK == g_curlInterface.easy_getinfo(m_state->m_easyHandle, CURLINFO_EFFECTIVE_URL,&efurl) && efurl)
    m_url = efurl;

  if (lastResponseCode == 207)
  {
    CStdString strResponse;
    ReadData(strResponse);

    CXBMCTinyXML davResponse;
    davResponse.Parse(strResponse);

    if (!davResponse.Parse(strResponse))
    {
      CLog::Log(LOGERROR, "%s - Unable to process dav response (%s)", __FUNCTION__, m_url.c_str());
      Close();
      return false;
    }

    TiXmlNode *pChild;
    // Iterate over all responses
    for (pChild = davResponse.RootElement()->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
    {
      if (CDAVCommon::ValueWithoutNamespace(pChild, "response"))
      {
        CStdString sRetCode = CDAVCommon::GetStatusTag(pChild->ToElement());
        CRegExp rxCode;
        rxCode.RegComp("HTTP/1\\.1\\s(\\d+)\\s.*"); 
        if (rxCode.RegFind(sRetCode) >= 0)
        {
          if (rxCode.GetSubCount())
          {
            lastResponseCode = atoi(rxCode.GetMatch(1).c_str());
            if( lastResponseCode < 0 || lastResponseCode >= 400)
              return false;
          }
        }

      }
    }
  }

  return true;
}
예제 #2
0
bool CVideoInfoTag::Save(TiXmlNode *node, const CStdString &tag, bool savePathInfo, const TiXmlElement *additionalNode)
{
  if (!node) return false;

  // we start with a <tag> tag
  TiXmlElement movieElement(tag.c_str());
  TiXmlNode *movie = node->InsertEndChild(movieElement);

  if (!movie) return false;

  XMLUtils::SetString(movie, "title", m_strTitle);
  if (!m_strOriginalTitle.IsEmpty())
    XMLUtils::SetString(movie, "originaltitle", m_strOriginalTitle);
  if (!m_strShowTitle.IsEmpty())
    XMLUtils::SetString(movie, "showtitle", m_strShowTitle);
  if (!m_strSortTitle.IsEmpty())
    XMLUtils::SetString(movie, "sorttitle", m_strSortTitle);
  XMLUtils::SetFloat(movie, "rating", m_fRating);
  XMLUtils::SetFloat(movie, "epbookmark", m_fEpBookmark);
  XMLUtils::SetInt(movie, "year", m_iYear);
  XMLUtils::SetInt(movie, "top250", m_iTop250);
  if (tag == "episodedetails" || tag == "tvshow")
  {
    XMLUtils::SetInt(movie, "season", m_iSeason);
    XMLUtils::SetInt(movie, "episode", m_iEpisode);
    XMLUtils::SetInt(movie, "displayseason",m_iSpecialSortSeason);
    XMLUtils::SetInt(movie, "displayepisode",m_iSpecialSortEpisode);
  }
  if (tag == "musicvideo")
  {
    XMLUtils::SetInt(movie, "track", m_iTrack);
    XMLUtils::SetString(movie, "album", m_strAlbum);
  }
  XMLUtils::SetString(movie, "votes", m_strVotes);
  XMLUtils::SetString(movie, "outline", m_strPlotOutline);
  XMLUtils::SetString(movie, "plot", m_strPlot);
  XMLUtils::SetString(movie, "tagline", m_strTagLine);
  XMLUtils::SetString(movie, "runtime", m_strRuntime);
  if (!m_strPictureURL.m_xml.empty())
  {
    CXBMCTinyXML doc;
    doc.Parse(m_strPictureURL.m_xml);
    const TiXmlNode* thumb = doc.FirstChild("thumb");
    while (thumb)
    {
      movie->InsertEndChild(*thumb);
      thumb = thumb->NextSibling("thumb");
    }
  }
  if (m_fanart.m_xml.size())
  {
    CXBMCTinyXML doc;
    doc.Parse(m_fanart.m_xml);
    movie->InsertEndChild(*doc.RootElement());
  }
  XMLUtils::SetString(movie, "mpaa", m_strMPAARating);
  XMLUtils::SetInt(movie, "playcount", m_playCount);
  XMLUtils::SetDate(movie, "lastplayed", m_lastPlayed);
  if (savePathInfo)
  {
    XMLUtils::SetString(movie, "file", m_strFile);
    XMLUtils::SetString(movie, "path", m_strPath);
    XMLUtils::SetString(movie, "filenameandpath", m_strFileNameAndPath);
    XMLUtils::SetString(movie, "basepath", m_basePath);
  }
  if (!m_strEpisodeGuide.IsEmpty())
  {
    CXBMCTinyXML doc;
    doc.Parse(m_strEpisodeGuide);
    if (doc.RootElement())
      movie->InsertEndChild(*doc.RootElement());
    else
      XMLUtils::SetString(movie, "episodeguide", m_strEpisodeGuide);
  }

  XMLUtils::SetString(movie, "id", m_strIMDBNumber);
  XMLUtils::SetStringArray(movie, "genre", m_genre);
  XMLUtils::SetStringArray(movie, "country", m_country);
  XMLUtils::SetStringArray(movie, "set", m_set);
  XMLUtils::SetStringArray(movie, "tag", m_tags);
  XMLUtils::SetStringArray(movie, "credits", m_writingCredits);
  XMLUtils::SetStringArray(movie, "director", m_director);
  XMLUtils::SetDate(movie, "premiered", m_premiered);
  XMLUtils::SetString(movie, "status", m_strStatus);
  XMLUtils::SetString(movie, "code", m_strProductionCode);
  XMLUtils::SetDate(movie, "aired", m_firstAired);
  XMLUtils::SetStringArray(movie, "studio", m_studio);
  XMLUtils::SetString(movie, "trailer", m_strTrailer);

  if (m_streamDetails.HasItems())
  {
    // it goes fileinfo/streamdetails/[video|audio|subtitle]
    TiXmlElement fileinfo("fileinfo");
    TiXmlElement streamdetails("streamdetails");
    for (int iStream=1; iStream<=m_streamDetails.GetVideoStreamCount(); iStream++)
    {
      TiXmlElement stream("video");
      XMLUtils::SetString(&stream, "codec", m_streamDetails.GetVideoCodec(iStream));
      XMLUtils::SetFloat(&stream, "aspect", m_streamDetails.GetVideoAspect(iStream));
      XMLUtils::SetInt(&stream, "width", m_streamDetails.GetVideoWidth(iStream));
      XMLUtils::SetInt(&stream, "height", m_streamDetails.GetVideoHeight(iStream));
      XMLUtils::SetInt(&stream, "durationinseconds", m_streamDetails.GetVideoDuration(iStream));
      streamdetails.InsertEndChild(stream);
    }
    for (int iStream=1; iStream<=m_streamDetails.GetAudioStreamCount(); iStream++)
    {
      TiXmlElement stream("audio");
      XMLUtils::SetString(&stream, "codec", m_streamDetails.GetAudioCodec(iStream));
      XMLUtils::SetString(&stream, "language", m_streamDetails.GetAudioLanguage(iStream));
      XMLUtils::SetInt(&stream, "channels", m_streamDetails.GetAudioChannels(iStream));
      streamdetails.InsertEndChild(stream);
    }
    for (int iStream=1; iStream<=m_streamDetails.GetSubtitleStreamCount(); iStream++)
    {
      TiXmlElement stream("subtitle");
      XMLUtils::SetString(&stream, "language", m_streamDetails.GetSubtitleLanguage(iStream));
      streamdetails.InsertEndChild(stream);
    }
    fileinfo.InsertEndChild(streamdetails);
    movie->InsertEndChild(fileinfo);
  }  /* if has stream details */

  // cast
  for (iCast it = m_cast.begin(); it != m_cast.end(); ++it)
  {
    // add a <actor> tag
    TiXmlElement cast("actor");
    TiXmlNode *node = movie->InsertEndChild(cast);
    TiXmlElement actor("name");
    TiXmlNode *actorNode = node->InsertEndChild(actor);
    TiXmlText name(it->strName);
    actorNode->InsertEndChild(name);
    TiXmlElement role("role");
    TiXmlNode *roleNode = node->InsertEndChild(role);
    TiXmlText character(it->strRole);
    roleNode->InsertEndChild(character);
    TiXmlElement thumb("thumb");
    TiXmlNode *thumbNode = node->InsertEndChild(thumb);
    TiXmlText th(it->thumbUrl.GetFirstThumb().m_url);
    thumbNode->InsertEndChild(th);
  }
  XMLUtils::SetStringArray(movie, "artist", m_artist);
  XMLUtils::SetStringArray(movie, "showlink", m_showLink);
 
  TiXmlElement resume("resume");
  XMLUtils::SetFloat(&resume, "position", (float)m_resumePoint.timeInSeconds);
  XMLUtils::SetFloat(&resume, "total", (float)m_resumePoint.totalTimeInSeconds);
  movie->InsertEndChild(resume);

  XMLUtils::SetString(movie, "dateadded", m_dateAdded.GetAsDBDateTime());

  if (additionalNode)
    movie->InsertEndChild(*additionalNode);

  return true;
}
예제 #3
0
bool CDVDStateSerializer::XMLToDVDState( dvd_state_t *state, const std::string &xmlstate )
{
  CXBMCTinyXML xmlDoc;

  xmlDoc.Parse(xmlstate.c_str());

  if( xmlDoc.Error() )
    return false;

  TiXmlHandle hRoot( xmlDoc.RootElement() );
  if( strcmp( hRoot.Element()->Value(), "navstate" ) != 0 ) return false;

  TiXmlElement *element = NULL;
  TiXmlText *text = NULL;
  int index = 0;

  element = hRoot.FirstChildElement("registers").FirstChildElement("sprm").Element();
  while( element )
  {
    element->Attribute("index", &index);

    text = TiXmlHandle( element ).FirstChildElement("value").FirstChild().Text();
    if( text && index >= 0 && index < 24 )
      sscanf(text->Value(), "0x%hx", &state->registers.SPRM[index]);

    element = element->NextSiblingElement("sprm");
  }

  element = hRoot.FirstChildElement("registers").FirstChildElement("gprm").Element();
  while( element )
  {
    element->Attribute("index", &index);
    if( index >= 0 && index < 16 )
    {
      text = TiXmlHandle( element ).FirstChildElement("value").FirstChild().Text();
      if( text )
        sscanf(text->Value(), "0x%hx", &state->registers.GPRM[index]);

      text = TiXmlHandle( element ).FirstChildElement("mode").FirstChild().Text();
      if( text )
        sscanf(text->Value(), "0x%c", &state->registers.GPRM_mode[index]);

      text = TiXmlHandle( element ).FirstChildElement("time").FirstChildElement("tv_sec").FirstChild().Text();
      if( text )
        sscanf(text->Value(), "%ld", &state->registers.GPRM_time[index].tv_sec);

      text = TiXmlHandle( element ).FirstChildElement("time").FirstChildElement("tv_usec").FirstChild().Text();
      if( text )
        sscanf(text->Value(), "%ld", (long int*)&state->registers.GPRM_time[index].tv_usec);
    }
    element = element->NextSiblingElement("gprm");
  }

  if( (text = hRoot.FirstChildElement("domain").FirstChild().Text()) )
    sscanf(text->Value(), "%d", (int*) &state->domain);

  if( (text = hRoot.FirstChildElement("vtsn").FirstChild().Text()) )
    sscanf(text->Value(), "%d", &state->vtsN);

  if( (text = hRoot.FirstChildElement("pgcn").FirstChild().Text()) )
    sscanf(text->Value(), "%d", &state->pgcN);

  if( (text = hRoot.FirstChildElement("pgn").FirstChild().Text()) )
    sscanf(text->Value(), "%d", &state->pgN);

  if( (text = hRoot.FirstChildElement("celln").FirstChild().Text()) )
    sscanf(text->Value(), "%d", &state->cellN);

  if( (text = hRoot.FirstChildElement("cell_restart").FirstChild().Text()) )
    sscanf(text->Value(), "%d", &state->cell_restart);

  if( (text = hRoot.FirstChildElement("blockn").FirstChild().Text()) )
    sscanf(text->Value(), "%d", &state->blockN);

  { TiXmlHandle hrsm = hRoot.FirstChildElement("rsm");

    if( (text = hrsm.FirstChildElement("vtsn").FirstChild().Text()) )
      sscanf(text->Value(), "%d", &state->rsm_vtsN);

    if( (text = hrsm.FirstChildElement("blockn").FirstChild().Text()) )
      sscanf(text->Value(), "%d", &state->rsm_blockN);

    if( (text = hrsm.FirstChildElement("pgcn").FirstChild().Text()) )
      sscanf(text->Value(), "%d", &state->rsm_pgcN);

    if( (text = hrsm.FirstChildElement("celln").FirstChild().Text()) )
      sscanf(text->Value(), "%d", &state->rsm_cellN);

    element = hrsm.FirstChildElement("registers").FirstChildElement("sprm").Element();
    while( element )
    {
      element->Attribute("index", &index);
      text = TiXmlHandle(element).FirstChildElement("value").FirstChild().Text();
      if( text && index >= 0 && index < 5 )
        sscanf(text->Value(), "0x%hx", &state->rsm_regs[index]);

      element = element->NextSiblingElement("sprm");
    }
  }
  return true;
}
예제 #4
0
bool CDirectoryTuxBox::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
  // so we know that we have enigma2
  static bool enigma2 = false;
  // Detect and delete slash at end
  CStdString strRoot = strPath;
  URIUtils::RemoveSlashAtEnd(strRoot);

  //Get the request strings
  CStdString strBQRequest;
  CStdString strXMLRootString;
  CStdString strXMLChildString;
  if(!GetRootAndChildString(strRoot, strBQRequest, strXMLRootString, strXMLChildString))
    return false;

  //Set url Protocol
  CURL url(strRoot);
  CStdString strFilter;
  CStdString protocol = url.GetProtocol();
  CStdString strOptions = url.GetOptions();
  url.SetProtocol("http");
  bool bIsBouquet=false;

  int ipoint = strOptions.Find("?path=");
  if (ipoint >=0)
  {
    // send Zap!
    return g_tuxbox.ZapToUrl(url, strOptions, ipoint);
  }
  else
  {
    ipoint = strOptions.Find("&reference=");
    if (ipoint >=0 || enigma2)
    {
      //List reference
      strFilter = strOptions.Right((strOptions.size()-(ipoint+11)));
      bIsBouquet = false; //On Empty is Bouquet
      if (enigma2)
      {
        CStdString strPort;
        strPort.Format(":%i",url.GetPort());
        if (strRoot.Right(strPort.GetLength()) != strPort) // If not root dir, enable Channels
          strFilter = "e2"; // Disable Bouquets for Enigma2

        GetRootAndChildStringEnigma2(strBQRequest, strXMLRootString, strXMLChildString);
        url.SetOptions("");
        url.SetFileName(strBQRequest);
      }
    }
  }
  if(strFilter.IsEmpty())
  {
    url.SetOptions(strBQRequest);
    bIsBouquet = true;
  }
  //Open
  CFileCurl http;
  int iTryConnect = 0;
  int iWaitTimer = 20;
  bool result = false;

  while (iTryConnect < 4)
  {
    http.SetTimeout(iWaitTimer);
    if(http.Open(url))
    {
      //We are connected!
      iTryConnect = 4;

      // restore protocol
      url.SetProtocol(protocol);

      int size_read = 0;
      int size_total = (int)http.GetLength();
      int data_size = 0;
      CStdString data;
      data.reserve(size_total);

      // read response from server into string buffer
      char buffer[16384];
      while ((size_read = http.Read(buffer, sizeof(buffer)-1)) > 0)
      {
        buffer[size_read] = 0;
        data += buffer;
        data_size += size_read;
      }
      http.Close();

      // parse returned xml
      CXBMCTinyXML doc;
      data.Replace("></",">-</"); //FILL EMPTY ELEMENTS WITH "-"!
      doc.Parse(data.c_str());
      TiXmlElement *root = doc.RootElement();
      if(root == NULL)
      {
        CLog::Log(LOGERROR, "%s - Unable to parse xml", __FUNCTION__);
        CLog::Log(LOGERROR, "%s - Sample follows...\n%s", __FUNCTION__, data.c_str());
        return false;
      }
      if( strXMLRootString.Equals(root->Value()) && bIsBouquet)
      {
        data.Empty();
        if (enigma2)
          result = g_tuxbox.ParseBouquetsEnigma2(root, items, url, strFilter, strXMLChildString);
        else
          result = g_tuxbox.ParseBouquets(root, items, url, strFilter, strXMLChildString);
      }
      else if( strXMLRootString.Equals(root->Value()) && !strFilter.IsEmpty() )
      {
        data.Empty();
        if (enigma2)
          result = g_tuxbox.ParseChannelsEnigma2(root, items, url, strFilter, strXMLChildString);
        else
          result = g_tuxbox.ParseChannels(root, items, url, strFilter, strXMLChildString);
      }
      else
      {
        CLog::Log(LOGERROR, "%s - Invalid root xml element for TuxBox", __FUNCTION__);
        CLog::Log(LOGERROR, "%s - Sample follows...\n%s", __FUNCTION__, data.c_str());
        data.Empty();
        result = false;
      }
    }
    else
    {
      CLog::Log(LOGERROR, "%s - Unable to get XML structure! Try count:%i, Wait Timer:%is",__FUNCTION__, iTryConnect, iWaitTimer);
      iTryConnect++;
      if (iTryConnect == 2) //try enigma2 instead of enigma1, best entrypoint here i thought
      {	
        enigma2 = true;
        GetRootAndChildStringEnigma2(strBQRequest, strXMLRootString, strXMLChildString);
        url.SetOptions("");
        url.SetFileName(strBQRequest);
//        iTryConnect = 0;
        iWaitTimer = 20;
      }
      else
        iWaitTimer = iWaitTimer+10;

      result = false;
      http.Close(); // Close old connections
    }
  }
  items.SetContent("movies");
  return result;
}
예제 #5
0
bool CScraperUrl::Get(const SUrlEntry& scrURL, std::string& strHTML, XFILE::CCurlFile& http, const CStdString& cacheContext)
{
  CURL url(scrURL.m_url);
  http.SetReferer(scrURL.m_spoof);
  CStdString strCachePath;

  if (scrURL.m_isgz)
    http.SetContentEncoding("gzip");

  if (!scrURL.m_cache.empty())
  {
    strCachePath = URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath,
                              "scrapers/" + cacheContext + "/" + scrURL.m_cache);
    if (XFILE::CFile::Exists(strCachePath))
    {
      XFILE::CFile file;
      XFILE::auto_buffer buffer;
      if (file.LoadFile(strCachePath, buffer))
      {
        strHTML.assign(buffer.get(), buffer.length());
        return true;
      }
    }
  }

  CStdString strHTML1(strHTML);

  if (scrURL.m_post)
  {
    CStdString strOptions = url.GetOptions();
    strOptions = strOptions.substr(1);
    url.SetOptions("");

    if (!http.Post(url.Get(), strOptions, strHTML1))
      return false;
  }
  else
    if (!http.Get(url.Get(), strHTML1))
      return false;

  strHTML = strHTML1;

  std::string mimeType(http.GetMimeType());
  CMime::EFileType ftype = CMime::GetFileTypeFromMime(mimeType);
  if (ftype == CMime::FileTypeUnknown)
    ftype = CMime::GetFileTypeFromContent(strHTML);

  if (ftype == CMime::FileTypeZip || ftype == CMime::FileTypeGZip)
  {
    XFILE::CZipFile file;
    std::string strBuffer;
    int iSize = file.UnpackFromMemory(strBuffer,strHTML,scrURL.m_isgz); // FIXME: use FileTypeGZip instead of scrURL.m_isgz?
    if (iSize > 0)
    {
      strHTML = strBuffer;
      CLog::Log(LOGDEBUG, "%s: Archive \"%s\" was unpacked in memory", __FUNCTION__, scrURL.m_url.c_str());
    }
    else
      CLog::Log(LOGWARNING, "%s: \"%s\" looks like archive, but cannot be unpacked", __FUNCTION__, scrURL.m_url.c_str());
  }

  std::string reportedCharset(http.GetServerReportedCharset());
  if (ftype == CMime::FileTypeHtml)
  {
    std::string realHtmlCharset, converted;
    if (!CCharsetDetection::ConvertHtmlToUtf8(strHTML, converted, reportedCharset, realHtmlCharset))
      CLog::Log(LOGWARNING, "%s: Can't find precise charset for HTML \"%s\", using \"%s\" as fallback", __FUNCTION__, scrURL.m_url.c_str(), realHtmlCharset.c_str());
    else
      CLog::Log(LOGDEBUG, "%s: Using \"%s\" charset for HTML \"%s\"", __FUNCTION__, realHtmlCharset.c_str(), scrURL.m_url.c_str());

    strHTML = converted;
  }
  else if (ftype == CMime::FileTypeXml)
  {
    CXBMCTinyXML xmlDoc;
    xmlDoc.Parse(strHTML, reportedCharset);
    
    std::string realXmlCharset(xmlDoc.GetUsedCharset());
    if (!realXmlCharset.empty())
    {
      CLog::Log(LOGDEBUG, "%s: Using \"%s\" charset for XML \"%s\"", __FUNCTION__, realXmlCharset.c_str(), scrURL.m_url.c_str());
      std::string converted;
      g_charsetConverter.ToUtf8(realXmlCharset, strHTML, converted);
      strHTML = converted;
    }
  }
  else if (ftype == CMime::FileTypePlainText || StringUtils::CompareNoCase(mimeType.substr(0, 5), "text/") == 0)
  {
    std::string realTextCharset, converted;
    CCharsetDetection::ConvertPlainTextToUtf8(strHTML, converted, reportedCharset, realTextCharset);
    strHTML = converted;
    if (reportedCharset != realTextCharset)
      CLog::Log(LOGWARNING, "%s: Using \"%s\" charset for plain text \"%s\" instead of server reported \"%s\" charset", __FUNCTION__, realTextCharset.c_str(), scrURL.m_url.c_str(), reportedCharset.c_str());
    else
      CLog::Log(LOGDEBUG, "%s: Using \"%s\" charset for plain text \"%s\"", __FUNCTION__, realTextCharset.c_str(), scrURL.m_url.c_str());
  }
  else if (!reportedCharset.empty())
  {
    CLog::Log(LOGDEBUG, "%s: Using \"%s\" charset for \"%s\"", __FUNCTION__, reportedCharset.c_str(), scrURL.m_url.c_str());
    if (reportedCharset != "UTF-8")
    {
      std::string converted;
      g_charsetConverter.ToUtf8(reportedCharset, strHTML, converted);
      strHTML = converted;
    }
  }
  else
    CLog::Log(LOGDEBUG, "%s: Using content of \"%s\" as binary or text with \"UTF-8\" charset", __FUNCTION__, scrURL.m_url.c_str());

  if (!scrURL.m_cache.empty())
  {
    CStdString strCachePath = URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath,
                              "scrapers/" + cacheContext + "/" + scrURL.m_cache);
    XFILE::CFile file;
    if (file.OpenForWrite(strCachePath,true))
      file.Write(strHTML.data(),strHTML.size());
    file.Close();
  }
  return true;
}
예제 #6
0
//*********************************************************************************************
bool CRTVDirectory::GetDirectory(const CURL& url2, CFileItemList &items)
{
  CURL url(url2);
  std::string strRoot = url.Get();
  URIUtils::AddSlashAtEnd(strRoot);

  // Host name is "*" so we try to discover all ReplayTVs.  This requires some trickery but works.
  if (url.GetHostName() == "*")
  {
    // Check to see whether the URL's path is blank or "Video"
    if (url.GetFileName() == "" || url.GetFileName() == "Video")
    {
      int iOldSize=items.Size();
      struct RTV * rtv = NULL;
      int numRTV;

      // Request that all ReplayTVs on the LAN identify themselves.  Each ReplayTV
      // is given 3000ms to respond to the request.  rtv_discovery returns an array
      // of structs containing the IP and friendly name of all ReplayTVs found on the LAN.
      // For some reason, DVArchive doesn't respond to this request (probably only responds
      // to requests from an IP address of a real ReplayTV).
      numRTV = rtv_discovery(&rtv, 3000);

      // Run through the array and add the ReplayTVs found as folders in XBMC.
      // We must add the IP of each ReplayTV as if it is a file name at the end of a the
      // auto-discover URL--e.g. rtv://*/192.168.1.100--because XBMC does not permit
      // dyamically added shares and will not play from them.  This little trickery is
      // the best workaround I could come up with.
      for (int i = 0; i < numRTV; i++)
      {
        CFileItemPtr pItem(new CFileItem(rtv[i].friendlyName));
        // This will keep the /Video or / and allow one to set up an auto ReplayTV
        // share of either type--simple file listing or ReplayGuide listing.
        pItem->SetPath(strRoot + rtv[i].hostname);
        pItem->m_bIsFolder = true;
        pItem->SetLabelPreformated(true);
        items.Add(pItem);
      }
      free(rtv);
      return (items.Size()>iOldSize);
      // Else the URL's path should be an IP address of the ReplayTV
    }
    else
    {
      std::string strURL, strRTV;
      size_t pos;

      // Isolate the IP from the URL and replace the "*" with the real IP
      // of the ReplayTV.  E.g., rtv://*/Video/192.168.1.100/ becomes
      // rtv://192.168.1.100/Video/ .  This trickery makes things work.
      strURL = StringUtils::TrimRight(strRoot, "/");
      pos = strURL.rfind('/');
      strRTV = strURL.substr(0, pos + 1);
      StringUtils::Replace(strRTV, "*", strURL.substr(pos + 1));
      CURL tmpURL(strRTV);

      // Force the newly constructed share into the right variables to
      // be further processed by the remainder of GetDirectory.
      url = tmpURL;
      strRoot = strRTV;
    }
  }

  // Allow for ReplayTVs on ports other than 80
  std::string strHostAndPort = url.GetHostName();
  if (url.HasPort())
  {
    char buffer[10];
    sprintf(buffer,"%i",url.GetPort());
    strHostAndPort += ':';
    strHostAndPort += buffer;
  }

  // No path given, list shows from ReplayGuide
  if (url.GetFileName() == "")
  {
    unsigned char * data = NULL;

    // Get the RTV guide data in XML format
    rtv_get_guide_xml(&data, strHostAndPort.c_str());

    // Begin parsing the XML data
    CXBMCTinyXML xmlDoc;
    xmlDoc.Parse( (const char *) data );
    if ( xmlDoc.Error() )
    {
      free(data);
      return false;
    }
    TiXmlElement* pRootElement = xmlDoc.RootElement();
    if (!pRootElement)
    {
      free(data);
      return false;
    }

    const TiXmlNode *pChild = pRootElement->FirstChild();
    while (pChild > 0)
    {
      std::string strTagName = pChild->ValueStr();

      if ( !strcmpi(strTagName.c_str(), "ITEM") )
      {
        const TiXmlNode *nameNode = pChild->FirstChild("DISPLAYNAME");
//        const TiXmlNode *qualityNode = pChild->FirstChild("QUALITY");
        const TiXmlNode *recordedNode = pChild->FirstChild("RECORDED");
        const TiXmlNode *pathNode = pChild->FirstChild("PATH");
//        const TiXmlNode *durationNode = pChild->FirstChild("DURATION");
        const TiXmlNode *sizeNode = pChild->FirstChild("SIZE");
        const TiXmlNode *atrbNode = pChild->FirstChild("ATTRIB");

        SYSTEMTIME dtDateTime;
        DWORD dwFileSize = 0;
        memset(&dtDateTime, 0, sizeof(dtDateTime));

        // DISPLAYNAME
        const char* szName = NULL;
        if (nameNode)
        {
          szName = nameNode->FirstChild()->Value() ;
        }
        else
        {
          // Something went wrong, the recording has no name
          free(data);
          return false;
        }

        // QUALITY
//        const char* szQuality = NULL;
//        if (qualityNode)
//        {
//          szQuality = qualityNode->FirstChild()->Value() ;
//        }

        // RECORDED
        if (recordedNode && recordedNode->FirstChild())
        {
          std::string strRecorded = recordedNode->FirstChild()->ValueStr();

          if (strRecorded.size() >= 19)
          {
            /* TODO:STRING_CLEANUP */
            int iYear, iMonth, iDay;
            iYear = atoi(strRecorded.substr(0, 4).c_str());
            iMonth = atoi(strRecorded.substr(5, 2).c_str());
            iDay = atoi(strRecorded.substr(8, 2).c_str());
            dtDateTime.wYear = iYear;
            dtDateTime.wMonth = iMonth;
            dtDateTime.wDay = iDay;

            int iHour, iMin, iSec;
            iHour = atoi(strRecorded.substr(11, 2).c_str());
            iMin = atoi(strRecorded.substr(14, 2).c_str());
            iSec = atoi(strRecorded.substr(17, 2).c_str());
            dtDateTime.wHour = iHour;
            dtDateTime.wMinute = iMin;
            dtDateTime.wSecond = iSec;
          }
        }

        // PATH
        const char* szPath = NULL;
        if (pathNode)
        {
          szPath = pathNode->FirstChild()->Value() ;
        }
        else
        {
          // Something went wrong, the recording has no filename
          free(data);
          return false;
        }

        // DURATION
//        const char* szDuration = NULL;
//        if (durationNode)
//        {
//          szDuration = durationNode->FirstChild()->Value() ;
//        }

        // SIZE
        // NOTE: Size here is actually just duration in minutes because
        // filesize is not reported by the stripped down GuideParser I use
        if (sizeNode)
        {
          dwFileSize = atol( sizeNode->FirstChild()->Value() );
        }

        // ATTRIB
        // NOTE: Not currently reported in the XML guide data, nor is it particularly
        // needed unless someone wants to add the ability to sub-divide the recordings
        // into categories, as on a real RTV.
        int attrib = 0;
        if (atrbNode)
        {
          attrib = atoi( atrbNode->FirstChild()->Value() );
        }

        bool bIsFolder(false);
        if (attrib & FILE_ATTRIBUTE_DIRECTORY)
          bIsFolder = true;

        CFileItemPtr pItem(new CFileItem(szName));
        pItem->m_dateTime=dtDateTime;
        pItem->SetPath(strRoot + szPath);
        // Hack to show duration of show in minutes as KB in XBMC because
        // it doesn't currently permit showing duration in minutes.
        // E.g., a 30 minute show will show as 29.3 KB in XBMC.
        pItem->m_dwSize = dwFileSize * 1000;
        pItem->m_bIsFolder = bIsFolder;
        pItem->SetLabelPreformated(true);
        items.Add(pItem);
      }

      pChild = pChild->NextSibling();
    }

    free(data);

    // Path given (usually Video), list filenames only
  }
  else
  {

    unsigned char * data;
    char * p, * q;
    unsigned long status;

    // Return a listing of all files in the given path
    status = rtv_list_files(&data, strHostAndPort.c_str(), url.GetFileName().c_str());
    if (status == 0)
    {
      return false;
    }

    // Loop through the file list using pointers p and q, where p will point to the current
    // filename and q will point to the next filename
    p = (char *) data;
    while (p)
    {
      // Look for the end of the current line of the file listing
      q = strchr(p, '\n');
      // If found, replace the newline character with the NULL terminator
      if (q)
      {
        *q = '\0';
        // Increment q so that it points to the next filename
        q++;
        // *p should be the current null-terminated filename in the list
        if (*p)
        {
          // Only display MPEG files in XBMC (but not circular.mpg, as that is the RTV
          // video buffer and XBMC may cause problems if it tries to play it)
          if (strstr(p, ".mpg") && !strstr(p, "circular"))
          {
            CFileItemPtr pItem(new CFileItem(p));
            pItem->SetPath(strRoot + p);
            pItem->m_bIsFolder = false;
            // The list returned by the RTV doesn't include file sizes, unfortunately
            //pItem->m_dwSize = atol(szSize);
            pItem->SetLabelPreformated(true);
            items.Add(pItem);
          }
        }
      }
      // Point p to the next filename in the list and loop
      p = q;
    }

    free(data);
  }

  return true;
}
예제 #7
0
bool CLastFmManager::RequestRadioTracks()
{
  unsigned int start = XbmcThreads::SystemClockMillis();
  CStdString url;
  CStdString html;
  url.Format("http://" + m_RadioBaseUrl + m_RadioBasePath + "/xspf.php?sk=%s&discovery=0&desktop=", m_RadioSession);
  {
    CFileCurl http;
    if (!http.Get(url, html))
    {
      m_RadioSession.empty();
      CLog::Log(LOGERROR, "LastFmManager: Connect to Last.fm to request tracks failed.");
      return false;
    }
  }
  //CLog::Log(LOGDEBUG, "RequestRadioTracks: %s", html.c_str());

  //parse playlist
  CXBMCTinyXML xmlDoc;

  xmlDoc.Parse(html);
  if (xmlDoc.Error())
  {
    m_RadioSession.empty();
    CLog::Log(LOGERROR, "LastFmManager: Unable to parse tracklist Error: %s", xmlDoc.ErrorDesc());
    return false;
  }

  TiXmlElement* pRootElement = xmlDoc.RootElement();
  if (!pRootElement )
  {
    CLog::Log(LOGWARNING, "LastFmManager: No more tracks received");
    m_RadioSession.empty();
    return false;
  }

  TiXmlElement* pBodyElement = pRootElement->FirstChildElement("trackList");
  if (!pBodyElement )
  {
    CLog::Log(LOGWARNING, "LastFmManager: No more tracks received, no tracklist");
    m_RadioSession.empty();
    return false;
  }

  TiXmlElement* pTrackElement = pBodyElement->FirstChildElement("track");

  if (!pTrackElement)
  {
    CLog::Log(LOGWARNING, "LastFmManager: No more tracks received, empty tracklist");
    m_RadioSession.empty();
    return false;
  }
  while (pTrackElement)
  {
    CFileItemPtr newItem(new CFileItem);

    TiXmlElement* pElement = pTrackElement->FirstChildElement("location");
    if (pElement)
    {
      TiXmlNode* child = pElement->FirstChild();
      if (child)
      {
        CStdString url = child->Value();
        url.Replace("http:", "lastfm:");
        newItem->SetPath(url);
      }
    }
    pElement = pTrackElement->FirstChildElement("title");
    if (pElement)
    {
      TiXmlNode* child = pElement->FirstChild();
      if (child)
      {
        newItem->SetLabel(child->Value());
        newItem->GetMusicInfoTag()->SetTitle(child->Value());
      }
    }
    pElement = pTrackElement->FirstChildElement("creator");
    if (pElement)
    {
      TiXmlNode* child = pElement->FirstChild();
      if (child)
      {
        newItem->GetMusicInfoTag()->SetArtist(child->Value());
      }
    }
    pElement = pTrackElement->FirstChildElement("album");
    if (pElement)
    {
      TiXmlNode* child = pElement->FirstChild();
      if (child)
      {
        newItem->GetMusicInfoTag()->SetAlbum(child->Value());
      }
    }

    pElement = pTrackElement->FirstChildElement("duration");
    if (pElement)
    {
      TiXmlNode* child = pElement->FirstChild();
      if (child)
      {
        int iDuration = atoi(child->Value())/1000;
        newItem->GetMusicInfoTag()->SetDuration(iDuration);
      }
    }
    newItem->FillInDefaultIcon();
    pElement = pTrackElement->FirstChildElement("image");
    if (pElement)
    {
      TiXmlNode* child = pElement->FirstChild();
      if (child)
      {
        CStdString coverUrl = child->Value();
        if ((coverUrl != "") && (coverUrl.Find("noimage") == -1) && (coverUrl.Right(1) != "/"))
        {
          newItem->SetThumbnailImage(coverUrl);
        }
      }
    }
    //trackauth is needed for validating the track when scrobbling
    pElement = pTrackElement->FirstChildElement("lastfm:trackauth");
    if (pElement)
    {
      TiXmlNode* child = pElement->FirstChild();
      if (child)
      {
        CStdString trackAuth = child->Value();
        //abuse comment field for the track authcode
        newItem->GetMusicInfoTag()->SetComment(trackAuth);
      }
    }

    {
      CSingleLock lock(m_lockCache);
      m_RadioTrackQueue->Add(newItem);
    }
    pTrackElement = pTrackElement->NextSiblingElement();
  }
  //end parse
  CSingleLock lock(m_lockCache);
  int iNrCachedTracks = m_RadioTrackQueue->size();
  CLog::Log(LOGDEBUG, "%s: Done (time: %i ms)", __FUNCTION__, (int)(XbmcThreads::SystemClockMillis() - start));
  return iNrCachedTracks > 0;
}