CStdString CWIN32Util::URLEncode(const CURL &url) { /* due to smb wanting encoded urls we have to build it manually */ CStdString flat = "smb://"; if(url.GetDomain().length() > 0) { flat += url.GetDomain(); flat += ";"; } /* samba messes up of password is set but no username is set. don't know why yet */ /* probably the url parser that goes crazy */ if(url.GetUserName().length() > 0 /* || url.GetPassWord().length() > 0 */) { flat += url.GetUserName(); flat += ":"; flat += url.GetPassWord(); flat += "@"; } else if( !url.GetHostName().IsEmpty() && !g_guiSettings.GetString("smb.username").IsEmpty() ) { /* okey this is abit uggly to do this here, as we don't really only url encode */ /* but it's the simplest place to do so */ flat += g_guiSettings.GetString("smb.username"); flat += ":"; flat += g_guiSettings.GetString("smb.password"); flat += "@"; } flat += url.GetHostName(); /* okey sadly since a slash is an invalid name we have to tokenize */ std::vector<CStdString> parts; std::vector<CStdString>::iterator it; CUtil::Tokenize(url.GetFileName(), parts, "/"); for( it = parts.begin(); it != parts.end(); it++ ) { flat += "/"; flat += (*it); } /* okey options should go here, thou current samba doesn't support any */ return flat; }
std::string CSMB::URLEncode(const CURL &url) { /* due to smb wanting encoded urls we have to build it manually */ std::string flat = "smb://"; /* samba messes up of password is set but no username is set. don't know why yet */ /* probably the url parser that goes crazy */ if(url.GetUserName().length() > 0 /* || url.GetPassWord().length() > 0 */) { if(!url.GetDomain().empty()) { flat += URLEncode(url.GetDomain()); flat += ";"; } flat += URLEncode(url.GetUserName()); if(url.GetPassWord().length() > 0) { flat += ":"; flat += URLEncode(url.GetPassWord()); } flat += "@"; } flat += URLEncode(url.GetHostName()); if (url.HasPort()) { flat += StringUtils::Format(":%i", url.GetPort()); } /* okey sadly since a slash is an invalid name we have to tokenize */ std::vector<std::string> parts; std::vector<std::string>::iterator it; StringUtils::Tokenize(url.GetFileName(), parts, "/"); for( it = parts.begin(); it != parts.end(); ++it ) { flat += "/"; flat += URLEncode((*it)); } /* okey options should go here, thou current samba doesn't support any */ return flat; }
CVFSURLWrapper(const CURL& url2) { m_strings.push_back(url2.Get()); m_strings.push_back(url2.GetDomain()); m_strings.push_back(url2.GetHostName()); m_strings.push_back(url2.GetFileName()); m_strings.push_back(url2.GetOptions()); m_strings.push_back(url2.GetUserName()); m_strings.push_back(url2.GetPassWord()); m_strings.push_back(url2.GetRedacted()); m_strings.push_back(url2.GetShareName()); url.url = m_strings[0].c_str(); url.domain = m_strings[1].c_str(); url.hostname = m_strings[2].c_str(); url.filename = m_strings[3].c_str(); url.port = url2.GetPort(); url.options = m_strings[4].c_str(); url.username = m_strings[5].c_str(); url.password = m_strings[6].c_str(); url.redacted = m_strings[7].c_str(); url.sharename = m_strings[8].c_str(); }
bool CWin32SMBDirectory::ConnectAndAuthenticate(CURL& url, bool allowPromptForCredential /*= false*/) { assert(url.GetProtocol() == "smb"); if (url.GetHostName().empty()) return false; // can't connect to empty host name if (url.GetUserName().empty() && url.GetPassWord().empty()) CPasswordManager::GetInstance().AuthenticateURL(url); // set username and password if any /* convert everything to wide strings */ std::wstring serverNameW; if (!g_charsetConverter.utf8ToW(url.GetHostName(), serverNameW, false, false, true)) { CLog::Log(LOGERROR, "%s: Can't convert server name \"%s\" to wide string", __FUNCTION__, url.GetHostName().c_str()); return false; } serverNameW = L"\\\\" + serverNameW; std::string serverShareName; // for error descriptions std::wstring serverShareNameW; if (!url.GetShareName().empty()) { serverShareName = "\\\\" + url.GetHostName() + "\\" + url.GetShareName(); if (!g_charsetConverter.utf8ToW(serverShareName, serverShareNameW, false, false, true)) { CLog::Log(LOGERROR, "%s: Can't convert share name \"%s\" to wide string", __FUNCTION__, serverShareName.c_str()); return false; } } else { serverShareName = "\\\\" + url.GetHostName(); serverShareNameW = serverNameW; } std::wstring usernameW; if (!url.GetUserName().empty() && !g_charsetConverter.utf8ToW(url.GetUserName(), usernameW, false, false, true)) { CLog::Log(LOGERROR, "%s: Can't convert username \"%s\" to wide string", __FUNCTION__, url.GetUserName().c_str()); return false; std::wstring domainW; if (!url.GetDomain().empty() && !g_charsetConverter.utf8ToW(url.GetDomain(), domainW, false, false, true)) { CLog::Log(LOGERROR, "%s: Can't convert domain name \"%s\" to wide string", __FUNCTION__, url.GetDomain().c_str()); return false; } if (!domainW.empty()) usernameW += L'@' + domainW; } std::wstring passwordW; if (!url.GetPassWord().empty() && !g_charsetConverter.utf8ToW(url.GetPassWord(), passwordW, false, false, true)) { CLog::Log(LOGERROR, "%s: Can't convert password to wide string", __FUNCTION__); return false; } std::string loginDescr; if (url.GetUserName().empty()) loginDescr = "without username"; else loginDescr = "with username \"" + url.GetUserName() + (url.GetDomain().empty() ? "" : "@" + url.GetDomain()) + "\""; loginDescr += url.GetPassWord().empty() ? " and without password" : " and with password"; NETRESOURCEW connInfo = {}; connInfo.dwType = RESOURCETYPE_ANY; connInfo.lpRemoteName = (LPWSTR)serverShareNameW.c_str(); DWORD connRes; for (int i = 0; i < 3; i++) // make up to three attempts to connect { connRes = WNetAddConnection2W(&connInfo, passwordW.empty() ? NULL : (LPWSTR)passwordW.c_str(), usernameW.empty() ? NULL : (LPWSTR)usernameW.c_str(), CONNECT_TEMPORARY); if (connRes == NO_ERROR) { CLog::Log(LOGDEBUG, "%s: Connected to \"%s\" %s", __FUNCTION__, serverShareName.c_str(), loginDescr.c_str()); return true; } if (connRes == ERROR_ACCESS_DENIED || connRes == ERROR_BAD_USERNAME || connRes == ERROR_INVALID_PASSWORD || connRes == ERROR_LOGON_FAILURE || connRes == ERROR_LOGON_TYPE_NOT_GRANTED || connRes == ERROR_LOGON_NOT_GRANTED) { if (connRes == ERROR_ACCESS_DENIED) CLog::Log(LOGERROR, "%s: Doesn't have permissions to access \"%s\" %s", __FUNCTION__, serverShareName.c_str(), loginDescr.c_str()); else CLog::Log(LOGERROR, "%s: Username/password combination was not accepted by \"%s\" when trying to connect %s", __FUNCTION__, serverShareName.c_str(), loginDescr.c_str()); if (allowPromptForCredential) RequireAuthentication(url); return false; // don't try any more } else if (connRes == ERROR_BAD_NET_NAME || connRes == ERROR_NO_NET_OR_BAD_PATH || connRes == ERROR_NO_NETWORK) { CLog::Log(LOGERROR, "%s: Can't find \"%s\"", __FUNCTION__, serverShareName.c_str()); return false; // don't try any more } else if (connRes == ERROR_BUSY) CLog::Log(LOGNOTICE, "%s: Network is busy for \"%s\"", __FUNCTION__, serverShareName.c_str()); else if (connRes == ERROR_SESSION_CREDENTIAL_CONFLICT) { CLog::Log(LOGWARNING, "%s: Can't connect to \"%s\" %s because of conflict of credential. Will try to close current connections.", __FUNCTION__, serverShareName.c_str(), loginDescr.c_str()); WNetCancelConnection2W((LPWSTR)serverShareNameW.c_str(), 0, FALSE); WNetCancelConnection2W((LPWSTR)(serverNameW + L"\\IPC$").c_str(), 0, FALSE); WNetCancelConnection2W((LPWSTR)serverNameW.c_str(), 0, FALSE); } } CLog::Log(LOGWARNING, "%s: Can't connect to \"%s\" %s. Error code: %lu", __FUNCTION__, serverShareName.c_str(), loginDescr.c_str(), (unsigned long)connRes); return false; }