home *** CD-ROM | disk | FTP | other *** search
/ Mastering MFC Development / MMD.ISO / labs / c11 / lab03 / ex01 / ftpget.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-20  |  9.5 KB  |  383 lines

  1. // FtpGet.cpp : implementation file
  2. //
  3.  
  4.  
  5. #include "stdafx.h"
  6. #include "afxinet.h"
  7.  
  8. #include <direct.h>        // for _mkdir()
  9. #include <errno.h>
  10. #include <time.h>
  11.  
  12. #include "ftp.h"
  13. #include "FtpView.h"
  14. #include "FtpGet.h"
  15.  
  16.  
  17. #ifdef _DEBUG
  18. #define new DEBUG_NEW
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CFtpGet
  25.  
  26. CFtpGet::CFtpGet()
  27. {
  28. }
  29. CFtpGet::CFtpGet(CFtpView* pView, CString& Server, CString& FileTypes, CString& Path, CString& LocalRoot, CString& Gateway, int CopyType)
  30. {
  31.     m_ftp= NULL;
  32.     m_TotalFileSize= 0;
  33.  
  34.     m_strServer= Server;
  35.     m_strFileTypes= FileTypes;
  36.     m_strPath= Path;
  37.     m_strLocalRoot= LocalRoot;
  38.     m_strGateway= Gateway;
  39.     m_CopyType= CopyType;
  40.  
  41.     m_pView= pView;
  42. }
  43.  
  44. CFtpGet::~CFtpGet()
  45. {
  46. }
  47.  
  48. /////////////////////////////////////////////////////
  49.  
  50. ///////////////////////////////////////////////////////////////////////
  51. // DoFtpTransfer()
  52. //    Initiate an FTP session, perform the operation, close up.
  53. void CFtpGet::DoFtpTransfer()
  54. {
  55.         try 
  56.         {
  57.             //
  58.             // 1) Create an Internet session
  59.             //
  60.             m_pView->AddToView("Creating session...");
  61.             CInternetSession session;
  62.  
  63.             //
  64.             // 2) Establish FTP connection
  65.             //
  66.             m_pView->AddToView("Getting ftp connection...");
  67.             // Heuristic:  If no gateway is specified then use server name directly,
  68.             //    otherwise use gateway as proxy server.
  69.             if (m_strGateway.IsEmpty()) 
  70.             {
  71.                 m_ftp= session.GetFtpConnection(m_strServer);
  72.             } 
  73.             else 
  74.             {
  75.                 m_ftp= session.GetFtpConnection(
  76.                     m_strGateway, 
  77.                     "anonymous@" + m_strServer, 
  78.                     "YourName@YourCom.com"
  79.                     );
  80.             }
  81.             m_pView->AddToView("Connection made.");
  82.  
  83.             //
  84.             // 3) Some miscellaneous initialization
  85.             //
  86.             // If no server path specified, make a "wildcard path".
  87.             if (m_strPath.IsEmpty()) 
  88.             {
  89.                 m_strPath= "*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\";
  90.                 if (m_CopyType==FC_LEAFFILES)
  91.                 {
  92.                     m_CopyType= FC_ALL;
  93.                 }
  94.             }
  95.             // Split path string up and place into string arrays, one for each path element.
  96.             PathToArray(m_strPath, m_arrStaticPath);    // original path as user entered.
  97.             PathToArray(m_strPath, m_arrDynamicPath);    // path with wildcard characters
  98.             m_count= 0;        // total files found.
  99.                                                         // replaced with matched directories.
  100.             //
  101.             // 4) Begin file transfer starting at root of FTP server.
  102.             //
  103.             CopyDirectory(0);        
  104.  
  105.             //
  106.             // 5) Close things up
  107.             //    
  108.             m_ftp->Close();
  109.             delete m_ftp;
  110.             session.Close();
  111.             m_pView->AddToView("Connection closed.");
  112.         } 
  113.         catch (CInternetException* pIE) 
  114.         {
  115.             CString err;
  116.             err.Format("Error: %d", pIE->m_dwError); 
  117.             AfxMessageBox(err);
  118.             m_pView->AddToView(err);
  119.             pIE->Delete();
  120.         } 
  121.         catch (CException* pIE) 
  122.         {
  123.             char msg[255];
  124.             pIE->GetErrorMessage(msg, 255);
  125.             AfxMessageBox(msg);
  126.             m_pView->AddToView(msg);
  127.             pIE->Delete();
  128.         }
  129.  
  130. }
  131.  
  132. ///////////////////////////////////////////////////////////////////////
  133. // CopyDirectory()
  134. //    Main function to do the copy of matched filenames.
  135. //    Return FALSE if there was a failure somewhere.
  136. //    
  137. BOOL CFtpGet::CopyDirectory(int PathLevel)
  138. {
  139.  
  140.     //
  141.     // 0) Initialization
  142.     //
  143.  
  144.     // Set source directory at ftp site.
  145.     // A level of 0 is the server root, 1 is first sub-dir, etc
  146.     if (!SetFtpDirectory(PathLevel)) 
  147.     {
  148.         m_pView->AddToView("Cannot set ftp directory");
  149.         return FALSE;
  150.     }
  151.  
  152.  
  153.     // Set a flag to determine whether or not this is a dir to copy.
  154.     BOOL bCopy= (m_CopyType==FC_ALL) || 
  155.         ((m_CopyType==FC_LEAFFILES)&&(PathLevel == m_arrDynamicPath.GetSize()));
  156.  
  157.     //
  158.     // 1) Find desired files for current directory and copy.
  159.     //
  160.  
  161.     CFtpFileFind ff(m_ftp);
  162.     BOOL success= ff.FindFile(m_strFileTypes);
  163.     while (success==TRUE)
  164.     {
  165.         {
  166.             // Need to call FindNextFile before doing any attribute methods.
  167.             success=ff.FindNextFile();
  168.  
  169.             CString strFilename= ff.GetFileName();
  170.             if (!ff.IsDirectory()) 
  171.             {
  172.                 // Get destination directory, create if needed.
  173.                 CString DestinationDir;
  174.                 if (GetLocalDirectory(PathLevel, DestinationDir)) 
  175.                 {
  176.                     CString FullName= DestinationDir + strFilename;
  177.                     // Do the copy.
  178.                     if (bCopy) {
  179.                         if (!m_ftp->GetFile(strFilename,FullName)) {
  180.                             CString msg;
  181.                             msg.Format("Cannot put to local directory, error: %d", ::GetLastError());
  182.                             m_pView->AddToView(msg);
  183.                         } 
  184.                     }
  185.                     // Output file information.
  186.                     DWORD filesize= ff.GetLength();
  187.                     m_TotalFileSize += filesize;
  188.                     CString msg;
  189.                     msg.Format("%ld: size %ld (total %ld) To %s", ++m_count, filesize, m_TotalFileSize, FullName);
  190.                     m_pView->AddToView(msg);
  191.                 } 
  192.                 else 
  193.                 {
  194.                     m_pView->AddToView("Cannot access local directory");
  195.                     return FALSE;
  196.                 }
  197.             } 
  198.         }
  199.     }
  200.     // Call Close to reset the search.
  201.     ff.Close();
  202.  
  203.     //
  204.     // 2) Terminate here if at end of path specification.
  205.     //
  206.  
  207.     if (PathLevel >= m_arrDynamicPath.GetSize()) 
  208.     {
  209.         return TRUE;
  210.     } 
  211.     else if (!strchr(m_arrStaticPath[PathLevel],'*') && !strchr(m_arrStaticPath[PathLevel],'?')) 
  212.     {
  213.  
  214.         // Just go down into path if no wildcards
  215.  
  216.         if (CopyDirectory(PathLevel+1)==FALSE)
  217.             return FALSE;
  218.  
  219.     } 
  220.     else 
  221.     {
  222.  
  223.     //
  224.     // 3) Start a new search looking for sub-directory names only.
  225.     //
  226.  
  227.         CStringArray arrSubDirNames;
  228.         success= ff.FindFile(m_arrStaticPath[PathLevel]);
  229.         while (success==TRUE)
  230.         {
  231.             {
  232.                 // Need to call FindNextFile before doing any attribute methods.
  233.                 success=ff.FindNextFile();
  234.                 // Only concerned with sub-directories.
  235.                 if (ff.IsDirectory()) 
  236.                 {
  237.                     CString strFilename= ff.GetFileName();
  238.                     // Ignore special directory names, "." and "..".
  239.                     if (!ff.IsDots())
  240.                     {
  241.                         // Save matching sub-directory names.
  242.                         arrSubDirNames.Add(strFilename);
  243.                     }
  244.                 } 
  245.             }
  246.         }
  247.         // Call Close to reset the search.
  248.         ff.Close();
  249.  
  250.     //
  251.     // 4) Recursively copy matching sub-directories.
  252.     //
  253.  
  254.         for (int idx= 0; idx< arrSubDirNames.GetSize(); idx++) 
  255.         {
  256.             // Replace wildcard name with matching name.
  257.             m_arrDynamicPath[PathLevel]= arrSubDirNames[idx];
  258.             // Recursive call for new sub-directory, end copy if any errors are encountered.
  259.             if (CopyDirectory(PathLevel+1) == FALSE)
  260.                 return FALSE;
  261.         }
  262.     }    // end of else
  263.  
  264.     return TRUE;
  265. }
  266. ///////////////////////////////////////////////////////////////////////
  267. //
  268. //    Utility functions
  269. //
  270. ///////////////////////////////////////////////////////////////////////
  271. // PathToArray()
  272. // Split path string into an array of strings, one per path element.
  273. void CFtpGet::PathToArray(CString& path, CStringArray& strArray)
  274. {
  275.     char* pSep= "\\/";    // either works as a separator.
  276.     // copy path string into a char array for strtok.
  277.     char* pStr= new char[path.GetLength()+1];
  278.     strcpy(pStr, path);
  279.     // Get first path element.
  280.     char* pPtr= strtok(pStr,pSep);
  281.     // Extract path elements until there are no more.
  282.     while (pPtr != NULL) {
  283.         strArray.Add(pPtr);
  284.         pPtr= strtok(NULL, pSep);
  285.     }
  286.     delete pStr;
  287. }
  288. ///////////////////////////////////////////////////////////////////////
  289. // BuildPath()
  290. // Given a level, build up a path from string array of path elements.
  291. // Note: level 0 means append zero elements
  292. void CFtpGet::BuildPath(int level, CString& path, CString& sep)
  293. {
  294.     ASSERT(level<=m_arrDynamicPath.GetSize());
  295.     for (int idx= 0; idx < level; idx++) 
  296.     {
  297.         path += m_arrDynamicPath[idx];
  298.         path += sep;
  299.     }
  300. }
  301. ///////////////////////////////////////////////////////////////////////
  302. // CreateLocalDirectory()
  303. // Create a directory path on local filesystem.
  304. // The passed path string is appended to the local root directory string.
  305. BOOL CFtpGet::CreateLocalDirectory(CString& path, CString& FullDir)
  306. {
  307.     CString msg;
  308.     // Attempt to create destination dir if not existing
  309.     if (_chdir(m_strLocalRoot)!=0)
  310.     {
  311.         msg.Format("Create %s?", m_strLocalRoot); 
  312.         if (AfxMessageBox(msg, MB_OKCANCEL) == IDOK)
  313.         {
  314.             if (_mkdir(m_strLocalRoot)!=0) 
  315.             {
  316.                 CString err;
  317.                 err.Format("Failed to create %s", m_strLocalRoot);
  318.                 m_pView->AddToView(err);
  319.                 return FALSE;
  320.             }
  321.         }
  322.         else
  323.             return FALSE;
  324.     }
  325.  
  326.     CStringArray strArray;
  327.     // Separate path name into path elements.
  328.     PathToArray(path, strArray);
  329.     // Start with the local root directory.
  330.     FullDir= m_strLocalRoot;
  331.     for (int idx=0; idx< strArray.GetSize(); idx++) 
  332.     {
  333.         FullDir += strArray[idx];
  334.         FullDir += "\\";
  335.         if (_mkdir(FullDir)!=0) 
  336.         {
  337.             if (errno != EEXIST) 
  338.             {    // continue only if directory exists.
  339.                 CString err;
  340.                 err.Format("mkdir error on %s: %d", FullDir, errno);
  341.                 m_pView->AddToView(err);
  342.                 return FALSE;
  343.             }
  344.         } 
  345.         else 
  346.         {
  347.             msg.Format("Creating new directory: %s", FullDir);
  348.             m_pView->AddToView(msg);
  349.         }
  350.     }
  351.     return TRUE;
  352. }
  353.  
  354. ///////////////////////////////////////////////////////////////////////
  355. // SetFtpDirectory()
  356. //    Set remote FTP directory based upon given level.
  357. BOOL CFtpGet::SetFtpDirectory(int level)
  358. {
  359.     CString strPath("/");
  360.     CString sep("/");
  361.     BuildPath(level, strPath, sep);
  362.     CString msg;
  363.     msg.Format("Searching Dir: %s", strPath);
  364.     m_pView->AddToView(msg);
  365.     return m_ftp->SetCurrentDirectory(strPath);
  366. }
  367. ///////////////////////////////////////////////////////////////////////
  368. // GetLocalDirectory()
  369. //    Given level, return string of local path. 
  370. //    Create path on filesytem if it does not exists.
  371. BOOL CFtpGet::GetLocalDirectory(int level, CString& FullDir)
  372. {
  373.     CString strPath;
  374.     CString sep("\\");
  375.     BuildPath(level, strPath, sep);
  376.     // Create it if necessary.
  377.     if (!CreateLocalDirectory(strPath, FullDir)) 
  378.     {
  379.         return FALSE;
  380.     }
  381.     return TRUE;
  382. }
  383.