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

📄 ftpsite.cpp

📁 很好用的ftp源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                    hr = m_cAccount.GetUserName(HANDLE_NULLSTR(m_pszServer), szUser, ARRAYSIZE(szUser));
                    if (S_OK == hr)
                    {
                        hr = m_cAccount.GetPassword(HANDLE_NULLSTR(m_pszServer), szUser, szPassword, ARRAYSIZE(szPassword));
                        if (S_OK == hr)
                        {
                            fKeepTryingToLogin = TRUE;
                            fSkipLoginDialog = TRUE;
                        }
                    }
                }
            
                if (!fSkipLoginDialog)
                {
                    // If the user tried to log in anonymously and failed, we want to try
                    // logging in with a password.  If the user tried logging in with a password
                    // and failed, we want to keep trying to log in with a password.
                    // 
                    // DisplayLoginDialog returns S_OK for OK pressed, S_FALSE for Cancel button, and
                    //       FAILED() for something is really messed up.
                    hr = m_cAccount.DisplayLoginDialog(hwnd, dwLoginFlags, HANDLE_NULLSTR(m_pszServer),
                                szUser, ARRAYSIZE(szUser), szPassword, ARRAYSIZE(szPassword));
                }

                // S_FALSE means the user cancelled out of the Login dialog.
                // We need to turn this into an error value so the caller,
                // CFtpDir::WithHint() won't call the callback.
                if (S_FALSE == hr)
                    hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);

                fKeepTryingToLogin = (SUCCEEDED(hr) ? TRUE : FALSE);
                if (fKeepTryingToLogin)
                {
                    // We need to set the cancelled error so we don't display the
                    // error message after this.
                    hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
                }

                fTryOldPassword = FALSE;
            }
            else
                fKeepTryingToLogin = FALSE;
        }
    }
    while (fKeepTryingToLogin);

    if (!*phint)
    {
        ASSERT(2 != HRESULT_CODE(hr));        // error 2 = wininet not configured


#ifdef DEBUG
        // Gee, I wonder why I couldn't connect, let's find out.
        TCHAR szBuff[1500];
        InternetGetLastResponseInfoDisplayWrap(FALSE, NULL, szBuff, ARRAYSIZE(szBuff));
        // This may happen if the server has too many connections.  We may want to sniff
        // for this and offer to keep trying.  These are the response from the various
        // FTP Servers in this case:
        // IIS v5: 421 Too many people are connected.  Please come back when the server is less busy.
        // UNIX: ???
#endif // DEBUG
    }
    // Was a different login name or password needed in order to login successfully?
    else
    {
        LPITEMIDLIST pidlVirtualDir;

        CollectMotd(*phint);
        _QueryServerFeatures(*phint);
        // Ref Count the open connections.
//                  DEBUG_CODE(g_dwOpenConnections++;);

        // Is it a VMS Server?
        if (m_fIsServerVMS)
        {
            // Yes, so skip getting pidlVirtualDir because wininet gives us
            // garbage for FtpGetCurrentDirectoryA().
        }
        else
        {
            // NOTE: If the connection isn't annonymous, the server may put the user
            //   into a sub directory called a virtual root.  We need to squirel that
            //   directory away because it may be needed when going into sub directories
            //   relative to this virtual root.
            //     Example: ftp://user1:password@server/ puts you into /users/user1/
            //     Then: ftp://user1:password@server/dir1 really should be /users/user1/dir1/
            hr = FtpGetCurrentDirectoryPidlWrap(*phint, TRUE, GetCWireEncoding(), &pidlVirtualDir);
            if (SUCCEEDED(hr))
            {
                // Are we rooted at '/'? (Meaning no virtual root)
                Pidl_Set(&m_pidlVirtualDir, pidlVirtualDir);
                ILFree(pidlVirtualDir);
            }
        }

        //DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "CFtpSite::GetHint() FtpGetCurrentDirectory() returned %#08lx", hr));
        if (StrCmp(HANDLE_NULLSTR(m_pszUser), szUser) || StrCmp(HANDLE_NULLSTR(m_pszPassword), szPassword))
        {
            // Yes, so redirect so the AddressBand and User Status Bar pane update.
            // We normally log in with m_pidl because normally we login with
            // a default directory ('\') and then change directories to the final location.
            // we do this so isolate access denied to the server and access denied to the
            // directory.
            //
            // We pass pidlFtpPath instead in this case because it will tell the browser
            // to re-direct and we won't get a chance to do the ChangeDir later.

            Str_SetPtr(&m_pszRedirPassword, szPassword);

            _RedirectAndUpdate(m_pszServer, m_ipPortNum, szUser, szPassword, pidlFtpPath, m_pszFragment, punkSite, pff);
            hr = HRESULT_FROM_WIN32(ERROR_NETWORK_ACCESS_DENIED);
        }
    }

    // Can we assume annonymous logins don't use virtual roots?
    ASSERT(FAILED(hr) || (m_pidlVirtualDir && szUser[0]) || !(m_pidlVirtualDir && szUser[0]));

    if (psb)
        psb->SetStatusMessage(IDS_EMPTY, NULL);
    ENTERCRITICALNOASSERT;

    // The directory is empty.
    _SetPidl(NULL);

    return hr;
}


/*****************************************************************************\
    FUNCTION: GetHint

    DESCRIPTION:
        An IShellFolder client wants a handle to the FTP site.
    Pull it from the cache if possible.

    The caller should have marked the IShellFolder as busy.

    EEK!  RFC 1738 is really scary.  FTP sites don't necessarily
    start you at the root, and RFC1738 says that ftp://foo/bar asks
    for the file bar in the DEFAULT directory, not the root!
\*****************************************************************************/
HRESULT CFtpSite::GetHint(HWND hwnd, LPCITEMIDLIST pidlFtpPath, CStatusBar * psb, HINTERNET * phint, IUnknown * punkSite, CFtpFolder * pff)
{
    HINTERNET hint = NULL;
    HINTERNET hintDll = GetWininetSessionHandle();
    HRESULT hr = S_OK;

    if (!hintDll)
    {
        // No point in retrying if we can't init Wininet
        hr = HRESULT_FROM_WIN32(GetLastError());    // Save error code
    }
    else
    {
        int cTriesLeft = 1; // This is a feature that would be cool to implement.
        hr = AssureNetConnection(NULL, hwnd, m_pszServer, NULL, TRUE);

        if (ILIsEmpty(pidlFtpPath))
            pidlFtpPath = NULL;

        if (SUCCEEDED(hr))
        {
            // BUGBUG -- I don't remember exactly what the CS is protecting
            ASSERTNONCRITICAL;
            ENTERCRITICALNOASSERT;

            do
            {
                BOOL fReuseExistingConnection = FALSE;
                hr = E_FAIL;    // We don't have our hint yet...

                ASSERTCRITICAL;
                hint = (HINTERNET) InterlockedExchangePointer(&m_hint, 0);
                if (hint)
                {
                    HINTERNET hintResponse;

                    TriggerDelayedAction(&m_hgti);      // Nothing will happen
                    fReuseExistingConnection = TRUE;    // We will need to change it for the current user.

                    // We want (S_OK == hr) if our login session is still good.  Else, we want to
                    // re-login.
                    hr = FtpCommandWrap(hint, FALSE, FALSE, FTP_TRANSFER_TYPE_ASCII, FTP_CMD_NO_OP, NULL, &hintResponse);
                    if (SUCCEEDED(hr))
                    {
                        TraceMsg(TF_FTPOPERATION, "CFtpSite::GetHint() We are going to use a cached HINTERNET.");
                        InternetCloseHandleWrap(hintResponse, TRUE);
                    }
                    else
                    {
                        TraceMsg(TF_FTPOPERATION, "CFtpSite::GetHint() Can't used cached HINTERNET because server didn't respond to NOOP.");
                        InternetCloseHandleWrap(hint, TRUE);
                    }
                }
                
                if (FAILED(hr))
                {
                    hr = _LoginToTheServer(hwnd, hintDll, &hint, pidlFtpPath, psb, punkSite, pff);
                    TraceMsg(TF_FTPOPERATION, "CFtpSite::GetHint() We had to login because we didn't have a cached HINTERNET.");
                }

                ASSERTCRITICAL;
                // BUGBUG -- is it safe to do this outside the crst?
                LEAVECRITICALNOASSERT;

                // Do we need to CD into a specific directory?  Yes, if...
                // 1. We succeeded above, AND
                // 2. We are already using a connection so the dir may be incorrect, OR
                // 3. We need a non-default dir.
                if (SUCCEEDED(hr) && (fReuseExistingConnection || pidlFtpPath))   // pidlFtpPath may be NULL.
                    hr = _SetDirectory(hint, hwnd, pidlFtpPath, psb, &cTriesLeft);

                ENTERCRITICALNOASSERT;
                ASSERTCRITICAL;
            }
            while (hr == HRESULT_FROM_WIN32(ERROR_FTP_DROPPED) && --cTriesLeft);

            LEAVECRITICALNOASSERT;
        }
    }

    *phint = hint;
    return hr;
}


HRESULT CFtpSite::_CheckToEnableCHMOD(LPCWIRESTR pwResponse)
{
    HRESULT hr = S_FALSE;
    // TODO: We should probably be more restictive in how we parse the
    //       response.  We should probably verify there is some kind of
    //       white space before and after the command.
    LPCWIRESTR pwCommand = StrStrIA(pwResponse, FTP_UNIXCMD_CHMODA);

    // Does this FTP server support the "SITE CHMOD" command?
    if (pwCommand)
    {
        // Yes, so we may want to use it later.
        m_fIsCHMODSupported = TRUE;

        // We can later respond with:
        // "SITE chmod xyz FileName.txt"
        // x is for Owner, (4=Read, 2=Write, 1=Execute)
        // y is for Owner, (4=Read, 2=Write, 1=Execute)
        // z is for Owner, (4=Read, 2=Write, 1=Execute)
    }

    return hr;
}


