📄 ftppidl.cpp
字号:
/*****************************************************************************\
ftppidl.cpp - Pointers to Item ID Lists
This is the only file that knows the internal format of our IDLs.
\*****************************************************************************/
#include "priv.h"
#include "ftppidl.h"
#include "ftpurl.h"
#include "cookie.h"
#define NOT_INITIALIZED 10
DWORD g_fNoPasswordsInAddressBar = NOT_INITIALIZED;
#define SESSIONKEY FILETIME
// Private FtpServerID Helpers
HRESULT FtpServerID_GetServer(LPCITEMIDLIST pidl, LPTSTR szServer, DWORD cchSize);
DWORD FtpItemID_GetTypeID(LPCITEMIDLIST pidl);
// v0 never went to customers but was used in NT5 before 1799 - Shipped in: Never.
// v1 This switch was to use password cookies for a security fix. - Shipped in: Never.
// v2 this was done to not use the IDelegate's IMalloc for non-first ItemIDs - Shipped in: Never (5/15/98)
// v3 add extra padding to ItemIDs so their dwType matches that of ServerIDs - Shipped in: IE5b1, IE5b2, NT5b2 (5/25/98)
// v4 add wzDisplayName to FtpItemID - Shipped in: IE5 RTM & NT5 b3 (11/16/98)
#define PIDL_VERSION_NUMBER_UPGRADE 3
#define PIDL_VERSION_NUMBER 4
#define SIZE_ITEMID_SIZEFIELD (sizeof(DWORD) + sizeof(WORD))
#define SIZE_ITEMID_TERMINATOR (sizeof(DWORD))
/****************************************************\
IDType
DESCRIPTION:
These bits go into FTPIDLIST.dwIDType and describe
what type of pidl it is AND which areas of the
data structure have been verified by getting the
data directly from the server.
\****************************************************/
#define IDTYPE_ISVALID 0x00000001 // Set if TYPE is valid
#define IDTYPE_SERVER (0x00000002 | IDTYPE_ISVALID) // Server
#define IDTYPE_DIR (0x00000004 | IDTYPE_ISVALID) // Folder/Dir
#define IDTYPE_FILE (0x00000008 | IDTYPE_ISVALID) // File
#define IDTYPE_FILEORDIR (0x00000010 | IDTYPE_ISVALID) // File or Dir. Wasn't specified.
#define IDTYPE_FRAGMENT (0x00000020 | IDTYPE_ISVALID) // File Fragment (i.e. foobar.htm#SECTION_3)
// These are bits that indicate
// For Server ItemIDs
#define IDVALID_PORT_NUM 0x00000100 // Was the port number specified
#define IDVALID_USERNAME 0x00000200 // Was the login name specified
#define IDVALID_PASSWORD 0x00000400 // Was the password specified
#define IDVALID_DLTYPE 0x00000800 // Download Type is specified.
#define IDVALID_DL_ASCII 0x00001000 // Download as ASCII if set, otherwise, download as BINARY.
#define IDVALID_HIDE_PASSWORD 0x00002000 // The Password entry is invalid so use the sessionkey to look it up.
#define VALID_SERVER_BITS (IDTYPE_ISVALID|IDTYPE_SERVER|IDVALID_PORT_NUM|IDVALID_USERNAME|IDVALID_PASSWORD|IDVALID_DLTYPE|IDVALID_DL_ASCII|IDVALID_HIDE_PASSWORD)
#define IS_VALID_SERVER_ITEMID(pItemId) (!(pItemId & ~VALID_SERVER_BITS))
// For Dir/File ItemIDs
#define IDVALID_FILESIZE 0x00010000 // Did we get the file size from the server?
#define IDVALID_MOD_DATE 0x00020000 // Did we get the modification date from the server?
#define VALID_DIRORFILE_BITS (IDTYPE_ISVALID|IDTYPE_DIR|IDTYPE_FILE|IDTYPE_FILEORDIR|IDTYPE_FRAGMENT|IDVALID_FILESIZE|IDVALID_MOD_DATE)
#define IS_VALID_DIRORFILE_ITEMID(pItemId) (!(pItemId & (~VALID_DIRORFILE_BITS & ~IDTYPE_ISVALID)))
#define IS_FRAGMENT(pFtpIDList) (IDTYPE_ISVALID != (IDTYPE_FRAGMENT & pFtpIDList->dwIDType))
///////////////////////////////////////////////////////////
// FTP Pidl Helper Functions
///////////////////////////////////////////////////////////
/*****************************************************************************\
FUNCTION: UrlGetAbstractPathFromPidl
DESCRIPTION:
pszUrlPath will be UNEscaped and in Wire Bytes.
\*****************************************************************************/
HRESULT UrlGetAbstractPathFromPidl(LPCITEMIDLIST pidl, BOOL fDirsOnly, BOOL fInWireBytes, void * pvPath, DWORD cchUrlPathSize)
{
HRESULT hr = S_OK;
LPWIRESTR pwWirePath = (LPWIRESTR) pvPath;
LPWSTR pwzDisplayPath = (LPWSTR) pvPath;
if (!EVAL(FtpPidl_IsValid(pidl)))
return E_INVALIDARG;
ASSERT(pvPath && (0 < cchUrlPathSize));
ASSERT(IsValidPIDL(pidl));
if (fInWireBytes)
{
pwWirePath[0] = '/';
pwWirePath[1] = '\0'; // Make this path absolute.
}
else
{
pwzDisplayPath[0] = L'/';
pwzDisplayPath[1] = L'\0'; // Make this path absolute.
}
if (!ILIsEmpty(pidl) && FtpID_IsServerItemID(pidl)) // If it's not a server, we are screwed.
pidl = _ILNext(pidl); // Skip past the Server Pidl.
for (; !ILIsEmpty(pidl); pidl = _ILNext(pidl))
{
if (!fDirsOnly || FtpItemID_IsDirectory(pidl, TRUE) || !ILIsEmpty(_ILNext(pidl)))
{
if (!FtpItemID_IsFragment(pidl))
{
if (fInWireBytes)
{
LPCWIRESTR pwWireName = FtpItemID_GetWireNameReference(pidl);
if (pwWireName)
{
// The caller should never need the URL Path escaped because
// that will happen when it's converted into an URL.
WirePathAppend(pwWirePath, cchUrlPathSize, pwWireName);
}
}
else
{
LPCWSTR pwzDisplayName = FtpItemID_GetDisplayNameReference(pidl);
if (pwzDisplayName)
{
// The caller should never need the URL Path escaped because
// that will happen when it's converted into an URL.
DisplayPathAppend(pwzDisplayPath, cchUrlPathSize, pwzDisplayName);
}
}
}
}
if (SUCCEEDED(hr) && (FtpItemID_IsDirectory(pidl, FALSE) || (FtpItemID_GetCompatFlags(pidl) & COMPAT_WEBBASEDDIR)))
{
if (fInWireBytes)
WirePathAppendSlash(pwWirePath, cchUrlPathSize); // Always make sure dirs end in '/'.
else
DisplayPathAppendSlash(pwzDisplayPath, cchUrlPathSize); // Always make sure dirs end in '/'.
}
}
return hr;
}
/*****************************************************************************\
FUNCTION: GetDisplayPathFromPidl
DESCRIPTION:
pwzDisplayPath will be UNEscaped and in display unicode.
\*****************************************************************************/
HRESULT GetDisplayPathFromPidl(LPCITEMIDLIST pidl, LPWSTR pwzDisplayPath, DWORD cchUrlPathSize, BOOL fDirsOnly)
{
return UrlGetAbstractPathFromPidl(pidl, fDirsOnly, FALSE, (void *) pwzDisplayPath, cchUrlPathSize);
}
/*****************************************************************************\
FUNCTION: GetWirePathFromPidl
DESCRIPTION:
pszUrlPath will be UNEscaped and in Wire Bytes.
\*****************************************************************************/
HRESULT GetWirePathFromPidl(LPCITEMIDLIST pidl, LPWIRESTR pwWirePath, DWORD cchUrlPathSize, BOOL fDirsOnly)
{
return UrlGetAbstractPathFromPidl(pidl, fDirsOnly, TRUE, (void *) pwWirePath, cchUrlPathSize);
}
/*****************************************************************************\
FUNCTION: UrlGetFileNameFromPidl
DESCRIPTION:
pszFileName will be filled with the file name if it exists. If it doesn't,
S_FALSE will be returned if the PIDL only points to a directory and not
a file.
HRESULT UrlGetFileNameFromPidl(LPCITEMIDLIST pidl, LPTSTR pszFileName, DWORD cchSize)
{
HRESULT hr = S_FALSE;
if (!EVAL(FtpPidl_IsValid(pidl)))
return E_INVALIDARG;
ASSERT(pszFileName && (0 < cchSize));
ASSERT(IsValidPIDL(pidl));
pszFileName[0] = TEXT('\0');
if (EVAL(FtpID_IsServerItemID(pidl))) // If it's not a server, we are screwed.
pidl = _ILNext(pidl); // Skip past the Server Pidl.
for (; !ILIsEmpty(pidl); pidl = _ILNext(pidl))
{
if (!FtpItemID_IsDirectory(pidl, FALSE))
{
// This isn't a directory, so the only time it's valid to not
// be the last ItemID is if this is a file ItemID and the next
// ItemID is a Fragment.
ASSERT(ILIsEmpty(_ILNext(pidl)) || FtpItemID_IsFragment(_ILNext(pidl)));
SHAnsiToTChar(FtpItemID_GetFileName(pidl), pszFileName, cchSize);
hr = S_OK;
break;
}
}
return hr;
}
\*****************************************************************************/
#ifndef UNICODE
/*****************************************************************************\
FUNCTION: UrlCreateFromPidlW
DESCRIPTION:
x.
\*****************************************************************************/
HRESULT UrlCreateFromPidlW(LPCITEMIDLIST pidl, DWORD shgno, LPWSTR pwzUrl, DWORD cchSize, DWORD dwFlags, BOOL fHidePassword)
{
HRESULT hr;
TCHAR szUrl[MAX_URL_STRING];
hr = UrlCreateFromPidl(pidl, shgno, szUrl, ARRAYSIZE(szUrl), dwFlags, fHidePassword);
if (SUCCEEDED(hr))
SHTCharToUnicode(szUrl, pwzUrl, cchSize);
return hr;
}
#else // UNICODE
/*****************************************************************************\
FUNCTION: UrlCreateFromPidlA
DESCRIPTION:
x.
\*****************************************************************************/
HRESULT UrlCreateFromPidlA(LPCITEMIDLIST pidl, DWORD shgno, LPSTR pszUrl, DWORD cchSize, DWORD dwFlags, BOOL fHidePassword)
{
HRESULT hr;
TCHAR szUrl[MAX_URL_STRING];
hr = UrlCreateFromPidl(pidl, shgno, szUrl, ARRAYSIZE(szUrl), dwFlags, fHidePassword);
if (SUCCEEDED(hr))
SHTCharToAnsi(szUrl, pszUrl, cchSize);
return hr;
}
#endif // UNICODE
BOOL IncludePassword(void)
{
if (NOT_INITIALIZED == g_fNoPasswordsInAddressBar)
g_fNoPasswordsInAddressBar = !SHRegGetBoolUSValue(SZ_REGKEY_FTPFOLDER, SZ_REGVALUE_PASSWDSIN_ADDRBAR, FALSE, TRUE);
return g_fNoPasswordsInAddressBar;
}
HRESULT ParseUrlCreateFromPidl(LPCITEMIDLIST pidl, LPTSTR pszUrl, DWORD cchSize, DWORD dwFlags, BOOL fHidePassword)
{
HRESULT hr = S_OK;
TCHAR szServer[INTERNET_MAX_HOST_NAME_LENGTH];
TCHAR szUrlPath[MAX_URL_STRING];
TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH];
TCHAR szPassword[INTERNET_MAX_PASSWORD_LENGTH];
TCHAR szFragment[MAX_PATH];
TCHAR szDownloadType[MAX_PATH] = TEXT("");
INTERNET_PORT ipPortNum = INTERNET_DEFAULT_FTP_PORT;
if (ILIsEmpty(pidl))
{
ASSERT(0); // BUGBUG: Work around until we can figure out why CFtpFolder has ILIsEmpty(m_pidlHere).
szServer[0] = szUrlPath[0] = szUserName[0] = szPassword[0] = TEXT('\0');
hr = E_FAIL;
}
else
{
FtpPidl_GetServer(pidl, szServer, ARRAYSIZE(szServer));
GetDisplayPathFromPidl(pidl, szUrlPath, ARRAYSIZE(szUrlPath), FALSE);
FtpPidl_GetUserName(pidl, szUserName, ARRAYSIZE(szUserName));
if (FAILED(FtpPidl_GetPassword(pidl, szPassword, ARRAYSIZE(szPassword), !fHidePassword)))
szPassword[0] = 0;
FtpPidl_GetFragment(pidl, szFragment, ARRAYSIZE(szPassword));
FtpPidl_GetDownloadTypeStr(pidl, szDownloadType, ARRAYSIZE(szDownloadType));
UrlPathAdd(szUrlPath, ARRAYSIZE(szUrlPath), szDownloadType);
ipPortNum = FtpPidl_GetPortNum(pidl);
}
if (SUCCEEDED(hr))
{
TCHAR szUserNameEscaped[INTERNET_MAX_USER_NAME_LENGTH];
szUserNameEscaped[0] = 0;
if (szUserName[0])
EscapeString(szUserName, szUserNameEscaped, ARRAYSIZE(szUserNameEscaped));
hr = UrlCreateEx(szServer, NULL_FOR_EMPTYSTR(szUserNameEscaped), szPassword, szUrlPath, szFragment, ipPortNum, szDownloadType, pszUrl, cchSize, dwFlags);
}
return hr;
}
/*****************************************************************************\
FUNCTION: GetFullPrettyName
DESCRIPTION:
The user wants a pretty name so these are the cases we need to worry
about:
URL: Pretty Name:
---------------------------------- ---------------------
ftp://joe:psswd@serv/ serv
ftp://joe:psswd@serv/dir1/ dir1 on serv
ftp://joe:psswd@serv/dir1/dir2/ dir2 on serv
ftp://joe:psswd@serv/dir1/dir2/file.txt file.txt on serv
\*****************************************************************************/
HRESULT GetFullPrettyName(LPCITEMIDLIST pidl, LPTSTR pszUrl, DWORD cchSize)
{
HRESULT hr = S_OK;
TCHAR szServer[INTERNET_MAX_HOST_NAME_LENGTH];
FtpPidl_GetServer(pidl, szServer, ARRAYSIZE(szServer));
// Is there anything after the ServerItemID?
if (!ILIsEmpty(_ILNext(pidl)))
{
// Yes, so let's get the name of the last item and
// make the string "<LastItemName> on <Server>".
LPCWSTR pwzLastItem = FtpItemID_GetDisplayNameReference(ILFindLastID(pidl));
LPTSTR pszStrArray[] = {szServer, (LPTSTR)pwzLastItem};
TCHAR szTemplate[MAX_PATH];
EVAL(LoadString(HINST_THISDLL, IDS_PRETTYNAMEFORMAT, szTemplate, ARRAYSIZE(szTemplate)));
EVAL(FormatMessage((FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY), (LPVOID)szTemplate,
0, 0, pszUrl, cchSize, (va_list*)pszStrArray));
}
else
{
// No, so we are done.
StrCpyN(pszUrl, szServer, cchSize);
}
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -