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

📄 ftpdrop.cpp

📁 很好用的ftp源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************\
    FILE: ftpdrop.cpp - IDropTarget interface

    Remarks:

    Note that you cannot create a shortcut on an FTP site.  Although
    there's nothing technically preventing it, it's not done because
    the shortcut won't be of much use on an FTP site.  (It points to
    your local machine, which doesn't help much for people not on the
    same network!)

    If you really want to put a shortcut file on an FTP site, create
    it on the desktop, then drag the shortcut onto the FTP site.

    The default verb for FTP sites is always "Copy".  This is true
    even if an intra-site drag-drop is being done.

    DESCRIPTION:
        DefView will cache the IDropTarget pointer (CFtpDrop) for a shell extension.
    When it calls CFtpDrop::Drop(), the work needs to be done on a background
    thread in order to not block the UI thread.  The problem is that if the user
    does another drag to the same Ftp Window, CFtpDrop::Drop() will be called again.
    For this reasons, CFtpDrop::Drop() cannot have any state after it returns.
    In order to accomplish this with the asynch background thread, we have
    CFtpDrop::Drop() call CDropOperation_Create(), and then CDropOperation->DoOperation().
    And then it will orphan (call Release()) the CDropOperation.  The CDropOperation
    will then destroy itself when the copy is finishes.  This enables subsequent calls
    to CFtpDrop::Drop() to spawn separate CDropOperation objects so each can maintain
    the state for that specifc operation and CFtpDrop remains stateless.
\*****************************************************************************/

#include "priv.h"
#include "ftpdrop.h"
#include "ftpurl.h"
#include "statusbr.h"
#include "newmenu.h"

class CDropOperation;
HRESULT CDropOperation_Create(CFtpFolder * pff, HWND hwnd, LPCTSTR pszzFSSource, LPCTSTR pszzFtpDest, CDropOperation ** ppfdt, DROPEFFECT de, OPS ops, int cobj);
HRESULT ConfirmCopy(LPCWSTR pszLocal, LPCWSTR pszFtpName, OPS * pOps, HWND hwnd, CFtpFolder * pff, CFtpDir * pfd, DROPEFFECT * pde, int nObjs, BOOL * pfFireChangeNotify);


// Declared because of recusion
HRESULT FtpCopyDirectory(HINTERNET hint, HINTPROCINFO * phpi, LPCOPYONEHDROPINFO pcohi);
HRESULT FtpCopyFile(HINTERNET hint, HINTPROCINFO * phpi, LPCOPYONEHDROPINFO pcohi);


HRESULT UpdateCopyFileName(LPCOPYONEHDROPINFO pcohi)
{
    HRESULT hr = S_OK;
    static WCHAR wzCopyTemplate[MAX_PATH] = L"";
    WCHAR wzLine1[MAX_PATH];

    if (!wzCopyTemplate[0])
        LoadStringW(HINST_THISDLL, IDS_COPYING, wzCopyTemplate, ARRAYSIZE(wzCopyTemplate));

    wnsprintfW(wzLine1, ARRAYSIZE(wzLine1), wzCopyTemplate, pcohi->pszFtpDest);

    EVAL(SUCCEEDED(pcohi->progInfo.ppd->SetLine(1, wzLine1, FALSE, NULL)));

    return hr;
}


HRESULT UpdateSrcDestDirs(LPCOPYONEHDROPINFO pcohi)
{
    HRESULT hr = S_OK;
    WCHAR wzFrom[MAX_PATH];
    WCHAR wzStatusStr[MAX_PATH];

    StrCpyN(wzFrom, pcohi->pszFSSource, ARRAYSIZE(wzFrom));
    PathRemoveFileSpecW(wzFrom);

    if (EVAL(SUCCEEDED(hr = CreateFromToStr(wzStatusStr, ARRAYSIZE(wzStatusStr), wzFrom, pcohi->pszDir))))
        EVAL(SUCCEEDED(hr = pcohi->progInfo.ppd->SetLine(2, wzStatusStr, FALSE, NULL)));    // Line one is the file being copied.

    return hr;
}


