bool CAFPDirectory::ResolveSymlink( const CStdString &dirName, const CStdString &fileName, struct stat *stat, CURL &resolvedUrl) { CSingleLock lock(gAfpConnection); int ret = 0; bool retVal = true; char resolvedLink[MAX_PATH]; CStdString fullpath = dirName; URIUtils::AddSlashAtEnd(fullpath); fullpath += fileName; CPasswordManager::GetInstance().AuthenticateURL(resolvedUrl); resolvedUrl.SetProtocol("afp"); resolvedUrl.SetHostName(gAfpConnection.GetConnectedIp()); ret = gAfpConnection.GetImpl()->afp_wrap_readlink(gAfpConnection.GetVolume(), fullpath.c_str(), resolvedLink, MAX_PATH); if(ret == 0) { fullpath = dirName; URIUtils::AddSlashAtEnd(fullpath); fullpath.append(resolvedLink); if(resolvedLink[0] == '/') { //use the special stat function for using an extra context //because we are inside of a dir traversation //and just can't change the global nfs context here //without destroying something... fullpath = resolvedLink; fullpath = fullpath.Right(fullpath.length()-1); resolvedUrl.SetFileName(fullpath); ret = gAfpConnection.stat(resolvedUrl, stat); if(ret < 0) { URIUtils::AddSlashAtEnd(fullpath); resolvedUrl.SetFileName(fullpath); ret = gAfpConnection.stat(resolvedUrl, stat); } } else { ret = gAfpConnection.GetImpl()->afp_wrap_getattr(gAfpConnection.GetVolume(), fullpath.c_str(), stat); resolvedUrl.SetFileName(gAfpConnection.GetUrl()->volumename + fullpath); } if (ret != 0) { CLog::Log(LOGERROR, "AFP: Failed to stat(%s) on link resolve %s\n", fullpath.c_str(), strerror(errno)); retVal = false;; } } else { CLog::Log(LOGERROR, "Failed to readlink(%s) %s\n", fullpath.c_str(), strerror(errno)); retVal = false; } return retVal; }
/*! \brief Set a skin file setting. * \param params The parameters. * \details params[0] = Name of skin setting. * params[1] = File mask or add-on type (optional). * params[2] = Extra URL to allow selection from or * content type if mask is an addon-on type (optional). */ static int SetFile(const std::vector<std::string>& params) { int string = CSkinSettings::GetInstance().TranslateString(params[0]); std::string value = CSkinSettings::GetInstance().GetString(string); VECSOURCES localShares; g_mediaManager.GetLocalDrives(localShares); // Note. can only browse one addon type from here // if browsing for addons, required param[1] is addontype string, with optional param[2] // as contenttype string see IAddon.h & ADDON::TranslateXX std::string strMask = (params.size() > 1) ? params[1] : ""; StringUtils::ToLower(strMask); ADDON::TYPE type; if ((type = TranslateType(strMask)) != ADDON_UNKNOWN) { CURL url; url.SetProtocol("addons"); url.SetHostName("enabled"); url.SetFileName(strMask+"/"); localShares.clear(); std::string content = (params.size() > 2) ? params[2] : ""; StringUtils::ToLower(content); url.SetPassword(content); std::string strMask; if (type == ADDON_SCRIPT) strMask = ".py"; std::string replace; if (CGUIDialogFileBrowser::ShowAndGetFile(url.Get(), strMask, TranslateType(type, true), replace, true, true, true)) { if (StringUtils::StartsWithNoCase(replace, "addons://")) CSkinSettings::GetInstance().SetString(string, URIUtils::GetFileName(replace)); else CSkinSettings::GetInstance().SetString(string, replace); } } else { // show all network drives g_mediaManager.GetNetworkLocations(localShares); if (params.size() > 2) { value = params[2]; URIUtils::AddSlashAtEnd(value); bool bIsSource; if (CUtil::GetMatchingSource(value,localShares,bIsSource) < 0) // path is outside shares - add it as a separate one { CMediaSource share; share.strName = g_localizeStrings.Get(13278); share.strPath = value; localShares.push_back(share); } } if (CGUIDialogFileBrowser::ShowAndGetFile(localShares, strMask, g_localizeStrings.Get(1033), value)) CSkinSettings::GetInstance().SetString(string, value); } return 0; }
std::string CGUIDialogNetworkSetup::ConstructPath() const { CURL url; if (m_protocol == NET_PROTOCOL_SMB) url.SetProtocol("smb"); else if (m_protocol == NET_PROTOCOL_FTP) url.SetProtocol("ftp"); else if (m_protocol == NET_PROTOCOL_HTTP) url.SetProtocol("http"); else if (m_protocol == NET_PROTOCOL_HTTPS) url.SetProtocol("https"); else if (m_protocol == NET_PROTOCOL_DAV) url.SetProtocol("dav"); else if (m_protocol == NET_PROTOCOL_DAVS) url.SetProtocol("davs"); else if (m_protocol == NET_PROTOCOL_UPNP) url.SetProtocol("upnp"); else if (m_protocol == NET_PROTOCOL_RSS) url.SetProtocol("rss"); else if (m_protocol == NET_PROTOCOL_NFS) url.SetProtocol("nfs"); else if (m_protocol == NET_PROTOCOL_SFTP) url.SetProtocol("sftp"); if (!m_username.empty()) { url.SetUserName(m_username); if (!m_password.empty()) url.SetPassword(m_password); } if(!m_server.empty()) url.SetHostName(m_server); if (((m_protocol == NET_PROTOCOL_FTP) || (m_protocol == NET_PROTOCOL_HTTP) || (m_protocol == NET_PROTOCOL_HTTPS) || (m_protocol == NET_PROTOCOL_DAV) || (m_protocol == NET_PROTOCOL_DAVS) || (m_protocol == NET_PROTOCOL_RSS) || (m_protocol == NET_PROTOCOL_SFTP) || (m_protocol == NET_PROTOCOL_NFS)) && !m_port.empty() && atoi(m_port.c_str()) > 0) { url.SetPort(atoi(m_port.c_str())); } if (!m_path.empty()) url.SetFileName(m_path); return url.Get(); }
CStdString CTextureCache::GetWrappedImageURL(const CStdString &image, const CStdString &type, const CStdString &options) { if (StringUtils::StartsWith(image, "image://")) return image; // already wrapped CURL url; url.SetProtocol("image"); url.SetUserName(type); url.SetHostName(image); if (!options.IsEmpty()) { url.SetFileName("transform"); url.SetOptions("?" + options); } return url.Get(); }
CURL URIUtils::CreateArchivePath(const std::string& type, const CURL& archiveUrl, const std::string& pathInArchive, const std::string& password) { CURL url; url.SetProtocol(type); if (!password.empty()) url.SetUserName(password); url.SetHostName(archiveUrl.Get()); /* NOTE: on posix systems, the replacement of \ with / is incorrect. Ideally this would not be done. We need to check that the ZipManager and RarManager code (and elsewhere) doesn't pass in non-posix paths. */ std::string strBuffer(pathInArchive); StringUtils::Replace(strBuffer, '\\', '/'); StringUtils::TrimLeft(strBuffer, "/"); url.SetFileName(strBuffer); return url; }
bool CZeroconfDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) { assert(strPath.substr(0, 11) == "zeroconf://"); CStdString path = strPath.substr(11, strPath.length()); URIUtils::RemoveSlashAtEnd(path); if(path.empty()) { std::vector<CZeroconfBrowser::ZeroconfService> found_services = CZeroconfBrowser::GetInstance()->GetFoundServices(); for(std::vector<CZeroconfBrowser::ZeroconfService>::iterator it = found_services.begin(); it != found_services.end(); ++it) { //only use discovered services we can connect to through directory CStdString tmp; if(GetXBMCProtocol(it->GetType(), tmp)) { CFileItemPtr item(new CFileItem("", true)); CURL url; url.SetProtocol("zeroconf"); CStdString service_path = CZeroconfBrowser::ZeroconfService::toPath(*it); CURL::Encode(service_path); url.SetFileName(service_path); item->m_strPath = url.Get(); //now do the formatting CStdString protocol = GetHumanReadableProtocol(it->GetType()); item->SetLabel(it->GetName() + " (" + protocol + ")"); item->SetLabelPreformated(true); //just set the default folder icon item->FillInDefaultIcon(); items.Add(item); } } return true; } else { //decode the path first CStdString decoded = path; CURL::Decode(decoded); try { CZeroconfBrowser::ZeroconfService zeroconf_service = CZeroconfBrowser::ZeroconfService::fromPath(decoded); if(!CZeroconfBrowser::GetInstance()->ResolveService(zeroconf_service)) { CLog::Log(LOGINFO, "CZeroconfDirectory::GetDirectory service ( %s ) could not be resolved in time", zeroconf_service.GetName().c_str()); return false; } else { assert(!zeroconf_service.GetIP().empty()); CURL service; service.SetPort(zeroconf_service.GetPort()); service.SetHostName(zeroconf_service.GetIP()); //do protocol conversion (_smb._tcp -> smb) //ToDo: try automatic conversion -> remove leading '_' and '._tcp'? CStdString protocol; if(!GetXBMCProtocol(zeroconf_service.GetType(), protocol)) { CLog::Log(LOGERROR, "CZeroconfDirectory::GetDirectory Unknown service type (%s), skipping; ", zeroconf_service.GetType().c_str()); return false; } service.SetProtocol(protocol); return CDirectory::GetDirectory(service.Get(), items, "", true, true); } } catch (std::runtime_error& e) { CLog::Log(LOGERROR, "CZeroconfDirectory::GetDirectory failed getting directory: '%s'. Error: '%s'", decoded.c_str(), e.what()); return false; } } }
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(); }
bool CNFSDirectory::ResolveSymlink( const CStdString &dirName, struct nfsdirent *dirent, CURL &resolvedUrl) { CSingleLock lock(gNfsConnection); int ret = 0; bool retVal = true; CStdString fullpath = dirName; char resolvedLink[MAX_PATH]; URIUtils::AddSlashAtEnd(fullpath); fullpath.append(dirent->name); resolvedUrl.Reset(); resolvedUrl.SetPort(2049); resolvedUrl.SetProtocol("nfs"); resolvedUrl.SetHostName(gNfsConnection.GetConnectedIp()); ret = gNfsConnection.GetImpl()->nfs_readlink(gNfsConnection.GetNfsContext(), fullpath.c_str(), resolvedLink, MAX_PATH); if(ret == 0) { struct stat tmpBuffer = {0}; fullpath = dirName; URIUtils::AddSlashAtEnd(fullpath); fullpath.append(resolvedLink); //special case - if link target is absolute it could be even another export //intervolume symlinks baby ... if(resolvedLink[0] == '/') { //use the special stat function for using an extra context //because we are inside of a dir traversation //and just can't change the global nfs context here //without destroying something... fullpath = resolvedLink; resolvedUrl.SetFileName(fullpath); ret = gNfsConnection.stat(resolvedUrl, &tmpBuffer); } else { ret = gNfsConnection.GetImpl()->nfs_stat(gNfsConnection.GetNfsContext(), fullpath.c_str(), &tmpBuffer); resolvedUrl.SetFileName(gNfsConnection.GetConnectedExport() + fullpath); } if (ret != 0) { CLog::Log(LOGERROR, "NFS: Failed to stat(%s) on link resolve %s\n", fullpath.c_str(), gNfsConnection.GetImpl()->nfs_get_error(gNfsConnection.GetNfsContext())); retVal = false;; } else { dirent->inode = tmpBuffer.st_ino; dirent->mode = tmpBuffer.st_mode; dirent->size = tmpBuffer.st_size; dirent->atime.tv_sec = tmpBuffer.st_atime; dirent->mtime.tv_sec = tmpBuffer.st_mtime; dirent->ctime.tv_sec = tmpBuffer.st_ctime; //map stat mode to nf3type if(S_ISBLK(tmpBuffer.st_mode)){ dirent->type = NF3BLK; } else if(S_ISCHR(tmpBuffer.st_mode)){ dirent->type = NF3CHR; } else if(S_ISDIR(tmpBuffer.st_mode)){ dirent->type = NF3DIR; } else if(S_ISFIFO(tmpBuffer.st_mode)){ dirent->type = NF3FIFO; } else if(S_ISREG(tmpBuffer.st_mode)){ dirent->type = NF3REG; } else if(S_ISLNK(tmpBuffer.st_mode)){ dirent->type = NF3LNK; } else if(S_ISSOCK(tmpBuffer.st_mode)){ dirent->type = NF3SOCK; } } } else { CLog::Log(LOGERROR, "Failed to readlink(%s) %s\n", fullpath.c_str(), gNfsConnection.GetImpl()->nfs_get_error(gNfsConnection.GetNfsContext())); retVal = false; } return retVal; }
bool CShoutcastDirectory::ParseStations(TiXmlElement *root, CFileItemList &items, CURL &url) { TiXmlElement *element = NULL; CStdString path; items.m_idepth = 2; /* station list */ element = root->FirstChildElement("tunein"); if(element == NULL) { CLog::Log(LOGWARNING, "%s - No tunein base found", __FUNCTION__); return false; } path = element->Attribute("base"); path.TrimLeft("/"); url.SetFileName(path); element = root->FirstChildElement("station"); if(element == NULL) { CLog::Log(LOGWARNING, "%s - No stations found", __FUNCTION__); return false; } int stations = 0; while(element != NULL && stations < 1000) { CStdString name = element->Attribute("name"); CStdString id = element->Attribute("id"); CStdString bitrate = element->Attribute("br"); CStdString genre = element->Attribute("genre"); CStdString listeners = element->Attribute("lc"); CStdString content = element->Attribute("mt"); CStdString label = name; url.SetOptions("?id=" + id); url.GetURL(path); //printf("%s: %s\n", name.c_str(), path.c_str()); CFileItem* pItem = new CFileItem; pItem->m_bIsFolder = false; /* we highjack the music tag for this stuff, they will be used by */ /* viewstates to sort and display proper information */ pItem->GetMusicInfoTag()->SetArtist(listeners); pItem->GetMusicInfoTag()->SetAlbum(bitrate); pItem->GetMusicInfoTag()->SetGenre(genre); /* this is what will be sorted upon */ pItem->GetVideoInfoTag()->m_fRating = (float)atoi(listeners.c_str()); pItem->m_dwSize = atoi(bitrate.c_str()); pItem->SetLabel(label); /* content type is known before hand, should save later lookup */ /* wonder if we could combine the contentype of the playlist and of the real stream */ pItem->SetContentType("audio/x-scpls"); pItem->m_strPath = path; items.Add(pItem); stations++; element = element->NextSiblingElement("station"); } return true; }
CStdString CGUIDialogNetworkSetup::ConstructPath() const { CURL url; if (m_protocol == NET_PROTOCOL_SMB) url.SetProtocol("smb"); else if (m_protocol == NET_PROTOCOL_FTP) url.SetProtocol("ftp"); else if (m_protocol == NET_PROTOCOL_HTTP) url.SetProtocol("http"); else if (m_protocol == NET_PROTOCOL_HTTPS) url.SetProtocol("https"); else if (m_protocol == NET_PROTOCOL_DAV) url.SetProtocol("dav"); else if (m_protocol == NET_PROTOCOL_DAVS) url.SetProtocol("davs"); else if (m_protocol == NET_PROTOCOL_DAAP) url.SetProtocol("daap"); else if (m_protocol == NET_PROTOCOL_UPNP) url.SetProtocol("upnp"); else if (m_protocol == NET_PROTOCOL_TUXBOX) url.SetProtocol("tuxbox"); else if (m_protocol == NET_PROTOCOL_RSS) url.SetProtocol("rss"); else if (m_protocol == NET_PROTOCOL_HTSP) url.SetProtocol("htsp"); else if (m_protocol == NET_PROTOCOL_VTP) url.SetProtocol("vtp"); else if (m_protocol == NET_PROTOCOL_MYTH) url.SetProtocol("myth"); else if (m_protocol == NET_PROTOCOL_NFS) url.SetProtocol("nfs"); else if (m_protocol == NET_PROTOCOL_SFTP) url.SetProtocol("sftp"); else if (m_protocol == NET_PROTOCOL_AFP) url.SetProtocol("afp"); if (!m_username.IsEmpty()) { url.SetUserName(m_username); if (!m_password.IsEmpty()) url.SetPassword(m_password); } if(!m_server.IsEmpty()) url.SetHostName(m_server); if (((m_protocol == NET_PROTOCOL_FTP) || (m_protocol == NET_PROTOCOL_HTTP) || (m_protocol == NET_PROTOCOL_HTTPS) || (m_protocol == NET_PROTOCOL_DAV) || (m_protocol == NET_PROTOCOL_DAVS) || (m_protocol == NET_PROTOCOL_RSS) || (m_protocol == NET_PROTOCOL_DAAP && !m_server.IsEmpty()) || (m_protocol == NET_PROTOCOL_HTSP) || (m_protocol == NET_PROTOCOL_VTP) || (m_protocol == NET_PROTOCOL_MYTH) || (m_protocol == NET_PROTOCOL_TUXBOX) || (m_protocol == NET_PROTOCOL_SFTP) || (m_protocol == NET_PROTOCOL_NFS)) && !m_port.IsEmpty() && atoi(m_port.c_str()) > 0) { url.SetPort(atoi(m_port)); } if (!m_path.IsEmpty()) url.SetFileName(m_path); return url.Get(); }
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(); }
bool CZeroconfDirectory::GetDirectory(const CURL& url, CFileItemList &items) { assert(url.IsProtocol("zeroconf")); std::string strPath = url.Get(); std::string path = strPath.substr(11, strPath.length()); URIUtils::RemoveSlashAtEnd(path); if(path.empty()) { std::vector<CZeroconfBrowser::ZeroconfService> found_services = CZeroconfBrowser::GetInstance()->GetFoundServices(); for(std::vector<CZeroconfBrowser::ZeroconfService>::iterator it = found_services.begin(); it != found_services.end(); ++it) { //only use discovered services we can connect to through directory std::string tmp; if(GetXBMCProtocol(it->GetType(), tmp)) { CFileItemPtr item(new CFileItem("", true)); CURL url; url.SetProtocol("zeroconf"); std::string service_path(CURL::Encode(CZeroconfBrowser::ZeroconfService::toPath(*it))); url.SetFileName(service_path); item->SetPath(url.Get()); //now do the formatting std::string protocol = GetHumanReadableProtocol(it->GetType()); item->SetLabel(it->GetName() + " (" + protocol + ")"); item->SetLabelPreformated(true); //just set the default folder icon item->FillInDefaultIcon(); items.Add(item); } } return true; } else { //decode the path first std::string decoded(CURL::Decode(path)); try { CZeroconfBrowser::ZeroconfService zeroconf_service = CZeroconfBrowser::ZeroconfService::fromPath(decoded); if(!CZeroconfBrowser::GetInstance()->ResolveService(zeroconf_service)) { CLog::Log(LOGINFO, "CZeroconfDirectory::GetDirectory service ( %s ) could not be resolved in time", zeroconf_service.GetName().c_str()); return false; } else { assert(!zeroconf_service.GetIP().empty()); CURL service; service.SetPort(zeroconf_service.GetPort()); service.SetHostName(zeroconf_service.GetIP()); //do protocol conversion (_smb._tcp -> smb) //ToDo: try automatic conversion -> remove leading '_' and '._tcp'? std::string protocol; if(!GetXBMCProtocol(zeroconf_service.GetType(), protocol)) { CLog::Log(LOGERROR, "CZeroconfDirectory::GetDirectory Unknown service type (%s), skipping; ", zeroconf_service.GetType().c_str()); return false; } service.SetProtocol(protocol); //first try to show the txt-record defined path if any if(GetDirectoryFromTxtRecords(zeroconf_service, service, items)) { return true; } else//no txt record path - so let the CDirectory handler show the folders { // CDirectory::GetDirectory returns false if authorization is required // The target vfs directory will call RequireAuthentication but that is // is not good enough as we can be running as a job and not under main thread, // so authentication dialog does not get called. Set it again here so // authentication dialog gets called and we will get called again with user/pass setup. bool status = CDirectory::GetDirectory(service, items, "", DIR_FLAG_ALLOW_PROMPT); if(!status) RequireAuthentication(service); return status; } } } catch (std::runtime_error& e) { CLog::Log(LOGERROR, "CZeroconfDirectory::GetDirectory failed getting directory: '%s'. Error: '%s'", decoded.c_str(), e.what()); return false; } } }