⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftppidl.cpp

📁 很好用的ftp源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
\*****************************************************************************/
HRESULT CreateFtpPidlFromUrlEx(LPCTSTR pszUrl, CWireEncoding * pwe, ULONG *pcchEaten, LPITEMIDLIST * ppidl, IMalloc * pm, BOOL fHidePassword, BOOL fIsTypeKnown, BOOL fIsDir)
{
    URL_COMPONENTS urlComps = {0};
    HRESULT hr = E_FAIL;

    // URL = "ftp://<UserName>:<Password>@<HostName>:<PortNum>/Dir1/Dir2/Dir3/file.txt[;Type=[a|b|d]]"
    TCHAR szServer[INTERNET_MAX_HOST_NAME_LENGTH];
    TCHAR szUrlPath[MAX_URL_STRING];
    TCHAR szExtraInfo[MAX_PATH];    // Includes Port Number and download type (ASCII, Binary, Detect)
    TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH];
    TCHAR szPassword[INTERNET_MAX_PASSWORD_LENGTH];

    *ppidl = 0;

    urlComps.dwStructSize = sizeof(urlComps);
    urlComps.lpszHostName = szServer;
    urlComps.dwHostNameLength = ARRAYSIZE(szServer);
    urlComps.lpszUrlPath = szUrlPath;
    urlComps.dwUrlPathLength = ARRAYSIZE(szUrlPath);

    urlComps.lpszUserName = szUserName;
    urlComps.dwUserNameLength = ARRAYSIZE(szUserName);
    urlComps.lpszPassword = szPassword;
    urlComps.dwPasswordLength = ARRAYSIZE(szPassword);
    urlComps.lpszExtraInfo = szExtraInfo;
    urlComps.dwExtraInfoLength = ARRAYSIZE(szExtraInfo);

    BOOL fResult = InternetCrackUrl(pszUrl, 0, ICU_DECODE, &urlComps);
    if (fResult && (INTERNET_SCHEME_FTP == urlComps.nScheme))
    {
        LPITEMIDLIST pidl;
        DWORD dwDownloadType = 0;   // Indicate that it hasn't yet been specified.
        BOOL fASCII;

        ASSERT(INTERNET_SCHEME_FTP == urlComps.nScheme);
        // NOTE:
        //          If the user is trying to give an NT UserName/DomainName pair, a bug will be encountered.
        //          Url in AddressBand="ftp://DomainName\UserName:Password@ServerName/"
        //          Url passed to us="ftp://DomainName/UserName:Password@ServerName/"
        //          We need to detect this case and fix it because this will cause "DomainName" to become
        //          the server name and the rest will become the UrlPath.
        // ASSERT(!StrChr(szUrlPath, TEXT(':')) && !StrChr(szUrlPath, TEXT('@')));

        if (S_OK == UrlRemoveDownloadType(szUrlPath, NULL, &fASCII))
        {
            if (fASCII)
                dwDownloadType = (IDVALID_DLTYPE | IDVALID_DL_ASCII);
            else
                dwDownloadType = IDVALID_DLTYPE;
        }

        if (!szServer[0])
        {
            TraceMsg(TF_FTPURL_UTILS, "CreateFtpPidlFromUrl() failed because szServer=%s", szServer);
            hr = E_FAIL;    // Bad URL so fail.
        }
        else
        {
            //TraceMsg(TF_FTPURL_UTILS, "CreateFtpPidlFromUrl() szServer=%s, szUrlPath=%s, szUserName=%s, szPassword=%s", szServer, szUrlPath, szUserName, szPassword);
            hr = FtpServerID_Create(szServer, szUserName, szPassword, dwDownloadType, urlComps.nPort, &pidl, pm, fHidePassword);
            if (EVAL(SUCCEEDED(hr)))
            {
                ASSERT(IsValidPIDL(pidl));
                if (szUrlPath[0] && StrCmp(szUrlPath, SZ_URL_SLASH))
                {
                    LPITEMIDLIST pidlSub;

                    hr = CreateFtpPidlFromDisplayPath(szUrlPath, pwe, pcchEaten, &pidlSub, fIsTypeKnown, fIsDir);
                    if (EVAL(SUCCEEDED(hr)))
                    {
                        // If the URL path ends in a slash, then it's safe to assume that web-based FTP
                        // is looking for a directory.  Otherwise, we choke during requests through Netscape
                        // proxies when the GET is redirected by the proxy to include the slash.
                        if (IsWebBasedFtpEnabled() && szUrlPath[lstrlen(szUrlPath)-1] == TEXT(CH_URL_URL_SLASHA))
                        {
                            LPCITEMIDLIST pidlLast = ILGetLastID(pidlSub);

                            if (pidlLast)
                                FtpItemID_SetCompatFlags(pidlLast, FtpItemID_GetCompatFlags(pidlLast) | COMPAT_WEBBASEDDIR);
                        }

                        *ppidl = ILCombine(pidl, pidlSub);
                        if (szExtraInfo[0])
                        {
                            LPITEMIDLIST pidlFragment;
                            WIRECHAR wFragment[MAX_PATH];

                            // The code page is just whatever the user is using but oh well, I don't 
                            // care about fragments.
                            SHUnicodeToAnsi(szExtraInfo, wFragment, ARRAYSIZE(wFragment));
                            // There is a fragment, so we need to add it.
                            hr = FtpItemID_CreateFake(szExtraInfo, wFragment, TRUE, FALSE, TRUE, &pidlFragment);
                            if (EVAL(SUCCEEDED(hr)))
                            {
                                LPITEMIDLIST pidlPrevious = *ppidl;

                                *ppidl = ILCombine(pidlPrevious, pidlFragment);
                                ILFree(pidlPrevious);
                                ILFree(pidlFragment);
                            }
                        }

                        hr = *ppidl ? S_OK : E_OUTOFMEMORY;
                        ILFree(pidlSub);
                    }
                    ILFree(pidl);
                }
                else
                    *ppidl = pidl;

                if (SUCCEEDED(hr))
                {
                    ASSERT(IsValidPIDL(*ppidl));
                    if (pcchEaten)
                        *pcchEaten = lstrlen(pszUrl);      // TODO: Someday we can do this recursively.
                }
            }
        }
    }
    else
        TraceMsg(TF_FTPURL_UTILS, "CreateFtpPidlFromUrl() failed InternetCrackUrl() because pszUrl=%s, fResult=%d, urlComps.nScheme=%d", pszUrl, fResult, urlComps.nScheme);

    //TraceMsg(TF_FTPURL_UTILS, "CreateFtpPidlFromUrl() is returning, hr=%#08lx", hr);
    return hr;
}


