Exemple #1
0
bool CFile::Cache(const CStdString& strFileName, const CStdString& strDest, XFILE::IFileCallback* pCallback, void* pContext)
{
  CFile file;
  CAsyncFileCallback* helper = NULL;

  if (file.Open(strFileName, true, READ_TRUNCATED))
  {
    if (file.GetLength() <= 0)
    {
      CLog::Log(LOGWARNING, "FILE::cache: the file %s has a length of 0 bytes", strFileName.c_str());
      file.Close();
      
      // Never save 0 byte files from the Plex Media Server.
      if (strFileName.Find(":32400") != -1)
        return false;
    }

    CFile newFile;
    if (CUtil::IsHD(strDest)) // create possible missing dirs
    {
      std::vector<CStdString> tokens;
      CStdString strDirectory;
      CUtil::GetDirectory(strDest,strDirectory);
      CUtil::RemoveSlashAtEnd(strDirectory);  // for the test below
      if (!(strDirectory.size() == 2 && strDirectory[1] == ':'))
      {
        CUtil::Tokenize(strDirectory,tokens,"\\");
        CStdString strCurrPath = tokens[0]+"\\";
        for (std::vector<CStdString>::iterator iter=tokens.begin()+1;iter!=tokens.end();++iter)
        {
          strCurrPath += *iter+"\\";
          CDirectory::Create(strCurrPath);
        }
      }
    }
    if (CFile::Exists(strDest))
      CFile::Delete(strDest);
    if (!newFile.OpenForWrite(strDest, true, true))  // overwrite always
    {
      file.Close();
      return false;
    }

    /* larger then 1 meg, let's do rendering async */
// Async render cannot be done in Linux because of the resulting ThreadMessage deadlock
#ifndef _LINUX
    if( file.GetLength() > 1024*1024 )
      helper = new CAsyncFileCallback(pCallback, pContext);
#endif

    // 128k is optimal for xbox
    int iBufferSize = 128 * 1024;

    CAutoBuffer buffer(iBufferSize);
    int iRead, iWrite;

    UINT64 llFileSize = file.GetLength();
    UINT64 llFileSizeOrg = llFileSize;
    UINT64 llPos = 0;
    int ipercent = 0;

    CStopWatch timer;
    timer.StartZero();
    float start = 0.0f;
    while (llFileSize > 0)
    {
      g_application.ResetScreenSaver();
      unsigned int iBytesToRead = iBufferSize;
      
      /* make sure we don't try to read more than filesize*/
      if (iBytesToRead > llFileSize) iBytesToRead = llFileSize;

      iRead = file.Read(buffer.get(), iBytesToRead);
      if (iRead == 0) break;
      else if (iRead < 0) 
      {
        CLog::Log(LOGERROR, "%s - Failed read from file %s", __FUNCTION__, strFileName.c_str());
        break;
      }

      /* write data and make sure we managed to write it all */
      iWrite = 0;
      while(iWrite < iRead)
      {
        int iWrite2 = newFile.Write(buffer.get()+iWrite, iRead-iWrite);
        if(iWrite2 <=0)          
          break;
        iWrite+=iWrite2;
      }

      if (iWrite != iRead)
      {
        CLog::Log(LOGERROR, "%s - Failed write to file %s", __FUNCTION__, strDest.c_str());
        break;
      }
      
      llFileSize -= iRead;
      llPos += iRead;

      // calculate the current and average speeds
      float end = timer.GetElapsedSeconds();
      float averageSpeed = llPos / end;
      start = end;

      float fPercent = 100.0f * (float)llPos / (float)llFileSizeOrg;

      if ((int)fPercent != ipercent)
      {
        if( helper )
        {
          helper->SetStatus((int)fPercent, averageSpeed);
          if(helper->IsCanceled())
            break;
        }
        else if( pCallback )
        {
          if (!pCallback->OnFileCallback(pContext, ipercent, averageSpeed)) 
            break;
        }

        ipercent = (int)fPercent;
      }
    }

    /* close both files */
    newFile.Close();
    file.Close();
    
    if(helper)
      delete helper;

    /* verify that we managed to completed the file */
    if (llPos != llFileSizeOrg)
    {      
      CFile::Delete(strDest);
      return false;
    }
    return true;
  }
  return false;
}
Exemple #2
0
void CGUIInfoLabel::Parse(const CStdString &label, int context)
{
  m_info.clear();
  // Step 1: Replace all $LOCALIZE[number] with the real string
  CStdString work = ReplaceLocalize(label);
  // Step 2: Replace all $ADDON[id number] with the real string
  work = ReplaceAddonStrings(work);
  // Step 3: Find all $INFO[info,prefix,postfix] blocks
  EINFOFORMAT format;
  do
  {
    format = NONE;
    size_t pos1 = work.size();
    size_t pos2;
    size_t len = 0;
    for (size_t i = 0; i < sizeof(infoformatmap) / sizeof(infoformat); i++)
    {
      pos2 = work.find(infoformatmap[i].str);
      if (pos2 != string::npos && pos2 < pos1)
      {
        pos1 = pos2;
        len = strlen(infoformatmap[i].str);
        format = infoformatmap[i].val;
      }
    }

    if (format != NONE)
    {
      if (pos1 > 0)
        m_info.push_back(CInfoPortion(0, work.substr(0, pos1), ""));

      pos2 = StringUtils::FindEndBracket(work, '[', ']', pos1 + len);
      if (pos2 != std::string::npos)
      {
        // decipher the block
        CStdString block = work.substr(pos1 + len, pos2 - pos1 - len);
        CStdStringArray params;
        StringUtils::SplitString(block, ",", params);
        int info;
        if (format == FORMATVAR)
        {
          info = g_infoManager.TranslateSkinVariableString(params[0], context);
          if (info == 0)
            info = g_infoManager.RegisterSkinVariableString(g_SkinInfo->CreateSkinVariable(params[0], context));
          if (info == 0) // skinner didn't define this conditional label!
            CLog::Log(LOGWARNING, "Label Formating: $VAR[%s] is not defined", params[0].c_str());
        }
        else
          info = g_infoManager.TranslateString(params[0]);
        CStdString prefix, postfix;
        if (params.size() > 1)
          prefix = params[1];
        if (params.size() > 2)
          postfix = params[2];
        m_info.push_back(CInfoPortion(info, prefix, postfix, format == FORMATESCINFO));
        // and delete it from our work string
        work = work.substr(pos2 + 1);
      }
      else
      {
        CLog::Log(LOGERROR, "Error parsing label - missing ']' in \"%s\"", label.c_str());
        return;
      }
    }
  }
  while (format != NONE);

  if (!work.empty())
    m_info.push_back(CInfoPortion(0, work, ""));
}
Exemple #3
0
// This *looks* like a copy function, therefor the name "Cache" is misleading
bool CFile::Cache(const CStdString& strFileName, const CStdString& strDest, XFILE::IFileCallback* pCallback, void* pContext)
{
  CFile file;

  if (strFileName.empty() || strDest.empty())
    return false;

  // special case for zips - ignore caching
  CURL url(strFileName);
  if (URIUtils::IsInZIP(strFileName) || URIUtils::IsInAPK(strFileName))
    url.SetOptions("?cache=no");
  if (file.Open(url.Get(), READ_TRUNCATED))
  {

    CFile newFile;
    if (URIUtils::IsHD(strDest)) // create possible missing dirs
    {
      vector<CStdString> tokens;
      CStdString strDirectory = URIUtils::GetDirectory(strDest);
      URIUtils::RemoveSlashAtEnd(strDirectory);  // for the test below
      if (!(strDirectory.size() == 2 && strDirectory[1] == ':'))
      {
        CURL url(strDirectory);
        CStdString pathsep;
#ifndef TARGET_POSIX
        pathsep = "\\";
#else
        pathsep = "/";
#endif
        CUtil::Tokenize(url.GetFileName(),tokens,pathsep.c_str());
        CStdString strCurrPath;
        // Handle special
        if (!url.GetProtocol().IsEmpty()) {
          pathsep = "/";
          strCurrPath += url.GetProtocol() + "://";
        } // If the directory has a / at the beginning, don't forget it
        else if (strDirectory[0] == pathsep[0])
          strCurrPath += pathsep;
        for (vector<CStdString>::iterator iter=tokens.begin();iter!=tokens.end();++iter)
        {
          strCurrPath += *iter+pathsep;
          CDirectory::Create(strCurrPath);
        }
      }
    }
    if (CFile::Exists(strDest))
      CFile::Delete(strDest);
    if (!newFile.OpenForWrite(strDest, true))  // overwrite always
    {
      file.Close();
      return false;
    }

    int iBufferSize = 128 * 1024;

    CAutoBuffer buffer(iBufferSize);
    int iRead, iWrite;

    UINT64 llFileSize = file.GetLength();
    UINT64 llPos = 0;

    CStopWatch timer;
    timer.StartZero();
    float start = 0.0f;
    while (true)
    {
      g_application.ResetScreenSaver();

      iRead = file.Read(buffer.get(), iBufferSize);
      if (iRead == 0) break;
      else if (iRead < 0)
      {
        CLog::Log(LOGERROR, "%s - Failed read from file %s", __FUNCTION__, strFileName.c_str());
        llFileSize = (uint64_t)-1;
        break;
      }

      /* write data and make sure we managed to write it all */
      iWrite = 0;
      while(iWrite < iRead)
      {
        int iWrite2 = newFile.Write(buffer.get()+iWrite, iRead-iWrite);
        if(iWrite2 <=0)
          break;
        iWrite+=iWrite2;
      }

      if (iWrite != iRead)
      {
        CLog::Log(LOGERROR, "%s - Failed write to file %s", __FUNCTION__, strDest.c_str());
        llFileSize = (uint64_t)-1;
        break;
      }

      llPos += iRead;

      // calculate the current and average speeds
      float end = timer.GetElapsedSeconds();

      if (pCallback && end - start > 0.5 && end)
      {
        start = end;

        float averageSpeed = llPos / end;
        int ipercent = 0;
        if(llFileSize)
          ipercent = 100 * llPos / llFileSize;

        if(!pCallback->OnFileCallback(pContext, ipercent, averageSpeed))
        {
          CLog::Log(LOGERROR, "%s - User aborted copy", __FUNCTION__);
          llFileSize = (uint64_t)-1;
          break;
        }
      }
    }

    /* close both files */
    newFile.Close();
    file.Close();

    /* verify that we managed to completed the file */
    if (llFileSize && llPos != llFileSize)
    {
      CFile::Delete(strDest);
      return false;
    }
    return true;
  }
  return false;
}
Exemple #4
0
bool CEGLNativeTypeAmlogic::ModeToResolution(const char *mode, RESOLUTION_INFO *res) const
{
  if (!res)
    return false;

  res->iWidth = 0;
  res->iHeight= 0;

  if(!mode)
    return false;

  CStdString fromMode = mode;
  fromMode.Trim();
  // strips, for example, 720p* to 720p
  // the * indicate the 'native' mode of the display
  if (fromMode.Right(1) == "*")
    fromMode = fromMode.Left(std::max(0, (int)fromMode.size() - 1));

  if (fromMode.Equals("720p"))
  {
    res->iWidth = 1280;
    res->iHeight= 720;
    res->iScreenWidth = 1280;
    res->iScreenHeight= 720;
    res->fRefreshRate = 60;
    res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
  }
  else if (fromMode.Equals("720p50hz"))
  {
    res->iWidth = 1280;
    res->iHeight= 720;
    res->iScreenWidth = 1280;
    res->iScreenHeight= 720;
    res->fRefreshRate = 50;
    res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
  }
  else if (fromMode.Equals("1080p"))
  {
    res->iWidth = 1280;
    res->iHeight= 720;
    res->iScreenWidth = 1920;
    res->iScreenHeight= 1080;
    res->fRefreshRate = 60;
    res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
  }
  else if (fromMode.Equals("1080p24hz"))
  {
    res->iWidth = 1280;
    res->iHeight= 720;
    res->iScreenWidth = 1920;
    res->iScreenHeight= 1080;
    res->fRefreshRate = 24;
    res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
  }
  else if (fromMode.Equals("1080p30hz"))
  {
    res->iWidth = 1280;
    res->iHeight= 720;
    res->iScreenWidth = 1920;
    res->iScreenHeight= 1080;
    res->fRefreshRate = 30;
    res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
  }
  else if (fromMode.Equals("1080p50hz"))
  {
    res->iWidth = 1280;
    res->iHeight= 720;
    res->iScreenWidth = 1920;
    res->iScreenHeight= 1080;
    res->fRefreshRate = 50;
    res->dwFlags = D3DPRESENTFLAG_PROGRESSIVE;
  }
  else if (fromMode.Equals("1080i"))
  {
    res->iWidth = 1280;
    res->iHeight= 720;
    res->iScreenWidth = 1920;
    res->iScreenHeight= 1080;
    res->fRefreshRate = 60;
    res->dwFlags = D3DPRESENTFLAG_INTERLACED;
  }
  else if (fromMode.Equals("1080i50hz"))
  {
    res->iWidth = 1280;
    res->iHeight= 720;
    res->iScreenWidth = 1920;
    res->iScreenHeight= 1080;
    res->fRefreshRate = 50;
    res->dwFlags = D3DPRESENTFLAG_INTERLACED;
  }
  else
  {
    return false;
  }


  res->iScreen       = 0;
  res->bFullScreen   = true;
  res->iSubtitles    = (int)(0.965 * res->iHeight);
  res->fPixelRatio   = 1.0f;
  res->strMode.Format("%dx%d @ %.2f%s - Full Screen", res->iScreenWidth, res->iScreenHeight, res->fRefreshRate,
    res->dwFlags & D3DPRESENTFLAG_INTERLACED ? "i" : "");

  return res->iWidth > 0 && res->iHeight> 0;
}
Exemple #5
0
// NB: The rar manager expects paths in rars to be terminated with a "\".
bool CRarManager::GetFilesInRar(CFileItemList& vecpItems, const CStdString& strRarPath,
                                bool bMask, const CStdString& strPathInRar)
{
#ifdef HAS_FILESYSTEM_RAR
  CSingleLock lock(m_CritSection);

  ArchiveList_struct* pFileList = NULL;
  map<CStdString,pair<ArchiveList_struct*,vector<CFileInfo> > >::iterator it = m_ExFiles.find(strRarPath);
  if (it == m_ExFiles.end())
  {
    if( urarlib_list((char*) strRarPath.c_str(), &pFileList, NULL) )
      m_ExFiles.insert(make_pair(strRarPath,make_pair(pFileList,vector<CFileInfo>())));
    else
    {
      if( pFileList ) urarlib_freelist(pFileList);
      return false;
    }
  }
  else
    pFileList = it->second.first;

  CFileItemPtr pFileItem;
  vector<CStdString> vec;
  set<CStdString> dirSet;
  CUtil::Tokenize(strPathInRar,vec,"/");
  unsigned int iDepth = vec.size();

  ArchiveList_struct* pIterator;
  CStdString strCompare = strPathInRar;
  if (!URIUtils::HasSlashAtEnd(strCompare) && !strCompare.IsEmpty())
    strCompare += '/';
  for( pIterator = pFileList; pIterator  ; pIterator ? pIterator = pIterator->next : NULL)
  {
    CStdString strDirDelimiter = (pIterator->item.HostOS==3 ? "/":"\\"); // win32 or unix paths?
    CStdString strName;

    /* convert to utf8 */
    if( pIterator->item.NameW && wcslen(pIterator->item.NameW) > 0)
      g_charsetConverter.wToUTF8(pIterator->item.NameW, strName);
    else
      g_charsetConverter.unknownToUTF8(pIterator->item.Name, strName);

    /* replace back slashes into forward slashes */
    /* this could get us into troubles, file could two different files, one with / and one with \ */
    strName.Replace('\\', '/');

    if (bMask)
    {
      if (!strstr(strName.c_str(),strCompare.c_str()))
        continue;

      vec.clear();
      CUtil::Tokenize(strName,vec,"/");
      if (vec.size() < iDepth)
        continue;
    }

    unsigned int iMask = (pIterator->item.HostOS==3 ? 0x0040000:16); // win32 or unix attribs?
    if (((pIterator->item.FileAttr & iMask) == iMask) || (vec.size() > iDepth+1 && bMask)) // we have a directory
    {
      if (!bMask) continue;
      if (vec.size() == iDepth)
        continue; // remove root of listing

      if (dirSet.find(vec[iDepth]) == dirSet.end())
      {
        dirSet.insert(vec[iDepth]);
        pFileItem.reset(new CFileItem(vec[iDepth]));
        pFileItem->m_strPath = vec[iDepth];
        pFileItem->m_strPath += '/';
        pFileItem->m_bIsFolder = true;
        pFileItem->m_idepth = pIterator->item.Method;
        pFileItem->m_iDriveType = pIterator->item.HostOS;
        //pFileItem->m_lEndOffset = long(pIterator->item.iOffset);
      }
    }
    else
    {
      if (vec.size() == iDepth+1 || !bMask)
      {
        if (vec.size() == 0)
          pFileItem.reset(new CFileItem(strName));
        else
          pFileItem.reset(new CFileItem(vec[iDepth]));
        pFileItem->m_strPath = strName.c_str()+strPathInRar.size();
        pFileItem->m_dwSize = pIterator->item.UnpSize;
        pFileItem->m_idepth = pIterator->item.Method;
        pFileItem->m_iDriveType = pIterator->item.HostOS;
        //pFileItem->m_lEndOffset = long(pIterator->item.iOffset);
      }
    }
    if (pFileItem)
      vecpItems.Add(pFileItem);

    pFileItem.reset();
  }
  return vecpItems.Size() > 0;
#else
  return false;
#endif
}
Exemple #6
0
void SamiTagConvertor::ConvertLine(CDVDOverlayText* pOverlay, const char* line, int len, const char* lang)
{
  CStdStringA strUTF8;
  strUTF8.assign(line, len);

  int pos = 0;
  int del_start = 0;
  while ((pos=m_tags->RegFind(strUTF8.c_str(), pos)) >= 0)
  {
    // Parse Tags
    CStdString fullTag = m_tags->GetMatch(0);
    fullTag.ToLower();
    strUTF8.erase(pos, fullTag.length());
    if (fullTag == "<b>")
    {
      tag_flag[FLAG_BOLD] = true;
      strUTF8.insert(pos, "[B]");
      pos += 3;
    }
    else if (fullTag == "</b>" && tag_flag[FLAG_BOLD])
    {
      tag_flag[FLAG_BOLD] = false;
      strUTF8.insert(pos, "[/B]");
      pos += 4;
    }
    else if (fullTag == "<i>")
    {
      tag_flag[FLAG_ITALIC] = true;
      strUTF8.insert(pos, "[I]");
      pos += 3;
    }
    else if (fullTag == "</i>" && tag_flag[FLAG_ITALIC])
    {
      tag_flag[FLAG_ITALIC] = false;
      strUTF8.insert(pos, "[/I]");
      pos += 4;
    }
    else if (fullTag == "</font>" && tag_flag[FLAG_COLOR])
    {
      tag_flag[FLAG_COLOR] = false;
      strUTF8.insert(pos, "[/COLOR]");
      pos += 8;
    }
    else if (fullTag.Left(5) == "<font")
    {
      int pos2 = 5;
      while ((pos2 = m_tagOptions->RegFind(fullTag.c_str(), pos2)) >= 0)
      {
        CStdString tagOptionName = m_tagOptions->GetMatch(1);
        CStdString tagOptionValue = m_tagOptions->GetMatch(2);
        pos2 += tagOptionName.length() + tagOptionValue.length();
        if (tagOptionName == "color")
        {
          tag_flag[FLAG_COLOR] = true;
          CStdString tempColorTag = "[COLOR ";
          if (tagOptionValue[0] == '#')
          {
            tagOptionValue.erase(0, 1);
            tempColorTag += "FF";
          }
          else if( tagOptionValue.size() == 6 )
          {
            bool bHex = true;
            for( int i=0 ; i<6 ; i++ )
            {
              char temp = tagOptionValue[i];
              if( !(('0' <= temp && temp <= '9') ||
                ('a' <= temp && temp <= 'f') ||
                ('A' <= temp && temp <= 'F') ))
              {
                bHex = false;
                break;
              }
            }
            if( bHex ) tempColorTag += "FF";
          }
          tempColorTag += tagOptionValue;
          tempColorTag += "]";
          strUTF8.insert(pos, tempColorTag);
          pos += tempColorTag.length();
        }
      }
    }
    else if (lang && (fullTag.Left(3) == "<p "))
    {
      int pos2 = 3;
      while ((pos2 = m_tagOptions->RegFind(fullTag.c_str(), pos2)) >= 0)
      {
        CStdString tagOptionName = m_tagOptions->GetMatch(1);
        CStdString tagOptionValue = m_tagOptions->GetMatch(2);
        pos2 += tagOptionName.length() + tagOptionValue.length();
        if (tagOptionName == "class")
        {
          if (tag_flag[FLAG_LANGUAGE])
          {
            strUTF8.erase(del_start, pos - del_start);
            pos = del_start;
          }
          if (!tagOptionValue.Compare(lang))
          {
            tag_flag[FLAG_LANGUAGE] = false;
          }
          else
          {
            tag_flag[FLAG_LANGUAGE] = true;
            del_start = pos;
          }
          break;
        }
      }
    }
    else if (fullTag == "</p>" && tag_flag[FLAG_LANGUAGE])
    {
      strUTF8.erase(del_start, pos - del_start);
      pos = del_start;
      tag_flag[FLAG_LANGUAGE] = false;
    }
    else if (fullTag == "<br>" && !strUTF8.IsEmpty())
    {
      strUTF8.Insert(pos, "\n");
      pos += 1;
    }
  }

  if(tag_flag[FLAG_LANGUAGE])
    strUTF8.erase(del_start);

  if (strUTF8.IsEmpty())
    return;

  if( strUTF8[strUTF8.size()-1] == '\n' )
    strUTF8.Delete(strUTF8.size()-1);

  // add a new text element to our container
  pOverlay->AddElement(new CDVDOverlayText::CElementText(strUTF8.c_str()));
}
Exemple #7
0
// Android apk directory i/o. Depends on libzip
// Basically the same format as zip.
// We might want to refactor CZipDirectory someday...
//////////////////////////////////////////////////////////////////////
bool CAPKDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
  // uses a <fully qualified path>/filename.apk/...
  CURL url(strPath);

  CStdString path = url.GetFileName();
  CStdString host = url.GetHostName();
  URIUtils::AddSlashAtEnd(path);

  // host name might be encoded rfc1738.txt, decode it.
  CURL::Decode(host);

  int zip_flags = 0, zip_error = 0, dir_marker = 0;
  struct zip *zip_archive;
  zip_archive = zip_open(host.c_str(), zip_flags, &zip_error);
  if (!zip_archive || zip_error)
  {
    CLog::Log(LOGERROR, "CAPKDirectory::GetDirectory: Unable to open archive : '%s'",
      host.c_str());
    return false;
  }

  CStdString test_name;
  int numFiles = zip_get_num_files(zip_archive);
  for (int zip_index = 0; zip_index < numFiles; zip_index++)
  {
    test_name = zip_get_name(zip_archive, zip_index, zip_flags);

    // check for non matching path.
    if (!test_name.Left(path.size()).Equals(path))
      continue;

    // libzip does not index folders, only filenames. We search for a /,
    // add it if it's not in our list already, and hope that no one has
    // any "file/name.exe" files in a zip.

    dir_marker = test_name.Find('/', path.size() + 1);
    if (dir_marker > 0)
    {
      // return items relative to path
      test_name=test_name.Left(dir_marker);

      if (items.Contains(host + "/" + test_name))
        continue;
    }

    struct zip_stat sb;
    zip_stat_init(&sb);
    if (zip_stat_index(zip_archive, zip_index, zip_flags, &sb) != -1)
    {
      g_charsetConverter.unknownToUTF8(test_name);
      CFileItemPtr pItem(new CFileItem(test_name));      
      pItem->m_dwSize    = sb.size;
      pItem->m_dateTime  = sb.mtime;    
      pItem->m_bIsFolder = dir_marker > 0 ;
      pItem->SetPath(host + "/" + test_name);
      pItem->SetLabel(test_name.Right(test_name.size() - path.size()));
      items.Add(pItem);      
    }
  }
  zip_close(zip_archive);

  return true;
}
Exemple #8
0
bool CZipManager::GetZipList(const CStdString& strPath, vector<SZipEntry>& items)
{
  CLog::Log(LOGDEBUG, "%s - Processing %s", __FUNCTION__, strPath.c_str());

  CURL url(strPath);
  struct __stat64 m_StatData = {};

  CStdString strFile = url.GetHostName();

  if (CFile::Stat(strFile,&m_StatData))
  {
    CLog::Log(LOGDEBUG,"CZipManager::GetZipList: failed to stat file %s", strPath.c_str());
    return false;
  }

  map<CStdString,vector<SZipEntry> >::iterator it = mZipMap.find(strFile);
  if (it != mZipMap.end()) // already listed, just return it if not changed, else release and reread
  {
    map<CStdString,int64_t>::iterator it2=mZipDate.find(strFile);
    CLog::Log(LOGDEBUG,"statdata: %"PRId64" new: %"PRIu64, it2->second, (uint64_t)m_StatData.st_mtime);

      if (m_StatData.st_mtime == it2->second)
      {
        items = it->second;
        return true;
      }
      mZipMap.erase(it);
      mZipDate.erase(it2);
  }

  CFile mFile;
  if (!mFile.Open(strFile))
  {
    CLog::Log(LOGDEBUG,"ZipManager: unable to open file %s!",strFile.c_str());
    return false;
  }

  unsigned int hdr;
  mFile.Read(&hdr, 4);
  if( Endian_SwapLE32(hdr) != ZIP_LOCAL_HEADER )
  {
    CLog::Log(LOGDEBUG,"ZipManager: not a zip file!");
    mFile.Close();
    return false;
  }
  // push date for update detection
  mZipDate.insert(make_pair(strFile,m_StatData.st_mtime));


  // Look for end of central directory record
  // Zipfile comment may be up to 65535 bytes
  // End of central directory record is 22 bytes (ECDREC_SIZE)
  // -> need to check the last 65557 bytes
  int64_t fileSize = mFile.GetLength();
  // Don't need to look in the last 18 bytes (ECDREC_SIZE-4)
  // But as we need to do overlapping between blocks (3 bytes),
  // we start the search at ECDREC_SIZE-1 from the end of file
  int searchSize = (int) min(65557, fileSize-ECDREC_SIZE+1);
  int blockSize = (int) min(1024, searchSize);
  int nbBlock = searchSize / blockSize;
  int extraBlockSize = searchSize % blockSize;
  // Signature is on 4 bytes
  // It could be between 2 blocks, so we need to read 3 extra bytes
  char *buffer = new char[blockSize+3];
  bool found = false;

  // Loop through blocks starting at the end of the file (minus ECDREC_SIZE-1)
  for (int nb=1; !found && (nb <= nbBlock); nb++)
  {
    mFile.Seek(fileSize-ECDREC_SIZE+1-(blockSize*nb),SEEK_SET);
    mFile.Read(buffer,blockSize+3);
    for (int i=blockSize-1; !found && (i >= 0); i--)
    {
      if ( Endian_SwapLE32(*((unsigned int*)(buffer+i))) == ZIP_END_CENTRAL_HEADER )
      {
        // Set current position to start of end of central directory
        mFile.Seek(fileSize-ECDREC_SIZE+1-(blockSize*nb)+i,SEEK_SET);
        found = true;
      }
    }
  }

  // If not found, look in the last block left...
  if ( !found && (extraBlockSize > 0) )
  {
    mFile.Seek(fileSize-ECDREC_SIZE+1-searchSize,SEEK_SET);
    mFile.Read(buffer,extraBlockSize+3);
    for (int i=extraBlockSize-1; !found && (i >= 0); i--)
    {
      if ( Endian_SwapLE32(*((unsigned int*)(buffer+i))) == ZIP_END_CENTRAL_HEADER )
      {
        // Set current position to start of end of central directory
        mFile.Seek(fileSize-ECDREC_SIZE+1-searchSize+i,SEEK_SET);
        found = true;
      }
    }
  }

  delete [] buffer;

  if ( !found )
  {
    CLog::Log(LOGDEBUG,"ZipManager: broken file %s!",strFile.c_str());
    mFile.Close();
    return false;
  }

  unsigned int cdirOffset, cdirSize;
  // Get size of the central directory
  mFile.Seek(12,SEEK_CUR);
  mFile.Read(&cdirSize,4);
  cdirSize = Endian_SwapLE32(cdirSize);
  // Get Offset of start of central directory with respect to the starting disk number
  mFile.Read(&cdirOffset,4);
  cdirOffset = Endian_SwapLE32(cdirOffset);

  // Go to the start of central directory
  mFile.Seek(cdirOffset,SEEK_SET);

  char temp[CHDR_SIZE];
  while (mFile.GetPosition() < cdirOffset + cdirSize)
  {
    SZipEntry ze;
    mFile.Read(temp,CHDR_SIZE);
    readCHeader(temp, ze);
    if (ze.header != ZIP_CENTRAL_HEADER)
    {
      CLog::Log(LOGDEBUG,"ZipManager: broken file %s!",strFile.c_str());
      mFile.Close();
      return false;
    }

    // Get the filename just after the central file header
    CStdString strName;
    mFile.Read(strName.GetBuffer(ze.flength), ze.flength);
    strName.ReleaseBuffer();
    g_charsetConverter.unknownToUTF8(strName);
    ZeroMemory(ze.name, 255);
    strncpy(ze.name, strName.c_str(), strName.size()>254 ? 254 : strName.size());

    // Jump after central file header extra field and file comment
    mFile.Seek(ze.eclength + ze.clength,SEEK_CUR);

    items.push_back(ze);
  }

  /* go through list and figure out file header lengths */
  for(vector<SZipEntry>::iterator it = items.begin(); it != items.end(); ++it)
  {
    SZipEntry& ze = *it;
    // Go to the local file header to get the extra field length
    // !! local header extra field length != central file header extra field length !!
    mFile.Seek(ze.lhdrOffset+28,SEEK_SET);
    mFile.Read(&(ze.elength),2);
    ze.elength = Endian_SwapLE16(ze.elength);

    // Compressed data offset = local header offset + size of local header + filename length + local file header extra field length
    ze.offset = ze.lhdrOffset + LHDR_SIZE + ze.flength + ze.elength;

  }

  mZipMap.insert(make_pair(strFile,items));
  mFile.Close();
  return true;
}
Exemple #9
0
void CURL::Parse(const CStdString& strURL1)
{
  Reset();
  // start by validating the path
  CStdString strURL = CUtil::ValidatePath(strURL1);

  // strURL can be one of the following:
  // format 1: protocol://[username:password]@hostname[:port]/directoryandfile
  // format 2: protocol://file
  // format 3: drive:directoryandfile
  //
  // first need 2 check if this is a protocol or just a normal drive & path
  if (!strURL.size()) return ;
  if (strURL.Equals("?", true)) return;

  // form is format 1 or 2
  // format 1: protocol://[domain;][username:password]@hostname[:port]/directoryandfile
  // format 2: protocol://file

  // decode protocol
  int iPos = strURL.Find("://");
  if (iPos < 0)
  {
    // This is an ugly hack that needs some work.
    // example: filename /foo/bar.zip/alice.rar/bob.avi
    // This should turn into zip://rar:///foo/bar.zip/alice.rar/bob.avi
    iPos = 0;
    bool is_apk = (strURL.Find(".apk/", iPos) > 0);
    while (1)
    {
      if (is_apk)
        iPos = strURL.Find(".apk/", iPos);
      else
        iPos = strURL.Find(".zip/", iPos);

      int extLen = 3;
      if (iPos < 0)
      {
        /* set filename and update extension*/
        SetFileName(strURL);
        return ;
      }
      iPos += extLen + 1;
      CStdString archiveName = strURL.Left(iPos);
      struct __stat64 s;
      if (XFILE::CFile::Stat(archiveName, &s) == 0)
      {
#ifdef TARGET_POSIX
        if (!S_ISDIR(s.st_mode))
#else
        if (!(s.st_mode & S_IFDIR))
#endif
        {
          Encode(archiveName);
          if (is_apk)
          {
            CURL c((CStdString)"apk" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1));
            *this = c;
          }
          else
          {
            CURL c((CStdString)"zip" + "://" + archiveName + '/' + strURL.Right(strURL.size() - iPos - 1));
            *this = c;
          }
          return;
        }
      }
    }
  }
  else
  {
    SetProtocol(strURL.Left(iPos));
    iPos += 3;
  }

  // virtual protocols
  // why not handle all format 2 (protocol://file) style urls here?
  // ones that come to mind are iso9660, cdda, musicdb, etc.
  // they are all local protocols and have no server part, port number, special options, etc.
  // this removes the need for special handling below.
  if (
    m_strProtocol.Equals("stack") ||
    m_strProtocol.Equals("virtualpath") ||
    m_strProtocol.Equals("multipath") ||
    m_strProtocol.Equals("filereader") ||
    m_strProtocol.Equals("special")
    )
  {
    SetFileName(strURL.Mid(iPos));
    return;
  }

  // check for username/password - should occur before first /
  if (iPos == -1) iPos = 0;

  // for protocols supporting options, chop that part off here
  // maybe we should invert this list instead?
  int iEnd = strURL.length();
  const char* sep = NULL;

  //TODO fix all Addon paths
  CStdString strProtocol2 = GetTranslatedProtocol();
  if(m_strProtocol.Equals("rss") ||
     m_strProtocol.Equals("rar") ||
     m_strProtocol.Equals("addons") ||
     m_strProtocol.Equals("image") ||
     m_strProtocol.Equals("videodb") ||
     m_strProtocol.Equals("musicdb") ||
     m_strProtocol.Equals("androidapp"))
    sep = "?";
  else
  if(strProtocol2.Equals("http")
    || strProtocol2.Equals("https")
    || strProtocol2.Equals("plugin")
    || strProtocol2.Equals("addons")
    || strProtocol2.Equals("hdhomerun")
    || strProtocol2.Equals("rtsp")
    || strProtocol2.Equals("apk")
    || strProtocol2.Equals("zip"))
    sep = "?;#|";
  else if(strProtocol2.Equals("ftp")
       || strProtocol2.Equals("ftps"))
    sep = "?;|";

  if(sep)
  {
    int iOptions = strURL.find_first_of(sep, iPos);
    if (iOptions >= 0 )
    {
      // we keep the initial char as it can be any of the above
      int iProto = strURL.find_first_of("|",iOptions);
      if (iProto >= 0)
      {
        SetProtocolOptions(strURL.substr(iProto+1));
        SetOptions(strURL.substr(iOptions,iProto-iOptions));
      }
      else
        SetOptions(strURL.substr(iOptions));
      iEnd = iOptions;
    }
  }

  int iSlash = strURL.Find("/", iPos);
  if(iSlash >= iEnd)
    iSlash = -1; // was an invalid slash as it was contained in options

  if( !m_strProtocol.Equals("iso9660") )
  {
    int iAlphaSign = strURL.Find("@", iPos);
    if (iAlphaSign >= 0 && iAlphaSign < iEnd && (iAlphaSign < iSlash || iSlash < 0))
    {
      // username/password found
      CStdString strUserNamePassword = strURL.Mid(iPos, iAlphaSign - iPos);

      // first extract domain, if protocol is smb
      if (m_strProtocol.Equals("smb"))
      {
        int iSemiColon = strUserNamePassword.Find(";");

        if (iSemiColon >= 0)
        {
          m_strDomain = strUserNamePassword.Left(iSemiColon);
          strUserNamePassword.Delete(0, iSemiColon + 1);
        }
      }

      // username:password
      int iColon = strUserNamePassword.Find(":");
      if (iColon >= 0)
      {
        m_strUserName = strUserNamePassword.Left(iColon);
        iColon++;
        m_strPassword = strUserNamePassword.Right(strUserNamePassword.size() - iColon);
      }
      // username
      else
      {
        m_strUserName = strUserNamePassword;
      }

      iPos = iAlphaSign + 1;
      iSlash = strURL.Find("/", iAlphaSign);

      if(iSlash >= iEnd)
        iSlash = -1;
    }
  }

  // detect hostname:port/
  if (iSlash < 0)
  {
    CStdString strHostNameAndPort = strURL.Mid(iPos, iEnd - iPos);
    int iColon = strHostNameAndPort.Find(":");
    if (iColon >= 0)
    {
      m_strHostName = strHostNameAndPort.Left(iColon);
      iColon++;
      CStdString strPort = strHostNameAndPort.Right(strHostNameAndPort.size() - iColon);
      m_iPort = atoi(strPort.c_str());
    }
    else
    {
      m_strHostName = strHostNameAndPort;
    }

  }
  else
  {
    CStdString strHostNameAndPort = strURL.Mid(iPos, iSlash - iPos);
    int iColon = strHostNameAndPort.Find(":");
    if (iColon >= 0)
    {
      m_strHostName = strHostNameAndPort.Left(iColon);
      iColon++;
      CStdString strPort = strHostNameAndPort.Right(strHostNameAndPort.size() - iColon);
      m_iPort = atoi(strPort.c_str());
    }
    else
    {
      m_strHostName = strHostNameAndPort;
    }
    iPos = iSlash + 1;
    if (iEnd > iPos)
    {
      m_strFileName = strURL.Mid(iPos, iEnd - iPos);

      iSlash = m_strFileName.Find("/");
      if(iSlash < 0)
        m_strShareName = m_strFileName;
      else
        m_strShareName = m_strFileName.Left(iSlash);
    }
  }

  // iso9960 doesnt have an hostname;-)
  if (m_strProtocol.CompareNoCase("iso9660") == 0
    || m_strProtocol.CompareNoCase("musicdb") == 0
    || m_strProtocol.CompareNoCase("videodb") == 0
    || m_strProtocol.CompareNoCase("sources") == 0
    || m_strProtocol.CompareNoCase("pvr") == 0
    || m_strProtocol.Left(3).CompareNoCase("mem") == 0)
  {
    if (m_strHostName != "" && m_strFileName != "")
    {
      CStdString strFileName = m_strFileName;
      m_strFileName.Format("%s/%s", m_strHostName.c_str(), strFileName.c_str());
      m_strHostName = "";
    }
    else
    {
      if (!m_strHostName.IsEmpty() && strURL[iEnd-1]=='/')
        m_strFileName = m_strHostName + "/";
      else
        m_strFileName = m_strHostName;
      m_strHostName = "";
    }
  }

  m_strFileName.Replace("\\", "/");

  /* update extension */
  SetFileName(m_strFileName);

  /* decode urlencoding on this stuff */
  if(URIUtils::ProtocolHasEncodedHostname(m_strProtocol))
  {
    Decode(m_strHostName);
    // Validate it as it is likely to contain a filename
    SetHostName(CUtil::ValidatePath(m_strHostName));
  }

  Decode(m_strUserName);
  Decode(m_strPassword);
}
Exemple #10
0
// return NULL + set pItem->m_bIsFolder to remove it completely from list.
IFileDirectory* CFileDirectoryFactory::Create(const CStdString& strPath, CFileItem* pItem, const CStdString& strMask)
{
  CStdString strExtension=URIUtils::GetExtension(strPath);
  strExtension.MakeLower();

#ifdef HAS_FILESYSTEM
  if ((strExtension.Equals(".ogg") || strExtension.Equals(".oga")) && CFile::Exists(strPath))
  {
    IFileDirectory* pDir=new COGGFileDirectory;
    //  Has the ogg file more than one bitstream?
    if (pDir->ContainsFiles(strPath))
    {
      return pDir; // treat as directory
    }

    delete pDir;
    return NULL;
  }
  if (strExtension.Equals(".nsf") && CFile::Exists(strPath))
  {
    IFileDirectory* pDir=new CNSFFileDirectory;
    //  Has the nsf file more than one track?
    if (pDir->ContainsFiles(strPath))
      return pDir; // treat as directory

    delete pDir;
    return NULL;
  }
  if (strExtension.Equals(".sid") && CFile::Exists(strPath))
  {
    IFileDirectory* pDir=new CSIDFileDirectory;
    //  Has the sid file more than one track?
    if (pDir->ContainsFiles(strPath))
      return pDir; // treat as directory

    delete pDir;
    return NULL;
  }
#ifdef HAS_ASAP_CODEC
  if (ASAPCodec::IsSupportedFormat(strExtension) && CFile::Exists(strPath))
  {
    IFileDirectory* pDir=new CASAPFileDirectory;
    //  Has the asap file more than one track?
    if (pDir->ContainsFiles(strPath))
      return pDir; // treat as directory

    delete pDir;
    return NULL;
  }
#endif

  if (pItem->IsRSS())
    return new CRSSDirectory();

#endif
#if defined(TARGET_ANDROID)
  if (strExtension.Equals(".apk"))
  {
    CStdString strUrl;
    URIUtils::CreateArchivePath(strUrl, "apk", strPath, "");

    CFileItemList items;
    CDirectory::GetDirectory(strUrl, items, strMask);
    if (items.Size() == 0) // no files
      pItem->m_bIsFolder = true;
    else if (items.Size() == 1 && items[0]->m_idepth == 0)
    {
      // one STORED file - collapse it down
      *pItem = *items[0];
    }
    else
    { // compressed or more than one file -> create a apk dir
      pItem->SetPath(strUrl);
      return new CAPKDirectory;
    }
    return NULL;
  }
#endif
  if (strExtension.Equals(".zip"))
  {
    CStdString strUrl;
    URIUtils::CreateArchivePath(strUrl, "zip", strPath, "");

    CFileItemList items;
    CDirectory::GetDirectory(strUrl, items, strMask);
    if (items.Size() == 0) // no files
      pItem->m_bIsFolder = true;
    else if (items.Size() == 1 && items[0]->m_idepth == 0)
    {
      // one STORED file - collapse it down
      *pItem = *items[0];
    }
    else
    { // compressed or more than one file -> create a zip dir
      pItem->SetPath(strUrl);
      return new CZipDirectory;
    }
    return NULL;
  }
  if (strExtension.Equals(".rar") || strExtension.Equals(".001"))
  {
    CStdString strUrl;
    URIUtils::CreateArchivePath(strUrl, "rar", strPath, "");

    vector<CStdString> tokens;
    CUtil::Tokenize(strPath,tokens,".");
    if (tokens.size() > 2)
    {
      if (strExtension.Equals(".001"))
      {
        if (tokens[tokens.size()-2].Equals("ts")) // .ts.001 - treat as a movie file to scratch some users itch
          return NULL;
      }
      CStdString token = tokens[tokens.size()-2];
      if (token.Left(4).CompareNoCase("part") == 0) // only list '.part01.rar'
      {
        // need this crap to avoid making mistakes - yeyh for the new rar naming scheme :/
        struct __stat64 stat;
        int digits = token.size()-4;
        CStdString strNumber, strFormat;
        strFormat.Format("part%%0%ii",digits);
        strNumber.Format(strFormat.c_str(),1);
        CStdString strPath2=strPath;
        strPath2.Replace(token,strNumber);
        if (atoi(token.substr(4).c_str()) > 1 && CFile::Stat(strPath2,&stat) == 0)
        {
          pItem->m_bIsFolder = true;
          return NULL;
        }
      }
    }

    CFileItemList items;
    CDirectory::GetDirectory(strUrl, items, strMask);
    if (items.Size() == 0) // no files - hide this
      pItem->m_bIsFolder = true;
    else if (items.Size() == 1 && items[0]->m_idepth == 0x30)
    {
      // one STORED file - collapse it down
      *pItem = *items[0];
    }
    else
    {
#ifdef HAS_FILESYSTEM_RAR
      // compressed or more than one file -> create a rar dir
      pItem->SetPath(strUrl);
      return new CRarDirectory;
#else
      return NULL;
#endif
    }
    return NULL;
  }
  if (strExtension.Equals(".xsp"))
  { // XBMC Smart playlist - just XML renamed to XSP
    // read the name of the playlist in
    CSmartPlaylist playlist;
    if (playlist.OpenAndReadName(strPath))
    {
      pItem->SetLabel(playlist.GetName());
      pItem->SetLabelPreformated(true);
    }
    IFileDirectory* pDir=new CSmartPlaylistDirectory;
    return pDir; // treat as directory
  }
  if (g_advancedSettings.m_playlistAsFolders && CPlayListFactory::IsPlaylist(strPath))
  { // Playlist file
    // currently we only return the directory if it contains
    // more than one file.  Reason is that .pls and .m3u may be used
    // for links to http streams etc.
    IFileDirectory *pDir = new CPlaylistFileDirectory();
    CFileItemList items;
    if (pDir->GetDirectory(strPath, items))
    {
      if (items.Size() > 1)
        return pDir;
    }
    delete pDir;
    return NULL;
  }
  return NULL;
}
Exemple #11
0
////////////////////////////////////////////////////////////////////////////////////
// Function: Parse()
// Opens the .cue file for reading, and constructs the track database information
////////////////////////////////////////////////////////////////////////////////////
bool CCueDocument::Parse(const CStdString &strFile)
{
  if (!m_file.Open(strFile))
    return false;

  CStdString strLine;
  m_iTotalTracks = -1;
  CStdString strCurrentFile = "";
  bool bCurrentFileChanged = false;
  int time;

  // Run through the .CUE file and extract the tracks...
  while (true)
  {
    if (!ReadNextLine(strLine))
      break;
    if (strLine.Left(7) == "INDEX 0")
    {
      // find the end of the number section
      time = ExtractTimeFromIndex(strLine);
      if (time == -1)
      { // Error!
        OutputDebugString("Mangled Time in INDEX 0x tag in CUE file!\n");
        return false;
      }
      if (m_iTotalTracks > 0)  // Set the end time of the last track
        m_Track[m_iTotalTracks - 1].iEndTime = time;

      m_Track[m_iTotalTracks].iStartTime = time; // start time of the next track
    }
    else if (strLine.Left(5) == "TITLE")
    {
      if (m_iTotalTracks == -1) // No tracks yet
        ExtractQuoteInfo(strLine, m_strAlbum);
      else if (!ExtractQuoteInfo(strLine, m_Track[m_iTotalTracks].strTitle))
      {
        // lets manage tracks titles without quotes
        CStdString titleNoQuote = strLine.Mid(5);
        titleNoQuote.TrimLeft();
        if (!titleNoQuote.IsEmpty())
        {
          g_charsetConverter.stringCharsetToUtf8(titleNoQuote);
          m_Track[m_iTotalTracks].strTitle = titleNoQuote;
        }
      }
    }
    else if (strLine.Left(9) == "PERFORMER")
    {
      if (m_iTotalTracks == -1) // No tracks yet
        ExtractQuoteInfo(strLine, m_strArtist);
      else // New Artist for this track
        ExtractQuoteInfo(strLine, m_Track[m_iTotalTracks].strArtist);
    }
    else if (strLine.Left(5) == "TRACK")
    {
      int iTrackNumber = ExtractNumericInfo(strLine.c_str() + 5);
 
      m_iTotalTracks++;

      CCueTrack track;
      m_Track.push_back(track);
      m_Track[m_iTotalTracks].strFile = strCurrentFile;

      if (iTrackNumber > 0)
        m_Track[m_iTotalTracks].iTrackNumber = iTrackNumber;
      else
        m_Track[m_iTotalTracks].iTrackNumber = m_iTotalTracks + 1;

      bCurrentFileChanged = false;
    }
    else if (strLine.Left(4) == "FILE")
    {
      // already a file name? then the time computation will be changed
      if(strCurrentFile.size() > 0)
        bCurrentFileChanged = true;

      ExtractQuoteInfo(strLine, strCurrentFile);

      // Resolve absolute paths (if needed).
      if (strCurrentFile.length() > 0)
        ResolvePath(strCurrentFile, strFile);
    }
    else if (strLine.Left(25) == "REM REPLAYGAIN_ALBUM_GAIN")
      m_replayGainAlbumGain = (float)atof(strLine.Mid(26));
    else if (strLine.Left(25) == "REM REPLAYGAIN_ALBUM_PEAK")
      m_replayGainAlbumPeak = (float)atof(strLine.Mid(26));
    else if (strLine.Left(25) == "REM REPLAYGAIN_TRACK_GAIN" && m_iTotalTracks >= 0)
      m_Track[m_iTotalTracks].replayGainTrackGain = (float)atof(strLine.Mid(26));
    else if (strLine.Left(25) == "REM REPLAYGAIN_TRACK_PEAK" && m_iTotalTracks >= 0)
      m_Track[m_iTotalTracks].replayGainTrackPeak = (float)atof(strLine.Mid(26));
  }

  // reset track counter to 0, and fill in the last tracks end time
  m_iTrack = 0;
  if (m_iTotalTracks > 0)
    m_Track[m_iTotalTracks].iEndTime = 0;
  else
    OutputDebugString("No INDEX 01 tags in CUE file!\n");
  m_file.Close();
  if (m_iTotalTracks > 0)
  {
    m_iTotalTracks++;
  }
  return (m_iTotalTracks > 0);
}
bool CCharsetConverter::isValidUtf8(const CStdString& str)
{
  return isValidUtf8(str.c_str(), str.size());
}
Exemple #13
0
void CAddonsDirectory::GenerateListing(CURL &path, VECADDONS& addons, CFileItemList &items, bool reposAsFolders)
{
    CStdString xbmcPath = CSpecialProtocol::TranslatePath("special://xbmc/addons");
    items.ClearItems();
    for (unsigned i=0; i < addons.size(); i++)
    {
        AddonPtr addon = addons[i];
        CFileItemPtr pItem;
        if (reposAsFolders && addon->Type() == ADDON_REPOSITORY)
            pItem = FileItemFromAddon(addon, "addons://", true);
        else
            pItem = FileItemFromAddon(addon, path.Get(), false);
        AddonPtr addon2;
        if (CAddonMgr::Get().GetAddon(addon->ID(),addon2))
            pItem->SetProperty("Addon.Status",g_localizeStrings.Get(305));
        else if ((addon->Type() == ADDON_PVRDLL) && (CStdString(pItem->GetProperty("Addon.Path").asString()).Left(xbmcPath.size()).Equals(xbmcPath)))
            pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24023));

        if (!addon->Props().broken.IsEmpty())
            pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24098));
        if (addon2 && addon2->Version() < addon->Version())
        {
            pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24068));
            pItem->SetProperty("Addon.UpdateAvail", true);
        }
        CAddonDatabase::SetPropertiesFromAddon(addon,pItem);
        items.Add(pItem);
    }
}
Exemple #14
0
bool CRSSDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
  CLog::Log(LOGDEBUG,"CRSSDirectory::GetDirectory - path [%s]", strPath.c_str());

  m_cacheDirectory = DIR_CACHE_ALWAYS;

  CStdString strURL = strPath;
  CStdString newURL;

  CStdString strRoot = strPath;
  if (CUtil::HasSlashAtEnd(strRoot))
    strRoot.Delete(strRoot.size() - 1);

  // If we have the items in the cache, return them
  if (g_directoryCache.GetDirectory(strRoot, items))
  {
    return true;
  }

  // Remove the rss:// prefix and replace it with http://
  if (strURL.Left(7) == "http://")
  {
    newURL = strURL;
  }
  else
  {
    strURL.Delete(0,6);
    
    // if first symbol is '/', we have local file
    if (strURL.Left(1) == "/")
    {
      newURL = "file://";
    }
    else 
    {
      newURL = "http://";
    }
    newURL = newURL + strURL;
  }
  
  // Remove the last slash
  if (CUtil::HasSlashAtEnd(newURL))
  {
    CUtil::RemoveSlashAtEnd(newURL);
  }

  // Create new thread and run the feed retreival from it
  // In order to allow progress dialog and cancel operation

  m_strUrl = newURL;

  Crc32 crc;
  crc.ComputeFromLowerCase(newURL);

  CStdString strLocalFile;
  strLocalFile.Format("special://temp/rss-%08x-%lu.xml", (unsigned __int32)crc, CTimeUtils::GetTimeMS());

  CLog::Log(LOGDEBUG,"CRSSDirectory::GetDirectory - going to load url [%s] to file [%s]", newURL.c_str(), strLocalFile.c_str());

  if (!BOXEE::Boxee::GetInstance().AsyncLoadUrl(newURL, _P(strLocalFile), "rss-load", NULL))
  {
    CGUIDialogOK::ShowAndGetInput(51014,0,0,0);
    return false;
  }

  SDL_LockMutex(m_pOpFinishedMutex);
  int result = SDL_CondWaitTimeout(m_pOpFinishedCond,m_pOpFinishedMutex,REQUEST_WAIT_PERIOD);
  SDL_UnlockMutex(m_pOpFinishedMutex);

  m_feed.GetItemList(items);

  if (result != 0)
  {
    m_cacheDirectory = DIR_CACHE_NEVER;
    // set this property so that the UI will handle the timeout
    CLog::Log(LOGDEBUG,"CRSSDirectory::GetDirectory, loading timed out, path [%s] loaded:%d out of %d", strPath.c_str(), items.Size(),items.GetPageContext().m_itemsPerPage);
    items.SetProperty("isRequestTimedOut",true);
  }

  CLog::Log(LOGDEBUG,"CRSSDirectory::GetDirectory - done loading url, got [%d] items (result=[%d])",items.Size(),result);

  if (items.Size() == 0)
  {
    m_cacheDirectory = DIR_CACHE_NEVER;
    return true;
  }
  else
  {
    CLog::Log(LOGDEBUG,"CRSSDirectory::GetDirectory - Going to add [DefaultSortLabel] property to each item. [path=%s][NumOfItems=%d] (vns)",strPath.c_str(),items.Size());

    for(int i=0; i<items.Size(); i++)
    {
      CFileItemPtr item = items[i];

      char pos[5];
      sprintf(pos,"%d",i+1);

      item->SetProperty("DefaultSortLabel",pos);
 
      //CLog::Log(LOGDEBUG,"CRSSDirectory::GetDirectory - For item [path=%s] set property [DefaultSortLabel=%s] (vns)", (item->m_strPath).c_str(),(item->GetProperty("DefaultSortLabel")).c_str());
    }

    items.SetProperty("preferredsortmethod", SORT_METHOD_DEFAULT);
    items.SetProperty("preferredsortorder", SORT_ORDER_ASC);
  }

  return true;
}
Exemple #15
0
bool CMusicArtistInfo::Load(CHTTP& http, const SScraperInfo& info, const CStdString& strFunction, const CScraperUrl* url)
{
  // load our scraper xml
  CScraperParser parser;
  if (!parser.Load(_P("q:\\system\\scrapers\\music\\"+info.strPath)))
    return false;

  bool bChained=true;
  if (!url)
  {
    bChained=false;
    url = &GetArtistURL();
  }

  std::vector<CStdString> strHTML;
  for (unsigned int i=0;i<url->m_url.size();++i)
  {
    CStdString strCurrHTML;
    if (!CScraperUrl::Get(url->m_url[i],strCurrHTML,http) || strCurrHTML.size() == 0)
      return false;
    strHTML.push_back(strCurrHTML);
  }

  // now grab our details using the scraper
  for (unsigned int i=0;i<strHTML.size();++i)
    parser.m_param[i] = strHTML[i];

  CStdString strXML = parser.Parse(strFunction);
  if (strXML.IsEmpty())
  {
    CLog::Log(LOGERROR, "%s: Unable to parse web site",__FUNCTION__);
    return false;
  }

  // abit ugly, but should work. would have been better if parser
  // set the charset of the xml, and we made use of that
  if (strXML.Find("encoding=\"utf-8\"") < 0)
    g_charsetConverter.unknownToUTF8(strXML);

    // ok, now parse the xml file
  TiXmlBase::SetCondenseWhiteSpace(false);
  TiXmlDocument doc;
  doc.Parse(strXML.c_str(),0,TIXML_ENCODING_UTF8);
  if (!doc.RootElement())
  {
    CLog::Log(LOGERROR, "%s: Unable to parse xml",__FUNCTION__);
    return false;
  }

  bool ret = Parse(doc.RootElement(),bChained);
  TiXmlElement* pRoot = doc.RootElement();
  TiXmlElement* xurl = pRoot->FirstChildElement("url");
  while (xurl && xurl->FirstChild())
  {
    const char* szFunction = xurl->Attribute("function");
    if (szFunction)
    {      
      CScraperUrl scrURL(xurl);
      Load(http,info,szFunction,&scrURL);
    }
    xurl = xurl->NextSiblingElement("url");
  }
  TiXmlBase::SetCondenseWhiteSpace(true);
  
  return ret;
}
Exemple #16
0
bool CLabelFormatter::FillMusicTag(const CStdString &fileName, CMusicInfoTag *tag) const
{
  // run through and find static content to split the string up
  int pos1 = fileName.Find(m_staticContent[0][0], 0);
  if (pos1 == (int)CStdString::npos)
    return false;
  for (unsigned int i = 1; i < m_staticContent[0].size(); i++)
  {
    int pos2 = m_staticContent[0][i].size() ? fileName.Find(m_staticContent[0][i], pos1) : fileName.size();
    if (pos2 == (int)CStdString::npos)
      return false;
    // found static content - thus we have the dynamic content surrounded
    FillMusicMaskContent(m_dynamicContent[0][i - 1].m_content, fileName.Mid(pos1, pos2 - pos1), tag);
    pos1 = pos2 + m_staticContent[0][i].size();
  }
  return true;
}
void CGUIDialogAudioSubtitleSettings::AddAudioStreams(unsigned int id)
{
  SettingInfo setting;
  setting.id = id;
  setting.name = g_localizeStrings.Get(460);
  setting.type = SettingInfo::SPIN;
  setting.min = 0;
  setting.data = &m_audioStream;

  // get the number of audio strams for the current movie
  setting.max = (float)g_application.m_pPlayer->GetAudioStreamCount() - 1;
  m_audioStream = g_application.m_pPlayer->GetAudioStream();

  if( m_audioStream < 0 ) m_audioStream = 0;

  // check if we have a single, stereo stream, and if so, allow us to split into
  // left, right or both
  if (!setting.max)
  {
    CStdString strAudioInfo;
    g_application.m_pPlayer->GetAudioInfo(strAudioInfo);
    int iNumChannels = atoi(strAudioInfo.Right(strAudioInfo.size() - strAudioInfo.Find("chns:") - 5).c_str());
    CStdString strAudioCodec = strAudioInfo.Mid(7, strAudioInfo.Find(") VBR") - 5);
    bool bDTS = strstr(strAudioCodec.c_str(), "DTS") != 0;
    bool bAC3 = strstr(strAudioCodec.c_str(), "AC3") != 0;
    if (iNumChannels == 2 && !(bDTS || bAC3))
    { // ok, enable these options
/*      if (g_settings.m_currentVideoSettings.m_AudioStream == -1)
      { // default to stereo stream
        g_settings.m_currentVideoSettings.m_AudioStream = 0;
      }*/
      setting.max = 2;
      for (int i = 0; i <= setting.max; i++)
        setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(13320 + i)));
      m_audioStream = -g_settings.m_currentVideoSettings.m_AudioStream - 1;
      m_settings.push_back(setting);
      return;
    }
  }

  // cycle through each audio stream and add it to our list control
  for (int i = 0; i <= setting.max; ++i)
  {
    CStdString strItem;
    CStdString strName;
    g_application.m_pPlayer->GetAudioStreamName(i, strName);
    if (strName.length() == 0)
      strName = "Unnamed";

    strItem.Format("%s (%i/%i)", strName.c_str(), i + 1, (int)setting.max + 1);
    setting.entry.push_back(make_pair(setting.entry.size(), strItem));
  }

  if( setting.max < 0 )
  {
    setting.max = 0;
    setting.entry.push_back(make_pair(setting.entry.size(), g_localizeStrings.Get(231)));
  }

  m_settings.push_back(setting);
}
Exemple #18
0
bool XLCDproc::Connect()
{
  CloseSocket();

  struct hostent *server;
  server = gethostbyname(g_advancedSettings.m_lcdHostName);
  if (server == NULL)
  {
     CLog::Log(LOGERROR, "XLCDproc::%s - Unable to resolve LCDd host.", __FUNCTION__);
     return false;
  }

  m_sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (m_sockfd == -1)
  {
    CLog::Log(LOGERROR, "XLCDproc::%s - Unable to create socket.", __FUNCTION__);
    return false;
  }

  struct sockaddr_in serv_addr = {};
  serv_addr.sin_family = AF_INET;
  memmove(&serv_addr.sin_addr, server->h_addr_list[0], server->h_length);
  //Connect to default LCDd port, hard coded for now.
  serv_addr.sin_port = htons(13666);

  if (connect(m_sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) == -1)
  {
    CLog::Log(LOGERROR, "XLCDproc::%s - Unable to connect to host, LCDd not running?", __FUNCTION__);
    return false;
  }

  // Start a new session
  CStdString hello;
  hello = "hello\n";

  if (write(m_sockfd,hello.c_str(),hello.size()) == -1)
  {
    CLog::Log(LOGERROR, "XLCDproc::%s - Unable to write to socket", __FUNCTION__);
    return false;
  }

  // Receive LCDproc data to determine row and column information
  char reply[1024];
  if (read(m_sockfd,reply,1024) == -1)
  {
    CLog::Log(LOGERROR, "XLCDproc::%s - Unable to read from socket", __FUNCTION__);
    return false;
  }

  unsigned int i=0;
  while ((strncmp("lcd",reply + i,3) != 0 ) && (i < (strlen(reply) - 5))) i++;
  if(sscanf(reply+i,"lcd wid %u hgt %u", &m_iColumns, &m_iRows))
    CLog::Log(LOGDEBUG, "XLCDproc::%s - LCDproc data: Columns %i - Rows %i.", __FUNCTION__, m_iColumns, m_iRows);

  //Build command to setup screen
  CStdString cmd;
  cmd = "screen_add xbmc\n";
  if (!g_advancedSettings.m_lcdHeartbeat)
    cmd.append("screen_set xbmc -heartbeat off\n");
  if (g_advancedSettings.m_lcdScrolldelay != 0)
  {
    cmd.append("widget_add xbmc line1 scroller\n");
    cmd.append("widget_add xbmc line2 scroller\n");
    cmd.append("widget_add xbmc line3 scroller\n");
    cmd.append("widget_add xbmc line4 scroller\n");
  }
  else
  {
    cmd.append("widget_add xbmc line1 string\n");
    cmd.append("widget_add xbmc line2 string\n");
    cmd.append("widget_add xbmc line3 string\n");
    cmd.append("widget_add xbmc line4 string\n");
  }

  //Send to server
  if (write(m_sockfd,cmd.c_str(),cmd.size()) == -1)
  {
    CLog::Log(LOGERROR, "XLCDproc::%s - Unable to write to socket", __FUNCTION__);
    return false;
  }

  return true;
}
Exemple #19
0
int CAPKFile::Stat(const CURL& url, struct __stat64* buffer)
{
  memset(buffer, 0, sizeof(struct __stat64));

  // do not use interal member vars here,
  //  we might be called without opening
  CStdString path = url.GetFileName();
  CStdString host = url.GetHostName();
  // host name might be encoded rfc1738.txt, decode it.
  CURL::Decode(host);

  struct zip *zip_archive;
  int zip_flags = 0, zip_error = 0;
  zip_archive = zip_open(host.c_str(), zip_flags, &zip_error);
  if (!zip_archive || zip_error)
  {
    CLog::Log(LOGERROR, "CAPKFile::Stat: Unable to open archive : '%s'",
      host.c_str());
    errno = ENOENT;
    return -1;
  }

  // check if file exists
  int zip_index = zip_name_locate(zip_archive, url.GetFileName().c_str(), zip_flags);
  if (zip_index != -1)
  {
    struct zip_stat sb;
    zip_stat_init(&sb);
    int rtn = zip_stat_index(zip_archive, zip_index, zip_flags, &sb);
    if (rtn != -1)
    {
      buffer->st_gid  = 0;
      buffer->st_size = sb.size;
      buffer->st_mode = _S_IFREG;
      buffer->st_atime = sb.mtime;
      buffer->st_ctime = sb.mtime;
      buffer->st_mtime = sb.mtime;
    }
  }

  // check if directory exists
  if (buffer->st_mode != _S_IFREG)
  {
    // zip directories have a '/' at end.
    if (!URIUtils::HasSlashAtEnd(path))
      URIUtils::AddSlashAtEnd(path);

    int numFiles = zip_get_num_files(zip_archive);
    for (int i = 0; i < numFiles; i++)
    {
      CStdString name = zip_get_name(zip_archive, i, zip_flags);
      if (!name.IsEmpty() && name.Left(path.size()).Equals(path))
      {
        buffer->st_gid  = 0;
        buffer->st_mode = _S_IFDIR;
        break;
      }
    }
  }
  zip_close(zip_archive);

  if (buffer->st_mode != 0)
  {
    errno = 0;
    return 0;
  }
  else
  {
    errno = ENOENT;
    return -1;
  }
}
bool CMusicInfoTagLoaderCDDA::Load(const CStdString& strFileName, CMusicInfoTag& tag, EmbeddedArt *art)
{
#ifdef HAS_DVD_DRIVE
  try
  {
    tag.SetURL(strFileName);
    bool bResult = false;

    // Get information for the inserted disc
    CCdInfo* pCdInfo = g_mediaManager.GetCdInfo();
    if (pCdInfo == NULL)
      return bResult;

    // Prepare cddb
    Xcddb cddb;
    cddb.setCacheDir(CProfilesManager::Get().GetCDDBFolder());

    int iTrack = atoi(strFileName.substr(13, strFileName.size() - 13 - 5).c_str());

    // duration is always available
    tag.SetDuration( ( pCdInfo->GetTrackInformation(iTrack).nMins * 60 )
                     + pCdInfo->GetTrackInformation(iTrack).nSecs );

    // Only load cached cddb info in this tag loader, the internet database query is made in CCDDADirectory
    if (pCdInfo->HasCDDBInfo() && cddb.isCDCached(pCdInfo))
    {
      // get cddb information
      if (cddb.queryCDinfo(pCdInfo))
      {
        // Fill the fileitems music tag with cddb information, if available
        CStdString strTitle = cddb.getTrackTitle(iTrack);
        if (strTitle.size() > 0)
        {
          // Tracknumber
          tag.SetTrackNumber(iTrack);

          // Title
          tag.SetTitle(strTitle);

          // Artist: Use track artist or disc artist
          CStdString strArtist = cddb.getTrackArtist(iTrack);
          if (strArtist.IsEmpty())
            cddb.getDiskArtist(strArtist);
          tag.SetArtist(strArtist);

          // Album
          CStdString strAlbum;
          cddb.getDiskTitle( strAlbum );
          tag.SetAlbum(strAlbum);

          // Album Artist
          CStdString strAlbumArtist;
          cddb.getDiskArtist(strAlbumArtist);
          tag.SetAlbumArtist(strAlbumArtist);

          // Year
          SYSTEMTIME dateTime;
          dateTime.wYear = atoi(cddb.getYear().c_str());
          tag.SetReleaseDate( dateTime );

          // Genre
          tag.SetGenre( cddb.getGenre() );

          tag.SetLoaded(true);
          bResult = true;
        }
      }
    }
    else
    {
      // No cddb info, maybe we have CD-Text
      trackinfo ti = pCdInfo->GetTrackInformation(iTrack);

      // Fill the fileitems music tag with CD-Text information, if available
      CStdString strTitle = ti.cdtext[CDTEXT_TITLE];
      if (strTitle.size() > 0)
      {
        // Tracknumber
        tag.SetTrackNumber(iTrack);

        // Title
        tag.SetTitle(strTitle);

        // Get info for track zero, as we may have and need CD-Text Album info
        xbmc_cdtext_t discCDText = pCdInfo->GetDiscCDTextInformation();

        // Artist: Use track artist or disc artist
        CStdString strArtist = ti.cdtext[CDTEXT_PERFORMER];
        if (strArtist.IsEmpty())
          strArtist = discCDText[CDTEXT_PERFORMER];
        tag.SetArtist(strArtist);

        // Album
        CStdString strAlbum;
        strAlbum = discCDText[CDTEXT_TITLE];
        tag.SetAlbum(strAlbum);

        // Genre: use track or disc genre
        CStdString strGenre = ti.cdtext[CDTEXT_GENRE];
        if (strGenre.IsEmpty())
          strGenre = discCDText[CDTEXT_GENRE];
        tag.SetGenre( strGenre );

        tag.SetLoaded(true);
        bResult = true;
      }
    }
    return bResult;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "Tag loader CDDB: exception in file %s", strFileName.c_str());
  }

