bool MatchesFilter(CStdString filter, CStdString ip) { // A single asterix matches all IPs. if (filter == _T("*")) return true; // Check for IP range syntax. int pos = filter.Find('/'); if (pos != -1) { // CIDR filter int prefixLength = _ttoi(filter.Mid(pos+1)); if (ip.Find(':') != -1) { // IPv6 address CStdString left = GetIPV6LongForm(filter.Left(pos)); if (left.Find(':') == -1) return false; ip = GetIPV6LongForm(ip); LPCTSTR i = ip; LPCTSTR f = left; while (prefixLength >= 4) { if (*i != *f) return false; if (!*i) return true; if (*i == ':') { ++i; ++f; } ++i; ++f; prefixLength -= 4; } if (!prefixLength) return true; int mask; if (prefixLength == 1) mask = 0x8; else if (prefixLength == 2) mask = 0xc; else mask = 0xe; return (DigitHexToDecNum(*i) & mask) == (DigitHexToDecNum(*f) & mask); } else { if (prefixLength < 0) prefixLength = 0; else if (prefixLength > 32) prefixLength = 32; // IPv4 address CStdString left = filter.Left(pos); if (left.Find(':') != -1) return false; unsigned long i = ntohl(inet_addr(ConvToLocal(ip))); unsigned long f = ntohl(inet_addr(ConvToLocal(left))); i &= prefixMasksV4[prefixLength]; f &= prefixMasksV4[prefixLength]; return i == f; } } else { // Literal filter if (filter.Find(':') != -1) return filter == GetIPV6ShortForm(ip); else return filter == ip; } }
bool CMythDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) { m_session = CMythSession::AquireSession(strPath); if (!m_session) return false; m_dll = m_session->GetLibrary(); if (!m_dll) return false; CStdString base(strPath); URIUtils::RemoveSlashAtEnd(base); CURL url(strPath); CStdString fileName = url.GetFileName(); URIUtils::RemoveSlashAtEnd(fileName); if (fileName == "") { /* * If we can't get the control then we can't connect to the backend. Don't even show any of the * virtual folders as none of them will work. Without this check the "Browse" functionality * when adding a myth:// source is way confusing as it shows folders so it looks like it has * connected successfully when it in fact hasn't. */ cmyth_conn_t control = m_session->GetControl(); if (!control) return false; CFileItemPtr item; item.reset(new CFileItem(base + "/recordings/", true)); item->SetLabel(g_localizeStrings.Get(22015)); // All recordings items.Add(item); item.reset(new CFileItem(base + "/tvshows/", true)); item->SetLabel(g_localizeStrings.Get(20343)); // TV shows items.Add(item); item.reset(new CFileItem(base + "/movies/", true)); item->SetLabel(g_localizeStrings.Get(20342)); // Movies items.Add(item); item.reset(new CFileItem(base + "/channels/", true)); item->SetLabel(g_localizeStrings.Get(22018)); // Live channels items.Add(item); item.reset(new CFileItem(base + "/guide/", true)); item->SetLabel(g_localizeStrings.Get(22020)); // Guide items.Add(item); items.AddSortMethod(SORT_METHOD_NONE, 564 /* Type */, LABEL_MASKS("", "", "%L", "")); // No sorting, as added to list. /* * Clear the directory cache so the cached sub-folders are guaranteed to be accurate. */ g_directoryCache.ClearSubPaths(base); return true; } else if (fileName == "channels") return GetChannels(base, items); else if (fileName == "guide") return GetGuide(base, items); else if (fileName.Left(6) == "guide/") return GetGuideForChannel(base, items, atoi(fileName.Mid(6))); else if (fileName == "movies") return GetRecordings(base, items, MOVIES); else if (fileName == "recordings") return GetRecordings(base, items); else if (fileName == "tvshows") return GetTvShowFolders(base, items); else if (fileName.Left(8) == "tvshows/") return GetRecordings(base, items, TV_SHOWS, fileName.Mid(8)); return false; }
// TODO: Currently no support for "embedded thumb" as there is no easy way to grab it // without sending a file that has this as it's album to this class void CGUIDialogMusicInfo::OnGetThumb() { CFileItemList items; // Current thumb if (CFile::Exists(m_albumItem->GetArt("thumb"))) { CFileItemPtr item(new CFileItem("thumb://Current", false)); item->SetArt("thumb", m_albumItem->GetArt("thumb")); item->SetLabel(g_localizeStrings.Get(20016)); items.Add(item); } // Grab the thumbnail(s) from the web vector<CStdString> thumbs; if (m_bArtistInfo) m_artist.thumbURL.GetThumbURLs(thumbs); else m_album.thumbURL.GetThumbURLs(thumbs); for (unsigned int i = 0; i < thumbs.size(); ++i) { CStdString strItemPath; strItemPath.Format("thumb://Remote%i", i); CFileItemPtr item(new CFileItem(strItemPath, false)); item->SetArt("thumb", thumbs[i]); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20015)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } // local thumb CStdString localThumb; if (m_bArtistInfo) { CMusicDatabase database; database.Open(); CStdString strArtistPath; if (database.GetArtistPath(m_artist.idArtist,strArtistPath)) localThumb = URIUtils::AddFileToFolder(strArtistPath, "folder.jpg"); } else localThumb = m_albumItem->GetUserMusicThumb(); if (CFile::Exists(localThumb)) { CFileItemPtr item(new CFileItem("thumb://Local", false)); item->SetArt("thumb", localThumb); item->SetLabel(g_localizeStrings.Get(20017)); items.Add(item); } else { CFileItemPtr item(new CFileItem("thumb://None", false)); if (m_bArtistInfo) item->SetIconImage("DefaultArtist.png"); else item->SetIconImage("DefaultAlbumCover.png"); item->SetLabel(g_localizeStrings.Get(20018)); items.Add(item); } CStdString result; bool flip=false; VECSOURCES sources(*CMediaSourceSettings::Get().GetSources("music")); AddItemPathToFileBrowserSources(sources, *m_albumItem); g_mediaManager.GetLocalDrives(sources); if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(1030), result, &flip)) return; // user cancelled if (result == "thumb://Current") return; // user chose the one they have CStdString newThumb; if (result.Left(14) == "thumb://Remote") { int number = atoi(result.Mid(14)); newThumb = thumbs[number]; } else if (result == "thumb://Local") newThumb = localThumb; else if (CFile::Exists(result)) newThumb = result; else // none newThumb = "-"; // force local thumbs to be ignored // update thumb in the database CMusicDatabase db; if (db.Open()) { db.SetArtForItem(m_albumItem->GetMusicInfoTag()->GetDatabaseId(), m_albumItem->GetMusicInfoTag()->GetType(), "thumb", newThumb); db.Close(); } m_albumItem->SetArt("thumb", newThumb); m_hasUpdatedThumb = true; // tell our GUI to completely reload all controls (as some of them // are likely to have had this image in use so will need refreshing) CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS); g_windowManager.SendMessage(msg); // Update our screen Update(); }
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_stSettings.m_currentVideoSettings.m_AudioStream == -1) { // default to stereo stream g_stSettings.m_currentVideoSettings.m_AudioStream = 0; }*/ setting.max = 2; for (int i = 0; i <= setting.max; i++) setting.entry.push_back(g_localizeStrings.Get(13320 + i)); m_audioStream = -g_stSettings.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(strItem); } if( setting.max < 0 ) { setting.max = 0; setting.entry.push_back(g_localizeStrings.Get(231).c_str()); } m_settings.push_back(setting); }
// TODO: Currently no support for "embedded thumb" as there is no easy way to grab it // without sending a file that has this as it's album to this class void CGUIWindowMusicInfo::OnGetThumb() { CFileItemList items; // Grab the thumbnail from the web CStdString thumbFromWeb; CUtil::AddFileToFolder(g_advancedSettings.m_cachePath, "allmusicThumb", thumbFromWeb); int iDownloaded=DownloadThumbnail(thumbFromWeb,true); if (iDownloaded > 0) { for (int i=0;i<iDownloaded;++i) { CStdString strThumb; strThumb.Format("thumb://Remote%i",i); CFileItem *item = new CFileItem(strThumb, false); strThumb.Format("%s%i.tbn",thumbFromWeb,i); item->SetThumbnailImage(strThumb); item->SetLabel(g_localizeStrings.Get(20055)); items.Add(item); } } // Current thumb if (CFile::Exists(m_albumItem->GetThumbnailImage())) { CFileItem *item = new CFileItem("thumb://Current", false); item->SetThumbnailImage(m_albumItem->GetThumbnailImage()); item->SetLabel(g_localizeStrings.Get(20016)); items.Add(item); } // local thumb CStdString cachedLocalThumb; CStdString localThumb; if (m_bArtistInfo) { CMusicDatabase database; database.Open(); CStdString strArtistPath; database.GetArtistPath(m_artist.idArtist,strArtistPath); CUtil::AddFileToFolder(strArtistPath,"folder.jpg",localThumb); } else CStdString localThumb = m_albumItem->GetUserMusicThumb(); if (CFile::Exists(localThumb)) { CUtil::AddFileToFolder(g_advancedSettings.m_cachePath, "localthumb.jpg", cachedLocalThumb); CPicture pic; if (pic.DoCreateThumbnail(localThumb, cachedLocalThumb)) { CFileItem *item = new CFileItem("thumb://Local", false); item->SetThumbnailImage(cachedLocalThumb); item->SetLabel(g_localizeStrings.Get(20017)); items.Add(item); } } CFileItem *item = new CFileItem("thumb://None", false); if (m_bArtistInfo) item->SetThumbnailImage("defaultArtistBig.png"); else item->SetThumbnailImage("defaultAlbumCover.png"); item->SetLabel(g_localizeStrings.Get(20018)); items.Add(item); CStdString result; if (!CGUIDialogFileBrowser::ShowAndGetImage(items, g_settings.m_musicSources, g_localizeStrings.Get(1030), result)) return; // user cancelled if (result == "thumb://Current") return; // user chose the one they have // delete the thumbnail if that's what the user wants, else overwrite with the // new thumbnail CStdString cachedThumb; if (m_bArtistInfo) cachedThumb = m_albumItem->GetCachedArtistThumb(); else cachedThumb = CUtil::GetCachedAlbumThumb(m_album.strAlbum, m_album.strArtist); if (result == "thumb://None") { // cache the default thumb CPicture pic; pic.CacheSkinImage("defaultAlbumCover.png", cachedThumb); } else if (result.Left(14).Equals("thumb://Remote")) CFile::Cache(thumbFromWeb+result.Mid(14)+".tbn", cachedThumb); else if (result == "thumb://Local") CFile::Cache(cachedLocalThumb, cachedThumb); else if (CFile::Exists(result)) { CPicture pic; pic.DoCreateThumbnail(result, cachedThumb); } m_albumItem->SetThumbnailImage(cachedThumb); m_hasUpdatedThumb = true; // tell our GUI to completely reload all controls (as some of them // are likely to have had this image in use so will need refreshing) CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS); g_graphicsContext.SendMessage(msg); // Update our screen Update(); }
// Allow user to select a Fanart void CGUIDialogVideoInfo::OnGetFanart() { CFileItemList items; CFileItem item(*m_movieItem->GetVideoInfoTag()); if (item.HasProperty("fanart_image")) { CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); itemCurrent->SetThumbnailImage(item.GetProperty("fanart_image").asString()); itemCurrent->SetLabel(g_localizeStrings.Get(20440)); items.Add(itemCurrent); } // ensure the fanart is unpacked m_movieItem->GetVideoInfoTag()->m_fanart.Unpack(); // Grab the thumbnails from the web for (unsigned int i = 0; i < m_movieItem->GetVideoInfoTag()->m_fanart.GetNumFanarts(); i++) { CStdString strItemPath; strItemPath.Format("fanart://Remote%i",i); CFileItemPtr item(new CFileItem(strItemPath, false)); CStdString thumb = m_movieItem->GetVideoInfoTag()->m_fanart.GetPreviewURL(i); item->SetThumbnailImage(CTextureCache::GetWrappedThumbURL(thumb)); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20441)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } CStdString strLocal = item.GetLocalFanart(); if (!strLocal.IsEmpty()) { CFileItemPtr itemLocal(new CFileItem("fanart://Local",false)); itemLocal->SetThumbnailImage(strLocal); itemLocal->SetLabel(g_localizeStrings.Get(20438)); // TODO: Do we need to clear the cached image? CTextureCache::Get().ClearCachedImage(strLocal); items.Add(itemLocal); } else { CFileItemPtr itemNone(new CFileItem("fanart://None", false)); itemNone->SetIconImage("DefaultVideo.png"); itemNone->SetLabel(g_localizeStrings.Get(20439)); items.Add(itemNone); } CStdString result; VECSOURCES sources(g_settings.m_videoSources); g_mediaManager.GetLocalDrives(sources); bool flip=false; if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445) || result.Equals("fanart://Current")) return; // user cancelled if (result.Equals("fanart://Local")) result = strLocal; if (result.Left(15) == "fanart://Remote") { int iFanart = atoi(result.Mid(15).c_str()); // set new primary fanart, and update our database accordingly m_movieItem->GetVideoInfoTag()->m_fanart.SetPrimaryFanart(iFanart); CVideoDatabase db; if (db.Open()) { db.UpdateFanart(*m_movieItem, (VIDEODB_CONTENT_TYPE)m_movieItem->GetVideoContentType()); db.Close(); } result = m_movieItem->GetVideoInfoTag()->m_fanart.GetImageURL(); } else if (result.Equals("fanart://None") || !CFile::Exists(result)) result.clear(); // set the fanart image if (flip && !result.IsEmpty()) result = CTextureCache::GetWrappedImageURL(result, "", "flipped"); CVideoDatabase db; if (db.Open()) { db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, "fanart", result); db.Close(); } CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show if (!result.IsEmpty()) m_movieItem->SetProperty("fanart_image", result); else m_movieItem->ClearProperty("fanart_image"); m_hasUpdatedThumb = true; // Update our screen Update(); }
void CExternalPlayer::Process() { SetName("CExternalPlayer"); CStdString mainFile = m_launchFilename; CStdString archiveContent = ""; if (m_args.find("{0}") == std::string::npos) { // Unwind archive names CURL url(m_launchFilename); CStdString protocol = url.GetProtocol(); if (protocol == "zip" || protocol == "rar"/* || protocol == "iso9660" ??*/) { mainFile = url.GetHostName(); archiveContent = url.GetFileName(); } if (protocol == "musicdb") mainFile = CFileMusicDatabase::TranslateUrl(url); } if (m_filenameReplacers.size() > 0) { for (unsigned int i = 0; i < m_filenameReplacers.size(); i++) { std::vector<CStdString> vecSplit; StringUtils::SplitString(m_filenameReplacers[i], " , ", vecSplit); // something is wrong, go to next substitution if (vecSplit.size() != 4) continue; CStdString strMatch = vecSplit[0]; strMatch.Replace(",,",","); bool bCaseless = vecSplit[3].Find('i') > -1; CRegExp regExp(bCaseless); if (!regExp.RegComp(strMatch.c_str())) { // invalid regexp - complain in logs CLog::Log(LOGERROR, "%s: Invalid RegExp:'%s'", __FUNCTION__, strMatch.c_str()); continue; } if (regExp.RegFind(mainFile) > -1) { CStdString strPat = vecSplit[1]; strPat.Replace(",,",","); if (!regExp.RegComp(strPat.c_str())) { // invalid regexp - complain in logs CLog::Log(LOGERROR, "%s: Invalid RegExp:'%s'", __FUNCTION__, strPat.c_str()); continue; } CStdString strRep = vecSplit[2]; strRep.Replace(",,",","); bool bGlobal = vecSplit[3].Find('g') > -1; bool bStop = vecSplit[3].Find('s') > -1; int iStart = 0; while ((iStart = regExp.RegFind(mainFile, iStart)) > -1) { int iLength = regExp.GetFindLen(); mainFile = mainFile.Left(iStart) + regExp.GetReplaceString(strRep.c_str()) + mainFile.Mid(iStart+iLength); if (!bGlobal) break; } CLog::Log(LOGINFO, "%s: File matched:'%s' (RE='%s',Rep='%s') new filename:'%s'.", __FUNCTION__, strMatch.c_str(), strPat.c_str(), strRep.c_str(), mainFile.c_str()); if (bStop) break; } } } CLog::Log(LOGNOTICE, "%s: Player : %s", __FUNCTION__, m_filename.c_str()); CLog::Log(LOGNOTICE, "%s: File : %s", __FUNCTION__, mainFile.c_str()); CLog::Log(LOGNOTICE, "%s: Content: %s", __FUNCTION__, archiveContent.c_str()); CLog::Log(LOGNOTICE, "%s: Args : %s", __FUNCTION__, m_args.c_str()); CLog::Log(LOGNOTICE, "%s: Start", __FUNCTION__); // make sure we surround the arguments with quotes where necessary CStdString strFName; CStdString strFArgs; #if defined(_WIN32) // W32 batch-file handline if (m_filename.Right(4) == ".bat" || m_filename.Right(4) == ".cmd") { // MSDN says you just need to do this, but cmd's handing of spaces and // quotes is soo broken it seems to work much better if you just omit // lpApplicationName and enclose the module in lpCommandLine in quotes //strFName = "cmd.exe"; //strFArgs = "/c "; } else #endif strFName = m_filename; strFArgs.append("\""); strFArgs.append(m_filename); strFArgs.append("\" "); strFArgs.append(m_args); int nReplaced = strFArgs.Replace("{0}", mainFile); if (!nReplaced) nReplaced = strFArgs.Replace("{1}", mainFile) + strFArgs.Replace("{2}", archiveContent); if (!nReplaced) { strFArgs.append(" \""); strFArgs.append(mainFile); strFArgs.append("\""); } int iActiveDevice = g_audioContext.GetActiveDevice(); if (iActiveDevice != CAudioContext::NONE) { CLog::Log(LOGNOTICE, "%s: Releasing audio device %d", __FUNCTION__, iActiveDevice); g_audioContext.SetActiveDevice(CAudioContext::NONE); } int iActiveDevice2 = g_audioContext2.GetActiveDevice(); if (iActiveDevice2 != CAudioContext::NONE) { CLog::Log(LOGNOTICE, "%s: Releasing 2nd audio device %d", __FUNCTION__, iActiveDevice2); g_audioContext2.SetActiveDevice(CAudioContext::NONE); } #if defined(_WIN32) if (m_warpcursor) { GetCursorPos(&m_ptCursorpos); int x = 0; int y = 0; switch (m_warpcursor) { case WARP_BOTTOM_RIGHT: x = GetSystemMetrics(SM_CXSCREEN); case WARP_BOTTOM_LEFT: y = GetSystemMetrics(SM_CYSCREEN); break; case WARP_TOP_RIGHT: x = GetSystemMetrics(SM_CXSCREEN); break; case WARP_CENTER: x = GetSystemMetrics(SM_CXSCREEN) / 2; y = GetSystemMetrics(SM_CYSCREEN) / 2; break; } CLog::Log(LOGNOTICE, "%s: Warping cursor to (%d,%d)", __FUNCTION__, x, y); SetCursorPos(x,y); } LONG currentStyle = GetWindowLong(g_hWnd, GWL_EXSTYLE); #endif if (m_hidexbmc && !m_islauncher) { CLog::Log(LOGNOTICE, "%s: Hiding XBMC window", __FUNCTION__); g_Windowing.Hide(); } #if defined(_WIN32) else if (currentStyle & WS_EX_TOPMOST) { CLog::Log(LOGNOTICE, "%s: Lowering XBMC window", __FUNCTION__); SetWindowPos(g_hWnd,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW); } CLog::Log(LOGDEBUG, "%s: Unlocking foreground window", __FUNCTION__); LockSetForegroundWindow(LSFW_UNLOCK); #endif m_playbackStartTime = CTimeUtils::GetTimeMS(); BOOL ret = TRUE; #if defined(_WIN32) ret = ExecuteAppW32(strFName.c_str(),strFArgs.c_str()); #elif defined(_LINUX) ret = ExecuteAppLinux(strFArgs.c_str()); #endif int64_t elapsedMillis = CTimeUtils::GetTimeMS() - m_playbackStartTime; if (ret && (m_islauncher || elapsedMillis < LAUNCHER_PROCESS_TIME)) { if (m_hidexbmc) { CLog::Log(LOGNOTICE, "%s: XBMC cannot stay hidden for a launcher process", __FUNCTION__); g_Windowing.Show(false); } { CSingleLock lock(g_graphicsContext); m_dialog = (CGUIDialogOK *)g_windowManager.GetWindow(WINDOW_DIALOG_OK); m_dialog->SetHeading(23100); m_dialog->SetLine(1, 23104); m_dialog->SetLine(2, 23105); m_dialog->SetLine(3, 23106); } if (!m_bAbortRequest) m_dialog->DoModal(); } m_bIsPlaying = false; CLog::Log(LOGNOTICE, "%s: Stop", __FUNCTION__); #if defined(_WIN32) g_Windowing.Restore(); if (currentStyle & WS_EX_TOPMOST) { CLog::Log(LOGNOTICE, "%s: Showing XBMC window TOPMOST", __FUNCTION__); SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); SetForegroundWindow(g_hWnd); } else #endif { CLog::Log(LOGNOTICE, "%s: Showing XBMC window", __FUNCTION__); g_Windowing.Show(); } #if defined(_WIN32) if (m_warpcursor) { m_xPos = 0; m_yPos = 0; if (&m_ptCursorpos != 0) { m_xPos = (m_ptCursorpos.x); m_yPos = (m_ptCursorpos.y); } CLog::Log(LOGNOTICE, "%s: Restoring cursor to (%d,%d)", __FUNCTION__, m_xPos, m_yPos); SetCursorPos(m_xPos,m_yPos); } #endif // We don't want to come back to an active screensaver g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); if (iActiveDevice != CAudioContext::NONE) { CLog::Log(LOGNOTICE, "%s: Reclaiming audio device %d", __FUNCTION__, iActiveDevice); g_audioContext.SetActiveDevice(iActiveDevice); } if (iActiveDevice2 != CAudioContext::NONE) { CLog::Log(LOGNOTICE, "%s: Reclaiming 2nd audio device %d", __FUNCTION__, iActiveDevice2); g_audioContext2.SetActiveDevice(iActiveDevice2); } if (!ret || (m_playOneStackItem && g_application.CurrentFileItem().IsStack())) m_callback.OnPlayBackStopped(); else m_callback.OnPlayBackEnded(); }
BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength) { switch (nID) { case 2: if (!nDataLength) { unsigned char buffer[2]; buffer[0] = m_nServerState / 256; buffer[1] = m_nServerState % 256; pAdminSocket->SendCommand(1, 2, buffer, 2); } else if (nDataLength == 2) { ToggleActive(*pData * 256 + pData[1]); unsigned char buffer[2]; buffer[0] = m_nServerState / 256; buffer[1] = m_nServerState % 256; pAdminSocket->SendCommand(1, 2, buffer, 2); } else { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1); } break; case 3: if (!nDataLength) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1); } else if (*pData == USERCONTROL_GETLIST) { int len = 4; std::map<int, t_connectiondata>::iterator iter; for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) { const t_connectiondata& data = iter->second; auto ip = ConvToNetwork(data.ip); auto user = ConvToNetwork(data.user); len += 4 + ip.size() + 2 + 4 + user.size() + 2 + 1; if (data.transferMode) { auto physicalFile = ConvToNetwork(data.physicalFile); auto logicalFile = ConvToNetwork(data.logicalFile); len += 2 + physicalFile.size() + 2 + logicalFile.size(); if (data.currentOffset != 0) { len += 8; } if (data.totalSize != -1) { len += 8; } } } unsigned char *buffer = new unsigned char[len]; buffer[0] = USERCONTROL_GETLIST; buffer[1] = ((m_UsersList.size() / 256) / 256) & 0xff; buffer[2] = (m_UsersList.size() / 256) & 0xff; buffer[3] = m_UsersList.size() % 256; unsigned char *p = buffer + 4; for (iter = m_UsersList.begin(); iter != m_UsersList.end(); ++iter) { const t_connectiondata& data = iter->second; auto ip = ConvToNetwork(data.ip); auto user = ConvToNetwork(data.user); memcpy(p, &data.userid, 4); p += 4; *p++ = (ip.size() / 256) & 0xff; *p++ = ip.size() % 256; memcpy(p, ip.c_str(), ip.size()); p += ip.size(); memcpy(p, &data.port, 4); p += 4; *p++ = (user.size() / 256) & 0xff; *p++ = user.size() % 256; memcpy(p, user.c_str(), user.size()); p += user.size(); *p = data.transferMode; if (data.transferMode) { // Bit 5 and 6 indicate presence of currentOffset and totalSize. if (data.currentOffset != 0) { *p |= 0x20; } if (data.totalSize != -1) { *p |= 0x40; } p++; auto physicalFile = ConvToNetwork(data.physicalFile); *p++ = (physicalFile.size() / 256) & 0xff; *p++ = physicalFile.size() % 256; memcpy(p, physicalFile.c_str(), physicalFile.size()); p += physicalFile.size(); auto logicalFile = ConvToNetwork(data.logicalFile); *p++ = (logicalFile.size() / 256) & 0xff; *p++ = logicalFile.size() % 256; memcpy(p, logicalFile.c_str(), logicalFile.size()); p += logicalFile.size(); if (data.currentOffset != 0) { memcpy(p, &data.currentOffset, 8); p += 8; } if (data.totalSize != -1) { memcpy(p, &data.totalSize, 8); p += 8; } } else { p++; } } m_pAdminInterface->SendCommand(1, 3, buffer, len); delete [] buffer; } else if (*pData == USERCONTROL_KICK || *pData == USERCONTROL_BAN) { if (nDataLength != 5) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else { int nUserID; memcpy(&nUserID, pData+1, 4); std::map<int, t_connectiondata>::iterator iter = m_UsersList.find(nUserID); if (iter!=m_UsersList.end()) { if (*pData == USERCONTROL_BAN) { // Get the list of IP filter rules. CStdString ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED); if (ips != _T("")) ips += _T(" "); int pos = ips.Find(' '); while (pos != -1) { CStdString blockedIP = ips.Left(pos); ips = ips.Mid(pos + 1); pos = ips.Find(' '); if (MatchesFilter(blockedIP, iter->second.ip)) break; } if (pos == -1) { ips = m_pOptions->GetOption(OPTION_IPFILTER_DISALLOWED); if (ips != _T("")) ips += _T(" "); ips += iter->second.ip; m_pOptions->SetOption(OPTION_IPFILTER_DISALLOWED, ips); } } t_controlmessage *msg = new t_controlmessage; msg->command = USERCONTROL_KICK; msg->socketid = nUserID; iter->second.pThread->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_CONTROL, (LPARAM)msg); char buffer[2]; buffer[0] = *pData; buffer[1] = 0; pAdminSocket->SendCommand(1, 3, &buffer, 2); } else { char buffer[2]; buffer[0] = USERCONTROL_KICK; buffer[1] = 1; pAdminSocket->SendCommand(1, 3, &buffer, 2); } } } else { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data", strlen("\001Protocol error: Invalid data") + 1); } break; case 5: if (!nDataLength) { unsigned char *pBuffer = NULL; DWORD nBufferLength = 0; if (m_pOptions && m_pOptions->GetAsCommand(&pBuffer, &nBufferLength)) { pAdminSocket->SendCommand(1, 5, pBuffer, nBufferLength); delete [] pBuffer; } } else if (m_pOptions) { if (nDataLength < 2) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length") + 1); } else { CStdString const listenPorts = m_pOptions->GetOption(OPTION_SERVERPORT); CStdString const listenPortsSsl = m_pOptions->GetOption(OPTION_TLSPORTS); bool const enableSsl = m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0; CStdString const ipBindings = m_pOptions->GetOption(OPTION_IPBINDINGS); int const nAdminListenPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT); CStdString const adminIpBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS); CStdString peerIP; UINT port = 0; bool bLocal = false; if (!pAdminSocket->GetPeerName(peerIP, port)) { return FALSE; } else { bLocal = IsLocalhost(peerIP); } if (!m_pOptions->ParseOptionsCommand(pData, nDataLength, bLocal)) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import settings.", strlen("\001Protocol error: Invalid data, could not import settings.")+1); char buffer = 1; pAdminSocket->SendCommand(1, 5, &buffer, 1); break; } char buffer = 0; pAdminSocket->SendCommand(1, 5, &buffer, 1); unsigned int threadnum = (int)m_pOptions->GetOptionVal(OPTION_THREADNUM); if (m_nServerState & STATE_ONLINE) { if (threadnum > m_ThreadArray.size()) { while (threadnum > m_ThreadArray.size()) { int index = GetNextThreadNotificationID(); CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index); m_ThreadNotificationIDs[index] = pThread; if (pThread->Create(THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED)) { pThread->ResumeThread(); m_ThreadArray.push_back(pThread); } } CStdString str; str.Format(_T("Number of threads increased to %d."), threadnum); ShowStatus(str, 0); } else if (threadnum < m_ThreadArray.size()) { CStdString str; str.Format(_T("Decreasing number of threads to %d."), threadnum); ShowStatus(str, 0); unsigned int i = 0; std::vector<CServerThread *> newList; for (auto iter = m_ThreadArray.begin(); iter != m_ThreadArray.end(); iter++, i++) { if (i >= threadnum) { (*iter)->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_GOOFFLINE, 2); m_ClosedThreads.push_back(*iter); } else newList.push_back(*iter); } m_ThreadArray.swap(newList); } } if (listenPorts != m_pOptions->GetOption(OPTION_SERVERPORT) || enableSsl != (m_pOptions->GetOptionVal(OPTION_ENABLETLS) != 0) || (m_pOptions->GetOptionVal(OPTION_ENABLETLS) && listenPortsSsl != m_pOptions->GetOption(OPTION_TLSPORTS)) || ipBindings != m_pOptions->GetOption(OPTION_IPBINDINGS)) { if (!m_ListenSocketList.empty()) { ShowStatus(_T("Closing all listening sockets"), 0); for (std::list<CListenSocket*>::iterator listIter = m_ListenSocketList.begin(); listIter != m_ListenSocketList.end(); ++listIter) { (*listIter)->Close(); delete *listIter; } m_ListenSocketList.clear(); if (!CreateListenSocket()) { ShowStatus(_T("Failed to create a listen socket on any of the specified ports. Server is not online!"), 1); m_nServerState &= ~STATE_ONLINE; } else { ShowStatus(_T("Listen socket port changed"), 0); if (!(m_nServerState & STATE_MASK_GOOFFLINE)) m_nServerState |= STATE_ONLINE; } SendState(); } } if (nAdminListenPort != m_pOptions->GetOptionVal(OPTION_ADMINPORT) || adminIpBindings != m_pOptions->GetOption(OPTION_ADMINIPBINDINGS)) { CreateAdminListenSocket(); } VerifyTlsSettings(pAdminSocket); VerifyPassiveModeSettings(pAdminSocket); } } break; case 6: if (!nDataLength) { unsigned char *pBuffer = NULL; DWORD nBufferLength = 0; CPermissions permissions = CPermissions(std::function<void()>()); permissions.GetAsCommand(&pBuffer, &nBufferLength); pAdminSocket->SendCommand(1, 6, pBuffer, nBufferLength); delete [] pBuffer; } else { if (nDataLength < 2) pAdminSocket->SendCommand(1, 1, "\001Protocol error: Unexpected data length", strlen("\001Protocol error: Unexpected data length")+1); else { CPermissions permissions = CPermissions(std::function<void()>()); if (!permissions.ParseUsersCommand(pData, nDataLength)) { pAdminSocket->SendCommand(1, 1, "\001Protocol error: Invalid data, could not import account settings.", strlen("\001Protocol error: Invalid data, could not import account settings.")+1); char buffer = 1; pAdminSocket->SendCommand(1, 6, &buffer, 1); break; } char buffer = 0; pAdminSocket->SendCommand(1, 6, &buffer, 1); } } break; case 8: pAdminSocket->SendCommand(1, 8, NULL, 0); break; default: { CStdStringA str; str.Format("\001Protocol error: Unknown command (%d).", nID); pAdminSocket->SendCommand(1, 1, str.c_str(), str.GetLength()); } break; } return TRUE; }
BOOL CServer::CreateAdminListenSocket() { if (!m_pOptions) return FALSE; m_AdminListenSocketList.clear(); CStdString ipBindings = m_pOptions->GetOption(OPTION_ADMINIPBINDINGS); int nAdminPort = (int)m_pOptions->GetOptionVal(OPTION_ADMINPORT); if (!DoCreateAdminListenSocket(nAdminPort, (ipBindings != _T("*")) ? _T("127.0.0.1") : NULL, AF_INET)) { int p = DoCreateAdminListenSocket(0, _T("127.0.0.1"), AF_INET); if (!p) { CStdString str; str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv4, the IPv4 admin interface has been disabled."), nAdminPort); ShowStatus(str, 1); } else { CStdString str; str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv4, for this session the IPv4 admin interface is available on port %u."), p); ShowStatus(str, 1); } } if (!m_pOptions->GetOptionVal(OPTION_DISABLE_IPV6)) { if (!DoCreateAdminListenSocket(nAdminPort, (ipBindings != _T("*")) ? _T("::1") : NULL, AF_INET6)) { int p = DoCreateAdminListenSocket(0, _T("::1"), AF_INET6); if (!p) { CStdString str; str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv6, the IPv6 admin interface has been disabled."), nAdminPort); ShowStatus(str, 1); } else { CStdString str; str.Format(_T("Failed to create listen socket for admin interface on port %d for IPv6, for this session the IPv6 admin interface is available on port %u."), p); ShowStatus(str, 1); } } } if (ipBindings != _T("*")) { if (ipBindings != _T("")) ipBindings += _T(" "); while (ipBindings != _T("")) { int pos = ipBindings.Find(' '); if (pos == -1) break; CStdString ip = ipBindings.Left(pos); ipBindings = ipBindings.Mid(pos+1); auto pAdminListenSocket = make_unique<CAdminListenSocket>(*m_pAdminInterface); int family; if (ip.Find(':') != -1) family = AF_INET6; else family = AF_INET; if (!pAdminListenSocket->Create(nAdminPort, SOCK_STREAM, FD_ACCEPT, ip, family) || !pAdminListenSocket->Listen(16)) { CStdString str; str.Format(_T("Failed to create listen socket for admin interface on port %d for address %s"), nAdminPort, ip); ShowStatus(str, 1); } else m_AdminListenSocketList.push_back(std::move(pAdminListenSocket)); } } return !m_AdminListenSocketList.empty(); }
void CGUIDialogVideoInfo::OnGetArt() { map<string, string> currentArt; string type = ChooseArtType(*m_movieItem, currentArt); if (type.empty()) return; // cancelled if (type == "fanart") { // TODO: this can be removed once these are unified. OnGetFanart(); return; } CFileItemList items; // Current thumb if (m_movieItem->HasArt(type)) { CFileItemPtr item(new CFileItem("thumb://Current", false)); item->SetArt("thumb", m_movieItem->GetArt(type)); item->SetLabel(g_localizeStrings.Get(13512)); items.Add(item); } else if ((type == "poster" || type == "banner") && currentArt.find("thumb") != currentArt.end()) { // add the 'thumb' type in CFileItemPtr item(new CFileItem("thumb://Thumb", false)); item->SetArt("thumb", currentArt["thumb"]); item->SetLabel(g_localizeStrings.Get(13512)); items.Add(item); } // Grab the thumbnails from the web vector<CStdString> thumbs; int season = (m_movieItem->GetVideoInfoTag()->m_type == "season") ? m_movieItem->GetVideoInfoTag()->m_iSeason : -1; m_movieItem->GetVideoInfoTag()->m_strPictureURL.GetThumbURLs(thumbs, type, season); for (unsigned int i = 0; i < thumbs.size(); ++i) { CStdString strItemPath; strItemPath.Format("thumb://Remote%i", i); CFileItemPtr item(new CFileItem(strItemPath, false)); item->SetArt("thumb", thumbs[i]); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(13513)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } CStdString localThumb = CVideoThumbLoader::GetLocalArt(*m_movieItem, type); if (!localThumb.empty()) { CFileItemPtr item(new CFileItem("thumb://Local", false)); item->SetArt("thumb", localThumb); item->SetLabel(g_localizeStrings.Get(13514)); items.Add(item); } else { // no local thumb exists, so we are just using the IMDb thumb or cached thumb // which is probably the IMDb thumb. These could be wrong, so allow the user // to delete the incorrect thumb CFileItemPtr item(new CFileItem("thumb://None", false)); item->SetIconImage("DefaultVideo.png"); item->SetLabel(g_localizeStrings.Get(13515)); items.Add(item); } CStdString result; VECSOURCES sources(g_settings.m_videoSources); g_mediaManager.GetLocalDrives(sources); if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(13511), result)) return; // user cancelled if (result == "thumb://Current") return; // user chose the one they have CStdString newThumb; if (result.Left(14) == "thumb://Remote") { int number = atoi(result.Mid(14)); newThumb = thumbs[number]; } else if (result == "thumb://Thumb") newThumb = currentArt["thumb"]; else if (result == "thumb://Local") newThumb = localThumb; else if (CFile::Exists(result)) newThumb = result; else // none newThumb = "-"; // force local thumbs to be ignored // update thumb in the database CVideoDatabase db; if (db.Open()) { db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, type, newThumb); db.Close(); } CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show m_movieItem->SetArt(type, newThumb); if (m_movieItem->HasProperty("set_folder_thumb")) { // have a folder thumb to set as well VIDEO::CVideoInfoScanner::ApplyThumbToFolder(m_movieItem->GetProperty("set_folder_thumb").asString(), newThumb); } m_hasUpdatedThumb = true; // Update our screen Update(); }
bool PVRIptvData::LoadPlayList(void) { if (m_strM3uUrl.IsEmpty()) { XBMC->Log(LOG_NOTICE, "Playlist file path is not configured. Channels not loaded."); return false; } CStdString strPlaylistContent; if (!GetCachedFileContents(M3U_FILE_NAME, m_strM3uUrl, strPlaylistContent, g_bCacheM3U)) { XBMC->Log(LOG_ERROR, "Unable to load playlist file '%s': file is missing or empty.", m_strM3uUrl.c_str()); return false; } std::stringstream stream(strPlaylistContent); /* load channels */ bool bFirst = true; int iChannelIndex = 0; int iUniqueGroupId = 0; int iCurrentGroupId = 0; int iChannelNum = g_iStartNumber; int iEPGTimeShift = 0; PVRIptvChannel tmpChannel; tmpChannel.strTvgId = ""; tmpChannel.strChannelName = ""; tmpChannel.strTvgName = ""; tmpChannel.strTvgLogo = ""; tmpChannel.iTvgShift = 0; char szLine[1024]; while(stream.getline(szLine, 1024)) { CStdString strLine = ""; strLine.append(szLine); strLine.TrimRight(" \t\r\n"); strLine.TrimLeft(" \t"); if (strLine.IsEmpty()) { continue; } if (bFirst) { bFirst = false; if (strLine.Left(3) == "\xEF\xBB\xBF") { strLine.Delete(0, 3); } if (strLine.Left((int)strlen(M3U_START_MARKER)) == M3U_START_MARKER) { double fTvgShift = atof(ReadMarkerValue(strLine, TVG_INFO_SHIFT_MARKER)); iEPGTimeShift = (int) (fTvgShift * 3600.0); continue; } else { break; } } if (strLine.Left((int)strlen(M3U_INFO_MARKER)) == M3U_INFO_MARKER) { bool bRadio = false; double fTvgShift = 0; CStdString strChnlName = ""; CStdString strTvgId = ""; CStdString strTvgName = ""; CStdString strTvgLogo = ""; CStdString strGroupName = ""; CStdString strRadio = ""; // parse line int iColon = (int)strLine.Find(':'); int iComma = (int)strLine.ReverseFind(','); if (iColon >= 0 && iComma >= 0 && iComma > iColon) { // parse name iComma++; strChnlName = strLine.Right((int)strLine.size() - iComma).Trim(); tmpChannel.strChannelName = XBMC->UnknownToUTF8(strChnlName); // parse info CStdString strInfoLine = strLine.Mid(++iColon, --iComma - iColon); strTvgId = ReadMarkerValue(strInfoLine, TVG_INFO_ID_MARKER); strTvgName = ReadMarkerValue(strInfoLine, TVG_INFO_NAME_MARKER); strTvgLogo = ReadMarkerValue(strInfoLine, TVG_INFO_LOGO_MARKER); strGroupName = ReadMarkerValue(strInfoLine, GROUP_NAME_MARKER); strRadio = ReadMarkerValue(strInfoLine, RADIO_MARKER); fTvgShift = atof(ReadMarkerValue(strInfoLine, TVG_INFO_SHIFT_MARKER)); if (strTvgId.IsEmpty()) { char buff[255]; sprintf(buff, "%d", atoi(strInfoLine)); strTvgId.append(buff); } if (strTvgLogo.IsEmpty()) { strTvgLogo = strChnlName; } bRadio = !strRadio.CompareNoCase("true"); tmpChannel.strTvgId = strTvgId; tmpChannel.strTvgName = XBMC->UnknownToUTF8(strTvgName); tmpChannel.strTvgLogo = XBMC->UnknownToUTF8(strTvgLogo); tmpChannel.iTvgShift = (int)(fTvgShift * 3600.0); tmpChannel.bRadio = bRadio; if (tmpChannel.iTvgShift == 0 && iEPGTimeShift != 0) { tmpChannel.iTvgShift = iEPGTimeShift; } if (!strGroupName.IsEmpty()) { strGroupName = XBMC->UnknownToUTF8(strGroupName); PVRIptvChannelGroup * pGroup; if ((pGroup = FindGroup(strGroupName)) == NULL) { PVRIptvChannelGroup group; group.strGroupName = strGroupName; group.iGroupId = ++iUniqueGroupId; group.bRadio = bRadio; m_groups.push_back(group); iCurrentGroupId = iUniqueGroupId; } else { iCurrentGroupId = pGroup->iGroupId; } } } } else if (strLine[0] != '#') { PVRIptvChannel channel; channel.iUniqueId = GetChannelId(tmpChannel.strChannelName.c_str(), strLine); channel.iChannelNumber = iChannelNum++; channel.strTvgId = tmpChannel.strTvgId; channel.strChannelName = tmpChannel.strChannelName; channel.strTvgName = tmpChannel.strTvgName; channel.strTvgLogo = tmpChannel.strTvgLogo; channel.iTvgShift = tmpChannel.iTvgShift; channel.bRadio = tmpChannel.bRadio; channel.strStreamURL = strLine; channel.iEncryptionSystem = 0; if (iCurrentGroupId > 0) { channel.bRadio = m_groups.at(iCurrentGroupId - 1).bRadio; m_groups.at(iCurrentGroupId - 1).members.push_back(iChannelIndex); } m_channels.push_back(channel); iChannelIndex++; tmpChannel.strTvgId = ""; tmpChannel.strChannelName = ""; tmpChannel.strTvgName = ""; tmpChannel.strTvgLogo = ""; tmpChannel.iTvgShift = 0; tmpChannel.bRadio = false; } } stream.clear(); if (m_channels.size() == 0) { XBMC->Log(LOG_ERROR, "Unable to load channels from file '%s': file is corrupted.", m_strM3uUrl.c_str()); return false; } ApplyChannelsLogos(); XBMC->Log(LOG_NOTICE, "Loaded %d channels.", m_channels.size()); return true; }
CStdString GetIPV6ShortForm(const CStdString& ip) { // This could be optimized a lot. // First get the long form in a well-known format CStdString l = GetIPV6LongForm(ip); if (l.IsEmpty()) return CStdString(); LPCTSTR p = l; TCHAR outbuf[42]; *outbuf = ':'; TCHAR* out = outbuf + 1; bool segmentStart = true; bool readLeadingZero = false; while (*p) { switch (*p) { case ':': if (readLeadingZero) *(out++) = '0'; *out++ = ':'; readLeadingZero = false; segmentStart = true; break; case '0': if (segmentStart) readLeadingZero = true; else { *out++ = '0'; readLeadingZero = false; } break; default: readLeadingZero = false; segmentStart = false; *out++ = *p; break; } ++p; } *(out++) = ':'; *out = 0; // Replace longest run of consecutive zeroes CStdString shortIp(outbuf); CStdString s = _T(":0:0:0:0:0:0:0:0:"); while (s.GetLength() > 2) { int pos = shortIp.Find(s); if (pos != -1) { shortIp = shortIp.Left( pos + 1 ) + shortIp.Mid(pos + s.GetLength() -1); break; } s = s.Mid(2); } shortIp.Replace(_T(":::"), _T("::")); if (shortIp[0] == ':' && shortIp[1] != ':') shortIp = shortIp.Mid(1); if (shortIp.GetLength() >= 2 && shortIp[shortIp.GetLength()-1] == ':' && shortIp[shortIp.GetLength()-2] != ':') shortIp = shortIp.Left(shortIp.GetLength()-1); return shortIp; }
bool IsRoutableAddress(const CStdString& address) { if (address.Find(_T(":")) != -1) { CStdString long_address = GetIPV6LongForm(address); if (long_address.IsEmpty()) return false; if (long_address[0] == '0') { // ::/128 if (long_address == _T("0000:0000:0000:0000:0000:0000:0000:0000")) return false; // ::1/128 if (long_address == _T("0000:0000:0000:0000:0000:0000:0000:0001")) return false; if (long_address.Left(30) == _T("0000:0000:0000:0000:0000:ffff:")) { // IPv4 mapped CStdString ipv4; ipv4.Format(_T("%d.%d.%d.%d"), DigitHexToDecNum(long_address[30]) * 16 + DigitHexToDecNum(long_address[31]), DigitHexToDecNum(long_address[32]) * 16 + DigitHexToDecNum(long_address[33]), DigitHexToDecNum(long_address[35]) * 16 + DigitHexToDecNum(long_address[36]), DigitHexToDecNum(long_address[37]) * 16 + DigitHexToDecNum(long_address[38])); return IsRoutableAddress(ipv4); } return true; } if (long_address[0] == 'f') { if (long_address[1] == 'e') { // fe80::/10 (link local) const TCHAR& c = long_address[2]; int v; if (c >= 'a') v = c - 'a' + 10; else v = c - '0'; if ((v & 0xc) == 0x8) return false; return true; } else if (long_address[1] == 'c' || long_address[1] == 'd') { // fc00::/7 (site local) return false; } } return true; } else { // Assumes address is already a valid IP address if (address.Left(3) == _T("127") || address.Left(3) == _T("10.") || address.Left(7) == _T("192.168") || address.Left(7) == _T("169.254")) return false; if (address.Left(3) == _T("172")) { CStdString middle = address.Mid(4); int pos = address.Find(_T(".")); if (pos == -1) return false; int part = _ttoi(middle.Left(pos)); if (part >= 16 && part <= 31) return false; } return true; } }
CStdString GetIPV6LongForm(CStdString short_address) { if (short_address[0] == '[') { if (short_address[short_address.GetLength() - 1] != ']') return _T(""); short_address = short_address.Mid(1, short_address.GetLength() - 2); } short_address.MakeLower(); TCHAR buffer[40] = { '0', '0', '0', '0', ':', '0', '0', '0', '0', ':', '0', '0', '0', '0', ':', '0', '0', '0', '0', ':', '0', '0', '0', '0', ':', '0', '0', '0', '0', ':', '0', '0', '0', '0', ':', '0', '0', '0', '0', 0 }; TCHAR* out = buffer; const unsigned int len = short_address.GetLength(); if (len > 39) return _T(""); // First part, before possible :: unsigned int i = 0; unsigned int grouplength = 0; for (i = 0; i < len + 1; i++) { const TCHAR& c = short_address[i]; if (c == ':' || !c) { if (!grouplength) { // Empty group length, not valid if (!c || short_address[i + 1] != ':') return _T(""); i++; break; } out += 4 - grouplength; for (unsigned int j = grouplength; j > 0; j--) *out++ = short_address[i - j]; // End of string... if (!c) { if (!*out) // ...on time return buffer; else // ...premature return _T(""); } else if (!*out) { // Too long return _T(""); } out++; grouplength = 0; if (short_address[i + 1] == ':') { i++; break; } continue; } else if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) { // Invalid character return _T(""); } // Too long group if (++grouplength > 4) return _T(""); } // Second half after :: TCHAR* end_first = out; out = &buffer[38]; unsigned int stop = i; for (i = len - 1; i > stop; i--) { if (out < end_first) { // Too long return _T(""); } const TCHAR& c = short_address[i]; if (c == ':') { if (!grouplength) { // Empty group length, not valid return _T(""); } out -= 5 - grouplength; grouplength = 0; continue; } else if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) { // Invalid character return _T(""); } // Too long group if (++grouplength > 4) return _T(""); *out-- = c; } if (!grouplength && stop + 1 < len) { // Empty group length, not valid return _T(""); } out -= 5 - grouplength; out += 2; int diff = out - end_first; if (diff < 0 || diff % 5) return _T(""); return buffer; }
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; int pos1 = work.size(); int pos2; int len = 0; for (size_t i = 0; i < sizeof(infoformatmap) / sizeof(infoformat); i++) { pos2 = work.Find(infoformatmap[i].str); if (pos2 != (int)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.Left(pos1), "")); pos2 = StringUtils::FindEndBracket(work, '[', ']', pos1 + len); if (pos2 > pos1) { // decipher the block CStdString block = work.Mid(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.Mid(pos2 + 1); } else { CLog::Log(LOGERROR, "Error parsing label - missing ']' in \"%s\"", label.c_str()); return; } } } while (format != NONE); if (!work.IsEmpty()) m_info.push_back(CInfoPortion(0, work, "")); }
int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader, CStdString& responseBody, CStdString& reverseHeader, CStdString& reverseBody, CStdString& sessionId) { CStdString method = m_httpParser->getMethod(); CStdString uri = m_httpParser->getUri(); CStdString queryString = m_httpParser->getQueryString(); CStdString body = m_httpParser->getBody(); CStdString contentType = m_httpParser->getValue("content-type"); sessionId = m_httpParser->getValue("x-apple-session-id"); CStdString authorization = m_httpParser->getValue("authorization"); int status = AIRPLAY_STATUS_OK; bool needAuth = false; if (ServerInstance->m_usePassword && !m_bAuthenticated) { needAuth = true; } int startQs = uri.Find('?'); if (startQs != -1) { uri = uri.Left(startQs); } // This is the socket which will be used for reverse HTTP // negotiate reverse HTTP via upgrade if (uri == "/reverse") { status = AIRPLAY_STATUS_SWITCHING_PROTOCOLS; responseHeader = "Upgrade: PTTH/1.0\r\nConnection: Upgrade\r\n"; } // The rate command is used to play/pause media. // A value argument should be supplied which indicates media should be played or paused. // 0.000000 => pause // 1.000000 => play else if (uri == "/rate") { const char* found = strstr(queryString.c_str(), "value="); int rate = found ? (int)(atof(found + strlen("value=")) + 0.5f) : 0; if (needAuth && !checkAuthorization(authorization, method, uri)) { status = AIRPLAY_STATUS_NEED_AUTH; } else if (rate == 0) { if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) { g_application.getApplicationMessenger().MediaPause(); } } else { if (g_application.m_pPlayer && g_application.m_pPlayer->IsPlaying() && g_application.m_pPlayer->IsPaused()) { g_application.getApplicationMessenger().MediaPause(); } } } // Contains a header like format in the request body which should contain a // Content-Location and optionally a Start-Position else if (uri == "/play") { CStdString location; float position = 0.0; if (needAuth && !checkAuthorization(authorization, method, uri)) { status = AIRPLAY_STATUS_NEED_AUTH; } else if (contentType == "application/x-apple-binary-plist") { if (m_pLibPlist->Load()) { m_pLibPlist->EnableDelayedUnload(false); const char* bodyChr = m_httpParser->getBody(); plist_t dict = NULL; m_pLibPlist->plist_from_bin(bodyChr, m_httpParser->getContentLength(), &dict); if (m_pLibPlist->plist_dict_get_size(dict)) { plist_t tmpNode = m_pLibPlist->plist_dict_get_item(dict, "Start-Position"); if (tmpNode) { double tmpDouble = 0; m_pLibPlist->plist_get_real_val(tmpNode, &tmpDouble); position = tmpDouble; } tmpNode = m_pLibPlist->plist_dict_get_item(dict, "Content-Location"); if (tmpNode) { char *tmpStr = NULL; m_pLibPlist->plist_get_string_val(tmpNode, &tmpStr); location=tmpStr; free(tmpStr); } if (dict) { m_pLibPlist->plist_free(dict); } } else { CLog::Log(LOGERROR, "Error parsing plist"); } m_pLibPlist->Unload(); } } else { // Get URL to play int start = body.Find("Content-Location: "); if (start == -1) return AIRPLAY_STATUS_NOT_IMPLEMENTED; start += strlen("Content-Location: "); int end = body.Find('\n', start); location = body.Mid(start, end - start); start = body.Find("Start-Position"); if (start != -1) { start += strlen("Start-Position: "); int end = body.Find('\n', start); CStdString positionStr = body.Mid(start, end - start); position = atof(positionStr.c_str()); } } if (status != AIRPLAY_STATUS_NEED_AUTH) { CFileItem fileToPlay(location, false); fileToPlay.SetProperty("StartPercent", position*100.0f); g_application.getApplicationMessenger().MediaPlay(fileToPlay); } } // Used to perform seeking (POST request) and to retrieve current player position (GET request). else if (uri == "/scrub") { if (needAuth && !checkAuthorization(authorization, method, uri)) { status = AIRPLAY_STATUS_NEED_AUTH; } else if (method == "GET") { if (g_application.m_pPlayer && g_application.m_pPlayer->GetTotalTime()) { float position = ((float) g_application.m_pPlayer->GetTime()) / 1000; responseBody.Format("duration: %d\r\nposition: %f", g_application.m_pPlayer->GetTotalTime(), position); } } else { const char* found = strstr(queryString.c_str(), "position="); if (found && g_application.m_pPlayer) { __int64 position = (__int64) (atof(found + strlen("position=")) * 1000.0); g_application.m_pPlayer->SeekTime(position); } } } // Sent when media playback should be stopped else if (uri == "/stop") { if (needAuth && !checkAuthorization(authorization, method, uri)) { status = AIRPLAY_STATUS_NEED_AUTH; } else { g_application.getApplicationMessenger().MediaStop(); } } // RAW JPEG data is contained in the request body else if (uri == "/photo") { if (needAuth && !checkAuthorization(authorization, method, uri)) { status = AIRPLAY_STATUS_NEED_AUTH; } else if (m_httpParser->getContentLength() > 0) { XFILE::CFile tmpFile; if (tmpFile.OpenForWrite("special://temp/airplay_photo.jpg", true)) { int writtenBytes=0; writtenBytes = tmpFile.Write(m_httpParser->getBody(), m_httpParser->getContentLength()); tmpFile.Close(); if (writtenBytes > 0 && (unsigned int)writtenBytes == m_httpParser->getContentLength()) { g_application.getApplicationMessenger().PictureShow("special://temp/airplay_photo.jpg"); } else { CLog::Log(LOGERROR,"AirPlayServer: Error writing tmpFile."); } } } } else if (uri == "/playback-info") { float position = 0.0f; float duration = 0.0f; float cacheDuration = 0.0f; bool playing = false; if (needAuth && !checkAuthorization(authorization, method, uri)) { status = AIRPLAY_STATUS_NEED_AUTH; } else if (g_application.m_pPlayer) { if (g_application.m_pPlayer->GetTotalTime()) { position = ((float) g_application.m_pPlayer->GetTime()) / 1000; duration = (float) g_application.m_pPlayer->GetTotalTime(); playing = g_application.m_pPlayer ? !g_application.m_pPlayer->IsPaused() : false; cacheDuration = (float) g_application.m_pPlayer->GetTotalTime() * g_application.GetCachePercentage()/100.0f; } responseBody.Format(PLAYBACK_INFO, duration, cacheDuration, position, (playing ? 1 : 0), duration); responseHeader = "Content-Type: text/x-apple-plist+xml\r\n"; if (g_application.m_pPlayer->IsCaching()) { ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_LOADING); } else if (playing) { ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PLAYING); } else { ComposeReverseEvent(reverseHeader, reverseBody, sessionId, EVENT_PAUSED); } } } else if (uri == "/server-info") { responseBody.Format(SERVER_INFO, g_application.getNetwork().GetFirstConnectedInterface()->GetMacAddress()); responseHeader = "Content-Type: text/x-apple-plist+xml\r\n"; } else if (uri == "/slideshow-features") { // Ignore for now. } else if (uri == "/authorize") { // DRM, ignore for now. } else if (uri == "200") //response OK from the event reverse message { status = AIRPLAY_STATUS_NO_RESPONSE_NEEDED; } else { CLog::Log(LOGERROR, "AIRPLAY Server: unhandled request [%s]\n", uri.c_str()); status = AIRPLAY_STATUS_NOT_IMPLEMENTED; } if (status == AIRPLAY_STATUS_NEED_AUTH) { ComposeAuthRequestAnswer(responseHeader, responseBody); } return status; }
// Get Thumb from user choice. // Options are: // 1. Current thumb // 2. IMDb thumb // 3. Local thumb // 4. No thumb (if no Local thumb is available) void CGUIDialogVideoInfo::OnGetThumb() { CFileItemList items; // Current thumb if (CFile::Exists(m_movieItem->GetThumbnailImage())) { CFileItemPtr item(new CFileItem("thumb://Current", false)); item->SetThumbnailImage(m_movieItem->GetThumbnailImage()); item->SetLabel(g_localizeStrings.Get(20016)); items.Add(item); } // Grab the thumbnails from the web vector<CStdString> thumbs; m_movieItem->GetVideoInfoTag()->m_strPictureURL.GetThumbURLs(thumbs); for (unsigned int i = 0; i < thumbs.size(); ++i) { CStdString strItemPath; strItemPath.Format("thumb://Remote%i", i); CFileItemPtr item(new CFileItem(strItemPath, false)); item->SetThumbnailImage(thumbs[i]); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20015)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } CStdString localThumb(m_movieItem->GetUserVideoThumb()); if (CFile::Exists(localThumb)) { CFileItemPtr item(new CFileItem("thumb://Local", false)); item->SetThumbnailImage(localThumb); item->SetLabel(g_localizeStrings.Get(20017)); items.Add(item); } else { // no local thumb exists, so we are just using the IMDb thumb or cached thumb // which is probably the IMDb thumb. These could be wrong, so allow the user // to delete the incorrect thumb CFileItemPtr item(new CFileItem("thumb://None", false)); item->SetIconImage("DefaultVideo.png"); item->SetLabel(g_localizeStrings.Get(20018)); items.Add(item); } CStdString result; VECSOURCES sources(g_settings.m_videoSources); g_mediaManager.GetLocalDrives(sources); if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20019), result)) return; // user cancelled if (result == "thumb://Current") return; // user chose the one they have CStdString newThumb; if (result.Left(14) == "thumb://Remote") { int number = atoi(result.Mid(14)); newThumb = thumbs[number]; } else if (result == "thumb://Local") newThumb = localThumb; else if (CFile::Exists(result)) newThumb = result; else // none newThumb = "-"; // force local thumbs to be ignored // update thumb in the database CVideoDatabase db; if (db.Open()) { db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, "thumb", newThumb); db.Close(); } CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show m_movieItem->SetThumbnailImage(newThumb); if (m_movieItem->HasProperty("set_folder_thumb")) { // have a folder thumb to set as well VIDEO::CVideoInfoScanner::ApplyThumbToFolder(m_movieItem->GetProperty("set_folder_thumb").asString(), newThumb); } m_hasUpdatedThumb = true; // Update our screen Update(); }
bool PVRXinFanData::LoadXinFanData(void) { TiXmlDocument xmlDoc; string strSettingsFile = GetSettingsFile(); if (!xmlDoc.LoadFile(strSettingsFile)) { XBMC->Log(LOG_ERROR, "invalid XinFan.TV data (no/invalid data file found at '%s')", strSettingsFile.c_str()); return false; } TiXmlElement *pRootElement = xmlDoc.RootElement(); if (strcmp(pRootElement->Value(), "xinfan") != 0) { XBMC->Log(LOG_ERROR, "invalid XinFan.TV data (no <xinfan> tag found)"); return false; } /* load channels */ int iUniqueChannelId = 0; TiXmlElement *pElement = pRootElement->FirstChildElement("channels"); if (pElement) { TiXmlNode *pChannelNode = NULL; while ((pChannelNode = pElement->IterateChildren(pChannelNode)) != NULL) { CStdString strTmp; PVRXinFanChannel channel; channel.iUniqueId = ++iUniqueChannelId; /* channel name */ if (!XMLUtils::GetString(pChannelNode, "name", strTmp)) continue; channel.strChannelName = strTmp; /* radio/TV */ XMLUtils::GetBoolean(pChannelNode, "radio", channel.bRadio); /* channel number */ if (!XMLUtils::GetInt(pChannelNode, "number", channel.iChannelNumber)) channel.iChannelNumber = iUniqueChannelId; /* sub channel number */ if (!XMLUtils::GetInt(pChannelNode, "subnumber", channel.iSubChannelNumber)) channel.iSubChannelNumber = 0; /* CAID */ if (!XMLUtils::GetInt(pChannelNode, "encryption", channel.iEncryptionSystem)) channel.iEncryptionSystem = 0; /* icon path */ if (!XMLUtils::GetString(pChannelNode, "icon", strTmp)) channel.strIconPath = m_strDefaultIcon; else channel.strIconPath = strTmp; /* stream url */ if (!XMLUtils::GetString(pChannelNode, "stream", strTmp)) channel.strStreamURL = m_strDefaultMovie; else channel.strStreamURL = strTmp; m_channels.push_back(channel); } } /* load channel groups */ int iUniqueGroupId = 0; pElement = pRootElement->FirstChildElement("channelgroups"); if (pElement) { TiXmlNode *pGroupNode = NULL; while ((pGroupNode = pElement->IterateChildren(pGroupNode)) != NULL) { CStdString strTmp; PVRXinFanChannelGroup group; group.iGroupId = ++iUniqueGroupId; /* group name */ if (!XMLUtils::GetString(pGroupNode, "name", strTmp)) continue; group.strGroupName = strTmp; /* radio/TV */ XMLUtils::GetBoolean(pGroupNode, "radio", group.bRadio); /* sort position */ XMLUtils::GetInt(pGroupNode, "position", group.iPosition); /* members */ TiXmlNode* pMembers = pGroupNode->FirstChild("members"); TiXmlNode *pMemberNode = NULL; while (pMembers != NULL && (pMemberNode = pMembers->IterateChildren(pMemberNode)) != NULL) { int iChannelId = atoi(pMemberNode->FirstChild()->Value()); if (iChannelId > -1) group.members.push_back(iChannelId); } m_groups.push_back(group); } } /* load EPG entries */ pElement = pRootElement->FirstChildElement("epg"); if (pElement) { TiXmlNode *pEpgNode = NULL; while ((pEpgNode = pElement->IterateChildren(pEpgNode)) != NULL) { CStdString strTmp; int iTmp; PVRXinFanEpgEntry entry; /* broadcast id */ if (!XMLUtils::GetInt(pEpgNode, "broadcastid", entry.iBroadcastId)) continue; /* channel id */ if (!XMLUtils::GetInt(pEpgNode, "channelid", iTmp)) continue; PVRXinFanChannel &channel = m_channels.at(iTmp - 1); entry.iChannelId = channel.iUniqueId; /* title */ if (!XMLUtils::GetString(pEpgNode, "title", strTmp)) continue; entry.strTitle = strTmp; /* start */ if (!XMLUtils::GetInt(pEpgNode, "start", iTmp)) continue; entry.startTime = iTmp; /* end */ if (!XMLUtils::GetInt(pEpgNode, "end", iTmp)) continue; entry.endTime = iTmp; /* plot */ if (XMLUtils::GetString(pEpgNode, "plot", strTmp)) entry.strPlot = strTmp; /* plot outline */ if (XMLUtils::GetString(pEpgNode, "plotoutline", strTmp)) entry.strPlotOutline = strTmp; /* icon path */ if (XMLUtils::GetString(pEpgNode, "icon", strTmp)) entry.strIconPath = strTmp; /* genre type */ XMLUtils::GetInt(pEpgNode, "genretype", entry.iGenreType); /* genre subtype */ XMLUtils::GetInt(pEpgNode, "genresubtype", entry.iGenreSubType); XBMC->Log(LOG_DEBUG, "loaded EPG entry '%s' channel '%d' start '%d' end '%d'", entry.strTitle.c_str(), entry.iChannelId, entry.startTime, entry.endTime); channel.epg.push_back(entry); } } /* load recordings */ iUniqueGroupId = 0; // reset unique ids pElement = pRootElement->FirstChildElement("recordings"); if (pElement) { TiXmlNode *pRecordingNode = NULL; while ((pRecordingNode = pElement->IterateChildren(pRecordingNode)) != NULL) { CStdString strTmp; PVRXinFanRecording recording; /* recording title */ if (!XMLUtils::GetString(pRecordingNode, "title", strTmp)) continue; recording.strTitle = strTmp; /* recording url */ if (!XMLUtils::GetString(pRecordingNode, "url", strTmp)) recording.strStreamURL = m_strDefaultMovie; else recording.strStreamURL = strTmp; /* recording path */ if (XMLUtils::GetString(pRecordingNode, "directory", strTmp)) recording.strDirectory = strTmp; iUniqueGroupId++; strTmp.Format("%d", iUniqueGroupId); recording.strRecordingId = strTmp; /* channel name */ if (XMLUtils::GetString(pRecordingNode, "channelname", strTmp)) recording.strChannelName = strTmp; /* plot */ if (XMLUtils::GetString(pRecordingNode, "plot", strTmp)) recording.strPlot = strTmp; /* plot outline */ if (XMLUtils::GetString(pRecordingNode, "plotoutline", strTmp)) recording.strPlotOutline = strTmp; /* genre type */ XMLUtils::GetInt(pRecordingNode, "genretype", recording.iGenreType); /* genre subtype */ XMLUtils::GetInt(pRecordingNode, "genresubtype", recording.iGenreSubType); /* duration */ XMLUtils::GetInt(pRecordingNode, "duration", recording.iDuration); /* recording time */ if (XMLUtils::GetString(pRecordingNode, "time", strTmp)) { time_t timeNow = time(NULL); struct tm* now = localtime(&timeNow); CStdString::size_type delim = strTmp.Find(':'); if (delim != CStdString::npos) { now->tm_hour = (int)strtol(strTmp.Left(delim), NULL, 0); now->tm_min = (int)strtol(strTmp.Mid(delim + 1), NULL, 0); now->tm_mday--; // yesterday recording.recordingTime = mktime(now); } } m_recordings.push_back(recording); } } /* load deleted recordings */ pElement = pRootElement->FirstChildElement("recordingsdeleted"); if (pElement) { TiXmlNode *pRecordingNode = NULL; while ((pRecordingNode = pElement->IterateChildren(pRecordingNode)) != NULL) { CStdString strTmp; PVRXinFanRecording recording; /* recording title */ if (!XMLUtils::GetString(pRecordingNode, "title", strTmp)) continue; recording.strTitle = strTmp; /* recording url */ if (!XMLUtils::GetString(pRecordingNode, "url", strTmp)) recording.strStreamURL = m_strDefaultMovie; else recording.strStreamURL = strTmp; /* recording path */ if (XMLUtils::GetString(pRecordingNode, "directory", strTmp)) recording.strDirectory = strTmp; iUniqueGroupId++; strTmp.Format("%d", iUniqueGroupId); recording.strRecordingId = strTmp; /* channel name */ if (XMLUtils::GetString(pRecordingNode, "channelname", strTmp)) recording.strChannelName = strTmp; /* plot */ if (XMLUtils::GetString(pRecordingNode, "plot", strTmp)) recording.strPlot = strTmp; /* plot outline */ if (XMLUtils::GetString(pRecordingNode, "plotoutline", strTmp)) recording.strPlotOutline = strTmp; /* genre type */ XMLUtils::GetInt(pRecordingNode, "genretype", recording.iGenreType); /* genre subtype */ XMLUtils::GetInt(pRecordingNode, "genresubtype", recording.iGenreSubType); /* duration */ XMLUtils::GetInt(pRecordingNode, "duration", recording.iDuration); /* recording time */ if (XMLUtils::GetString(pRecordingNode, "time", strTmp)) { time_t timeNow = time(NULL); struct tm* now = localtime(&timeNow); CStdString::size_type delim = strTmp.Find(':'); if (delim != CStdString::npos) { now->tm_hour = (int)strtol(strTmp.Left(delim), NULL, 0); now->tm_min = (int)strtol(strTmp.Mid(delim + 1), NULL, 0); now->tm_mday--; // yesterday recording.recordingTime = mktime(now); } } m_recordingsDeleted.push_back(recording); } } /* load timers */ pElement = pRootElement->FirstChildElement("timers"); if (pElement) { TiXmlNode *pTimerNode = NULL; while ((pTimerNode = pElement->IterateChildren(pTimerNode)) != NULL) { CStdString strTmp; int iTmp; PVRXinFanTimer timer; time_t timeNow = time(NULL); struct tm* now = localtime(&timeNow); /* channel id */ if (!XMLUtils::GetInt(pTimerNode, "channelid", iTmp)) continue; PVRXinFanChannel &channel = m_channels.at(iTmp - 1); timer.iChannelId = channel.iUniqueId; /* state */ if (XMLUtils::GetInt(pTimerNode, "state", iTmp)) timer.state = (PVR_TIMER_STATE) iTmp; /* title */ if (!XMLUtils::GetString(pTimerNode, "title", strTmp)) continue; timer.strTitle = strTmp; /* summary */ if (!XMLUtils::GetString(pTimerNode, "summary", strTmp)) continue; timer.strSummary = strTmp; /* start time */ if (XMLUtils::GetString(pTimerNode, "starttime", strTmp)) { CStdString::size_type delim = strTmp.Find(':'); if (delim != CStdString::npos) { now->tm_hour = (int)strtol(strTmp.Left(delim), NULL, 0); now->tm_min = (int)strtol(strTmp.Mid(delim + 1), NULL, 0); timer.startTime = mktime(now); } } /* end time */ if (XMLUtils::GetString(pTimerNode, "endtime", strTmp)) { CStdString::size_type delim = strTmp.Find(':'); if (delim != CStdString::npos) { now->tm_hour = (int)strtol(strTmp.Left(delim), NULL, 0); now->tm_min = (int)strtol(strTmp.Mid(delim + 1), NULL, 0); timer.endTime = mktime(now); } } XBMC->Log(LOG_DEBUG, "loaded timer '%s' channel '%d' start '%d' end '%d'", timer.strTitle.c_str(), timer.iChannelId, timer.startTime, timer.endTime); m_timers.push_back(timer); } } return true; }
void SSortFileItem::ByStudioNoThe(CFileItemPtr &item) { if (!item) return; CStdString studio = item->GetVideoInfoTag()->m_strStudio; item->SetSortLabel(studio.Mid(StartsWithToken(studio))); }
void CGUITextLayout::ParseText(const CStdString &text, vector<DWORD> &parsedText) { if (!m_font) return; // run through the string, searching for: // [B] or [/B] -> toggle bold on and off // [I] or [/I] -> toggle italics on and off // [COLOR ffab007f] or [/COLOR] -> toggle color on and off // [CAPS <option>] or [/CAPS] -> toggle capatilization on and off DWORD currentStyle = m_font->GetStyle(); // start with the default font's style DWORD currentColor = 0; stack<DWORD> colorStack; colorStack.push(0); // these aren't independent, but that's probably not too much of an issue // eg [UPPERCASE]Glah[LOWERCASE]FReD[/LOWERCASE]Georeg[/UPPERCASE] will work (lower case >> upper case) // but [LOWERCASE]Glah[UPPERCASE]FReD[/UPPERCASE]Georeg[/LOWERCASE] won't #define FONT_STYLE_UPPERCASE 4 #define FONT_STYLE_LOWERCASE 8 int startPos = 0; size_t pos = text.Find('['); while (pos != CStdString::npos && pos + 1 < text.size()) { DWORD newStyle = 0; DWORD newColor = currentColor; bool newLine = false; // have a [ - check if it's an ON or OFF switch bool on(true); int endPos = pos++; // finish of string if (text[pos] == '/') { on = false; pos++; } // check for each type if (text.Mid(pos,2) == "B]") { // bold - finish the current text block and assign the bold state newStyle = FONT_STYLE_BOLD; pos += 2; } else if (text.Mid(pos,2) == "I]") { // italics newStyle = FONT_STYLE_ITALICS; pos += 2; } else if (text.Mid(pos,10) == "UPPERCASE]") { newStyle = FONT_STYLE_UPPERCASE; pos += 10; } else if (text.Mid(pos,10) == "LOWERCASE]") { newStyle = FONT_STYLE_LOWERCASE; pos += 10; } else if (text.Mid(pos,3) == "CR]" && on) { newLine = true; pos += 3; } else if (text.Mid(pos,5) == "COLOR") { // color size_t finish = text.Find("]", pos + 5); if (on && finish != CStdString::npos) { // create new color newColor = m_colors.size(); m_colors.push_back(g_colorManager.GetColor(text.Mid(pos + 5, finish - pos - 5))); colorStack.push(newColor); } else if (!on && finish == pos + 5) { // revert to previous color if (colorStack.size() > 1) colorStack.pop(); newColor = colorStack.top(); } pos = finish + 1; } if (newStyle || newColor != currentColor || newLine) { // we have a new style or a new color, so format up the previous segment CStdString subText = text.Mid(startPos, endPos - startPos); if (currentStyle & FONT_STYLE_UPPERCASE) subText.ToUpper(); if (currentStyle & FONT_STYLE_LOWERCASE) subText.ToLower(); AppendToUTF32(subText, ((currentStyle & 3) << 24) | (currentColor << 16), parsedText); if (newLine) parsedText.push_back(L'\n'); // and switch to the new style startPos = pos; currentColor = newColor; if (on) currentStyle |= newStyle; else currentStyle &= ~newStyle; } pos = text.Find('[',pos); } // now grab the remainder of the string CStdString subText = text.Mid(startPos, text.GetLength() - startPos); if (currentStyle & FONT_STYLE_UPPERCASE) subText.ToUpper(); if (currentStyle & FONT_STYLE_LOWERCASE) subText.ToLower(); AppendToUTF32(subText, ((currentStyle & 3) << 24) | (currentColor << 16), parsedText); }
CStdString CNetworkInterfaceLinux::GetCurrentDefaultGateway(void) { CStdString result = ""; #if defined(TARGET_DARWIN) FILE* pipe = popen("echo \"show State:/Network/Global/IPv4\" | scutil | grep Router", "r"); if (pipe) { CStdString tmpStr; char buffer[256] = {'\0'}; if (fread(buffer, sizeof(char), sizeof(buffer), pipe) > 0 && !ferror(pipe)) { tmpStr = buffer; result = tmpStr.Mid(11); } else { CLog::Log(LOGWARNING, "Unable to determine gateway"); } pclose(pipe); } #elif defined(TARGET_FREEBSD) size_t needed; int mib[6]; char *buf, *next, *lim; char line[16]; struct rt_msghdr *rtm; struct sockaddr *sa; struct sockaddr_in *sockin; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = 0; mib[4] = NET_RT_DUMP; mib[5] = 0; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) return result; if ((buf = (char *)malloc(needed)) == NULL) return result; if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { free(buf); return result; } lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; sa = (struct sockaddr *)(rtm + 1); sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa); sockin = (struct sockaddr_in *)sa; if (inet_ntop(AF_INET, &sockin->sin_addr.s_addr, line, sizeof(line)) == NULL) { free(buf); return result; } result = line; break; } free(buf); #else FILE* fp = fopen("/proc/net/route", "r"); if (!fp) { // TBD: Error return result; } char* line = NULL; char iface[16]; char dst[128]; char gateway[128]; size_t linel = 0; int n; int linenum = 0; while (getdelim(&line, &linel, '\n', fp) > 0) { // skip first two lines if (linenum++ < 1) continue; // search where the word begins n = sscanf(line, "%16s %128s %128s", iface, dst, gateway); if (n < 3) continue; if (strcmp(iface, m_interfaceName.c_str()) == 0 && strcmp(dst, "00000000") == 0 && strcmp(gateway, "00000000") != 0) { unsigned char gatewayAddr[4]; int len = CNetwork::ParseHex(gateway, gatewayAddr); if (len == 4) { struct in_addr in; in.s_addr = (gatewayAddr[0] << 24) | (gatewayAddr[1] << 16) | (gatewayAddr[2] << 8) | (gatewayAddr[3]); result = inet_ntoa(in); break; } } } free(line); fclose(fp); #endif return result; }
void CDateTimeSpan::SetFromTimeString(const CStdString& time) // hh:mm { int hour = atoi(time.Mid(0,2).c_str()); int minutes = atoi(time.Mid(3,2).c_str()); SetDateTimeSpan(0,hour,minutes,0); }
//////////////////////////////////////////////////////////////////////////////////// // Function: Parse() // Opens the .cue file for reading, and constructs the track database information //////////////////////////////////////////////////////////////////////////////////// bool CCueDocument::Parse(const CStdString &strFile) { if (!m_file.Open(strFile)) return false; CStdString strLine; m_iTotalTracks = -1; CStdString strCurrentFile = ""; bool bCurrentFileChanged = false; int time; // Run through the .CUE file and extract the tracks... while (true) { if (!ReadNextLine(strLine)) break; if (strLine.Left(7) == "INDEX 0") { // find the end of the number section time = ExtractTimeFromIndex(strLine); if (time == -1) { // Error! OutputDebugString("Mangled Time in INDEX 0x tag in CUE file!\n"); return false; } if (m_iTotalTracks > 0) // Set the end time of the last track m_Track[m_iTotalTracks - 1].iEndTime = time; m_Track[m_iTotalTracks].iStartTime = time; // start time of the next track } else if (strLine.Left(5) == "TITLE") { if (m_iTotalTracks == -1) // No tracks yet ExtractQuoteInfo(strLine, m_strAlbum); else if (!ExtractQuoteInfo(strLine, m_Track[m_iTotalTracks].strTitle)) { // lets manage tracks titles without quotes CStdString titleNoQuote = strLine.Mid(5); titleNoQuote.TrimLeft(); if (!titleNoQuote.IsEmpty()) { g_charsetConverter.stringCharsetToUtf8(titleNoQuote); m_Track[m_iTotalTracks].strTitle = titleNoQuote; } } } else if (strLine.Left(9) == "PERFORMER") { if (m_iTotalTracks == -1) // No tracks yet ExtractQuoteInfo(strLine, m_strArtist); else // New Artist for this track ExtractQuoteInfo(strLine, m_Track[m_iTotalTracks].strArtist); } else if (strLine.Left(5) == "TRACK") { int iTrackNumber = ExtractNumericInfo(strLine.c_str() + 5); m_iTotalTracks++; CCueTrack track; m_Track.push_back(track); m_Track[m_iTotalTracks].strFile = strCurrentFile; if (iTrackNumber > 0) m_Track[m_iTotalTracks].iTrackNumber = iTrackNumber; else m_Track[m_iTotalTracks].iTrackNumber = m_iTotalTracks + 1; bCurrentFileChanged = false; } else if (strLine.Left(4) == "FILE") { // already a file name? then the time computation will be changed if(strCurrentFile.size() > 0) bCurrentFileChanged = true; ExtractQuoteInfo(strLine, strCurrentFile); // Resolve absolute paths (if needed). if (strCurrentFile.length() > 0) ResolvePath(strCurrentFile, strFile); } else if (strLine.Left(25) == "REM REPLAYGAIN_ALBUM_GAIN") m_replayGainAlbumGain = (float)atof(strLine.Mid(26)); else if (strLine.Left(25) == "REM REPLAYGAIN_ALBUM_PEAK") m_replayGainAlbumPeak = (float)atof(strLine.Mid(26)); else if (strLine.Left(25) == "REM REPLAYGAIN_TRACK_GAIN" && m_iTotalTracks >= 0) m_Track[m_iTotalTracks].replayGainTrackGain = (float)atof(strLine.Mid(26)); else if (strLine.Left(25) == "REM REPLAYGAIN_TRACK_PEAK" && m_iTotalTracks >= 0) m_Track[m_iTotalTracks].replayGainTrackPeak = (float)atof(strLine.Mid(26)); } // reset track counter to 0, and fill in the last tracks end time m_iTrack = 0; if (m_iTotalTracks > 0) m_Track[m_iTotalTracks].iEndTime = 0; else OutputDebugString("No INDEX 01 tags in CUE file!\n"); m_file.Close(); if (m_iTotalTracks > 0) { m_iTotalTracks++; } return (m_iTotalTracks > 0); }
CLinuxTimezone::CLinuxTimezone() : m_IsDST(0) { char* line = NULL; size_t linelen = 0; CStdString s; vector<CStdString> tokens; // Load timezones FILE* fp = fopen("/usr/share/zoneinfo/zone.tab", "r"); if (fp) { CStdString countryCode; CStdString timezoneName; while (getdelim(&line, &linelen, '\n', fp) > 0) { tokens.clear(); s = line; s.TrimLeft(" \t").TrimRight(" \n"); if (s.length() == 0) continue; if (s[0] == '#') continue; CUtil::Tokenize(s, tokens, " \t"); if (tokens.size() < 3) continue; countryCode = tokens[0]; timezoneName = tokens[2]; if (m_timezonesByCountryCode.count(countryCode) == 0) { vector<CStdString> timezones; timezones.push_back(timezoneName); m_timezonesByCountryCode[countryCode] = timezones; } else { vector<CStdString>& timezones = m_timezonesByCountryCode[countryCode]; timezones.push_back(timezoneName); } m_countriesByTimezoneName[timezoneName] = countryCode; } fclose(fp); } if (line) { free(line); line = NULL; linelen = 0; } // Load countries fp = fopen("/usr/share/zoneinfo/iso3166.tab", "r"); if (fp) { CStdString countryCode; CStdString countryName; while (getdelim(&line, &linelen, '\n', fp) > 0) { s = line; s.TrimLeft(" \t").TrimRight(" \n"); if (s.length() == 0) continue; if (s[0] == '#') continue; // Search for the first non space from the 2nd character and on int i = 2; while (s[i] == ' ' || s[i] == '\t') i++; countryCode = s.Left(2); countryName = s.Mid(i); m_counties.push_back(countryName); m_countryByCode[countryCode] = countryName; m_countryByName[countryName] = countryCode; } sort(m_counties.begin(), m_counties.end(), sortstringbyname()); fclose(fp); } free(line); }
CStdString CSpecialProtocol::TranslatePath(const CURL &url) { // check for special-protocol, if not, return if (!url.GetProtocol().Equals("special")) { #if defined(TARGET_POSIX) && defined(_DEBUG) CStdString 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(); } CStdString FullFileName = url.GetFileName(); CStdString translatedPath; CStdString FileName; CStdString RootDir; // Split up into the special://root and the rest of the filename int pos = FullFileName.Find('/'); if (pos != -1 && pos > 1) { RootDir = FullFileName.Left(pos); if (pos < FullFileName.GetLength()) FileName = FullFileName.Mid(pos + 1); } else RootDir = FullFileName; if (RootDir.Equals("subtitles")) translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("subtitles.custompath"), FileName); else if (RootDir.Equals("userdata")) translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), FileName); else if (RootDir.Equals("database")) translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetDatabaseFolder(), FileName); else if (RootDir.Equals("thumbnails")) translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetThumbnailsFolder(), FileName); else if (RootDir.Equals("recordings") || RootDir.Equals("cdrips")) translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("audiocds.recordingpath"), FileName); else if (RootDir.Equals("screenshots")) translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("debug.screenshotpath"), FileName); else if (RootDir.Equals("musicplaylists")) translatedPath = URIUtils::AddFileToFolder(CUtil::MusicPlaylistsLocation(), FileName); else if (RootDir.Equals("videoplaylists")) translatedPath = URIUtils::AddFileToFolder(CUtil::VideoPlaylistsLocation(), FileName); else if (RootDir.Equals("skin")) translatedPath = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), FileName); else if (RootDir.Equals("logpath")) translatedPath = URIUtils::AddFileToFolder(g_advancedSettings.m_logFolder, FileName); // from here on, we have our "real" special paths else if (RootDir.Equals("xbmc") || RootDir.Equals("xbmcbin") || RootDir.Equals("home") || RootDir.Equals("userhome") || RootDir.Equals("temp") || RootDir.Equals("profile") || RootDir.Equals("masterprofile") || RootDir.Equals("frameworks")) { CStdString basePath = GetPath(RootDir); if (!basePath.IsEmpty()) 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); }
//------------------------------------------------------------------------------------------------------------------- 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'}; line = 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); strKeyword.TrimRight(" "); CStdString strValue(s+1); strValue.Replace("\\n", "\n"); strValue.Replace("\\t", "\t"); strValue.Replace("\\\\", "\\"); g_charsetConverter.unknownToUTF8(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]; 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 < strValue.GetLength() - 2; i++) { if (strValue[i] == ' ' && strValue[i + 1] == '/' && strValue[i + 2] == ' ') { m_strDisk_artist = TrimToUTF8(strValue.Left(i)); m_strDisk_title = TrimToUTF8(strValue.Mid(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 (strKeyword.Left(6) == "TTITLE") addTitle(strKeyword + "=" + strValue); else if (strKeyword == "EXTD") { CStdString strExtd(strValue); if (m_strYear.IsEmpty()) { // Extract Year from extended info // as a fallback int iPos = strExtd.Find("YEAR:"); if (iPos > -1) // You never know if you really get UTF-8 strings from cddb g_charsetConverter.unknownToUTF8(strExtd.Mid(iPos + 6, 4), m_strYear); } if (m_strGenre.IsEmpty()) { // Extract ID3 Genre // as a fallback int iPos = strExtd.Find("ID3G:"); if (iPos > -1) { CStdString strGenre = strExtd.Mid(iPos + 5, 4); strGenre.TrimLeft(' '); if (StringUtils::IsNaturalNumber(strGenre)) { CID3Tag tag; m_strGenre=tag.ParseMP3Genre(strGenre); } } } } else if (strKeyword.Left(4) == "EXTT") addExtended(strKeyword + "=" + strValue); } //writeLog("parseData Ende"); }
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 _LINUX 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) { m_strProtocolOptions = strURL.substr(iProto+1); m_strOptions = strURL.substr(iOptions,iProto-iOptions); } else m_strOptions = strURL.substr(iOptions); iEnd = iOptions; m_options.AddOptions(m_strOptions); } } 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("lastfm") == 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); }
void CMythSession::SetSeasonAndEpisode(const cmyth_proginfo_t &program, int *season, int *episode) { /* * A valid programid generated from an XMLTV source should look like: * [EP|MV|SH|SP][seriesid][episode][season]([partnumber][parttotal]) * mythtv/trunk/programs/mytfilldatabaseline/xmltvparser.cpp - Line 522 onwards. * * Season changed to a base36 character for XMLTV in Myth 0.24. http://svn.mythtv.org/trac/changeset/24724 * * A valid SchedulesDirect programid appears to have a similar format to the XMLTV programid but * doesn't have any obvious way to parse out the season and episode information. The number at the * end of the programid could possibly be the completely sequential number for the episode, but * even that doesn't seem to match up with TVDB. SchedulesDirect data does seem to have a valid * original air date though, so if we identify a SchedulesDirect programid, leave the season and * episode as 0. */ CStdString programid = GetValue(m_dll->proginfo_programid(program)); CStdString seriesid = GetValue(m_dll->proginfo_seriesid(program)); /* * Default the season and episode to 0 so XBMC treats the content as an episode and displays tag * information. If the season and episode can be parsed from the programid these will be * overwritten. */ *season = 0; *episode = 0; if (programid.IsEmpty() // Can't do anything if the program ID is empty || seriesid.IsEmpty()) // Can't figure out the end parsing if the series ID is empty { return; CStdString category = programid.Left(2); // Valid for both XMLTV and SchedulesDirect sources if (category != "MV" // Movie && category != "EP" // Series && category != "SH" // TV Show && category != "SP") // Sports return; if (programid.Mid(category.length(), seriesid.length()) != seriesid) // Series ID does not follow the category return; CStdString remainder = programid.Mid(category.length() + seriesid.length()); // Whatever is after series ID /* * All SchedulesDirect remainders appear to be 4 characters and start with a 0. If the assumption * is correct that the number somehow relates to the sequential episode number across all seasons * then we can ignore remainders that start with 0. It will be very unlikely for a sequential * episode number for a series to be > 999. */ if (remainder.length() == 4 // All SchedulesDirect codes seem to be 4 characters && remainder.Left(0) == "0") // Padded with 0's for low number. No valid XMLTV remainder will start with 0. return; /* * If the remainder is more than 5 characters, it must include the optional part number and total * number of parts. Strip off the last 2 characters assuming that there are ridiculously few * cases where the number of parts for a single episode is > 9. */ if (remainder.length() >= 5) // Must include optional part number and total number of parts remainder = remainder.Left(remainder.length() - 2); // Assumes part number and total are both < 10 /* * Now for some heuristic black magic. */ if (remainder.length() == 2) // Single character season and episode. { *season = atoi(remainder.Right(1)); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10 *episode = atoi(remainder.Left(1)); } else if (remainder.length() == 3) // Ambiguous in Myth 0.23. Single character season in Myth 0.24 { /* * Following heuristics are intended to work with largest possible number of cases. It won't be * perfect, but way better than just assuming the season is < 10. */ if (remainder.Right(1) == "0") // e.g. 610. Unlikely to have a season of 0 (specials) with more than 9 special episodes. { *season = atoi(remainder.Right(2)); *episode = atoi(remainder.Left(1)); } else if (remainder.Mid(2, 1) == "0") // e.g. 203. Can't have a season start with 0. Must be end of episode. { *season = atoi(remainder.Right(1)); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10 *episode = atoi(remainder.Left(2)); } else if (atoi(remainder.Left(1)) > 3) // e.g. 412. Very unlikely to have more than 39 episodes per season if season > 9. { /* * TODO: See if a check for > 2 is better, e.g. is it still unlike to have more than 29 episodes * per season if season > 9? */ *season = atoi(remainder.Right(2)); *episode = atoi(remainder.Left(1)); } else // e.g. 129. Assume season is < 10 or Myth 0.24 Base 36 season. { *season = atoi(remainder.Right(1)); // TODO: Fix for base 36 in Myth 0.24. Assume season < 10 *episode = atoi(remainder.Left(2)); } } else if (remainder.length() == 4) // Double digit season and episode in Myth 0.23 OR TODO: has part number and total number of parts { *season = atoi(remainder.Right(2)); *episode = atoi(remainder.Left(2)); } return; }
// Allow user to select a Fanart void CGUIDialogMusicInfo::OnGetFanart() { CFileItemList items; if (m_albumItem->HasArt("fanart")) { CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); itemCurrent->SetArt("thumb", m_albumItem->GetArt("fanart")); itemCurrent->SetLabel(g_localizeStrings.Get(20440)); items.Add(itemCurrent); } // Grab the thumbnails from the web for (unsigned int i = 0; i < m_artist.fanart.GetNumFanarts(); i++) { CStdString strItemPath; strItemPath.Format("fanart://Remote%i",i); CFileItemPtr item(new CFileItem(strItemPath, false)); CStdString thumb = m_artist.fanart.GetPreviewURL(i); item->SetArt("thumb", CTextureCache::GetWrappedThumbURL(thumb)); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20441)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } // Grab a local thumb CMusicDatabase database; database.Open(); CStdString strArtistPath; database.GetArtistPath(m_artist.idArtist,strArtistPath); CFileItem item(strArtistPath,true); CStdString strLocal = item.GetLocalFanart(); if (!strLocal.IsEmpty()) { CFileItemPtr itemLocal(new CFileItem("fanart://Local",false)); itemLocal->SetArt("thumb", strLocal); itemLocal->SetLabel(g_localizeStrings.Get(20438)); // TODO: Do we need to clear the cached image? CTextureCache::Get().ClearCachedImage(strLocal); items.Add(itemLocal); } else { CFileItemPtr itemNone(new CFileItem("fanart://None", false)); itemNone->SetIconImage("DefaultArtist.png"); itemNone->SetLabel(g_localizeStrings.Get(20439)); items.Add(itemNone); } CStdString result; VECSOURCES sources = *CMediaSourceSettings::Get().GetSources("music"); g_mediaManager.GetLocalDrives(sources); bool flip=false; if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445)) return; // user cancelled // delete the thumbnail if that's what the user wants, else overwrite with the // new thumbnail if (result.Equals("fanart://Current")) return; if (result.Equals("fanart://Local")) result = strLocal; if (result.Left(15) == "fanart://Remote") { int iFanart = atoi(result.Mid(15).c_str()); m_artist.fanart.SetPrimaryFanart(iFanart); result = m_artist.fanart.GetImageURL(); } else if (result.Equals("fanart://None") || !CFile::Exists(result)) result.clear(); if (flip && !result.empty()) result = CTextureCache::GetWrappedImageURL(result, "", "flipped"); // update thumb in the database CMusicDatabase db; if (db.Open()) { db.SetArtForItem(m_albumItem->GetMusicInfoTag()->GetDatabaseId(), m_albumItem->GetMusicInfoTag()->GetType(), "fanart", result); db.Close(); } m_albumItem->SetArt("fanart", result); m_hasUpdatedThumb = true; // tell our GUI to completely reload all controls (as some of them // are likely to have had this image in use so will need refreshing) CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS); g_windowManager.SendMessage(msg); // Update our screen Update(); }
// Allow user to select a Fanart void CGUIWindowVideoInfo::OnGetFanart() { CFileItemList items; // ensure the fanart is unpacked m_movieItem->GetVideoInfoTag()->m_fanart.Unpack(); // Grab the thumbnails from the web CStdString strPath; CUtil::AddFileToFolder(g_advancedSettings.m_cachePath,"fanartthumbs",strPath); CUtil::WipeDir(strPath); DIRECTORY::CDirectory::Create(strPath); for (unsigned int i = 0; i < m_movieItem->GetVideoInfoTag()->m_fanart.GetNumFanarts(); i++) { CStdString strItemPath; strItemPath.Format("fanart://Remote%i",i); CFileItemPtr item(new CFileItem(strItemPath, false)); item->SetThumbnailImage("http://this.is/a/thumb/from/the/web"); item->SetIconImage("defaultPicture.png"); item->GetVideoInfoTag()->m_fanart = m_movieItem->GetVideoInfoTag()->m_fanart; item->SetProperty("fanart_number", (int)i); item->SetLabel(g_localizeStrings.Get(415)); item->SetProperty("labelonthumbload", g_localizeStrings.Get(20015)); // make sure any previously cached thumb is removed if (CFile::Exists(item->GetCachedPictureThumb())) CFile::Delete(item->GetCachedPictureThumb()); items.Add(item); } CFileItem item(*m_movieItem->GetVideoInfoTag()); CStdString cachedThumb(item.GetCachedFanart()); CStdString strLocal = item.CacheFanart(true); if (!strLocal.IsEmpty()) { CFileItemPtr itemLocal(new CFileItem("fanart://Local",false)); itemLocal->SetThumbnailImage(strLocal); itemLocal->SetLabel(g_localizeStrings.Get(20017)); items.Add(itemLocal); } if (CFile::Exists(cachedThumb)) { CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); itemCurrent->SetThumbnailImage(cachedThumb); itemCurrent->SetLabel(g_localizeStrings.Get(20016)); items.Add(itemCurrent); } CFileItemPtr itemNone(new CFileItem("fanart://None", false)); itemNone->SetThumbnailImage("defaultVideoBig.png"); itemNone->SetLabel(g_localizeStrings.Get(20018)); items.Add(itemNone); CStdString result; VECSOURCES sources(g_settings.m_videoSources); g_mediaManager.GetLocalDrives(sources); bool flip=false; if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20019), result, &flip) || result.Equals("fanart://Current")) return; // user cancelled if (CFile::Exists(cachedThumb)) CFile::Delete(cachedThumb); if (result.Equals("fanart://Local")) result = strLocal; if (result.Left(15) == "fanart://Remote") { int iFanart = atoi(result.Mid(15).c_str()); // set new primary fanart, and update our database accordingly m_movieItem->GetVideoInfoTag()->m_fanart.SetPrimaryFanart(iFanart); CVideoDatabase db; if (db.Open()) { db.UpdateFanart(*m_movieItem, GetContentType(m_movieItem.get())); db.Close(); } // download the fullres fanart image CStdString tempFile = "special://temp/fanart_download.jpg"; CAsyncFileCopy downloader; bool succeeded = downloader.Copy(m_movieItem->GetVideoInfoTag()->m_fanart.GetImageURL(), tempFile, g_localizeStrings.Get(13413)); if (succeeded) { CPicture pic; if (flip) pic.ConvertFile(tempFile, cachedThumb,0,1920,-1,100,true); else pic.CacheImage(tempFile, cachedThumb); } CFile::Delete(tempFile); if (!succeeded) return; // failed or cancelled download, so don't do anything } else if (CFile::Exists(result)) { // local file CPicture pic; if (flip) pic.ConvertFile(result, cachedThumb,0,1920,-1,100,true); else pic.CacheImage(result, cachedThumb); } CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show if (CFile::Exists(cachedThumb)) m_movieItem->SetProperty("fanart_image", cachedThumb); else m_movieItem->ClearProperty("fanart_image"); m_hasUpdatedThumb = true; // Update our screen Update(); }