/*****************************************************************************\
     FUNCTION: Win32FindDataFromPidl
 
    DESCRIPTION:
        Fill in the WIN32_FIND_DATA data structure from the info in the pidl.
\*****************************************************************************/
HRESULT Win32FindDataFromPidl(LPCITEMIDLIST pidl, LPWIN32_FIND_DATAW pwfd, BOOL fFullPath, BOOL fInDisplayFormat)
{
    HRESULT hr = E_INVALIDARG;
    LPCITEMIDLIST pidlLast = ILGetLastID(pidl);

    ASSERT(pwfd);
    if (!EVAL(FtpPidl_IsValid(pidl)))
        return E_INVALIDARG;

    // I don't want to lie when I pass out File Size and Date info.
    if ((IDVALID_FILESIZE | IDVALID_MOD_DATE) & FtpItemID_GetTypeID(pidlLast))
    {
        pwfd->nFileSizeLow = FtpItemID_GetFileSizeLo(pidlLast);
        pwfd->nFileSizeHigh = FtpItemID_GetFileSizeHi(pidlLast);
        pwfd->dwFileAttributes = FtpItemID_GetAttributes(pidlLast);

        // See the notes in priv.h on how time works.
        pwfd->ftCreationTime = FtpPidl_GetFTPFileTime(pidlLast);
        pwfd->ftLastWriteTime = pwfd->ftCreationTime;
        pwfd->ftLastAccessTime = pwfd->ftCreationTime;

        if (fFullPath)
        {
            if (fInDisplayFormat)
                hr = GetDisplayPathFromPidl(pidl, pwfd->cFileName, ARRAYSIZE(pwfd->cFileName), FALSE);
            else
                hr = GetWirePathFromPidl(pidl, (LPWIRESTR)pwfd->cFileName, ARRAYSIZE(pwfd->cFileName), FALSE);
        }
        else
        { 
            hr = S_OK;
            if (fInDisplayFormat)
                StrCpyNW(pwfd->cFileName, FtpPidl_GetLastFileDisplayName(pidl), ARRAYSIZE(pwfd->cFileName));
            else
                StrCpyNA((LPWIRESTR)pwfd->cFileName, FtpPidl_GetLastItemWireName(pidl), ARRAYSIZE(pwfd->cFileName));
        }
    }

    return hr;
}






/****************************************************\
    FTP Server ItemIDs
\****************************************************/

/****************************************************\
    FTP PIDL Cooking functions
\****************************************************/

/*****************************************************************************\
    DATA STRUCTURE: FTPIDLIST

    DESCRIPTION:
        What our private IDLIST looks like for a file, a dir, or a fragment.

    The bytes sent to an ftp server or received from an FTP server are
    wire bytes (could be UTF-8 or DBCS/MBCS) encoded.  We also store
    a unicode version that has already been converted after trying to guess
    the code page.

    Note that the use of any TCHAR inside an IDLIST is COMPLETELY WRONG!
    IDLISTs can be saved in a file and reloaded later.  If it were saved
    by an ANSI version of the shell extension but loaded by a UNICODE
    version, things would turn ugly real fast.
\*****************************************************************************/

/*****************************************************************************\
    FTPSERVERIDLIST structure

    A typical full pidl looks like this:
    <Not Our ItemID> [Our ItemID]

    <The Internet>\[server,username,password,port#,downloadtype]\[subdir]\...\[file]

    The <The Internet> part is whatever the shell gives us in our
    CFtpFolder::_Initialize, telling us where in the namespace
    we are rooted.

    We are concerned only with the parts after the <The Internet> root,
    the offset to which is remembered in the CFtpFolder class
    in m_ibPidlRoot.  Ways of accessing various bits of
    information related to our full pidl are provided by our
    CFtpFolder implementation, qv.

    The first FTP IDList entry describes the server.  The remaining
    entries describe objects (files or folders) on the server.
\*****************************************************************************/

typedef struct tagFTPSERVERIDLIST
{
    DWORD dwIDType;                 // Server ItemID or Dir ItemID?  Which Bits are valid?
    DWORD dwVersion;                // version
    SESSIONKEY sessionKey;          // Session Key
    DWORD dwPasswordCookie;         // Password Cookie
    DWORD dwReserved1;              // for future use
    DWORD dwReserved2;              // for future use
    DWORD dwReserved3;              // for future use
    DWORD dwPortNumber;             // Port Number on server
    DWORD cchServerSize;            // StrLen of szServer
    CHAR szServer[INTERNET_MAX_HOST_NAME_LENGTH];        // Server
    DWORD cchUserNameSize;          // StrLen of szUserName
    CHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH];      // User Name for Login
    DWORD cchPasswordSize;          // StrLen of szPassword
    CHAR szPassword[INTERNET_MAX_PASSWORD_LENGTH];      // Password for Login
} FTPSERVERIDLIST;