#endif

  tag.SetLoaded(false);

  return false;
}
Exemple #21
0
bool URIUtils::GetParentPath(const CStdString& strPath, CStdString& strParent)
{
  strParent = "";

  CURL url(strPath);
  CStdString strFile = url.GetFileName();
  if ( URIUtils::ProtocolHasParentInHostname(url.GetProtocol()) && strFile.IsEmpty())
  {
    strFile = url.GetHostName();
    return GetParentPath(strFile, strParent);
  }
  else if (url.GetProtocol() == "stack")
  {
    CStackDirectory dir;
    CFileItemList items;
    dir.GetDirectory(strPath,items);
    GetDirectory(items[0]->GetPath(),items[0]->m_strDVDLabel);
    if (items[0]->m_strDVDLabel.Mid(0,6).Equals("rar://") || items[0]->m_strDVDLabel.Mid(0,6).Equals("zip://"))
      GetParentPath(items[0]->m_strDVDLabel, strParent);
    else
      strParent = items[0]->m_strDVDLabel;
    for( int i=1;i<items.Size();++i)
    {
      GetDirectory(items[i]->GetPath(),items[i]->m_strDVDLabel);
      if (items[0]->m_strDVDLabel.Mid(0,6).Equals("rar://") || items[0]->m_strDVDLabel.Mid(0,6).Equals("zip://"))
        items[i]->SetPath(GetParentPath(items[i]->m_strDVDLabel));
      else
        items[i]->SetPath(items[i]->m_strDVDLabel);

      GetCommonPath(strParent,items[i]->GetPath());
    }
    return true;
  }
  else if (url.GetProtocol() == "multipath")
  {
    // get the parent path of the first item
    return GetParentPath(CMultiPathDirectory::GetFirstPath(strPath), strParent);
  }
  else if (url.GetProtocol() == "plugin")
  {
    if (!url.GetOptions().IsEmpty())
    {
      url.SetOptions("");
      strParent = url.Get();
      return true;
    }
    if (!url.GetFileName().IsEmpty())
    {
      url.SetFileName("");
      strParent = url.Get();
      return true;
    }
    if (!url.GetHostName().IsEmpty())
    {
      url.SetHostName("");
      strParent = url.Get();
      return true;
    }
    return true;  // already at root
  }
  else if (url.GetProtocol() == "special")
  {
    if (HasSlashAtEnd(strFile) )
      strFile = strFile.Left(strFile.size() - 1);
    if(strFile.ReverseFind('/') < 0)
      return false;
  }
  else if (strFile.size() == 0)
  {
    if (url.GetHostName().size() > 0)
    {
      // we have an share with only server or workgroup name
      // set hostname to "" and return true to get back to root
      url.SetHostName("");
      strParent = url.Get();
      return true;
    }
    return false;
  }

  if (HasSlashAtEnd(strFile) )
  {
    strFile = strFile.Left(strFile.size() - 1);
  }

  int iPos = strFile.ReverseFind('/');
#ifndef _LINUX
  if (iPos < 0)
  {
    iPos = strFile.ReverseFind('\\');
  }
#endif
  if (iPos < 0)
  {
    url.SetFileName("");
    strParent = url.Get();
    return true;
  }

  strFile = strFile.Left(iPos);

  AddSlashAtEnd(strFile);

  url.SetFileName(strFile);
  strParent = url.Get();
  return true;
}
Exemple #22
0
bool CFTPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
{
  g_directoryCache.ClearDirectory(strPath);
  CFileItemList vecCacheItems;

  CFileCurl reader;

  CURL url(strPath);

  CStdString path = url.GetFileName();
  if( !path.IsEmpty() && !path.Right(1).Equals("/") )
  {
    path += "/";
    url.SetFileName(path);
  }

  if (!reader.Open(url, false))
    return false;


  char buffer[MAX_PATH + 1024];
  while( reader.ReadString(buffer, sizeof(buffer)) )
  {
    CStdString strBuffer = buffer;

    StringUtils::RemoveCRLF(strBuffer);

    struct ftpparse lp = {};
    if (ftpparse(&lp, (char*)strBuffer.c_str(), strBuffer.size()) == 1)
    {
      if( lp.namelen == 0 )
        continue;

      if( lp.flagtrycwd == 0 && lp.flagtryretr == 0 )
        continue;

      /* buffer name as it's not allways null terminated */
      CStdString name;
      name.assign(lp.name, lp.namelen);

      if( name.Equals("..") || name.Equals(".") )
        continue;

      /* this should be conditional if we ever add    */
      /* support for the utf8 extension in ftp client */
      g_charsetConverter.stringCharsetToUtf8(name);

      CFileItemPtr pItem(new CFileItem(name));
      
      pItem->m_strPath = path + name;
      pItem->m_bIsFolder = (bool)(lp.flagtrycwd != 0);
      if (pItem->m_bIsFolder)
        CUtil::AddSlashAtEnd(pItem->m_strPath);

      /* qualify the url with host and all */
      url.SetFileName(pItem->m_strPath);
      url.GetURL(pItem->m_strPath);

      pItem->m_dwSize = lp.size;
      pItem->m_dateTime=lp.mtime;

      if( m_cacheDirectory )
        vecCacheItems.Add(pItem);

      /* if file is ok by mask or a folder add it */
      if( pItem->m_bIsFolder || IsAllowed(name) )
        items.Add(pItem);
    }
  }


 if (m_cacheDirectory)
    g_directoryCache.SetDirectory(path, vecCacheItems);
  return true;
}
Exemple #23
0
bool CGUIDialogVideoInfo::OnMessage(CGUIMessage& message)
{
  switch ( message.GetMessage() )
  {
  case GUI_MSG_WINDOW_DEINIT:
    {
      ClearCastList();
    }
    break;

  case GUI_MSG_WINDOW_INIT:
    {
      m_dlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);

      m_bRefresh = false;
      m_bRefreshAll = true;
      m_hasUpdatedThumb = false;

      CGUIDialog::OnMessage(message);
      m_bViewReview = true;

      CVideoDatabase database;
      ADDON::ScraperPtr scraper;

      if(database.Open())
      {
        scraper = database.GetScraperForPath(m_movieItem->GetVideoInfoTag()->GetPath());
        database.Close();
      }

      CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_REFRESH, (g_settings.GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !m_movieItem->GetVideoInfoTag()->m_strIMDBNumber.Left(2).Equals("xx") && scraper);
      CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_GET_THUMB, (g_settings.GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !m_movieItem->GetVideoInfoTag()->m_strIMDBNumber.Mid(2).Equals("plugin"));

      VIDEODB_CONTENT_TYPE type = (VIDEODB_CONTENT_TYPE)m_movieItem->GetVideoContentType();
      if (type == VIDEODB_CONTENT_TVSHOWS || type == VIDEODB_CONTENT_MOVIES)
        CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_GET_FANART, (g_settings.GetCurrentProfile().canWriteDatabases() || g_passwordManager.bMasterUser) && !m_movieItem->GetVideoInfoTag()->m_strIMDBNumber.Mid(2).Equals("plugin"));
      else
        CONTROL_DISABLE(CONTROL_BTN_GET_FANART);

      Update();
      return true;
    }
    break;


  case GUI_MSG_CLICKED:
    {
      int iControl = message.GetSenderId();
      if (iControl == CONTROL_BTN_REFRESH)
      {
        if (m_movieItem->GetVideoInfoTag()->m_iSeason < 0 && !m_movieItem->GetVideoInfoTag()->m_strShowTitle.IsEmpty()) // tv show
        {
          bool bCanceled=false;
          if (CGUIDialogYesNo::ShowAndGetInput(20377,20378,-1,-1,bCanceled))
          {
            m_bRefreshAll = true;
            CVideoDatabase db;
            if (db.Open())
            {
              db.SetPathHash(m_movieItem->GetVideoInfoTag()->m_strPath,"");
              db.Close();
            }
          }
          else
            m_bRefreshAll = false;

          if (bCanceled)
            return false;
        }
        m_bRefresh = true;
        Close();
        return true;
      }
      else if (iControl == CONTROL_BTN_TRACKS)
      {
        m_bViewReview = !m_bViewReview;
        Update();
      }
      else if (iControl == CONTROL_BTN_PLAY)
      {
        Play();
      }
      else if (iControl == CONTROL_BTN_RESUME)
      {
        Play(true);
      }
      else if (iControl == CONTROL_BTN_GET_THUMB)
      {
        OnGetThumb();
      }
      else if (iControl == CONTROL_BTN_PLAY_TRAILER)
      {
        PlayTrailer();
      }
      else if (iControl == CONTROL_BTN_GET_FANART)
      {
        OnGetFanart();
      }
      else if (iControl == CONTROL_BTN_DIRECTOR)
      {
        CStdString strDirector = StringUtils::Join(m_movieItem->GetVideoInfoTag()->m_director, g_advancedSettings.m_videoItemSeparator);
        OnSearch(strDirector);
      }
      else if (iControl == CONTROL_LIST)
      {
        int iAction = message.GetParam1();
        if (ACTION_SELECT_ITEM == iAction || ACTION_MOUSE_LEFT_CLICK == iAction)
        {
          CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControl);
          OnMessage(msg);
          int iItem = msg.GetParam1();
          if (iItem < 0 || iItem >= m_castList->Size())
            break;
          CStdString strItem = m_castList->Get(iItem)->GetLabel();
          CStdString strFind;
          strFind.Format(" %s ",g_localizeStrings.Get(20347));
          int iPos = strItem.Find(strFind);
          if (iPos == -1)
            iPos = strItem.size();
          CStdString tmp = strItem.Left(iPos);
          OnSearch(tmp);
        }
      }
    }
    break;
  case GUI_MSG_NOTIFY_ALL:
    {
      if (IsActive() && message.GetParam1() == GUI_MSG_UPDATE_ITEM && message.GetItem())
      {
        CFileItemPtr item = boost::static_pointer_cast<CFileItem>(message.GetItem());
        if (item && m_movieItem->GetPath().Equals(item->GetPath()))
        { // Just copy over the stream details and the thumb if we don't already have one
          if (!m_movieItem->HasThumbnail())
            m_movieItem->SetThumbnailImage(item->GetThumbnailImage());
          m_movieItem->GetVideoInfoTag()->m_streamDetails = item->GetVideoInfoTag()->m_streamDetails;
        }
        return true;
      }
    }
  }

  return CGUIDialog::OnMessage(message);
}
CStdString OutlookExtensionCacheNuker::BuildExtendDatPath(CStdString sProfileDirName)
{
	LOG_WS_INFO(_T("Getting path for extend.dat"));

	if( m_pProcessController)
	{
		m_pProcessController->ReportProgress(_T("Getting path for extend.dat"));
	}

	CStdString sPath;
	CStdString sTest;

	// Outlook98 is ambigiuous
	if ( IsOutlook98() )
	{
		sPath = GetWindowsPath();
		if( IsWindows98() )
		{
			return sPath;
		}

		sTest.Format(_T("%s\\extend.dat"), sPath.c_str());
		if( _taccess(sTest.c_str(), 0) == 0)
		{
			CStdString sMsg;
			sMsg.Format(_T("Extend.dat found at %s"), sTest.c_str() );
			LOG_WS_INFO(sMsg.c_str() );
			if( m_pProcessController)
			{
				m_pProcessController->ReportProgress(sMsg.c_str() );
			}
			return(sPath);
		}
	}

	sPath = GetLocalAppDataPath();
	if (!(IsWindows98() && sProfileDirName.IsEmpty()))
	{						
		int nPos = sPath.Find(_T("\\"), GetProfilesRoot().size()+1);
		sPath = GetProfilesRoot() + _T("\\") + sProfileDirName + _T("\\") + sPath.Right(sPath.size() - nPos - 1);
	}

	sPath += _T("\\Microsoft\\Outlook");

	sTest.Format(_T("%s\\extend.dat"), sPath.c_str());
	if( _taccess(sTest.c_str(), 0) == 0)
	{
		CStdString sMsg;
		sMsg.Format(_T("Extend.dat found at %s"), sTest.c_str() );
		LOG_WS_INFO(sMsg.c_str() );
		if( m_pProcessController)
		{
			m_pProcessController->ReportProgress(sMsg.c_str());
		}
	}
	else
	{
		LOG_WS_INFO(_T("Extend.dat not found"));
		if( m_pProcessController)
		{
			m_pProcessController->ReportProgress(_T("Extend.dat not found"));
		}
	}

	return sPath;
}
bool CPlayListM3U::Load(const CStdString& strFileName)
{
  char szLine[4096];
  CStdString strLine;
  CStdString strInfo = "";
  long lDuration = 0;

  Clear();

  m_strPlayListName = URIUtils::GetFileName(strFileName);
  URIUtils::GetParentPath(strFileName, m_strBasePath);

  CFile file;
  if (!file.Open(strFileName) )
  {
    file.Close();
    return false;
  }

  while (file.ReadString(szLine, 1024))
  {
    strLine = szLine;
    strLine.TrimRight(" \t\r\n");
    strLine.TrimLeft(" \t");

    if (strLine.Left( (int)strlen(M3U_INFO_MARKER) ) == M3U_INFO_MARKER)
    {
      // start of info
      int iColon = (int)strLine.find(":");
      int iComma = (int)strLine.find(",");
      if (iColon >= 0 && iComma >= 0 && iComma > iColon)
      {
        // Read the info and duration
        iColon++;
        CStdString strLength = strLine.Mid(iColon, iComma - iColon);
        lDuration = atoi(strLength.c_str());
        iComma++;
        strInfo = strLine.Right((int)strLine.size() - iComma);
        g_charsetConverter.unknownToUTF8(strInfo);
      }
    }
    else if (strLine != M3U_START_MARKER && strLine.Left(strlen(M3U_ARTIST_MARKER)) != M3U_ARTIST_MARKER && strLine.Left(strlen(M3U_ALBUM_MARKER)) != M3U_ALBUM_MARKER )
    {
      CStdString strFileName = strLine;

      if (strFileName.size() > 0 && strFileName[0] == '#')
        continue; // assume a comment or something else we don't support

      // Skip self - do not load playlist recursively
      if (URIUtils::GetFileName(strFileName).Equals(m_strPlayListName))
        continue;

      if (strFileName.length() > 0)
      {
        g_charsetConverter.unknownToUTF8(strFileName);

        // If no info was read from from the extended tag information, use the file name
        if (strInfo.length() == 0)
        {
          strInfo = URIUtils::GetFileName(strFileName);
        }

        // should substitition occur befor or after charset conversion??
        strFileName = URIUtils::SubstitutePath(strFileName);

        // Get the full path file name and add it to the the play list
        CUtil::GetQualifiedFilename(m_strBasePath, strFileName);
        CFileItemPtr newItem(new CFileItem(strInfo));
        newItem->SetPath(strFileName);
        if (lDuration && newItem->IsAudio())
          newItem->GetMusicInfoTag()->SetDuration(lDuration);
        Add(newItem);

        // Reset the values just in case there part of the file have the extended marker
        // and part don't
        strInfo = "";
        lDuration = 0;
      }
    }
  }

  file.Close();
  return true;
}
void CScraperParser::ParseExpression(const CStdString& input, CStdString& dest, TiXmlElement* element, bool bAppend)
{
  CStdString strOutput = element->Attribute("output");

  TiXmlElement* pExpression = element->FirstChildElement("expression");
  if (pExpression)
  {
    bool bInsensitive=true;
    const char* sensitive = pExpression->Attribute("cs");
    if (sensitive)
      if (stricmp(sensitive,"yes") == 0)
        bInsensitive=false; // match case sensitive

    CRegExp reg(bInsensitive);
    CStdString strExpression;
    if (pExpression->FirstChild())
      strExpression = pExpression->FirstChild()->Value();
    else
      strExpression = "(.*)";
    ReplaceBuffers(strExpression);
    ReplaceBuffers(strOutput);

    if (!reg.RegComp(strExpression.c_str()))
    {
      return;
    }

    bool bRepeat = false;
    const char* szRepeat = pExpression->Attribute("repeat");
    if (szRepeat)
      if (stricmp(szRepeat,"yes") == 0)
        bRepeat = true;

    const char* szClear = pExpression->Attribute("clear");
    if (szClear)
      if (stricmp(szClear,"yes") == 0)
        dest=""; // clear no matter if regexp fails

    bool bClean[MAX_SCRAPER_BUFFERS];
    GetBufferParams(bClean,pExpression->Attribute("noclean"),true);

    bool bTrim[MAX_SCRAPER_BUFFERS];
    GetBufferParams(bTrim,pExpression->Attribute("trim"),false);

    bool bFixChars[MAX_SCRAPER_BUFFERS];
    GetBufferParams(bFixChars,pExpression->Attribute("fixchars"),false);

    bool bEncode[MAX_SCRAPER_BUFFERS];
    GetBufferParams(bEncode,pExpression->Attribute("encode"),false);

    int iOptional = -1;
    pExpression->QueryIntAttribute("optional",&iOptional);

    int iCompare = -1;
    pExpression->QueryIntAttribute("compare",&iCompare);
    if (iCompare > -1)
      m_param[iCompare-1].ToLower();
    CStdString curInput = input;
    for (int iBuf=0;iBuf<MAX_SCRAPER_BUFFERS;++iBuf)
    {
      if (bClean[iBuf])
        InsertToken(strOutput,iBuf+1,"!!!CLEAN!!!");
      if (bTrim[iBuf])
        InsertToken(strOutput,iBuf+1,"!!!TRIM!!!");
      if (bFixChars[iBuf])
        InsertToken(strOutput,iBuf+1,"!!!FIXCHARS!!!");
      if (bEncode[iBuf])
        InsertToken(strOutput,iBuf+1,"!!!ENCODE!!!");
    }
    int i = reg.RegFind(curInput.c_str());
    while (i > -1 && (i < (int)curInput.size() || curInput.size() == 0))
    {
      if (!bAppend)
      {
        dest = "";
        bAppend = true;
      }
      CStdString strCurOutput=strOutput;

      if (iOptional > -1) // check that required param is there
      {
        char temp[4];
        sprintf(temp,"\\%i",iOptional);
        std::string szParam = reg.GetReplaceString(temp);
        CRegExp reg2;
        reg2.RegComp("(.*)(\\\\\\(.*\\\\2.*)\\\\\\)(.*)");
        int i2=reg2.RegFind(strCurOutput.c_str());
        while (i2 > -1)
        {
          std::string szRemove = reg2.GetReplaceString("\\2");
          int iRemove = szRemove.size();
          int i3 = strCurOutput.find(szRemove);
          if (!szParam.empty())
          {
            strCurOutput.erase(i3+iRemove,2);
            strCurOutput.erase(i3,2);
          }
          else
            strCurOutput.replace(strCurOutput.begin()+i3,strCurOutput.begin()+i3+iRemove+2,"");

          i2 = reg2.RegFind(strCurOutput.c_str());
        }
      }

      int iLen = reg.GetFindLen();
      // nasty hack #1 - & means \0 in a replace string
      strCurOutput.Replace("&","!!!AMPAMP!!!");
      std::string result = reg.GetReplaceString(strCurOutput.c_str());
      if (!result.empty())
      {
        CStdString strResult(result);
        strResult.Replace("!!!AMPAMP!!!","&");
        Clean(strResult);
        ReplaceBuffers(strResult);
        if (iCompare > -1)
        {
          CStdString strResultNoCase = strResult;
          strResultNoCase.ToLower();
          if (strResultNoCase.Find(m_param[iCompare-1]) != -1)
            dest += strResult;
        }
        else
          dest += strResult;
      }
      if (bRepeat && iLen > 0)
      {
        curInput.erase(0,i+iLen>(int)curInput.size()?curInput.size():i+iLen);
        i = reg.RegFind(curInput.c_str());
      }
      else
        i = -1;
    }
  }
}
Exemple #27
0
judo::Element * cXData::cItem_obsolete::Build () const {
	judo::Element * e = new judo::Element(var);
	CStdString value = LocaleToUTF8(GetValue());
	e->addCDATA(value, value.size());
    return e;	
}
void CScraperParser::Clean(CStdString& strDirty)
{
  int i=0;
  CStdString strBuffer;
  while ((i=strDirty.Find("!!!CLEAN!!!",i)) != -1)
  {
    int i2;
    if ((i2=strDirty.Find("!!!CLEAN!!!",i+11)) != -1)
    {
      strBuffer = strDirty.substr(i+11,i2-i-11);
      CStdString strConverted(strBuffer);
      HTML::CHTMLUtil::RemoveTags(strConverted);
      RemoveWhiteSpace(strConverted);
      strDirty.erase(i,i2-i+11);
      strDirty.Insert(i,strConverted);
      i += strConverted.size();
    }
    else
      break;
  }
  i=0;
  while ((i=strDirty.Find("!!!TRIM!!!",i)) != -1)
  {
    int i2;
    if ((i2=strDirty.Find("!!!TRIM!!!",i+10)) != -1)
    {
      strBuffer = strDirty.substr(i+10,i2-i-10);
      RemoveWhiteSpace(strBuffer);
      strDirty.erase(i,i2-i+10);
      strDirty.Insert(i,strBuffer);
      i += strBuffer.size();
    }
    else
      break;
  }
  i=0;
  while ((i=strDirty.Find("!!!FIXCHARS!!!",i)) != -1)
  {
    int i2;
    if ((i2=strDirty.Find("!!!FIXCHARS!!!",i+14)) != -1)
    {
      strBuffer = strDirty.substr(i+14,i2-i-14);
      CStdStringW wbuffer;
      g_charsetConverter.toW(strBuffer,wbuffer,GetSearchStringEncoding());
      CStdStringW wConverted;
      HTML::CHTMLUtil::ConvertHTMLToW(wbuffer,wConverted);
      g_charsetConverter.fromW(wConverted,strBuffer,GetSearchStringEncoding());
      RemoveWhiteSpace(strBuffer);
      ConvertJSON(strBuffer);
      strDirty.erase(i,i2-i+14);
      strDirty.Insert(i,strBuffer);
      i += strBuffer.size();
    }
    else
      break;
  }
  i=0;
  while ((i=strDirty.Find("!!!ENCODE!!!",i)) != -1)
  {
    int i2;
    if ((i2=strDirty.Find("!!!ENCODE!!!",i+12)) != -1)
    {
      strBuffer = strDirty.substr(i+12,i2-i-12);
      CURL::Encode(strBuffer);
      strDirty.erase(i,i2-i+12);
      strDirty.Insert(i,strBuffer);
      i += strBuffer.size();
    }
    else
      break;
  }
}
Exemple #29
0
/*!
 \brief Create a IDirectory object of the share type specified in \e strPath .
 \param strPath Specifies the share type to access, can be a share or share with path.
 \return IDirectory object to access the directories on the share.
 \sa IDirectory
 */