/*****************************************************************************\
    FUNCTION: _QueryServerFeatures

    DESCRIPTION:
        Find out what the server is and isn't capable of.  Information we could
    use:
        SITE: Find out OS specific commands that may be useful.  "chmod" is one
              of them.
        HELP SITE: Find out what the OS supports.
        SYST: Find out the OS type.
        NOOP: See if the connection is still alive.
        MLST: Unambiguous Directory listing with dates in UTC.
        MLSD: 
        FEAT: Features supported. UTF8 is the one we care about. 

    Response to "SITE HELP" for these servers:
        UNIX Type: L8 Version: BSD-199506
        UNIX Type: L8
           UMASK   CHMOD   GROUP   NEWER   INDEX   ALIAS   GROUPS 
           IDLE    HELP    GPASS   MINFO   EXEC    CDPATH 

        Windows_NT version 4.0
           CKM DIRSTYLE HELP STATS    
\*****************************************************************************/
HRESULT CFtpSite::_QueryServerFeatures(HINTERNET hint)
{
    HRESULT hr = E_FAIL;
    HINTERNET hintResponse;

    // Can we turn on 'UTF8' encoding?
    if (SUCCEEDED(FtpCommandWrap(hint, FALSE, FALSE, FTP_TRANSFER_TYPE_ASCII, FTP_CMD_UTF8, NULL, &hintResponse)))
    {
        m_fInUTF8Mode = TRUE;
        m_cwe.SetUTF8Support(TRUE);
        TraceMsg(TF_FTP_OTHER, "_QueryServerFeatures() in UTF8 Mode");

        InternetCloseHandleWrap(hintResponse, TRUE);
    }
    else
    {
        TraceMsg(TF_FTP_OTHER, "_QueryServerFeatures() NOT in UTF8 Mode");
        m_fInUTF8Mode = FALSE;
    }

    if (!m_fFeaturesQueried)
    {
        // Is type of server software is running?  We want to know if we are running
        // on VMS, because in that case we want to fall back to HTML view (URLMON).
        // This is because the wininet guys don't want to support it.
        if (SUCCEEDED(FtpCommandWrap(hint, FALSE, FALSE, FTP_TRANSFER_TYPE_ASCII, FTP_CMD_SYSTEM, NULL, &hintResponse)))
        {
            DWORD dwError;
            WIRECHAR wResponse[MAX_URL_STRING];
            DWORD cchSize = ARRAYSIZE(wResponse);

            if (SUCCEEDED(InternetGetLastResponseInfoWrap(TRUE, &dwError, wResponse, &cchSize)))
            {
                // Is this a VMS server?
                if (StrStrIA(wResponse, FTP_SYST_VMS))
                    m_fIsServerVMS = TRUE;

                TraceMsg(TF_FTP_OTHER, "_QueryServerFeatures() SYSTM returned %hs.", wResponse);
            }

            InternetCloseHandleWrap(hintResponse, TRUE);
        }


#ifdef FEATURE_CHANGE_PERMISSIONS
        // Is the server capable of supporting the UNIX "chmod" command
        // to change permissions on the file?
        if (SUCCEEDED(FtpCommandWrap(hint, FALSE, FALSE, FTP_TRANSFER_TYPE_ASCII, FTP_CMD_SITE_HELP, NULL, &hintResponse)))
        {
            DWORD dwError;
            WIRECHAR wResponse[MAX_URL_STRING];
            DWORD cchSize = ARRAYSIZE(wResponse);

            if (SUCCEEDED(InternetGetLastResponseInfoWrap(TRUE, &dwError, wResponse, &cchSize)))
            {
                _CheckToEnableCHMOD(wResponse);
//                TraceMsg(TF_FTP_OTHER, "_QueryServerFeatures() SITE HELP returned success");
            }

            InternetCloseHandleWrap(hintResponse, TRUE);
        }
#endif // FEATURE_CHANGE_PERMISSIONS

/*
        // Is the server capable of supporting the UNIX "chmod" command
        // to change permissions on the file?
        if (SUCCEEDED(FtpCommandWrap(hint, FALSE, FALSE, FTP_TRANSFER_TYPE_ASCII, FTP_CMD_SITE, NULL, &hintResponse)))
        {
            DWORD dwError;
            WIRECHAR wResponse[MAX_URL_STRING];
            DWORD cchSize = ARRAYSIZE(wResponse);

            if (SUCCEEDED(InternetGetLastResponseInfoWrap(TRUE, &dwError, wResponse, &cchSize)))
            {
                TraceMsg(TF_FTP_OTHER, "_QueryServerFeatures() SITE returned succeess");
            }

            InternetCloseHandleWrap(hintResponse, TRUE);
        }
*/
    

⌨️ 快捷键说明

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