typedef UNALIGNED FTPSERVERIDLIST * LPFTPSERVERIDLIST;


LPFTPSERVERIDLIST FtpServerID_GetData(LPCITEMIDLIST pidl)
{
    LPFTPSERVERIDLIST pFtpServerItemId = (LPFTPSERVERIDLIST) ProtocolIdlInnerData(pidl);

    if (!FtpPidl_IsValid(pidl) || 
        !IS_VALID_SERVER_ITEMID(pFtpServerItemId->dwIDType)) // If any other bits are sit, it's invalid.
        pFtpServerItemId = NULL;

    return pFtpServerItemId;
}


LPFTPSERVERIDLIST FtpServerID_GetDataSafe(LPCITEMIDLIST pidl)
{
    LPFTPSERVERIDLIST pFtpServerItemId = NULL;
    
    if (EVAL(pidl) && !ILIsEmpty(pidl))
        pFtpServerItemId = (LPFTPSERVERIDLIST) ProtocolIdlInnerData(pidl);

    return pFtpServerItemId;
}


BOOL FtpID_IsServerItemID(LPCITEMIDLIST pidl)
{
    LPFTPSERVERIDLIST pFtpServerItemID = FtpServerID_GetDataSafe(pidl);
    BOOL fIsServerItemID = FALSE;

    if (pFtpServerItemID && IS_VALID_SERVER_ITEMID(pFtpServerItemID->dwIDType))
        fIsServerItemID = TRUE;

    return fIsServerItemID;
}


LPCITEMIDLIST FtpID_GetLastIDReferense(LPCITEMIDLIST pidl)
{
    LPCITEMIDLIST pidlCurrent = pidl;
    LPCITEMIDLIST pidlNext = pidl;

    if (!pidl || ILIsEmpty(pidl))
        return pidl;

    for (; !ILIsEmpty(pidlNext); pidl = _ILNext(pidl))
    {
        pidlCurrent = pidlNext;
        pidlNext = _ILNext(pidlNext);
    }

    return pidlCurrent;
}


CCookieList * g_pCookieList = NULL;

CCookieList * GetCookieList(void)
{
    ENTERCRITICAL;
    if (!g_pCookieList)
        g_pCookieList = new CCookieList();
    ASSERT(g_pCookieList);
    LEAVECRITICAL;

    return g_pCookieList;
}

SESSIONKEY g_SessionKey = {-1, -1};

HRESULT PurgeSessionKey(void)
{
    GetSystemTimeAsFileTime(&g_SessionKey);

    return S_OK;
}

SESSIONKEY GetSessionKey(void)
{    
    if (-1 == g_SessionKey.dwHighDateTime)
        PurgeSessionKey();
    
    return g_SessionKey;
}

BOOL AreSessionKeysEqual(SESSIONKEY sk1, SESSIONKEY sk2)
{
    if ((sk1.dwHighDateTime == sk2.dwHighDateTime) &&
        (sk1.dwLowDateTime == sk2.dwLowDateTime))
    {
        return TRUE;
    }

    return FALSE;
}

// This is used in order to make sure Alpha machines don't get DWORD mis-aligned.
#define LENGTH_AFTER_ALIGN(nLen, nAlignSize)        (((nLen) % (nAlignSize)) ? ((nLen) + ((nAlignSize) - ((nLen) % (nAlignSize)))) : (nLen))

/****************************************************\
    FUNCTION: FtpServerID_Create

    DESCRIPTION:
        Create a Ftp Server ItemID and fill it in.
\****************************************************/
HRESULT FtpServerID_Create(LPCTSTR pszServer, LPCTSTR pszUserName, LPCTSTR pszPassword, 
                     DWORD dwFlags, INTERNET_PORT ipPortNum, LPITEMIDLIST * ppidl, IMalloc *pm, BOOL fHidePassword)
{
    HRESULT hr;
    DWORD cb;
    LPITEMIDLIST pidl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -