📄 ftpurl.cpp
字号:
urlComps.dwStructSize = sizeof(urlComps);
urlComps.lpszHostName = szServer;
urlComps.dwHostNameLength = ARRAYSIZE(szServer);
urlComps.lpszUrlPath = szUrlPath;
urlComps.dwUrlPathLength = ARRAYSIZE(szUrlPath);
urlComps.lpszExtraInfo = szExtraInfo;
urlComps.dwExtraInfoLength = ARRAYSIZE(szExtraInfo);
urlComps.lpszUserName = szUserName;
urlComps.dwUserNameLength = ARRAYSIZE(szUserName);
urlComps.lpszPassword = szPassword;
urlComps.dwPasswordLength = ARRAYSIZE(szPassword);
fResult = InternetCrackUrl(pszUrlPath, 0, ICU_DECODE, &urlComps);
if (fResult)
{
urlComps.dwStructSize = sizeof(urlComps);
urlComps.lpszHostName = szServer;
urlComps.lpszUserName = (LPTSTR)(pszUserName ? pszUserName : szUserName);
urlComps.dwUserNameLength = (pszUserName ? lstrlen(pszUserName) : lstrlen(szUserName));
urlComps.lpszPassword = (LPTSTR)pszPassword; // It may be valid for caller to pass NULL
urlComps.dwPasswordLength = (pszPassword ? lstrlen(pszPassword) : 0);
urlComps.lpszExtraInfo = szExtraInfo;
urlComps.dwExtraInfoLength = ARRAYSIZE(szExtraInfo);
fResult = InternetCreateUrl(&urlComps, (ICU_ESCAPE | ICU_USERNAME), pszUrlPath, &cchSize);
if (fResult)
{
hr = S_OK;
}
}
return hr;
}
// InternetCreateUrlW() will write into pszUrl but won't terminate the string.
// This is hard to detect because half the time the place where the terminator should
// go may coincidentally contain a terminator. This code forces the bug to happen.
#define TEST_FOR_INTERNETCREATEURL_BUG 1
#define INTERNETCREATEURL_BUG_WORKAROUND 1
HRESULT UrlCreateEx(LPCTSTR pszServer, LPCTSTR pszUser, LPCTSTR pszPassword, LPCTSTR pszUrlPath, LPCTSTR pszFragment, INTERNET_PORT ipPortNum, LPCTSTR pszDownloadType, LPTSTR pszUrl, DWORD cchSize, DWORD dwFlags)
{
HRESULT hr = E_FAIL;
DWORD cchSizeCopy = cchSize;
#if DEBUG && TEST_FOR_INTERNETCREATEURL_BUG
LPTSTR pszDebugStr = pszUrl;
for (DWORD dwIndex = (cchSize - 2); dwIndex; dwIndex--)
{
#ifndef INTERNETCREATEURL_BUG_WORKAROUND
pszDebugStr[0] = -1; // This will force a buffer w/o terminators.
#else // INTERNETCREATEURL_BUG_WORKAROUND
pszDebugStr[0] = 0; // This will work around the bug.
#endif // INTERNETCREATEURL_BUG_WORKAROUND
pszDebugStr++;
}
#endif // DEBUG && TEST_FOR_INTERNETCREATEURL_BUG
URL_COMPONENTS urlComp = {sizeof(URL_COMPONENTS), NULL, 0, INTERNET_SCHEME_FTP, (LPTSTR) pszServer, 0,
ipPortNum, (LPTSTR) NULL_FOR_EMPTYSTR(pszUser), 0, (LPTSTR) NULL_FOR_EMPTYSTR(pszPassword), 0,
(LPTSTR) pszUrlPath, 0, (LPTSTR) NULL, 0};
if (EVAL(InternetCreateUrl(&urlComp, dwFlags | ICU_USERNAME, pszUrl, &cchSizeCopy)))
{
hr = S_OK;
if (pszFragment)
StrCatBuff(pszUrl, pszFragment, cchSize);
}
#if DEBUG && TEST_FOR_INTERNETCREATEURL_BUG
#ifdef INTERNETCREATEURL_BUG_WORKAROUND
// Make sure we hit a terminator and not a -1, which should never happen in URL strings.
for (pszDebugStr = pszUrl; pszDebugStr[0]; pszDebugStr++)
ASSERT(-1 != pszDebugStr[0]);
#endif // INTERNETCREATEURL_BUG_WORKAROUND
#endif // DEBUG && TEST_FOR_INTERNETCREATEURL_BUG
return hr;
}
HRESULT UrlCreate(LPCTSTR pszServer, LPCTSTR pszUser, LPCTSTR pszPassword, LPCTSTR pszUrlPath, LPCTSTR pszFragment, INTERNET_PORT ipPortNum, LPCTSTR pszDownloadType, LPTSTR pszUrl, DWORD cchSize)
{
return UrlCreateEx(pszServer, pszUser, pszPassword, pszUrlPath, pszFragment, ipPortNum, pszDownloadType, pszUrl, cchSize, ICU_ESCAPE);
}
BOOL IsEmptyUrlPath(LPCTSTR pszUrlPath)
{
BOOL fResult = FALSE;
if (!pszUrlPath ||
!pszUrlPath[0] ||
(((TEXT('/') == pszUrlPath[0]) && (!pszUrlPath[1]))))
{
fResult = TRUE;
}
return fResult;
}
///////////////////////////////////////////////////////////////////////
// Wire Path Functions (UTF-8 or DBCS/MBCS)
///////////////////////////////////////////////////////////////////////
/*****************************************************************************\
FUNCTION: WirePathAdd
DESCRIPTION:
...
\*****************************************************************************/
HRESULT WirePathAdd(LPWIRESTR pwWirePath, DWORD cchUrlSize, LPCWIRESTR pwWireSegment)
{
// If the segment starts with a slash, skip it.
if ('/' == pwWireSegment[0])
pwWireSegment = CharNextA(pwWireSegment);
StrCatBuffA(pwWirePath, pwWireSegment, cchUrlSize);
return S_OK;
}
/*****************************************************************************\
FUNCTION: WirePathAppendSlash
DESCRIPTION:
\*****************************************************************************/
HRESULT WirePathAppendSlash(LPWIRESTR pwWirePath, DWORD cchWirePathSize)
{
HRESULT hr = E_FAIL;
DWORD cchSize = lstrlenA(pwWirePath);
// Is there enough room?
if (cchSize < (cchWirePathSize - 1))
{
LPWIRESTR pwEndOfPath = &pwWirePath[cchSize - 1];
// Is it missing a backslash?
if ((pwEndOfPath >= pwWirePath) && '/' != pwEndOfPath[0])
StrCatA(pwEndOfPath, SZ_URL_SLASHA); // Yes, so add it.
hr = S_OK;
}
return hr;
}
/*****************************************************************************\
FUNCTION: WirePathAppend
DESCRIPTION:
...
\*****************************************************************************/
HRESULT WirePathAppend(LPWIRESTR pwWirePath, DWORD cchUrlSize, LPCWIRESTR pwWireSegment)
{
if (!EVAL(pwWireSegment))
return E_INVALIDARG;
WirePathAppendSlash(pwWirePath, cchUrlSize); // Make sure the base url ends in a '/'. Note it may be "ftp://".
return WirePathAdd(pwWirePath, cchUrlSize, pwWireSegment);
}
/*****************************************************************************\
FUNCTION: UrlGetFirstPathSegment
PARAMETERS:
[IN] pszFullPath - "Dir1\Dir2\Dir3"
[OUT] szFirstItem - "Dir1" [OPTIONAL]
[OUT] szRemaining - "Dir2\Dir3" [OPTIONAL]
\*****************************************************************************/
HRESULT WirePathGetFirstSegment(LPCWIRESTR pwFtpWirePath, LPWIRESTR wFirstItem, DWORD cchFirstItemSize, BOOL * pfWasFragSeparator, LPWIRESTR wRemaining, DWORD cchRemainingSize, BOOL * pfIsDir)
{
HRESULT hr = S_OK;
LPCWIRESTR pwSegEnding = StrChrA(pwFtpWirePath, CH_URL_URL_SLASH);
if (pfIsDir)
*pfIsDir = FALSE;
ASSERT((CH_URL_URL_SLASHA != pwFtpWirePath[0])); // You will probably not get what you want.
if (pwSegEnding)
{
if (wFirstItem)
{
DWORD cchSize = (DWORD) (pwSegEnding - pwFtpWirePath + 1);
StrCpyNA(wFirstItem, pwFtpWirePath, (cchSize <= cchFirstItemSize) ? cchSize : cchFirstItemSize);
}
if (pfIsDir && (CH_URL_URL_SLASHA == pwSegEnding[0]))
*pfIsDir = TRUE; // Tell them that it is a directory.
if (wRemaining)
StrCpyNA(wRemaining, CharNextA(pwSegEnding), cchRemainingSize);
if (0 == pwSegEnding[1])
hr = S_FALSE; // End of the line.
}
else
{
if (wFirstItem)
StrCpyNA(wFirstItem, pwFtpWirePath, cchFirstItemSize); // pszFullPath contains only one segment
if (wRemaining)
wRemaining[0] = 0;
hr = S_FALSE; // Indicate that there aren't any more directories left.
}
return hr;
}
///////////////////////////////////////////////////////////////////////
// Display Path Functions (Unicode)
///////////////////////////////////////////////////////////////////////
/*****************************************************************************\
FUNCTION: DisplayPathAdd
DESCRIPTION:
...
\*****************************************************************************/
HRESULT DisplayPathAdd(LPWSTR pwzUrl, DWORD cchUrlSize, LPCWSTR pwzSegment)
{
// If the segment starts with a slash, skip it.
if (L'/' == pwzSegment[0])
pwzSegment = CharNext(pwzSegment);
StrCatBuffW(pwzUrl, pwzSegment, cchUrlSize);
return S_OK;
}
/*****************************************************************************\
FUNCTION: DisplayPathAppendSlash
DESCRIPTION:
\*****************************************************************************/
HRESULT DisplayPathAppendSlash(LPWSTR pwzDisplayPath, DWORD cchSize)
{
DWORD cchCurrentSize = lstrlenW(pwzDisplayPath);
HRESULT hr = CO_E_PATHTOOLONG;
if (cchCurrentSize < (cchSize - 2))
{
LPWSTR pwzEndOfPath = &pwzDisplayPath[cchCurrentSize - 1];
// Is it missing a backslash?
if ((pwzEndOfPath >= pwzDisplayPath) && TEXT('/') != pwzEndOfPath[0])
StrCatBuff(pwzEndOfPath, SZ_URL_SLASH, (cchCurrentSize + 2)); // Yes, so add it.
hr = S_OK;
}
return hr;
}
/*****************************************************************************\
FUNCTION: DisplayPathAppend
DESCRIPTION:
...
\*****************************************************************************/
HRESULT DisplayPathAppend(LPWSTR pwzDisplayPath, DWORD cchUrlSize, LPCWSTR pwzDisplaySegment)
{
if (!EVAL(pwzDisplaySegment))
return E_INVALIDARG;
DisplayPathAppendSlash(pwzDisplayPath, cchUrlSize); // Make sure the base url ends in a '/'. Note it may be "ftp://".
return DisplayPathAdd(pwzDisplayPath, cchUrlSize, pwzDisplaySegment);
}
/*****************************************************************************\
FUNCTION: DisplayPathGetFirstSegment
PARAMETERS:
[IN] pszFullPath - "Dir1\Dir2\Dir3"
[OUT] szFirstItem - "Dir1" [OPTIONAL]
[OUT] szRemaining - "Dir2\Dir3" [OPTIONAL]
\*****************************************************************************/
HRESULT DisplayPathGetFirstSegment(LPCWSTR pwzFullPath, LPWSTR pwzFirstItem, DWORD cchFirstItemSize, BOOL * pfWasFragSeparator, LPWSTR pwzRemaining, DWORD cchRemainingSize, BOOL * pfIsDir)
{
HRESULT hr = S_OK;
LPWSTR pwzSegEnding = StrChrW(pwzFullPath, CH_URL_URL_SLASH);
if (pfIsDir)
*pfIsDir = FALSE;
// This will happen if the user enters an incorrect URL, like "ftp://wired//"
// ASSERT((CH_URL_URL_SLASHW != pwzFullPath[0])); // You will probably not get what you want.
if (pwzSegEnding)
{
if (pwzFirstItem)
{
DWORD cchSize = (DWORD) (pwzSegEnding - pwzFullPath + 1);
StrCpyNW(pwzFirstItem, pwzFullPath, (cchSize <= cchFirstItemSize) ? cchSize : cchFirstItemSize);
}
if (pfIsDir && (CH_URL_URL_SLASHW == pwzSegEnding[0]))
*pfIsDir = TRUE; // Tell them that it is a directory.
if (pwzRemaining)
StrCpyNW(pwzRemaining, CharNextW(pwzSegEnding), cchRemainingSize);
if (0 == pwzSegEnding[1])
hr = S_FALSE; // End of the line.
}
else
{
if (pwzFirstItem)
StrCpyNW(pwzFirstItem, pwzFullPath, cchFirstItemSize); // pszFullPath contains only one segment
if (pwzRemaining)
pwzRemaining[0] = 0;
hr = S_FALSE; // Indicate that there aren't any more directories left.
}
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -