Example #1
0
std::string CFavouritesService::GetFavouritesUrl(const CFileItem& item, int contextWindow) const
{
  CURL url;
  url.SetProtocol("favourites");
  url.SetHostName(CURL::Encode(GetExecutePath(item, contextWindow)));
  return url.Get();
}
Example #2
0
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;
}
Example #3
0
/*! \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;
}
Example #4
0
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();
}
Example #5
0
bool CWinLibraryDirectory::GetStoragePath(std::string library, std::string & path)
{
  CURL url;
  url.SetProtocol("win-lib");
  url.SetHostName(library);

  if (!IsValid(url))
    return false;

  path = url.Get();
  return true;
}
Example #6
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();
}
Example #7
0
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();
}
Example #8
0
static bool LoadFromFile(const std::string& strPath, CFileItemList& items)
{
  CXBMCTinyXML doc;
  if (!doc.LoadFile(strPath))
  {
    CLog::Log(LOGERROR, "Unable to load %s (row %i column %i)", strPath.c_str(), doc.Row(), doc.Column());
    return false;
  }
  TiXmlElement *root = doc.RootElement();
  if (!root || strcmp(root->Value(), "favourites"))
  {
    CLog::Log(LOGERROR, "Favourites.xml doesn't contain the <favourites> root element");
    return false;
  }

  TiXmlElement *favourite = root->FirstChildElement("favourite");
  while (favourite)
  {
    // format:
    // <favourite name="Cool Video" thumb="foo.jpg">PlayMedia(c:\videos\cool_video.avi)</favourite>
    // <favourite name="My Album" thumb="bar.tbn">ActivateWindow(MyMusic,c:\music\my album)</favourite>
    // <favourite name="Apple Movie Trailers" thumb="path_to_thumb.png">RunScript(special://xbmc/scripts/apple movie trailers/default.py)</favourite>
    const char *name = favourite->Attribute("name");
    const char *thumb = favourite->Attribute("thumb");
    if (name && favourite->FirstChild())
    {
      CURL url;
      url.SetProtocol("favourites");
      url.SetHostName(CURL::Encode(favourite->FirstChild()->Value()));
      const std::string favURL(url.Get());
      if (!items.Contains(favURL))
      {
        const CFileItemPtr item(std::make_shared<CFileItem>(name));
        item->SetPath(favURL);
        if (thumb)
          item->SetArt("thumb", thumb);
        items.Add(item);
      }
    }
    favourite = favourite->NextSiblingElement("favourite");
  }
  return true;
}
Example #9
0
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;
}
Example #10
0
bool CPlexClient::Init(std::string data, std::string ip)
{
  m_url = "";

  int port = 32400;
  m_protocol = "http";

  std::string s;
  std::istringstream f(data);
  while (std::getline(f, s))
  {
    int pos = s.find(':');
    if (pos > 0)
    {
      std::string substr = s.substr(0, pos);
      std::string name = StringUtils::Trim(substr);
      substr = s.substr(pos + 1);
      std::string val = StringUtils::Trim(substr);
      if (name == "Content-Type")
        m_contentType = val;
      else if (name == "Resource-Identifier")
        m_uuid = val;
      else if (name == "Name")
        m_serverName = val;
      else if (name == "Port")
        port = atoi(val.c_str());
    }
  }

  CURL url;
  url.SetHostName(ip);
  url.SetPort(port);
  url.SetProtocol(m_protocol);
  if (CPlexUtils::GetIdentity(url, 2))
    m_url = url.Get();

  return !m_url.empty();
}
Example #11
0
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;
    }
  }
}
Example #12
0
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;
}
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();
}
Example #14
0
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;
    }
  }
}