HRESULT DeleteOneFileCB(HINTERNET hint, HINTPROCINFO * phpi, LPVOID pv, BOOL * pfReleaseHint)
{
    LPCOPYONEHDROPINFO pcohi = (LPCOPYONEHDROPINFO) pv;
    WIRECHAR wFtpPath[MAX_PATH];

    phpi->pfd->GetFtpSite()->GetCWireEncoding()->UnicodeToWireBytes(pcohi->pmlc, pcohi->pszFtpDest, (phpi->pfd->IsUTF8Supported() ? WIREENC_USE_UTF8 : WIREENC_NONE), wFtpPath, ARRAYSIZE(wFtpPath));
    return FtpDeleteFileWrap(hint, TRUE, wFtpPath);
}


HRESULT UpdateProgressDialogStr(LPCOPYONEHDROPINFO pcohi)
{
    EVAL(SUCCEEDED(UpdateCopyFileName(pcohi)));
    EVAL(SUCCEEDED(UpdateSrcDestDirs(pcohi)));
    return S_OK;
}


/*****************************************************************************\
    CopyFileSysItem

    This function may cause recursion.
\*****************************************************************************/
HRESULT CopyFileSysItem(HINTERNET hint, HINTPROCINFO * phpi, LPCOPYONEHDROPINFO pcohi)
{
    HRESULT hr = S_OK;

    // Check if the user canceled.
    if (pcohi->progInfo.ppd)
    {
        if (pcohi->progInfo.ppd->HasUserCancelled())
            return HRESULT_FROM_WIN32(ERROR_CANCELLED);

        if (pcohi->dwOperation != COHDI_FILESIZE_COUNT)
            UpdateProgressDialogStr(pcohi);
    }

    if (PathIsDirectory(pcohi->pszFSSource))
    {
        hr = FtpCopyDirectory(hint, phpi, pcohi);

        if (SUCCEEDED(hr) && (pcohi->dwOperation != COHDI_FILESIZE_COUNT))
        {
            /*
            WIN32_FIND_DATA wfd;
            HANDLE handle = FindFirstFile(pcohi->pszFSSource, &wfd);

            // BUGBUG: The date is wrong doing it this way, but it's faster.  We should
            //         find out if FtpCreateDirectory always stamps the directory with
            //         the current date, and then update wfd with the current time/date.
            //         This will simulate the server entry w/o the perf hit.
            if (handle != INVALID_HANDLE_VALUE)
            {
                // If we are the root, then we need to notify the shell that
                // a folder was created so the view needs to be updated.
                // We fire the FtpChangeNotify() call for SHCNE_MKDIR in FtpCreateDirectoryWithCN().
                // FtpChangeNotify(SHCNE_MKDIR) is fired in FtpCreateDirectoryWithCN
                FindClose(handle);
            }
            */
        }
    }
    else
        hr = FtpCopyFile(hint, phpi, pcohi);

    return hr;
}


