bool CPlexClient::Init(const TiXmlElement* DeviceNode) { m_url = ""; m_presence = XMLUtils::GetAttribute(DeviceNode, "presence") == "1"; if (!m_presence) return false; m_uuid = XMLUtils::GetAttribute(DeviceNode, "clientIdentifier"); m_owned = XMLUtils::GetAttribute(DeviceNode, "owned"); m_serverName = XMLUtils::GetAttribute(DeviceNode, "name"); m_accessToken = XMLUtils::GetAttribute(DeviceNode, "accessToken"); m_httpsRequired = XMLUtils::GetAttribute(DeviceNode, "httpsRequired"); m_platform = XMLUtils::GetAttribute(DeviceNode, "platform"); std::vector<PlexConnection> connections; const TiXmlElement* ConnectionNode = DeviceNode->FirstChildElement("Connection"); while (ConnectionNode) { PlexConnection connection; connection.port = XMLUtils::GetAttribute(ConnectionNode, "port"); connection.address = XMLUtils::GetAttribute(ConnectionNode, "address"); connection.protocol = XMLUtils::GetAttribute(ConnectionNode, "protocol"); connection.external = XMLUtils::GetAttribute(ConnectionNode, "local") == "0" ? 1 : 0; connections.push_back(connection); ConnectionNode = ConnectionNode->NextSiblingElement("Connection"); } CURL url; if (!connections.empty()) { // sort so that all external=0 are first. These are the local connections. std::sort(connections.begin(), connections.end(), [] (PlexConnection const& a, PlexConnection const& b) { return a.external < b.external; }); for (const auto &connection : connections) { url.SetHostName(connection.address); url.SetPort(atoi(connection.port.c_str())); url.SetProtocol(connection.protocol); url.SetProtocolOptions("&X-Plex-Token=" + m_accessToken); int timeout = connection.external ? 5 : 1; if (CPlexUtils::GetIdentity(url, timeout)) { CLog::Log(LOGDEBUG, "CPlexClient::Init " "serverName(%s), ipAddress(%s), protocol(%s)", m_serverName.c_str(), connection.address.c_str(), connection.protocol.c_str()); m_url = url.Get(); m_protocol = url.GetProtocol(); m_local = (connection.external == 0); break; } } } return !m_url.empty(); }
void CCurlFile::ParseAndCorrectUrl(CURL &url2) { CStdString strProtocol = url2.GetTranslatedProtocol(); url2.SetProtocol(strProtocol); if( strProtocol.Equals("ftp") || strProtocol.Equals("ftps") ) { /* this is uggly, depending on from where */ /* we get the link it may or may not be */ /* url encoded. if handed from ftpdirectory */ /* it won't be so let's handle that case */ CStdString partial, filename(url2.GetFileName()); CStdStringArray array; /* our current client doesn't support utf8 */ g_charsetConverter.utf8ToStringCharset(filename); /* TODO: create a tokenizer that doesn't skip empty's */ CUtil::Tokenize(filename, array, "/"); filename.Empty(); for(CStdStringArray::iterator it = array.begin(); it != array.end(); it++) { if(it != array.begin()) filename += "/"; partial = *it; CURL::Encode(partial); filename += partial; } /* make sure we keep slashes */ if(url2.GetFileName().Right(1) == "/") filename += "/"; url2.SetFileName(filename); CStdString options = url2.GetOptions().Mid(1); options.TrimRight('/'); // hack for trailing slashes being added from source m_ftpauth = ""; m_ftpport = ""; m_ftppasvip = false; /* parse options given */ CUtil::Tokenize(options, array, "&"); for(CStdStringArray::iterator it = array.begin(); it != array.end(); it++) { CStdString name, value; int pos = it->Find('='); if(pos >= 0) { name = it->Left(pos); value = it->Mid(pos+1, it->size()); } else { name = (*it); value = ""; } if(name.Equals("auth")) { m_ftpauth = value; if(m_ftpauth.IsEmpty()) m_ftpauth = "any"; } else if(name.Equals("active")) { m_ftpport = value; if(value.IsEmpty()) m_ftpport = "-"; } else if(name.Equals("pasvip")) { if(value == "0") m_ftppasvip = false; else m_ftppasvip = true; } } /* ftp has no options */ url2.SetOptions(""); } else if( strProtocol.Equals("http") || strProtocol.Equals("https")) { if (g_guiSettings.GetBool("network.usehttpproxy") && !g_guiSettings.GetString("network.httpproxyserver").empty() && !g_guiSettings.GetString("network.httpproxyport").empty() && m_proxy.IsEmpty()) { m_proxy = g_guiSettings.GetString("network.httpproxyserver"); m_proxy += ":" + g_guiSettings.GetString("network.httpproxyport"); if (g_guiSettings.GetString("network.httpproxyusername").length() > 0 && m_proxyuserpass.IsEmpty()) { m_proxyuserpass = g_guiSettings.GetString("network.httpproxyusername"); m_proxyuserpass += ":" + g_guiSettings.GetString("network.httpproxypassword"); } m_proxytype = (ProxyType)g_guiSettings.GetInt("network.httpproxytype"); CLog::Log(LOGDEBUG, "Using proxy %s, type %d", m_proxy.c_str(), proxyType2CUrlProxyType[m_proxytype]); } // get username and password m_username = url2.GetUserName(); m_password = url2.GetPassWord(); // handle any protocol options CStdString options = url2.GetProtocolOptions(); options.TrimRight('/'); // hack for trailing slashes being added from source if (options.length() > 0) { // clear protocol options url2.SetProtocolOptions(""); // set xbmc headers CStdStringArray array; CUtil::Tokenize(options, array, "&"); for(CStdStringArray::iterator it = array.begin(); it != array.end(); it++) { // parse name, value CStdString name, value; int pos = it->Find('='); if(pos >= 0) { name = it->Left(pos); value = it->Mid(pos+1, it->size()); } else { name = (*it); value = ""; } // url decode value CURL::Decode(value); if(name.Equals("auth")) { m_httpauth = value; if(m_httpauth.IsEmpty()) m_httpauth = "any"; } else if (name.Equals("Referer")) SetReferer(value); else if (name.Equals("User-Agent")) SetUserAgent(value); else if (name.Equals("Cookie")) SetCookie(value); else if (name.Equals("Encoding")) SetContentEncoding(value); else if (name.Equals("noshout") && value.Equals("true")) m_skipshout = true; else SetRequestHeader(name, value); } } } if (m_username.length() > 0 && m_password.length() > 0) m_url = url2.GetWithoutUserDetails(); else m_url = url2.Get(); }
std::string CPlayListM3U::GetBestBandwidthStream(const std::string &strFileName, size_t bandwidth) { // we may be passed a playlist that does not contain playlists of different // bitrates (eg: this playlist is really the HLS video). So, default the // return to the filename so it can be played char szLine[4096]; std::string strLine; size_t maxBandwidth = 0; // open the file, and if it fails, return CFile file; if (!file.Open(strFileName) ) { file.Close(); return strFileName; } // get protocol options if they were set, so we can restore them again at the end CURL playlistUrl(strFileName); // and set the fallback value CURL subStreamUrl = CURL(strFileName); // determine the base CURL basePlaylistUrl(URIUtils::GetParentPath(strFileName)); basePlaylistUrl.SetOptions(""); basePlaylistUrl.SetProtocolOptions(""); std::string basePart = basePlaylistUrl.Get(); // convert bandwidth specified in kbps to bps used by the m3u8 bandwidth *= 1000; while (file.ReadString(szLine, 1024)) { // read and trim a line strLine = szLine; StringUtils::Trim(strLine); // skip the first line if (strLine == M3U_START_MARKER) continue; else if (StringUtils::StartsWith(strLine, M3U_STREAM_MARKER)) { // parse the line so we can pull out the bandwidth std::map< std::string, std::string > params = ParseStreamLine(strLine); std::map< std::string, std::string >::iterator it = params.find(M3U_BANDWIDTH_MARKER); if (it != params.end()) { size_t streamBandwidth = atoi(it->second.c_str()); if ((maxBandwidth < streamBandwidth) && (streamBandwidth <= bandwidth)) { // read the next line if (!file.ReadString(szLine, 1024)) continue; strLine = szLine; StringUtils::Trim(strLine); // this line was empty if (strLine.empty()) continue; // store the max bandwidth maxBandwidth = streamBandwidth; // if the path is absolute just use it if (CURL::IsFullPath(strLine)) subStreamUrl = CURL(strLine); else subStreamUrl = CURL(basePart + strLine); } } } } // if any protocol options were set, restore them subStreamUrl.SetProtocolOptions(playlistUrl.GetProtocolOptions()); return subStreamUrl.Get(); }
void CCurlFile::ParseAndCorrectUrl(CURL &url2) { CStdString strProtocol = url2.GetTranslatedProtocol(); url2.SetProtocol(strProtocol); if( strProtocol.Equals("ftp") || strProtocol.Equals("ftps") ) { // we was using url optons for urls, keep the old code work and warning if (!url2.GetOptions().IsEmpty()) { CLog::Log(LOGWARNING, "%s: ftp url option is deprecated, please switch to use protocol option (change '?' to '|'), url: [%s]", __FUNCTION__, url2.Get().c_str()); url2.SetProtocolOptions(url2.GetOptions().Mid(1)); /* ftp has no options */ url2.SetOptions(""); } /* this is uggly, depending on from where */ /* we get the link it may or may not be */ /* url encoded. if handed from ftpdirectory */ /* it won't be so let's handle that case */ CStdString partial, filename(url2.GetFileName()); CStdStringArray array; // if server sent us the filename in non-utf8, we need send back with same encoding. if (url2.GetProtocolOption("utf8") == "0") g_charsetConverter.utf8ToStringCharset(filename); /* TODO: create a tokenizer that doesn't skip empty's */ CUtil::Tokenize(filename, array, "/"); filename.Empty(); for(CStdStringArray::iterator it = array.begin(); it != array.end(); it++) { if(it != array.begin()) filename += "/"; partial = *it; CURL::Encode(partial); filename += partial; } /* make sure we keep slashes */ if(url2.GetFileName().Right(1) == "/") filename += "/"; url2.SetFileName(filename); m_ftpauth = ""; if (url2.HasProtocolOption("auth")) { m_ftpauth = url2.GetProtocolOption("auth"); if(m_ftpauth.IsEmpty()) m_ftpauth = "any"; } m_ftpport = ""; if (url2.HasProtocolOption("active")) { m_ftpport = url2.GetProtocolOption("active"); if(m_ftpport.IsEmpty()) m_ftpport = "-"; } m_ftppasvip = url2.HasProtocolOption("pasvip") && url2.GetProtocolOption("pasvip") != "0"; } else if( strProtocol.Equals("http") || strProtocol.Equals("https")) { if (CSettings::Get().GetBool("network.usehttpproxy") && !CSettings::Get().GetString("network.httpproxyserver").empty() && !CSettings::Get().GetString("network.httpproxyport").empty() && m_proxy.IsEmpty()) { m_proxy = CSettings::Get().GetString("network.httpproxyserver"); m_proxy += ":" + CSettings::Get().GetString("network.httpproxyport"); if (CSettings::Get().GetString("network.httpproxyusername").length() > 0 && m_proxyuserpass.IsEmpty()) { m_proxyuserpass = CSettings::Get().GetString("network.httpproxyusername"); m_proxyuserpass += ":" + CSettings::Get().GetString("network.httpproxypassword"); } m_proxytype = (ProxyType)CSettings::Get().GetInt("network.httpproxytype"); CLog::Log(LOGDEBUG, "Using proxy %s, type %d", m_proxy.c_str(), proxyType2CUrlProxyType[m_proxytype]); } // get username and password m_username = url2.GetUserName(); m_password = url2.GetPassWord(); // handle any protocol options std::map<CStdString, CStdString> options; url2.GetProtocolOptions(options); if (options.size() > 0) { // clear protocol options url2.SetProtocolOptions(""); // set xbmc headers for(std::map<CStdString, CStdString>::const_iterator it = options.begin(); it != options.end(); ++it) { const CStdString &name = it->first; CStdString value = it->second; // url decode value CURL::Decode(value); if(name.Equals("auth")) { m_httpauth = value; if(m_httpauth.IsEmpty()) m_httpauth = "any"; } else if (name.Equals("Referer")) SetReferer(value); else if (name.Equals("User-Agent")) SetUserAgent(value); else if (name.Equals("Cookie")) SetCookie(value); else if (name.Equals("Encoding")) SetContentEncoding(value); else if (name.Equals("noshout") && value.Equals("true")) m_skipshout = true; else if (name.Equals("seekable") && value.Equals("0")) m_seekable = false; else SetRequestHeader(name, value); } } } if (m_username.length() > 0 && m_password.length() > 0) m_url = url2.GetWithoutUserDetails(); else m_url = url2.Get(); }