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; }
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, "")); }
// 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; }
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; }
// 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 }
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())); }
// 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; }
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; }
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); }
// 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; }
//////////////////////////////////////////////////////////////////////////////////// // 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()); }
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); } }
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; }
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; }
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); }
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; }
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; }
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; }
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; }
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; } } }
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; } }
/*! \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; }
//------------------------------------------------------------------------------------------------------------------- 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"); }