HRESULT FtpCopyItem(HINTERNET hint, HINTPROCINFO * phpi, LPCOPYONEHDROPINFO pcohi, LPWIN32_FIND_DATA pwfd, LPCWIRESTR pwCurrentDir)
{
    HRESULT hr = S_OK;
    TCHAR szFrom[MAX_PATH];
    WCHAR wzDestDir[MAX_PATH];
    TCHAR szServer[INTERNET_MAX_HOST_NAME_LENGTH];
    COPYONEHDROPINFO cohi = {pcohi->pff, szFrom, pwfd->cFileName, wzDestDir, pcohi->dwOperation, pcohi->ops, FALSE, pcohi->pmlc, pcohi->pidlServer, pcohi->fFireChangeNotify, NULL};
    CFtpDir * pfd = phpi->pfd;
    BOOL fSkipCurrentFile = FALSE;
    CWireEncoding * pwe = phpi->pfd->GetFtpSite()->GetCWireEncoding();

    cohi.progInfo.ppd = pcohi->progInfo.ppd;
    cohi.progInfo.hint = pcohi->progInfo.hint;
    cohi.progInfo.uliBytesCompleted.QuadPart = pcohi->progInfo.uliBytesCompleted.QuadPart;
    cohi.progInfo.uliBytesTotal.QuadPart = pcohi->progInfo.uliBytesTotal.QuadPart;

    EVAL(SUCCEEDED(pwe->WireBytesToUnicode(pcohi->pmlc, pwCurrentDir, (pfd->IsUTF8Supported() ? WIREENC_USE_UTF8 : WIREENC_NONE), wzDestDir, ARRAYSIZE(wzDestDir))));
    DisplayPathAppend(wzDestDir, ARRAYSIZE(wzDestDir), pcohi->pszFtpDest);

    if (EVAL(SUCCEEDED(pfd->GetFtpSite()->GetServer(szServer, ARRAYSIZE(szServer)))) &&
        SUCCEEDED(pfd->GetFtpSite()->GetFtpDir(szServer, wzDestDir, &(phpi->pfd))))
    {
        ASSERT(phpi->hwnd);
        // Make sure the user thinks it's ok to replace.  We don't care about replacing directories
        if ((pcohi->dwOperation != COHDI_FILESIZE_COUNT) &&
            !(FILE_ATTRIBUTE_DIRECTORY & pwfd->dwFileAttributes))
        {
            TCHAR szSourceFile[MAX_PATH];

            StrCpyN(szSourceFile, pcohi->pszFSSource, ARRAYSIZE(szSourceFile));
            if (PathAppend(szSourceFile, pwfd->cFileName))
            {
                // PERF: We should do the Confirm copy only if the upload fails because it's
                //       so costly.
                hr = ConfirmCopy(szSourceFile, pwfd->cFileName, &(cohi.ops), phpi->hwnd, pcohi->pff, phpi->pfd, NULL, 1, &cohi.fFireChangeNotify);
                if (S_FALSE == hr)
                {
                    // S_FALSE from ConfirmCopy() means doen't replace this specific file, but continue
                    // copying.  We need to return S_OK or we will cancel copying all the files.
                    fSkipCurrentFile = TRUE;
                    hr = S_OK;
                }
            }
            else
                hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);    // Path too long, probably.
        }

        if (!fSkipCurrentFile && (S_OK == hr) && IS_VALID_FILE(pwfd->cFileName))
        {
            StrCpyN(szFrom, pcohi->pszFSSource, ARRAYSIZE(szFrom));     // Set the source directory.
            // Specify the file/dir in that directory to copy.
            if (PathAppend(szFrom, pwfd->cFileName))
            {
                // 5. Call CopyFileSysItem() to get it copied (maybe recursively)
                //TraceMsg(TF_FTPOPERATION, "FtpCopyDirectory() calling CopyFileSysItem(From=%s. To=%s)", szFrom, pwfd->cFileName);
                hr = CopyFileSysItem(hint, phpi, &cohi);
                if (FAILED(hr) && (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr) &&
                    (pcohi->dwOperation != COHDI_FILESIZE_COUNT))
                {
                    int nResult = DisplayWininetError(phpi->hwnd, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_FILECOPY, IDS_FTPERR_WININET, MB_OK, pcohi->progInfo.ppd);
                    hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
                }
            }
            else
                hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);    // Path too long, probably.
        }


        pcohi->progInfo.hint = cohi.progInfo.hint;    // Maybe the user cancelled.
        pcohi->progInfo.uliBytesCompleted.QuadPart = cohi.progInfo.uliBytesCompleted.QuadPart;
        pcohi->progInfo.uliBytesTotal.QuadPart = cohi.progInfo.uliBytesTotal.QuadPart;
        pcohi->ops = cohi.ops;
        phpi->pfd->Release();
    }

    phpi->pfd = pfd;
    return hr;
}

HRESULT _FtpSetCurrentDirectory(HINTERNET hint, HINTPROCINFO * phpi, LPCWSTR pwzFtpPath)
{
    HRESULT hr;
    WIRECHAR wFtpPath[MAX_PATH];
    CWireEncoding * pwe = phpi->pfd->GetFtpSite()->GetCWireEncoding();

    hr = pwe->UnicodeToWireBytes(NULL, pwzFtpPath, (phpi->pfd->IsUTF8Supported() ? WIREENC_USE_UTF8 : WIREENC_NONE), wFtpPath, ARRAYSIZE(wFtpPath));
    if (SUCCEEDED(hr))
        hr = FtpSetCurrentDirectoryWrap(hint, TRUE, wFtpPath);

    return hr;
}