IDirectory* CDirectoryFactory::Create(const CStdString& strPath)
{
  CURL url(strPath);

  CFileItem item(strPath, false);
  IFileDirectory* pDir=CFileDirectoryFactory::Create(strPath, &item);
  if (pDir)
    return pDir;

  CStdString strProtocol = url.GetProtocol();

  if (strProtocol.size() == 0 || strProtocol == "file") return new CHDDirectory();
  if (strProtocol == "special") return new CSpecialProtocolDirectory();
  if (strProtocol == "sources") return new CSourcesDirectory();
  if (strProtocol == "addons") return new CAddonsDirectory();
#if defined(HAS_FILESYSTEM_CDDA) && defined(HAS_DVD_DRIVE)
  if (strProtocol == "cdda") return new CCDDADirectory();
#endif
#ifdef HAS_FILESYSTEM
  if (strProtocol == "iso9660") return new CISO9660Directory();
#endif
  if (strProtocol == "udf") return new CUDFDirectory();
  if (strProtocol == "plugin") return new CPluginDirectory();
#if defined(TARGET_ANDROID)
  if (strProtocol == "apk") return new CAPKDirectory();
#endif
  if (strProtocol == "zip") return new CZipDirectory();
  if (strProtocol == "rar") 
  {
#ifdef HAS_FILESYSTEM_RAR
    return new CRarDirectory();
#else
    CLog::Log(LOGWARNING, "%s - Compiled without non-free, rar support is disabled", __FUNCTION__);
#endif
  }
  if (strProtocol == "multipath") return new CMultiPathDirectory();
  if (strProtocol == "stack") return new CStackDirectory();
  if (strProtocol == "playlistmusic") return new CPlaylistDirectory();
  if (strProtocol == "playlistvideo") return new CPlaylistDirectory();
  if (strProtocol == "musicdb") return new CMusicDatabaseDirectory();
  if (strProtocol == "musicsearch") return new CMusicSearchDirectory();
  if (strProtocol == "videodb") return new CVideoDatabaseDirectory();
  if (strProtocol == "library") return new CLibraryDirectory();
  if (strProtocol == "filereader")
    return CDirectoryFactory::Create(url.GetFileName());

  if( g_application.getNetwork().IsAvailable(true) )  // true to wait for the network (if possible)
  {
    if (strProtocol == "lastfm") return new CLastFMDirectory();
    if (strProtocol == "tuxbox") return new CTuxBoxDirectory();
    if (strProtocol == "ftp" || strProtocol == "ftps") return new CFTPDirectory();
    if (strProtocol == "http" || strProtocol == "https") return new CHTTPDirectory();
    if (strProtocol == "dav" || strProtocol == "davs") return new CDAVDirectory();
#ifdef HAS_FILESYSTEM_SFTP
    if (strProtocol == "sftp" || strProtocol == "ssh") return new CSFTPDirectory();
#endif
#ifdef HAS_FILESYSTEM_SMB
#ifdef _WIN32
    if (strProtocol == "smb") return new CWINSMBDirectory();
#else
    if (strProtocol == "smb") return new CSMBDirectory();
#endif
#endif
#ifdef HAS_FILESYSTEM
#ifdef HAS_FILESYSTEM_DAAP
    if (strProtocol == "daap") return new CDAAPDirectory();
#endif
#ifdef HAS_FILESYSTEM_RTV
    if (strProtocol == "rtv") return new CRTVDirectory();
#endif
#endif
#ifdef HAS_UPNP
    if (strProtocol == "upnp") return new CUPnPDirectory();
#endif
    if (strProtocol == "hdhomerun") return new CHomeRunDirectory();
    if (strProtocol == "sling") return new CSlingboxDirectory();
    if (strProtocol == "myth") return new CMythDirectory();
    if (strProtocol == "cmyth") return new CMythDirectory();
    if (strProtocol == "rss") return new CRSSDirectory();
#ifdef HAS_FILESYSTEM_SAP
    if (strProtocol == "sap") return new CSAPDirectory();
#endif
#ifdef HAS_FILESYSTEM_VTP
    if (strProtocol == "vtp") return new CVTPDirectory();
#endif
#ifdef HAS_FILESYSTEM_HTSP
    if (strProtocol == "htsp") return new CHTSPDirectory();
#endif
#ifdef HAS_PVRCLIENTS
    if (strProtocol == "pvr") return new CPVRDirectory();
#endif
#ifdef HAS_ZEROCONF
    if (strProtocol == "zeroconf") return new CZeroconfDirectory();
#endif
#ifdef HAS_FILESYSTEM_NFS
    if (strProtocol == "nfs") return new CNFSDirectory();
#endif
#ifdef HAS_FILESYSTEM_AFP
      if (strProtocol == "afp") return new CAFPDirectory();
#endif
#ifdef HAVE_LIBBLURAY
      if (strProtocol == "bluray") return new CBlurayDirectory();
#endif
#if defined(TARGET_ANDROID)
      if (strProtocol == "androidapp") return new CAndroidAppDirectory();
#endif
  }

  CLog::Log(LOGWARNING, "%s - Unsupported protocol(%s) in %s", __FUNCTION__, strProtocol.c_str(), url.Get().c_str() );
  return NULL;
}
Exemple #30
0
//-------------------------------------------------------------------------------------------------------------------
void Xcddb::parseData(const char *buffer)
{
  //writeLog("parseData Start");

  std::map<CStdString, CStdString> keywords;
  std::list<CStdString> keywordsOrder; // remember order of keywords as it appears in data received from CDDB

  // Collect all the keywords and put them in map. 
  // Multiple occurrences of the same keyword indicate that 
  // the data contained on those lines should be concatenated
  char *line;
  const char trenner[3] = {'\n', '\r', '\0'};
  strtok((char*)buffer, trenner); // skip first line
  while ((line = strtok(0, trenner)))
  {
    // Lines that begin with # are comments, should be ignored
    if (line[0] != '#')
    {
      char *s = strstr(line, "=");
      if (s != NULL)
      {
        CStdString strKeyword(line, s - line);
        StringUtils::TrimRight(strKeyword);

        CStdString strValue(s+1);
        StringUtils::Replace(strValue, "\\n", "\n");
        StringUtils::Replace(strValue, "\\t", "\t");
        StringUtils::Replace(strValue, "\\\\", "\\");

        std::map<CStdString, CStdString>::const_iterator it = keywords.find(strKeyword);
        if (it != keywords.end())
          strValue = it->second + strValue; // keyword occured before, concatenate
        else
          keywordsOrder.push_back(strKeyword);

        keywords[strKeyword] = strValue;
      }
    }
  }

  // parse keywords 
  for (std::list<CStdString>::const_iterator it = keywordsOrder.begin(); it != keywordsOrder.end(); ++it)
  {
    CStdString strKeyword = *it;
    CStdString strValue = keywords[strKeyword];

    /* TODO:STRING_CLEANUP */
    if (strKeyword == "DTITLE")
    {
      // DTITLE may contain artist and disc title, separated with " / ",
      // for example: DTITLE=Modern Talking / Album: Victory (The 11th Album)
      bool found = false;
      for (int i = 0; i < (int)strValue.size() - 2; i++)
      {
        if (strValue[i] == ' ' && strValue[i + 1] == '/' && strValue[i + 2] == ' ')
        {
          m_strDisk_artist = TrimToUTF8(strValue.substr(0, i));
          m_strDisk_title = TrimToUTF8(strValue.substr(i+3));
          found = true;
          break;
        }
      }

      if (!found)
        m_strDisk_title = TrimToUTF8(strValue);
    }
    else if (strKeyword == "DYEAR")
      m_strYear = TrimToUTF8(strValue);
    else if (strKeyword== "DGENRE")
      m_strGenre = TrimToUTF8(strValue);
    else if (StringUtils::StartsWith(strKeyword, "TTITLE"))
      addTitle(strKeyword + "=" + strValue);
    else if (strKeyword == "EXTD")
    {
      CStdString strExtd(strValue);

      if (m_strYear.empty())
      {
        // Extract Year from extended info
        // as a fallback
        size_t iPos = strExtd.find("YEAR: ");
        if (iPos != std::string::npos) // You never know if you really get UTF-8 strings from cddb
          g_charsetConverter.unknownToUTF8(strExtd.substr(iPos + 6, 4), m_strYear);
      }

      if (m_strGenre.empty())
      {
        // Extract ID3 Genre
        // as a fallback
        size_t iPos = strExtd.find("ID3G: ");
        if (iPos != std::string::npos)
        {
          CStdString strGenre = strExtd.substr(iPos + 5, 4);
          StringUtils::TrimLeft(strGenre);
          if (StringUtils::IsNaturalNumber(strGenre))
          {
            int iGenre = strtol(strGenre, NULL, 10);
            m_strGenre = TagLib::ID3v1::genre(iGenre).to8Bit(true);
          }
        }
      }
    }
    else if (StringUtils::StartsWith(strKeyword, "EXTT"))
      addExtended(strKeyword + "=" + strValue);
  }

  //writeLog("parseData Ende");
}