bool CPVRDirectory::Exists(const CURL& url) { return (url.GetProtocol() == "pvr" && url.GetHostName() == "recordings"); }
bool CMultiPathDirectory::GetDirectory(const CURL& url, CFileItemList &items) { CLog::Log(LOGDEBUG,"CMultiPathDirectory::GetDirectory(%s)", url.GetRedacted().c_str()); vector<std::string> vecPaths; if (!GetPaths(url, vecPaths)) return false; XbmcThreads::EndTime progressTime(3000); // 3 seconds before showing progress bar CGUIDialogProgress* dlgProgress = NULL; unsigned int iFailures = 0; for (unsigned int i = 0; i < vecPaths.size(); ++i) { // show the progress dialog if we have passed our time limit if (progressTime.IsTimePast() && !dlgProgress) { dlgProgress = (CGUIDialogProgress *)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); if (dlgProgress) { dlgProgress->SetHeading(CVariant{15310}); dlgProgress->SetLine(0, CVariant{15311}); dlgProgress->SetLine(1, CVariant{""}); dlgProgress->SetLine(2, CVariant{""}); dlgProgress->Open(); dlgProgress->ShowProgressBar(true); dlgProgress->SetProgressMax((int)vecPaths.size()*2); dlgProgress->Progress(); } } if (dlgProgress) { CURL url(vecPaths[i]); dlgProgress->SetLine(1, CVariant{url.GetWithoutUserDetails()}); dlgProgress->SetProgressAdvance(); dlgProgress->Progress(); } CFileItemList tempItems; CLog::Log(LOGDEBUG,"Getting Directory (%s)", vecPaths[i].c_str()); if (CDirectory::GetDirectory(vecPaths[i], tempItems, m_strFileMask, m_flags)) items.Append(tempItems); else { CLog::Log(LOGERROR,"Error Getting Directory (%s)", vecPaths[i].c_str()); iFailures++; } if (dlgProgress) { dlgProgress->SetProgressAdvance(); dlgProgress->Progress(); } } if (dlgProgress) dlgProgress->Close(); if (iFailures == vecPaths.size()) return false; // merge like-named folders into a sub multipath:// style url MergeItems(items); return true; }
int CFileCache::Stat(const CURL& url, struct __stat64* buffer) { return CFile::Stat(url.Get(), buffer); }
bool CZipManager::GetZipList(const CURL& url, vector<SZipEntry>& items) { CLog::Log(LOGDEBUG, "%s - Processing %s", __FUNCTION__, url.GetRedacted().c_str()); struct __stat64 m_StatData = {}; CStdString strFile = url.GetHostName(); if (CFile::Stat(strFile,&m_StatData)) { CLog::Log(LOGDEBUG,"CZipManager::GetZipList: failed to stat file %s", url.GetRedacted().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; }
bool CMythFile::SetupLiveTV(const CURL& url) { if (url.GetFileName().Left(9) != "channels/") return false; if(!SetupConnection(url, true, true, true)) return false; CStdString channel = url.GetFileNameWithoutPath(); if(!URIUtils::GetExtension(channel).Equals(".ts")) { CLog::Log(LOGERROR, "%s - invalid channel url %s", __FUNCTION__, channel.c_str()); return false; } URIUtils::RemoveExtension(channel); for(int i=0;i<16;i++) { m_recorder = m_dll->conn_get_recorder_from_num(m_control, i); if(!m_recorder) continue; if(m_dll->recorder_is_recording(m_recorder)) { /* for now don't allow reuse of tuners, we would have to change tuner on channel * * and make sure we don't stop the tuner when stopping playback as that affects * * other clients */ #if 0 /* if already recording, check if it is this channel */ cmyth_proginfo_t program; program = m_dll->recorder_get_cur_proginfo(m_recorder); if(program) { if(channel == GetValue(m_dll->proginfo_chanstr(program))) { m_dll->ref_release(program); break; } m_dll->ref_release(program); } #endif } else { /* not recording, check if it supports this channel */ if(m_dll->recorder_check_channel(m_recorder, (char*)channel.c_str()) == 0) break; } m_dll->ref_release(m_recorder); m_recorder = NULL; } if(!m_recorder) { CLog::Log(LOGERROR, "%s - unable to get recorder", __FUNCTION__); return false; } m_recording = !!m_dll->recorder_is_recording(m_recorder); if(!m_recording) CLog::Log(LOGDEBUG, "%s - recorder isn't running, let's start it", __FUNCTION__); char* msg = NULL; if(!(m_recorder = m_dll->spawn_live_tv(m_recorder, 16*1024, 4096, prog_update_callback, &msg, (char*)channel.c_str()))) { CLog::Log(LOGERROR, "%s - unable to spawn live tv: %s", __FUNCTION__, msg ? msg : ""); return false; } m_program = m_dll->recorder_get_cur_proginfo(m_recorder); m_timestamp = XbmcThreads::SystemClockMillis(); if(m_program) m_starttime = m_dll->proginfo_rec_start(m_program); if(m_recording) { /* recorder was running when we started, seek to last position */ if(!m_dll->livetv_seek(m_recorder, 0, SEEK_END)) CLog::Log(LOGDEBUG, "%s - failed to seek to last position", __FUNCTION__); } m_filename = GetValue(m_dll->recorder_get_filename(m_recorder)); return true; }
void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) { if (pItem->HasArt("thumb")) return; CTextureDatabase db; db.Open(); if (pItem->IsCBR() || pItem->IsCBZ()) { std::string strTBN(URIUtils::ReplaceExtension(pItem->GetPath(),".tbn")); if (CFile::Exists(strTBN)) { db.SetTextureForPath(pItem->GetPath(), "thumb", strTBN); CTextureCache::GetInstance().BackgroundCacheImage(strTBN); pItem->SetArt("thumb", strTBN); return; } } if ((pItem->m_bIsFolder || pItem->IsCBR() || pItem->IsCBZ()) && !pItem->m_bIsShareOrDrive && !pItem->IsParentFolder() && !pItem->IsPath("add")) { // first check for a folder.jpg std::string thumb = "folder.jpg"; CURL pathToUrl = pItem->GetURL(); if (pItem->IsCBR()) { pathToUrl = URIUtils::CreateArchivePath("rar",pItem->GetURL(),""); thumb = "cover.jpg"; } if (pItem->IsCBZ()) { pathToUrl = URIUtils::CreateArchivePath("zip",pItem->GetURL(),""); thumb = "cover.jpg"; } if (pItem->IsMultiPath()) pathToUrl = CURL(CMultiPathDirectory::GetFirstPath(pItem->GetPath())); thumb = URIUtils::AddFileToFolder(pathToUrl.Get(), thumb); if (CFile::Exists(thumb)) { db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); CTextureCache::GetInstance().BackgroundCacheImage(thumb); pItem->SetArt("thumb", thumb); return; } if (!pItem->IsPlugin()) { // we load the directory, grab 4 random thumb files (if available) and then generate // the thumb. CFileItemList items; CDirectory::GetDirectory(pathToUrl, items, CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), DIR_FLAG_NO_FILE_DIRS); // create the folder thumb by choosing 4 random thumbs within the folder and putting // them into one thumb. // count the number of images for (int i=0; i < items.Size();) { if (!items[i]->IsPicture() || items[i]->IsZIP() || items[i]->IsRAR() || items[i]->IsPlayList()) { items.Remove(i); } else i++; } if (items.IsEmpty()) { if (pItem->IsCBZ() || pItem->IsCBR()) { CDirectory::GetDirectory(pathToUrl, items, CServiceBroker::GetFileExtensionProvider().GetPictureExtensions(), DIR_FLAG_NO_FILE_DIRS); for (int i=0;i<items.Size();++i) { CFileItemPtr item = items[i]; if (item->m_bIsFolder) { ProcessFoldersAndArchives(item.get()); pItem->SetArt("thumb", items[i]->GetArt("thumb")); pItem->SetIconImage(items[i]->GetIconImage()); return; } } } return; // no images in this folder } // randomize them items.Randomize(); if (items.Size() < 4 || pItem->IsCBR() || pItem->IsCBZ()) { // less than 4 items, so just grab the first thumb items.Sort(SortByLabel, SortOrderAscending); std::string thumb = CTextureUtils::GetWrappedThumbURL(items[0]->GetPath()); db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); CTextureCache::GetInstance().BackgroundCacheImage(thumb); pItem->SetArt("thumb", thumb); } else { // ok, now we've got the files to get the thumbs from, lets create it... // we basically load the 4 images and combine them std::vector<std::string> files; for (int thumb = 0; thumb < 4; thumb++) files.push_back(items[thumb]->GetPath()); std::string thumb = CTextureUtils::GetWrappedImageURL(pItem->GetPath(), "picturefolder"); std::string relativeCacheFile = CTextureCache::GetCacheFile(thumb) + ".png"; if (CPicture::CreateTiledThumb(files, CTextureCache::GetCachedPath(relativeCacheFile))) { CTextureDetails details; details.file = relativeCacheFile; details.width = g_advancedSettings.m_imageRes; details.height = g_advancedSettings.m_imageRes; CTextureCache::GetInstance().AddCachedTexture(thumb, details); db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); pItem->SetArt("thumb", CTextureCache::GetCachedPath(relativeCacheFile)); } } } // refill in the icon to get it to update pItem->FillInDefaultIcon(); } }
CStdString CPasswordManager::GetLookupPath(const CURL &url) const { return "smb://" + url.GetHostName() + "/" + url.GetShareName(); }
bool URIUtils::HasEncodedHostname(const CURL& url) { return HasParentInHostname(url) || url.IsProtocol("musicsearch") || url.IsProtocol( "image"); }
/* returns filename extension including period of filename */ std::string URIUtils::GetExtension(const CURL& url) { return URIUtils::GetExtension(url.GetFileName()); }
void CCurlFile::ParseAndCorrectUrl(CURL &url2) { CStdString strProtocol = url2.GetTranslatedProtocol(); url2.SetProtocol(strProtocol); if( strProtocol.Equals("ftp") || strProtocol.Equals("ftps") ) { /* this is uggly, depending on from where */ /* we get the link it may or may not be */ /* url encoded. if handed from ftpdirectory */ /* it won't be so let's handle that case */ CStdString partial, filename(url2.GetFileName()); CStdStringArray array; /* our current client doesn't support utf8 */ g_charsetConverter.utf8ToStringCharset(filename); /* TODO: create a tokenizer that doesn't skip empty's */ CUtil::Tokenize(filename, array, "/"); filename.Empty(); for(CStdStringArray::iterator it = array.begin(); it != array.end(); it++) { if(it != array.begin()) filename += "/"; partial = *it; CURL::Encode(partial); filename += partial; } /* make sure we keep slashes */ if(url2.GetFileName().Right(1) == "/") filename += "/"; url2.SetFileName(filename); CStdString options = url2.GetOptions().Mid(1); options.TrimRight('/'); // hack for trailing slashes being added from source m_ftpauth = ""; m_ftpport = ""; m_ftppasvip = false; /* parse options given */ CUtil::Tokenize(options, array, "&"); for(CStdStringArray::iterator it = array.begin(); it != array.end(); it++) { CStdString name, value; int pos = it->Find('='); if(pos >= 0) { name = it->Left(pos); value = it->Mid(pos+1, it->size()); } else { name = (*it); value = ""; } if(name.Equals("auth")) { m_ftpauth = value; if(m_ftpauth.IsEmpty()) m_ftpauth = "any"; } else if(name.Equals("active")) { m_ftpport = value; if(value.IsEmpty()) m_ftpport = "-"; } else if(name.Equals("pasvip")) { if(value == "0") m_ftppasvip = false; else m_ftppasvip = true; } } /* ftp has no options */ url2.SetOptions(""); } else if( strProtocol.Equals("http") || strProtocol.Equals("https")) { if (g_guiSettings.GetBool("network.usehttpproxy") && !g_guiSettings.GetString("network.httpproxyserver").empty() && !g_guiSettings.GetString("network.httpproxyport").empty() && m_proxy.IsEmpty()) { m_proxy = g_guiSettings.GetString("network.httpproxyserver"); m_proxy += ":" + g_guiSettings.GetString("network.httpproxyport"); if (g_guiSettings.GetString("network.httpproxyusername").length() > 0 && m_proxyuserpass.IsEmpty()) { m_proxyuserpass = g_guiSettings.GetString("network.httpproxyusername"); m_proxyuserpass += ":" + g_guiSettings.GetString("network.httpproxypassword"); } m_proxytype = (ProxyType)g_guiSettings.GetInt("network.httpproxytype"); CLog::Log(LOGDEBUG, "Using proxy %s, type %d", m_proxy.c_str(), proxyType2CUrlProxyType[m_proxytype]); } // get username and password m_username = url2.GetUserName(); m_password = url2.GetPassWord(); // handle any protocol options std::map<CStdString, CStdString> options; url2.GetProtocolOptions(options); if (options.size() > 0) { // clear protocol options url2.SetProtocolOptions(""); // set xbmc headers for(std::map<CStdString, CStdString>::const_iterator it = options.begin(); it != options.end(); ++it) { const CStdString &name = it->first; CStdString value = it->second; // url decode value CURL::Decode(value); if(name.Equals("auth")) { m_httpauth = value; if(m_httpauth.IsEmpty()) m_httpauth = "any"; } else if (name.Equals("Referer")) SetReferer(value); else if (name.Equals("User-Agent")) SetUserAgent(value); else if (name.Equals("Cookie")) SetCookie(value); else if (name.Equals("Encoding")) SetContentEncoding(value); else if (name.Equals("noshout") && value.Equals("true")) m_skipshout = true; else SetRequestHeader(name, value); } } } if (m_username.length() > 0 && m_password.length() > 0) m_url = url2.GetWithoutUserDetails(); else m_url = url2.Get(); }
std::string URIUtils::GetFileName(const CURL& url) { return GetFileName(url.GetFileName()); }
/* STATIC FUNCTIONS */ bool CCurlFile::GetHttpHeader(const CURL &url, CHttpHeader &headers) { try { CCurlFile file; if(file.Stat(url, NULL) == 0) { headers = file.GetHttpHeader(); return true; } return false; } catch(...) { CLog::Log(LOGERROR, "%s - Exception thrown while trying to retrieve header url: %s", __FUNCTION__, url.Get().c_str()); return false; } }
int CCurlFile::Stat(const CURL& url, struct __stat64* buffer) { // if file is already running, get info from it if( m_opened ) { CLog::Log(LOGWARNING, "%s - Stat called on open file %s", __FUNCTION__, url.Get().c_str()); if (buffer) { memset(buffer, 0, sizeof(struct __stat64)); buffer->st_size = GetLength(); buffer->st_mode = _S_IFREG; } return 0; } CURL url2(url); ParseAndCorrectUrl(url2); ASSERT(m_state->m_easyHandle == NULL); g_curlInterface.easy_aquire(url2.GetProtocol(), url2.GetHostName(), &m_state->m_easyHandle, NULL); SetCommonOptions(m_state); SetRequestHeaders(m_state); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_TIMEOUT, 5); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_NOBODY, 1); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_WRITEDATA, NULL); /* will cause write failure*/ g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_FILETIME , 1); if(url2.GetProtocol() == "ftp") { // nocwd is less standard, will return empty list for non-existed remote dir on some ftp server, avoid it. if (url2.GetFileName().Right(1).Equals("/")) g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_SINGLECWD); else g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_NOCWD); } CURLcode result = g_curlInterface.easy_perform(m_state->m_easyHandle); if(result == CURLE_HTTP_RETURNED_ERROR) { long code; if(g_curlInterface.easy_getinfo(m_state->m_easyHandle, CURLINFO_RESPONSE_CODE, &code) == CURLE_OK && code == 404 ) return -1; } if(result == CURLE_GOT_NOTHING || result == CURLE_HTTP_RETURNED_ERROR || result == CURLE_RECV_ERROR /* some silly shoutcast servers */ ) { /* some http servers and shoutcast servers don't give us any data on a head request */ /* request normal and just fail out, it's their loss */ /* somehow curl doesn't reset CURLOPT_NOBODY properly so reset everything */ SetCommonOptions(m_state); SetRequestHeaders(m_state); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_TIMEOUT, 5); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_RANGE, "0-0"); g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_WRITEDATA, NULL); /* will cause write failure*/ g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_FILETIME , 1); result = g_curlInterface.easy_perform(m_state->m_easyHandle); } if( result == CURLE_HTTP_RANGE_ERROR ) { /* crap can't use the range option, disable it and try again */ g_curlInterface.easy_setopt(m_state->m_easyHandle, CURLOPT_RANGE, NULL); result = g_curlInterface.easy_perform(m_state->m_easyHandle); } if( result != CURLE_WRITE_ERROR && result != CURLE_OK ) { g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); errno = ENOENT; return -1; } double length; if (CURLE_OK != g_curlInterface.easy_getinfo(m_state->m_easyHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &length) || length < 0.0) { if (url.GetProtocol() == "ftp") { g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); errno = ENOENT; return -1; } else length = 0.0; } SetCorrectHeaders(m_state); if(buffer) { char *content; if (CURLE_OK != g_curlInterface.easy_getinfo(m_state->m_easyHandle, CURLINFO_CONTENT_TYPE, &content)) { g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); errno = ENOENT; return -1; } else { memset(buffer, 0, sizeof(struct __stat64)); buffer->st_size = (int64_t)length; if(content && strstr(content, "text/html")) //consider html files directories buffer->st_mode = _S_IFDIR; else buffer->st_mode = _S_IFREG; } long filetime; if (CURLE_OK != g_curlInterface.easy_getinfo(m_state->m_easyHandle, CURLINFO_FILETIME, &filetime)) { CLog::Log(LOGWARNING, "%s - Cannot get curl filetime for %s", __FUNCTION__, url.Get().c_str()); } else { if (filetime != -1) buffer->st_mtime = filetime; } } g_curlInterface.easy_release(&m_state->m_easyHandle, NULL); return 0; }
bool CLastFmManager::ChangeStation(const CURL& stationUrl) { unsigned int start = XbmcThreads::SystemClockMillis(); InitProgressDialog(stationUrl.Get()); StopRadio(false); if (!RadioHandShake()) { CloseProgressDialog(); CGUIDialogOK::ShowAndGetInput(15200, 15206, 0, 0); return false; } UpdateProgressDialog(15252); // Selecting station... CFileCurl http; CStdString url; CStdString html; url.Format("http://" + m_RadioBaseUrl + m_RadioBasePath + "/adjust.php?session=%s&url=%s&debug=%i", m_RadioSession, stationUrl.Get().c_str(), 0); if (!http.Get(url, html)) { CLog::Log(LOGERROR, "Connect to Last.fm to change station failed."); CloseProgressDialog(); return false; } //CLog::Log(LOGDEBUG, "ChangeStation: %s", html.c_str()); CStdString strErrorCode; Parameter("error", html, strErrorCode); if (strErrorCode != "") { CLog::Log(LOGERROR, "Last.fm returned an error (%s) response for change station request.", strErrorCode.c_str()); CloseProgressDialog(); return false; } UpdateProgressDialog(261); //Waiting for start.... g_playlistPlayer.ClearPlaylist(PLAYLIST_MUSIC); RequestRadioTracks(); CacheTrackThumb(XBMC_LASTFM_MINTRACKS); AddToPlaylist(XBMC_LASTFM_MINTRACKS); Create(); //start thread m_hWorkerEvent.Set(); //kickstart the thread CSingleLock lock(m_lockPlaylist); CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_MUSIC); if ((int)playlist.size()) { g_application.m_strPlayListFile = stationUrl.Get(); //needed to highlight the playing item g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_MUSIC); g_playlistPlayer.Play(0); CLog::Log(LOGDEBUG, "%s: Done (time: %i ms)", __FUNCTION__, (int)(XbmcThreads::SystemClockMillis() - start)); CloseProgressDialog(); return true; } CloseProgressDialog(); return false; }
CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& items) { // don't expect derived classes to clear the sources m_sources.clear(); if (windowId == 0) return GetViewState(g_windowManager.GetActiveWindow(),items); const CURL url=items.GetURL(); if (items.IsAddonsPath()) return new CGUIViewStateAddonBrowser(items); if (items.HasSortDetails()) return new CGUIViewStateFromItems(items); if (url.IsProtocol("musicdb")) return new CGUIViewStateMusicDatabase(items); if (url.IsProtocol("musicsearch")) return new CGUIViewStateMusicSearch(items); if (items.IsSmartPlayList() || url.IsProtocol("upnp") || items.IsLibraryFolder()) { if (items.GetContent() == "songs" || items.GetContent() == "albums" || items.GetContent() == "mixed") return new CGUIViewStateMusicSmartPlaylist(items); else if (items.GetContent() == "musicvideos") return new CGUIViewStateVideoMusicVideos(items); else if (items.GetContent() == "tvshows") return new CGUIViewStateVideoTVShows(items); else if (items.GetContent() == "episodes") return new CGUIViewStateVideoEpisodes(items); else if (items.GetContent() == "movies") return new CGUIViewStateVideoMovies(items); } if (url.IsProtocol("library")) return new CGUIViewStateLibrary(items); if (items.IsPlayList()) return new CGUIViewStateMusicPlaylist(items); if (items.GetPath() == "special://musicplaylists/") return new CGUIViewStateWindowMusicSongs(items); if (url.IsProtocol("androidapp")) return new CGUIViewStateWindowPrograms(items); if (windowId==WINDOW_MUSIC_NAV) return new CGUIViewStateWindowMusicNav(items); if (windowId==WINDOW_MUSIC_FILES) return new CGUIViewStateWindowMusicSongs(items); if (windowId==WINDOW_MUSIC_PLAYLIST) return new CGUIViewStateWindowMusicPlaylist(items); if (windowId==WINDOW_MUSIC_PLAYLIST_EDITOR) return new CGUIViewStateWindowMusicSongs(items); if (windowId==WINDOW_VIDEO_FILES) return new CGUIViewStateWindowVideoFiles(items); if (windowId==WINDOW_VIDEO_NAV) return new CGUIViewStateWindowVideoNav(items); if (windowId==WINDOW_VIDEO_PLAYLIST) return new CGUIViewStateWindowVideoPlaylist(items); if (windowId==WINDOW_TV_CHANNELS) return new CGUIViewStateWindowPVRChannels(windowId, items); if (windowId==WINDOW_TV_RECORDINGS) return new CGUIViewStateWindowPVRRecordings(windowId, items); if (windowId==WINDOW_TV_GUIDE) return new CGUIViewStateWindowPVRGuide(windowId, items); if (windowId==WINDOW_TV_TIMERS) return new CGUIViewStateWindowPVRTimers(windowId, items); if (windowId==WINDOW_TV_SEARCH) return new CGUIViewStateWindowPVRSearch(windowId, items); if (windowId==WINDOW_RADIO_CHANNELS) return new CGUIViewStateWindowPVRChannels(windowId, items); if (windowId==WINDOW_RADIO_RECORDINGS) return new CGUIViewStateWindowPVRRecordings(windowId, items); if (windowId==WINDOW_RADIO_GUIDE) return new CGUIViewStateWindowPVRGuide(windowId, items); if (windowId==WINDOW_RADIO_TIMERS) return new CGUIViewStateWindowPVRTimers(windowId, items); if (windowId==WINDOW_RADIO_SEARCH) return new CGUIViewStateWindowPVRSearch(windowId, items); if (windowId==WINDOW_PICTURES) return new CGUIViewStateWindowPictures(items); if (windowId==WINDOW_PROGRAMS) return new CGUIViewStateWindowPrograms(items); if (windowId==WINDOW_ADDON_BROWSER) return new CGUIViewStateAddonBrowser(items); // Use as fallback/default return new CGUIViewStateGeneral(items); }
CURL URIUtils::SubstitutePath(const CURL& url, bool reverse /* = false */) { const std::string pathToUrl = url.Get(); return CURL(SubstitutePath(pathToUrl, reverse)); }
bool CPVRFile::Exists(const CURL& url) { return g_PVRManager.IsStarted() && g_PVRRecordings->GetByPath(url.Get())->HasPVRRecordingInfoTag(); }
bool URIUtils::HasExtension(const CURL& url, const std::string& strExtensions) { return HasExtension(url.GetFileName(), strExtensions); }
std::string CSpecialProtocol::TranslatePath(const CURL &url) { // check for special-protocol, if not, return if (!url.IsProtocol("special")) { #if defined(TARGET_POSIX) && defined(_DEBUG) std::string path(url.Get()); if (path.length() >= 2 && path[1] == ':') { CLog::Log(LOGWARNING, "Trying to access old style dir: %s\n", path.c_str()); // printf("Trying to access old style dir: %s\n", path.c_str()); } #endif return url.Get(); } std::string FullFileName = url.GetFileName(); std::string translatedPath; std::string FileName; std::string RootDir; // Split up into the special://root and the rest of the filename size_t pos = FullFileName.find('/'); if (pos != std::string::npos && pos > 1) { RootDir = FullFileName.substr(0, pos); if (pos < FullFileName.size()) FileName = FullFileName.substr(pos + 1); } else RootDir = FullFileName; if (RootDir == "subtitles") translatedPath = URIUtils::AddFileToFolder(CSettings::GetInstance().GetString(CSettings::SETTING_SUBTITLES_CUSTOMPATH), FileName); else if (RootDir == "userdata") translatedPath = URIUtils::AddFileToFolder(CProfilesManager::GetInstance().GetUserDataFolder(), FileName); else if (RootDir == "database") translatedPath = URIUtils::AddFileToFolder(CProfilesManager::GetInstance().GetDatabaseFolder(), FileName); else if (RootDir == "thumbnails") translatedPath = URIUtils::AddFileToFolder(CProfilesManager::GetInstance().GetThumbnailsFolder(), FileName); else if (RootDir == "recordings" || RootDir == "cdrips") translatedPath = URIUtils::AddFileToFolder(CSettings::GetInstance().GetString(CSettings::SETTING_AUDIOCDS_RECORDINGPATH), FileName); else if (RootDir == "screenshots") translatedPath = URIUtils::AddFileToFolder(CSettings::GetInstance().GetString(CSettings::SETTING_DEBUG_SCREENSHOTPATH), FileName); else if (RootDir == "musicplaylists") translatedPath = URIUtils::AddFileToFolder(CUtil::MusicPlaylistsLocation(), FileName); else if (RootDir == "videoplaylists") translatedPath = URIUtils::AddFileToFolder(CUtil::VideoPlaylistsLocation(), FileName); else if (RootDir == "skin") translatedPath = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), FileName); else if (RootDir == "logpath") translatedPath = URIUtils::AddFileToFolder(g_advancedSettings.m_logFolder, FileName); // from here on, we have our "real" special paths else { auto rootName = m_pathMap.find(RootDir); if (rootName != m_pathMap.end()) { std::string basePath = GetPath(RootDir); if (!basePath.empty()) translatedPath = URIUtils::AddFileToFolder(basePath, FileName); else translatedPath.clear(); } } // check if we need to recurse in if (URIUtils::IsSpecial(translatedPath)) { // we need to recurse in, as there may be multiple translations required return TranslatePath(translatedPath); } // Validate the final path, just in case return CUtil::ValidatePath(translatedPath); }
bool CTextureCache::CanCacheImageURL(const CURL &url) { return (url.GetUserName().empty() || url.GetUserName() == "music"); }
CStdString CGUIDialogNetworkSetup::ConstructPath() const { CURL url; if (m_protocol == NET_PROTOCOL_SMB) url.SetProtocol("smb"); else if (m_protocol == NET_PROTOCOL_FTP) url.SetProtocol("ftp"); else if (m_protocol == NET_PROTOCOL_HTTP) url.SetProtocol("http"); else if (m_protocol == NET_PROTOCOL_HTTPS) url.SetProtocol("https"); else if (m_protocol == NET_PROTOCOL_DAV) url.SetProtocol("dav"); else if (m_protocol == NET_PROTOCOL_DAVS) url.SetProtocol("davs"); else if (m_protocol == NET_PROTOCOL_DAAP) url.SetProtocol("daap"); else if (m_protocol == NET_PROTOCOL_UPNP) url.SetProtocol("upnp"); else if (m_protocol == NET_PROTOCOL_TUXBOX) url.SetProtocol("tuxbox"); else if (m_protocol == NET_PROTOCOL_RSS) url.SetProtocol("rss"); else if (m_protocol == NET_PROTOCOL_HTSP) url.SetProtocol("htsp"); else if (m_protocol == NET_PROTOCOL_VTP) url.SetProtocol("vtp"); else if (m_protocol == NET_PROTOCOL_MYTH) url.SetProtocol("myth"); else if (m_protocol == NET_PROTOCOL_NFS) url.SetProtocol("nfs"); else if (m_protocol == NET_PROTOCOL_SFTP) url.SetProtocol("sftp"); if (!m_username.IsEmpty()) { url.SetUserName(m_username); if (!m_password.IsEmpty()) url.SetPassword(m_password); } if(!m_server.IsEmpty()) url.SetHostName(m_server); if (((m_protocol == NET_PROTOCOL_FTP) || (m_protocol == NET_PROTOCOL_HTTP) || (m_protocol == NET_PROTOCOL_HTTPS) || (m_protocol == NET_PROTOCOL_DAV) || (m_protocol == NET_PROTOCOL_DAVS) || (m_protocol == NET_PROTOCOL_RSS) || (m_protocol == NET_PROTOCOL_DAAP && !m_server.IsEmpty()) || (m_protocol == NET_PROTOCOL_HTSP) || (m_protocol == NET_PROTOCOL_VTP) || (m_protocol == NET_PROTOCOL_MYTH) || (m_protocol == NET_PROTOCOL_TUXBOX) || (m_protocol == NET_PROTOCOL_SFTP) || (m_protocol == NET_PROTOCOL_NFS)) && !m_port.IsEmpty() && atoi(m_port.c_str()) > 0) { url.SetPort(atoi(m_port)); } if (!m_path.IsEmpty()) url.SetFileName(m_path); return url.Get(); }
std::string CGUIDialogNetworkSetup::ConstructPath() const { CURL url; if (m_protocol == NET_PROTOCOL_SMB) url.SetProtocol("smb"); else if (m_protocol == NET_PROTOCOL_FTP) url.SetProtocol("ftp"); else if (m_protocol == NET_PROTOCOL_HTTP) url.SetProtocol("http"); else if (m_protocol == NET_PROTOCOL_HTTPS) url.SetProtocol("https"); else if (m_protocol == NET_PROTOCOL_DAV) url.SetProtocol("dav"); else if (m_protocol == NET_PROTOCOL_DAVS) url.SetProtocol("davs"); else if (m_protocol == NET_PROTOCOL_UPNP) url.SetProtocol("upnp"); else if (m_protocol == NET_PROTOCOL_RSS) url.SetProtocol("rss"); else if (m_protocol == NET_PROTOCOL_NFS) url.SetProtocol("nfs"); else if (m_protocol == NET_PROTOCOL_SFTP) url.SetProtocol("sftp"); if (!m_username.empty()) { url.SetUserName(m_username); if (!m_password.empty()) url.SetPassword(m_password); } if(!m_server.empty()) url.SetHostName(m_server); if (((m_protocol == NET_PROTOCOL_FTP) || (m_protocol == NET_PROTOCOL_HTTP) || (m_protocol == NET_PROTOCOL_HTTPS) || (m_protocol == NET_PROTOCOL_DAV) || (m_protocol == NET_PROTOCOL_DAVS) || (m_protocol == NET_PROTOCOL_RSS) || (m_protocol == NET_PROTOCOL_SFTP) || (m_protocol == NET_PROTOCOL_NFS)) && !m_port.empty() && atoi(m_port.c_str()) > 0) { url.SetPort(atoi(m_port.c_str())); } if (!m_path.empty()) url.SetFileName(m_path); return url.Get(); }
bool CMythFile::SetupRecording(const CURL& url) { if (url.GetFileName().Left(11) != "recordings/" && url.GetFileName().Left(7) != "movies/" && url.GetFileName().Left(8) != "tvshows/") return false; if(!SetupConnection(url, true, false, false)) return false; m_filename = url.GetFileNameWithoutPath(); m_program = m_dll->proginfo_get_from_basename(m_control, m_filename.c_str()); if(!m_program) { CLog::Log(LOGERROR, "%s - unable to get find selected file", __FUNCTION__); return false; } m_file = m_dll->conn_connect_file(m_program, m_control, 16*1024, 4096); if(!m_file) { CLog::Log(LOGERROR, "%s - unable to connect to file", __FUNCTION__); return false; } /* * proginfo_get_from_basename doesn't return the recording status. Hopefully this will be added to * mythbackend eventually. * * Since cycling through the recorders to check if the program is recording takes some time * (depending on the MythTV backend configuration), make some assumptions based on the recording * end time since nearly all recordings opened won't be recording. */ m_recording = false; CDateTime start = GetValue(m_dll->proginfo_rec_start(m_program)); CDateTime end = GetValue(m_dll->proginfo_rec_end(m_program)); if (end > start // Assume could be recording if empty date comes back as the epoch && end < CDateTime::GetCurrentDateTime()) CLog::Log(LOGDEBUG, "%s - Assumed not recording since recording end time before current time: %s", __FUNCTION__, end.GetAsLocalizedDateTime().c_str()); else { CLog::Log(LOGDEBUG, "%s - Checking recording status using tuners since recording end time NULL or before current time: %s", __FUNCTION__, end.GetAsLocalizedDateTime().c_str()); for(int i=0;i<16 && !m_recording;i++) { cmyth_recorder_t recorder = m_dll->conn_get_recorder_from_num(m_control, i); if(!recorder) continue; if(m_dll->recorder_is_recording(recorder)) { cmyth_proginfo_t program = m_dll->recorder_get_cur_proginfo(recorder); if(m_dll->proginfo_compare(program, m_program) == 0) m_recording = true; m_dll->ref_release(program); } m_dll->ref_release(recorder); } } if (m_recording) CLog::Log(LOGDEBUG, "%s - Currently recording: %s", __FUNCTION__, m_filename.c_str()); return true; }
bool CSlingboxFile::Open(const CURL& url) { // Setup the IP/hostname and port (setup default port if none specified) unsigned int uiPort; if (url.HasPort()) uiPort = (unsigned int)url.GetPort(); else uiPort = 5001; m_pSlingbox->SetAddress(url.GetHostName().c_str(), uiPort); // Prepare to connect to the Slingbox bool bAdmin; if (StringUtils::EqualsNoCase(url.GetUserName(), "administrator")) bAdmin = true; else if (StringUtils::EqualsNoCase(url.GetUserName(), "viewer")) bAdmin = false; else { CLog::Log(LOGERROR, "%s - Invalid or no username specified for Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); return false; } // Connect to the Slingbox if (m_pSlingbox->Connect(bAdmin, url.GetPassWord().c_str())) { CLog::Log(LOGDEBUG, "%s - Successfully connected to Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); } else { CLog::Log(LOGERROR, "%s - Error connecting to Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); return false; } // Initialize the stream if (m_pSlingbox->InitializeStream()) { CLog::Log(LOGDEBUG, "%s - Successfully initialized stream on Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); } else { CLog::Log(LOGERROR, "%s - Error initializing stream on Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); return false; } // Set correct input if (url.GetFileNameWithoutPath() != "") { if (m_pSlingbox->SetInput(atoi(url.GetFileNameWithoutPath().c_str()))) CLog::Log(LOGDEBUG, "%s - Successfully requested change to input %i on Slingbox: %s", __FUNCTION__, atoi(url.GetFileNameWithoutPath().c_str()), url.GetHostName().c_str()); else CLog::Log(LOGERROR, "%s - Error requesting change to input %i on Slingbox: %s", __FUNCTION__, atoi(url.GetFileNameWithoutPath().c_str()), url.GetHostName().c_str()); } // Load the video settings LoadSettings(url.GetHostName()); // Setup video options if (m_pSlingbox->StreamSettings((CSlingbox::Resolution)m_sSlingboxSettings.iVideoResolution, m_sSlingboxSettings.iVideoBitrate, m_sSlingboxSettings.iVideoFramerate, m_sSlingboxSettings.iVideoSmoothing, m_sSlingboxSettings.iAudioBitrate, m_sSlingboxSettings.iIFrameInterval)) { CLog::Log(LOGDEBUG, "%s - Successfully set stream options (resolution: %ix%i; " "video bitrate: %i kbit/s; fps: %i; smoothing: %i%%; audio bitrate %i kbit/s; " "I frame interval: %i) on Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.iVideoWidth, m_sSlingboxSettings.iVideoHeight, m_sSlingboxSettings.iVideoBitrate, m_sSlingboxSettings.iVideoFramerate, m_sSlingboxSettings.iVideoSmoothing, m_sSlingboxSettings.iAudioBitrate, m_sSlingboxSettings.iIFrameInterval, url.GetHostName().c_str()); } else { CLog::Log(LOGERROR, "%s - Error setting stream options on Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); } // Start the stream if (m_pSlingbox->StartStream()) { CLog::Log(LOGDEBUG, "%s - Successfully started stream on Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); } else { CLog::Log(LOGERROR, "%s - Error starting stream on Slingbox: %s", __FUNCTION__, url.GetHostName().c_str()); return false; } // Check for correct input if (url.GetFileNameWithoutPath() != "") { int input = atoi(url.GetFileNameWithoutPath().c_str()); if (m_pSlingbox->GetInput() == -1) CLog::Log(LOGDEBUG, "%s - Unable to confirm change to input %i on Slingbox: %s", __FUNCTION__, input, url.GetHostName().c_str()); else if (m_pSlingbox->GetInput() == input) CLog::Log(LOGDEBUG, "%s - Comfirmed change to input %i on Slingbox: %s", __FUNCTION__, input, url.GetHostName().c_str()); else CLog::Log(LOGERROR, "%s - Error changing to input %i on Slingbox: %s", __FUNCTION__, input, url.GetHostName().c_str()); } return true; }
bool CMultiPathDirectory::GetPaths(const CURL& url, vector<std::string>& vecPaths) { const std::string pathToUrl(url.Get()); return GetPaths(pathToUrl, vecPaths); }
CAfpConnection::afpConnnectError CAfpConnection::Connect(const CURL& url) { CSingleLock lock(*this); struct afp_connection_request *conn_req = NULL; struct afp_url tmpurl; CURL nonConstUrl(getAuthenticatedPath(url)); // we need a editable copy of the url bool serverChanged=false; if (!initLib()) return AfpFailed; m_pLibAfp->afp_default_url(&tmpurl); // if hostname has changed - assume server changed if (!nonConstUrl.GetHostName().Equals(m_pAfpUrl->servername, false)|| (m_pAfpServer && m_pAfpServer->connect_state == 0)) { serverChanged = true; Disconnect(); } // if volume changed - also assume server changed (afpclient can't reuse old servobject it seems) if (!nonConstUrl.GetShareName().Equals(m_pAfpUrl->volumename, false)) { // no reusing of old server object possible with libafpclient it seems... serverChanged = true; Disconnect(); } // first, try to parse the URL if (m_pLibAfp->afp_parse_url(&tmpurl, nonConstUrl.Get().c_str(), 0) != 0) { // Okay, this isn't a real URL CLog::Log(LOGDEBUG, "AFP: Could not parse url: %s!\n", nonConstUrl.Get().c_str()); return AfpFailed; } else // parsed sucessfull { // this is our current url object whe are connected to (at least we try) *m_pAfpUrl = tmpurl; } // if no username and password is set - use no user authent uam if (strlen(m_pAfpUrl->password) == 0 && strlen(m_pAfpUrl->username) == 0) { // try anonymous strncpy(m_pAfpUrl->uamname, "No User Authent", sizeof(m_pAfpUrl->uamname)); CLog::Log(LOGDEBUG, "AFP: Using anonymous authentication."); } else if ((nonConstUrl.GetPassWord().IsEmpty() || nonConstUrl.GetUserName().IsEmpty()) && serverChanged) { // this is our current url object whe are connected to (at least we try) return AfpAuth; } // we got a password in the url if (!nonConstUrl.GetPassWord().IsEmpty()) { // copy password because afp_parse_url just puts garbage into the password field :( strncpy(m_pAfpUrl->password, nonConstUrl.GetPassWord().c_str(), 127); } // whe are not connected or we want to connect to another server if (!m_pAfpServer || serverChanged) { // code from cmdline tool conn_req = (struct afp_connection_request*)malloc(sizeof(struct afp_connection_request)); memset(conn_req, 0, sizeof(struct afp_connection_request)); conn_req->url = *m_pAfpUrl; conn_req->url.requested_version = 31; if (strlen(m_pAfpUrl->uamname)>0) { if ((conn_req->uam_mask = m_pLibAfp->find_uam_by_name(m_pAfpUrl->uamname)) == 0) { CLog::Log(LOGDEBUG, "AFP:I don't know about UAM %s\n", m_pAfpUrl->uamname); m_pAfpUrl->volumename[0] = '\0'; m_pAfpUrl->servername[0] = '\0'; free(conn_req); return AfpFailed; } } else { conn_req->uam_mask = m_pLibAfp->default_uams_mask(); } // try to connect #ifdef USE_CVS_AFPFS if ((m_pAfpServer = m_pLibAfp->afp_wrap_server_full_connect(NULL, conn_req, NULL)) == NULL) #else if ((m_pAfpServer = m_pLibAfp->afp_wrap_server_full_connect(NULL, conn_req)) == NULL) #endif { m_pAfpUrl->volumename[0] = '\0'; m_pAfpUrl->servername[0] = '\0'; free(conn_req); CLog::Log(LOGERROR, "AFP: Error connecting to %s", url.Get().c_str()); return AfpFailed; } // success! CLog::Log(LOGDEBUG, "AFP: Connected to server %s using UAM \"%s\"\n", m_pAfpServer->server_name, m_pLibAfp->uam_bitmap_to_string(m_pAfpServer->using_uam)); // we don't need it after here ... free(conn_req); } // if server changed reconnect volume if (serverChanged) { disconnectVolume(); // disconnect old volume connectVolume(m_pAfpUrl->volumename); // connect new volume } return AfpOk; }
bool CFileCache::Exists(const CURL& url) { return CFile::Exists(url.Get()); }
void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) { switch (pMsg->dwMessage) { case TMSG_SHUTDOWN: { switch (CSettings::Get().GetInt("powermanagement.shutdownstate")) { case POWERSTATE_SHUTDOWN: Powerdown(); break; case POWERSTATE_SUSPEND: Suspend(); break; case POWERSTATE_HIBERNATE: Hibernate(); break; case POWERSTATE_QUIT: Quit(); break; case POWERSTATE_MINIMIZE: Minimize(); break; case TMSG_RENDERER_FLUSH: g_renderManager.Flush(); break; } } break; case TMSG_POWERDOWN: { g_application.Stop(EXITCODE_POWERDOWN); g_powerManager.Powerdown(); } break; case TMSG_QUIT: { g_application.Stop(EXITCODE_QUIT); } break; case TMSG_PAUSE: { if (g_application.m_pPlayer->IsPlaying()) { CLog::Log(LOGNOTICE, "App pause and media is playing, pause it first"); g_application.m_pPlayer->Pause(); //g_application.StopPlaying(); } g_application.SetAppState(0); } break; case TMSG_RESUME: { g_application.SetAppState(1); /* if (g_application.m_pPlayer->IsPausedPlayback()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } */ } break; case TMSG_HIBERNATE: { g_PVRManager.SetWakeupCommand(); g_powerManager.Hibernate(); } break; case TMSG_SUSPEND: { g_PVRManager.SetWakeupCommand(); g_powerManager.Suspend(); } break; case TMSG_RESTART: case TMSG_RESET: { g_application.Stop(EXITCODE_REBOOT); g_powerManager.Reboot(); } break; case TMSG_RESTARTAPP: { #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX) g_application.Stop(EXITCODE_RESTARTAPP); #endif } break; case TMSG_INHIBITIDLESHUTDOWN: { g_application.InhibitIdleShutdown(pMsg->param1 != 0); } break; case TMSG_ACTIVATESCREENSAVER: { g_application.ActivateScreenSaver(); } break; case TMSG_MEDIA_PLAY: { // first check if we were called from the PlayFile() function if (pMsg->lpVoid && pMsg->param2 == 0) { CFileItem *item = (CFileItem *)pMsg->lpVoid; g_application.PlayFile(*item, pMsg->param1 != 0); delete item; return; } // restore to previous window if needed if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO || g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); //g_application.StopPlaying(); // play file if(pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; if (list->Size() > 0) { int playlist = PLAYLIST_MUSIC; for (int i = 0; i < list->Size(); i++) { if ((*list)[i]->IsVideo()) { playlist = PLAYLIST_VIDEO; break; } } g_playlistPlayer.ClearPlaylist(playlist); g_playlistPlayer.SetCurrentPlaylist(playlist); //For single item lists try PlayMedia. This covers some more cases where a playlist is not appropriate //It will fall through to PlayFile if (list->Size() == 1 && !(*list)[0]->IsPlayList()) g_application.PlayMedia(*((*list)[0]), playlist); else { // Handle "shuffled" option if present if (list->HasProperty("shuffled") && list->GetProperty("shuffled").isBoolean()) g_playlistPlayer.SetShuffle(playlist, list->GetProperty("shuffled").asBoolean(), false); // Handle "repeat" option if present if (list->HasProperty("repeat") && list->GetProperty("repeat").isInteger()) g_playlistPlayer.SetRepeat(playlist, (PLAYLIST::REPEAT_STATE)list->GetProperty("repeat").asInteger(), false); g_playlistPlayer.Add(playlist, (*list)); g_playlistPlayer.Play(pMsg->param1); } } delete list; } else if (pMsg->param1 == PLAYLIST_MUSIC || pMsg->param1 == PLAYLIST_VIDEO) { if (g_playlistPlayer.GetCurrentPlaylist() != pMsg->param1) g_playlistPlayer.SetCurrentPlaylist(pMsg->param1); PlayListPlayerPlay(pMsg->param2); } } break; case TMSG_MEDIA_RESTART: g_application.Restart(true); break; case TMSG_PICTURE_SHOW: { CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!pSlideShow) return ; // stop playing file if (g_application.m_pPlayer->IsPlayingVideo()) g_application.StopPlaying(); if (g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_graphicsContext.Lock(); if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW) g_windowManager.ActivateWindow(WINDOW_SLIDESHOW); if (URIUtils::IsZIP(pMsg->strParam) || URIUtils::IsRAR(pMsg->strParam)) // actually a cbz/cbr { CFileItemList items; CURL pathToUrl; if (URIUtils::IsZIP(pMsg->strParam)) pathToUrl = URIUtils::CreateArchivePath("zip", CURL(pMsg->strParam), ""); else pathToUrl = URIUtils::CreateArchivePath("rar", CURL(pMsg->strParam), ""); CUtil::GetRecursiveListing(pathToUrl.Get(), items, g_advancedSettings.m_pictureExtensions, XFILE::DIR_FLAG_NO_FILE_DIRS); if (items.Size() > 0) { pSlideShow->Reset(); for (int i=0;i<items.Size();++i) { pSlideShow->Add(items[i].get()); } pSlideShow->Select(items[0]->GetPath()); } } else { CFileItem item(pMsg->strParam, false); pSlideShow->Reset(); pSlideShow->Add(&item); pSlideShow->Select(pMsg->strParam); } g_graphicsContext.Unlock(); } break; case TMSG_PICTURE_SLIDESHOW: { CGUIWindowSlideShow *pSlideShow = (CGUIWindowSlideShow *)g_windowManager.GetWindow(WINDOW_SLIDESHOW); if (!pSlideShow) return ; if (g_application.m_pPlayer->IsPlayingVideo()) g_application.StopPlaying(); g_graphicsContext.Lock(); pSlideShow->Reset(); CFileItemList items; CStdString strPath = pMsg->strParam; CStdString extensions = g_advancedSettings.m_pictureExtensions; if (pMsg->param1) extensions += "|.tbn"; CUtil::GetRecursiveListing(strPath, items, extensions); if (items.Size() > 0) { for (int i=0;i<items.Size();++i) pSlideShow->Add(items[i].get()); pSlideShow->StartSlideShow(); //Start the slideshow! } if (g_windowManager.GetActiveWindow() != WINDOW_SLIDESHOW) { if(items.Size() == 0) { CSettings::Get().SetString("screensaver.mode", "screensaver.xbmc.builtin.dim"); g_application.ActivateScreenSaver(); } else g_windowManager.ActivateWindow(WINDOW_SLIDESHOW); } g_graphicsContext.Unlock(); } break; case TMSG_SETLANGUAGE: g_application.SetLanguage(pMsg->strParam); break; case TMSG_MEDIA_STOP: { // restore to previous window if needed bool stopSlideshow = true; bool stopVideo = true; bool stopMusic = true; if (pMsg->param1 >= PLAYLIST_MUSIC && pMsg->param1 <= PLAYLIST_PICTURE) { stopSlideshow = (pMsg->param1 == PLAYLIST_PICTURE); stopVideo = (pMsg->param1 == PLAYLIST_VIDEO); stopMusic = (pMsg->param1 == PLAYLIST_MUSIC); } if ((stopSlideshow && g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) || (stopVideo && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) || (stopMusic && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); // stop playing file if (g_application.m_pPlayer->IsPlaying()) g_application.StopPlaying(); } break; case TMSG_MEDIA_PAUSE: if (g_application.m_pPlayer->HasPlayer()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_MEDIA_UNPAUSE: if (g_application.m_pPlayer->IsPausedPlayback()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_MEDIA_PAUSE_IF_PLAYING: if (g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_SWITCHTOFULLSCREEN: if( g_windowManager.GetActiveWindow() != WINDOW_FULLSCREEN_VIDEO ) g_application.SwitchToFullScreen(); break; case TMSG_SETVIDEORESOLUTION: { RESOLUTION res = (RESOLUTION)pMsg->param1; bool forceUpdate = pMsg->param2 == 1 ? true : false; g_graphicsContext.SetVideoResolution(res, forceUpdate); } break; case TMSG_TOGGLEFULLSCREEN: g_graphicsContext.Lock(); g_graphicsContext.ToggleFullScreenRoot(); g_graphicsContext.Unlock(); break; case TMSG_MINIMIZE: g_application.Minimize(); break; case TMSG_EXECUTE_OS: /* Suspend AE temporarily so exclusive or hog-mode sinks */ /* don't block external player's access to audio device */ if (!CAEFactory::Suspend()) { CLog::Log(LOGNOTICE, "%s: Failed to suspend AudioEngine before launching external program",__FUNCTION__); } #if defined( TARGET_POSIX) && !defined(TARGET_DARWIN) CUtil::RunCommandLine(pMsg->strParam.c_str(), (pMsg->param1 == 1)); #elif defined(TARGET_WINDOWS) CWIN32Util::XBMCShellExecute(pMsg->strParam.c_str(), (pMsg->param1 == 1)); #endif /* Resume AE processing of XBMC native audio */ if (!CAEFactory::Resume()) { CLog::Log(LOGFATAL, "%s: Failed to restart AudioEngine after return from external player",__FUNCTION__); } break; case TMSG_EXECUTE_SCRIPT: CScriptInvocationManager::Get().Execute(pMsg->strParam); break; case TMSG_EXECUTE_BUILT_IN: CBuiltins::Execute(pMsg->strParam.c_str()); break; case TMSG_PLAYLISTPLAYER_PLAY: if (pMsg->param1 != -1) g_playlistPlayer.Play(pMsg->param1); else g_playlistPlayer.Play(); break; case TMSG_PLAYLISTPLAYER_PLAY_SONG_ID: if (pMsg->param1 != -1) { bool *result = (bool*)pMsg->lpVoid; *result = g_playlistPlayer.PlaySongId(pMsg->param1); } else g_playlistPlayer.Play(); break; case TMSG_PLAYLISTPLAYER_NEXT: g_playlistPlayer.PlayNext(); break; case TMSG_PLAYLISTPLAYER_PREV: g_playlistPlayer.PlayPrevious(); break; case TMSG_PLAYLISTPLAYER_ADD: if(pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; g_playlistPlayer.Add(pMsg->param1, (*list)); delete list; } break; case TMSG_PLAYLISTPLAYER_INSERT: if (pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; g_playlistPlayer.Insert(pMsg->param1, (*list), pMsg->param2); delete list; } break; case TMSG_PLAYLISTPLAYER_REMOVE: if (pMsg->param1 != -1) g_playlistPlayer.Remove(pMsg->param1,pMsg->param2); break; case TMSG_PLAYLISTPLAYER_CLEAR: g_playlistPlayer.ClearPlaylist(pMsg->param1); break; case TMSG_PLAYLISTPLAYER_SHUFFLE: g_playlistPlayer.SetShuffle(pMsg->param1, pMsg->param2 > 0); break; case TMSG_PLAYLISTPLAYER_REPEAT: g_playlistPlayer.SetRepeat(pMsg->param1, (PLAYLIST::REPEAT_STATE)pMsg->param2); break; case TMSG_PLAYLISTPLAYER_GET_ITEMS: if (pMsg->lpVoid) { PLAYLIST::CPlayList playlist = g_playlistPlayer.GetPlaylist(pMsg->param1); CFileItemList *list = (CFileItemList *)pMsg->lpVoid; for (int i = 0; i < playlist.size(); i++) list->Add(CFileItemPtr(new CFileItem(*playlist[i]))); } break; case TMSG_PLAYLISTPLAYER_SWAP: if (pMsg->lpVoid) { vector<int> *indexes = (vector<int> *)pMsg->lpVoid; if (indexes->size() == 2) g_playlistPlayer.Swap(pMsg->param1, indexes->at(0), indexes->at(1)); delete indexes; } break; // Window messages below here... case TMSG_DIALOG_DOMODAL: //doModel of window { CGUIDialog* pDialog = (CGUIDialog*)g_windowManager.GetWindow(pMsg->param1); if (!pDialog) return ; pDialog->DoModal(); } break; case TMSG_NETWORKMESSAGE: { g_application.getNetwork().NetworkMessage((CNetwork::EMESSAGE)pMsg->param1, pMsg->param2); } break; case TMSG_GUI_DO_MODAL: { CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid; if (pDialog) pDialog->DoModal(pMsg->param1, pMsg->strParam); } break; case TMSG_GUI_SHOW: { CGUIDialog *pDialog = (CGUIDialog *)pMsg->lpVoid; if (pDialog) pDialog->Show(); } break; case TMSG_GUI_WINDOW_CLOSE: { CGUIWindow *window = (CGUIWindow *)pMsg->lpVoid; if (window) window->Close(pMsg->param1 & 0x1 ? true : false, pMsg->param1, pMsg->param1 & 0x2 ? true : false); } break; case TMSG_GUI_ACTIVATE_WINDOW: { g_windowManager.ActivateWindow(pMsg->param1, pMsg->params, pMsg->param2 > 0); } break; case TMSG_GUI_ADDON_DIALOG: { if (pMsg->lpVoid) { // TODO: This is ugly - really these python dialogs should just be normal XBMC dialogs ((ADDON::CGUIAddonWindowDialog *) pMsg->lpVoid)->Show_Internal(pMsg->param2 > 0); } } break; #ifdef HAS_PYTHON case TMSG_GUI_PYTHON_DIALOG: { // This hack is not much better but at least I don't need to make ApplicationMessenger // know about Addon (Python) specific classes. CAction caction(pMsg->param1); ((CGUIWindow*)pMsg->lpVoid)->OnAction(caction); } break; #endif case TMSG_GUI_ACTION: { if (pMsg->lpVoid) { CAction *action = (CAction *)pMsg->lpVoid; if (pMsg->param1 == WINDOW_INVALID) g_application.OnAction(*action); else { CGUIWindow *pWindow = g_windowManager.GetWindow(pMsg->param1); if (pWindow) pWindow->OnAction(*action); else CLog::Log(LOGWARNING, "Failed to get window with ID %i to send an action to", pMsg->param1); } delete action; } } break; case TMSG_GUI_MESSAGE: { if (pMsg->lpVoid) { CGUIMessage *message = (CGUIMessage *)pMsg->lpVoid; g_windowManager.SendMessage(*message, pMsg->param1); delete message; } } break; case TMSG_GUI_INFOLABEL: { if (pMsg->lpVoid) { vector<string> *infoLabels = (vector<string> *)pMsg->lpVoid; for (unsigned int i = 0; i < pMsg->params.size(); i++) infoLabels->push_back(g_infoManager.GetLabel(g_infoManager.TranslateString(pMsg->params[i]))); } } break; case TMSG_GUI_INFOBOOL: { if (pMsg->lpVoid) { vector<bool> *infoLabels = (vector<bool> *)pMsg->lpVoid; for (unsigned int i = 0; i < pMsg->params.size(); i++) infoLabels->push_back(g_infoManager.EvaluateBool(pMsg->params[i])); } } break; case TMSG_CALLBACK: { ThreadMessageCallback *callback = (ThreadMessageCallback*)pMsg->lpVoid; callback->callback(callback->userptr); } break; case TMSG_VOLUME_SHOW: { CAction action(pMsg->param1); g_application.ShowVolumeBar(&action); } break; case TMSG_SPLASH_MESSAGE: { if (g_application.GetSplash()) g_application.GetSplash()->Show(pMsg->strParam); } break; case TMSG_DISPLAY_SETUP: { *((bool*)pMsg->lpVoid) = g_application.InitWindow(); g_application.SetRenderGUI(true); } break; case TMSG_DISPLAY_DESTROY: { *((bool*)pMsg->lpVoid) = g_application.DestroyWindow(); g_application.SetRenderGUI(false); } break; case TMSG_UPDATE_CURRENT_ITEM: { CFileItem* item = (CFileItem*)pMsg->lpVoid; if (!item) return; if (pMsg->param1 == 1 && item->HasMusicInfoTag()) // only grab music tag g_infoManager.SetCurrentSongTag(*item->GetMusicInfoTag()); else if (pMsg->param1 == 2 && item->HasVideoInfoTag()) // only grab video tag g_infoManager.SetCurrentVideoTag(*item->GetVideoInfoTag()); else g_infoManager.SetCurrentItem(*item); delete item; break; } case TMSG_LOADPROFILE: { CGUIWindowLoginScreen::LoadProfile(pMsg->param1); break; } case TMSG_CECTOGGLESTATE: { *((bool*)pMsg->lpVoid) = g_peripherals.ToggleDeviceState(STATE_SWITCH_TOGGLE); break; } case TMSG_CECACTIVATESOURCE: { g_peripherals.ToggleDeviceState(STATE_ACTIVATE_SOURCE); break; } case TMSG_CECSTANDBY: { g_peripherals.ToggleDeviceState(STATE_STANDBY); break; } case TMSG_START_ANDROID_ACTIVITY: { #if defined(TARGET_ANDROID) if (pMsg->params.size()) { CXBMCApp::StartActivity(pMsg->params[0], pMsg->params.size() > 1 ? pMsg->params[1] : "", pMsg->params.size() > 2 ? pMsg->params[2] : "", pMsg->params.size() > 3 ? pMsg->params[3] : ""); } #endif break; } } }
bool CSMBDirectory::GetDirectory(const CURL& url, CFileItemList &items) { // We accept smb://[[[domain;]user[:password@]]server[/share[/path[/file]]]] /* samba isn't thread safe with old interface, always lock */ CSingleLock lock(smb); smb.Init(); //Separate roots for the authentication and the containing items to allow browsing to work correctly std::string strRoot = url.Get(); std::string strAuth; lock.Leave(); // OpenDir is locked int fd = OpenDir(url, strAuth); if (fd < 0) return false; URIUtils::AddSlashAtEnd(strRoot); URIUtils::AddSlashAtEnd(strAuth); std::string strFile; // need to keep the samba lock for as short as possible. // so we first cache all directory entries and then go over them again asking for stat // "stat" is locked each time. that way the lock is freed between stat requests vector<CachedDirEntry> vecEntries; struct smbc_dirent* dirEnt; lock.Enter(); while ((dirEnt = smbc_readdir(fd))) { CachedDirEntry aDir; aDir.type = dirEnt->smbc_type; aDir.name = dirEnt->name; vecEntries.push_back(aDir); } smbc_closedir(fd); lock.Leave(); for (size_t i=0; i<vecEntries.size(); i++) { CachedDirEntry aDir = vecEntries[i]; // We use UTF-8 internally, as does SMB strFile = aDir.name; if (!strFile.empty() && strFile != "." && strFile != ".." && strFile != "lost+found" && aDir.type != SMBC_PRINTER_SHARE && aDir.type != SMBC_IPC_SHARE) { int64_t iSize = 0; bool bIsDir = true; int64_t lTimeDate = 0; bool hidden = false; if(StringUtils::EndsWith(strFile, "$") && aDir.type == SMBC_FILE_SHARE ) continue; // only stat files that can give proper responses if ( aDir.type == SMBC_FILE || aDir.type == SMBC_DIR ) { // set this here to if the stat should fail bIsDir = (aDir.type == SMBC_DIR); struct stat info = {0}; if ((m_flags & DIR_FLAG_NO_FILE_INFO)==0 && g_advancedSettings.m_sambastatfiles) { // make sure we use the authenticated path wich contains any default username const std::string strFullName = strAuth + smb.URLEncode(strFile); lock.Enter(); if( smbc_stat(strFullName.c_str(), &info) == 0 ) { char value[20]; // We poll for extended attributes which symbolizes bits but split up into a string. Where 0x02 is hidden and 0x12 is hidden directory. // According to the libsmbclient.h it's supposed to return 0 if ok, or the length of the string. It seems always to return the length wich is 4 if (smbc_getxattr(strFullName.c_str(), "system.dos_attr.mode", value, sizeof(value)) > 0) { long longvalue = strtol(value, NULL, 16); if (longvalue & SMBC_DOS_MODE_HIDDEN) hidden = true; } else CLog::Log(LOGERROR, "Getting extended attributes for the share: '%s'\nunix_err:'%x' error: '%s'", CURL::GetRedacted(strFullName).c_str(), errno, strerror(errno)); bIsDir = S_ISDIR(info.st_mode); lTimeDate = info.st_mtime; if(lTimeDate == 0) // if modification date is missing, use create date lTimeDate = info.st_ctime; iSize = info.st_size; } else CLog::Log(LOGERROR, "%s - Failed to stat file %s", __FUNCTION__, CURL::GetRedacted(strFullName).c_str()); lock.Leave(); } } FILETIME fileTime, localTime; TimeTToFileTime(lTimeDate, &fileTime); FileTimeToLocalFileTime(&fileTime, &localTime); if (bIsDir) { CFileItemPtr pItem(new CFileItem(strFile)); std::string path(strRoot); // needed for network / workgroup browsing // skip if root if we are given a server if (aDir.type == SMBC_SERVER) { /* create url with same options, user, pass.. but no filename or host*/ CURL rooturl(strRoot); rooturl.SetFileName(""); rooturl.SetHostName(""); path = smb.URLEncode(rooturl); } path = URIUtils::AddFileToFolder(path,aDir.name); URIUtils::AddSlashAtEnd(path); pItem->SetPath(path); pItem->m_bIsFolder = true; pItem->m_dateTime=localTime; if (hidden) pItem->SetProperty("file:hidden", true); items.Add(pItem); } else { CFileItemPtr pItem(new CFileItem(strFile)); pItem->SetPath(strRoot + aDir.name); pItem->m_bIsFolder = false; pItem->m_dwSize = iSize; pItem->m_dateTime=localTime; if (hidden) pItem->SetProperty("file:hidden", true); items.Add(pItem); } } } return true; }
bool CPosixDirectory::GetDirectory(const CURL& url, CFileItemList &items) { std::string root = url.Get(); if (IsAliasShortcut(root)) TranslateAliasShortcut(root); DIR *dir = opendir(root.c_str()); if (!dir) return false; struct dirent* entry; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; CFileItemPtr pItem(new CFileItem(entry->d_name)); std::string itemPath(URIUtils::AddFileToFolder(root, entry->d_name)); bool bStat = false; struct stat buffer; // Unix-based readdir implementations may return an incorrect dirent.d_ino value that // is not equal to the (correct) stat() obtained one. In this case the file type // could not be determined and the value of dirent.d_type is set to DT_UNKNOWN. // In order to get a correct value we have to incur the cost of calling stat. if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) { if (stat(itemPath.c_str(), &buffer) == 0) bStat = true; } if (entry->d_type == DT_DIR || (bStat && buffer.st_mode & S_IFDIR)) { pItem->m_bIsFolder = true; URIUtils::AddSlashAtEnd(itemPath); } else { pItem->m_bIsFolder = false; } if (StringUtils::StartsWith(entry->d_name, ".")) pItem->SetProperty("file:hidden", true); pItem->SetPath(itemPath); if (!(m_flags & DIR_FLAG_NO_FILE_INFO)) { if (bStat || stat(pItem->GetPath(), &buffer) == 0) { FILETIME fileTime, localTime; TimeTToFileTime(buffer.st_mtime, &fileTime); FileTimeToLocalFileTime(&fileTime, &localTime); pItem->m_dateTime = localTime; if (!pItem->m_bIsFolder) pItem->m_dwSize = buffer.st_size; } } items.Add(pItem); } closedir(dir); return true; }