/*****************************************************************************\
     FtpCopyDirectory
 
    DESCRIPTION:
        This function will need to copy all the items in the directory to the
    FTP server if the item is a folder, it will need to recurse.

    Recursion algorithm:
    // 1. Create Directory
    // 2. Get Current Directory (To save for later).
    // 3. Change Directory Into new Directory.
    // 4. Find Next item (file/dir) in file system
    // 5. Call CopyFileSysItem() to get it copied (maybe recursively)
    // 6. Go to Step 4 if there are any left.
    // 7. Go back to original directory (Step 2)
\*****************************************************************************/
HRESULT FtpCopyDirectory(HINTERNET hint, HINTPROCINFO * phpi, LPCOPYONEHDROPINFO pcohi)
{
    HRESULT hr = S_OK;

    if (phpi->psb && (pcohi->dwOperation != COHDI_FILESIZE_COUNT))
        phpi->psb->SetStatusMessage(IDS_COPYING, pcohi->pszFSSource);

    //TraceMsg(TF_FTPOPERATION, "FtpCopyDirectory() calling FtpCreateDirectoryA(%s)", pcohi->pszFSSource);

    // Create the directories on the first pass when we calculate file sizes.
    // We then skip creating them on the copy pass.
    if (pcohi->dwOperation == COHDI_FILESIZE_COUNT)
    {
        hr = FtpSafeCreateDirectory(phpi->hwnd, hint, pcohi->pmlc, pcohi->pff, phpi->pfd, pcohi->progInfo.ppd, pcohi->pszFtpDest, pcohi->fIsRoot);
    }

    // 1. Create Directory
    if (SUCCEEDED(hr))
    {
        WIRECHAR wCurrentDir[MAX_PATH];

        hr = FtpGetCurrentDirectoryWrap(hint, TRUE, wCurrentDir, ARRAYSIZE(wCurrentDir));
        if (EVAL(SUCCEEDED(hr)))
        {
            // NOTE: At this point, pcohi->pszFSSource is the DIRECTORY on the local
            //       file system that is being copied.
            hr = _FtpSetCurrentDirectory(hint, phpi, pcohi->pszFtpDest);
            if (SUCCEEDED(hr))
            {
                WCHAR szSearchStr[MAX_PATH*2];
                WIN32_FIND_DATA wfd;
                HANDLE handle = NULL;

                StrCpyN(szSearchStr, pcohi->pszFSSource, ARRAYSIZE(szSearchStr));
                // We need to copy the entire directory.
                if (PathAppend(szSearchStr, SZ_ALL_FILES))
                {
                    // 4. Find Next item (file/dir) in file system
                    handle = FindFirstFile(szSearchStr, &wfd);
                    if (handle != INVALID_HANDLE_VALUE)
                    {
                        do
                        {
                            //TraceMsg(TF_WININET_DEBUG, "FindFirstFileNext() returned %s", wfd.cFileName);
                            hr = FtpCopyItem(hint, phpi, pcohi, &wfd, wCurrentDir);

                            // 6. Check if the user canceled.
                            if ((pcohi->progInfo.ppd) && (pcohi->progInfo.ppd->HasUserCancelled()))
                            {
                                hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
                                break;
                            }

                            // 7. Repeat if there are any left and it wasn't cancelled (S_FALSE)
                        }
                        while ((S_OK == hr) && FindNextFile(handle, &wfd));

                        FindClose(handle);
                    }
                }
                else
                    hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);    // Path too long, probably.
            }

            // 7. Go back to original directory (from Step 2)
            // The only time we don't want to return to the original directory is if
            // the hinst was freed in an wininet callback function.  We may cache the hinst
            // so we need the directory to be valid later.
            if (pcohi->progInfo.hint)
            {
                EVAL(SUCCEEDED(FtpSetCurrentDirectoryWrap(hint, TRUE, wCurrentDir)));
            }
        }
    }
    else
    {
        if (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr)
        {
            DisplayWininetError(phpi->hwnd, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_DIRCOPY, IDS_FTPERR_WININET, MB_OK, pcohi->progInfo.ppd);
            hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
        }
    }

    return hr;
}


HRESULT UpdateCopyProgressInfo(IProgressDialog * ppd, LPCTSTR pszFileName)
{
    HRESULT hr = E_FAIL;
    TCHAR szTemplate[MAX_PATH];

    if (EVAL(LoadString(HINST_THISDLL, IDS_COPYING, szTemplate, ARRAYSIZE(szTemplate))))
    {
        TCHAR szStatusStr[MAX_PATH];
        WCHAR wzStatusStr[MAX_PATH];

        wnsprintf(szStatusStr, ARRAYSIZE(szStatusStr), szTemplate, pszFileName);
        SHTCharToUnicode(szStatusStr, wzStatusStr, ARRAYSIZE(wzStatusStr));
        EVAL(SUCCEEDED(hr = ppd->SetLine(1, wzStatusStr, FALSE, NULL)));
    }

    return hr;

⌨️ 快捷键说明

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