home *** CD-ROM | disk | FTP | other *** search
/ PC World 2003 June / PCWorld_2003-06_cd.bin / KOMUNIK / MIRRORIT / SRC / DOWNLOADDLG.CPP < prev    next >
C/C++ Source or Header  |  1999-02-10  |  10KB  |  439 lines

  1. // DownLoadDlg.cpp : implementation file
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "MirrorIt.h"
  6. #include "Session.h"
  7. #include "URL.h"
  8. #include "HTTPSocket.h"
  9. #include "DownLoadDlg.h"
  10.  
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16.  
  17. #define RETRIEVE_DOCUMENT    (1)
  18. #define RETRIEVE_FILE        (0)
  19. #define RETRIEVE_ERROR        (-1)
  20. #define RETRIEVE_UNKNOWN    (-2)
  21. #define RETRIEVE_ABORT        (-3)
  22. #define STORE_ERROR            (-4)
  23. #define STORE_SKIP            (-5)
  24. #define NO_STOREERROR        (-6)
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CDownLoadDlg dialog
  28.  
  29.  
  30. CDownLoadDlg::CDownLoadDlg(CWnd* pParent /*=NULL*/)
  31.     : CDialog(CDownLoadDlg::IDD, pParent)
  32. {
  33.     //{{AFX_DATA_INIT(CDownLoadDlg)
  34.         // NOTE: the ClassWizard will add member initialization here
  35.     //}}AFX_DATA_INIT
  36.  
  37.     m_bAbort = FALSE;
  38.     m_numFiles = 0;
  39.     m_numBytes = 0;
  40.     m_bMinimized = FALSE;
  41. }
  42.  
  43.  
  44. void CDownLoadDlg::DoDataExchange(CDataExchange* pDX)
  45. {
  46.     CDialog::DoDataExchange(pDX);
  47.     //{{AFX_DATA_MAP(CDownLoadDlg)
  48.     DDX_Control(pDX, IDC_PROGRESS, m_Progress);
  49.     //}}AFX_DATA_MAP
  50. }
  51.  
  52.  
  53. BEGIN_MESSAGE_MAP(CDownLoadDlg, CDialog)
  54.     //{{AFX_MSG_MAP(CDownLoadDlg)
  55.     ON_WM_SIZE()
  56.     //}}AFX_MSG_MAP
  57. END_MESSAGE_MAP()
  58.  
  59. /////////////////////////////////////////////////////////////////////////////
  60. // CDownLoadDlg message handlers
  61.  
  62. int CDownLoadDlg::LoadSessions(CPtrArray & sessions)
  63. {
  64.     Create(IDD_DOWNLOAD);
  65.     CString caption;
  66.     
  67.     caption.LoadString(IDS_MIRRORINGDIALOG);
  68.     SetWindowText(caption);
  69.     ModifyStyleEx(0, WS_EX_APPWINDOW);
  70.     ShowWindow(SW_SHOW);
  71.  
  72.     CRect rc;
  73.     CAnimateCtrl m_AnimateCtrl;
  74.     
  75.     CWnd* pFrame = GetDlgItem(IDC_ANIMFRAME);
  76.     pFrame->GetClientRect(&rc);
  77.     m_AnimateCtrl.Create(WS_CHILD | WS_VISIBLE | ACS_TRANSPARENT | ACS_AUTOPLAY,
  78.                          rc, pFrame, IDC_ANIMATE);
  79.     m_AnimateCtrl.Open(IDR_AVI); //"C:\\TEMP\\1\\1.AVI");
  80.     InvalidateRect(&rc);
  81.     UpdateWindow();
  82.  
  83.     for (int i = 0; i < sessions.GetSize(); i++)
  84.     {
  85.         if (m_bAbort) break;
  86.  
  87.         BOOL b = LoadSession(*(CSession *)sessions.GetAt(i));
  88.         ((CMirrorItApp *)AfxGetApp()) -> theLogFile.Close();
  89.         if (b)
  90.         {
  91.             break;
  92.         }
  93.     }
  94.     return 1;
  95. }
  96.  
  97. void CDownLoadDlg::OnCancel() 
  98. {
  99.     m_bAbort = TRUE;    
  100. }
  101.  
  102. int CDownLoadDlg::WaitFor(BOOL * wait)
  103. {
  104.     BOOL bDoingBackgroundProcessing = TRUE;
  105.     
  106.     while ( bDoingBackgroundProcessing )
  107.     {
  108.         MSG msg;
  109.         Sleep(1);
  110.         while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  111.         {
  112.             if ( !AfxGetApp() -> PumpMessage( ) )
  113.             {
  114.                 bDoingBackgroundProcessing = FALSE;
  115.                 ::PostQuitMessage( 0 );
  116.                 return 1;
  117.             }
  118.         }
  119.         // let MFC do its idle processing
  120.         LONG lIdle = 0;
  121.         while ( AfxGetApp()->OnIdle(lIdle++ ) )
  122.             ;
  123.         if (*wait) break;
  124.         if (m_bAbort) return 1;
  125.     }
  126.     return 0;
  127. }
  128.  
  129. int CDownLoadDlg::ProcessMessages()
  130. {
  131.     MSG msg;
  132.  
  133.     Sleep(1);
  134.     while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  135.     {
  136.         if ( !AfxGetApp() -> PumpMessage( ) )
  137.         {
  138.             ::PostQuitMessage( 0 );
  139.             return 1;
  140.         }
  141.     }
  142.     // let MFC do its idle processing
  143.     LONG lIdle = 0;
  144.     while ( AfxGetApp()->OnIdle(lIdle++ ) )
  145.         ;
  146.     if (m_bAbort) return 1;
  147.     return 0;
  148. }
  149.  
  150. int CDownLoadDlg::LoadSession(CSession & session)
  151. {
  152.     CStringList links;
  153.     CString basestr = session.m_BaseURL, strurl;
  154.     CURL base(basestr);
  155.     if (base.scheme.IsEmpty())
  156.     {
  157.         basestr = "http://" + basestr;
  158.     }
  159.     else
  160.     if (base.scheme.Compare("http") != 0)
  161.     {
  162.         return 0;
  163.     }
  164.     CURL base2(basestr);
  165.     if (base2.path.IsEmpty())
  166.     {
  167.         base2.path = "/";
  168.         base2.build(basestr);
  169.     }
  170.  
  171.     int currentlevel = 0, c = 1;
  172.  
  173.     CreateDirectoryTree(session.m_Directory);
  174.     CreateLog(session, links);
  175.  
  176.     links.AddHead(basestr);
  177.     while (links.GetCount())
  178.     {
  179.         int i;
  180.  
  181.         strurl = links.GetHead();
  182.         links.RemoveHead();
  183.  
  184.         CURL url(strurl);
  185.  
  186.         if (url.urltype != URL_INVALID && !visitedlinks.Find(strurl))
  187.         {
  188.             CString temp;
  189.             temp.Format(IDS_DOWNLOADINFO, m_numFiles, m_numBytes);
  190.  
  191.             visitedlinks.AddTail(strurl);
  192.             SetDlgItemText(IDC_URL, strurl);
  193.             SetDlgItemText(IDC_DOWNLOADINFO, temp);
  194.             m_Progress.SetPos(0);
  195.             if (ProcessMessages()) break;
  196.  
  197.             i = RetrieveDocument(strurl, url, session, links);
  198.             if (i == RETRIEVE_ABORT) break;
  199.             if (i == RETRIEVE_ERROR) continue;
  200.             m_numFiles++;
  201.         }
  202.         if (session.m_BNumberOfFiles && m_numFiles >= (int)session.m_NumberOfFiles)
  203.             break;
  204.         if (session.m_BNumberOfKBytes && m_numBytes >= (int)session.m_NumberOfBytes)
  205.             break;
  206.  
  207.         c--;
  208.         if (c <= 0)
  209.         {
  210.             currentlevel++;
  211.             c = links.GetCount();
  212.             if (session.m_BNumberOfLevels && currentlevel >= (int)session.m_NumberOfLevels)
  213.                 break;
  214.         }
  215.  
  216.     }
  217.  
  218.     return links.GetCount();
  219. }
  220.  
  221. int CDownLoadDlg::RetrieveDocument(CString surl, CURL & url, CSession & session, CStringList & links)
  222. {
  223.     CString line, temp;
  224.     CString getpath, getserver;
  225.     CHTTPSocket sock;
  226.     UINT getport = 80;
  227.  
  228.     m_bAbort = FALSE;
  229.     if (m_bMinimized)
  230.         SetWindowText(surl);
  231.  
  232.     url.fragment.Empty();
  233.     url.relbuild(temp);
  234.     getpath = temp;
  235.     getserver = url.net_loc;
  236.     if (session.m_BProxy && !sock.inserverlist(url.net_loc, session.m_NoProxy))
  237.     {
  238.         getport = session.m_ProxyPort;
  239.         getpath = surl;
  240.         getserver = session.m_ProxyServer;
  241.     }
  242.  
  243.     line = "GET " + getpath + " HTTP/1.0\r\n";
  244.     if (session.m_ModifiedSince)
  245.     {
  246.         line += "If-Modified-Since: " + sock.FormatTime(session.m_TModifiedSince) + "\r\n";
  247.     }
  248.     if (!session.m_Password.IsEmpty() || !session.m_UserName.IsEmpty())
  249.     {
  250.         line += "Authorization: Basic " + sock.mimeencode(session.m_UserName + ":" + session.m_Password) + "\r\n";
  251.     }
  252. //    line += "User-Agent: MirrorIt/1.0.0\r\n";
  253. //    line += "User-Agent: Mozilla/4.03 [en] (X11; I; Linux.2.0.32.i486)\r\n";
  254. //    line += "User-Agent: Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)\r\n";
  255. //    line += "User-Agent: Mozilla/5.0 (compatible; MSIE 5.0b2; Windows 98)\r\n";
  256. //    line += "Referer: http://server.eroticportal.com/6/\r\n";
  257.     line += "Accept: */*\r\n";
  258.     line += "\r\n";
  259. //    sock.AddLog(line);
  260.  
  261.     sock.basenet_loc = url.net_loc;
  262.     sock.base = surl;
  263.     sock.links = &links;
  264.     sock.session = &session;
  265.     sock.m_numBytes = &m_numBytes;
  266.     sock.m_progress = &m_Progress;
  267.  
  268.     CString filename = sock.getfilename(surl);
  269.     sock.m_filename = session.m_Directory + filename;
  270. //    sock.AddLog(surl);    //get file
  271.  
  272.     sock.Create();
  273.     if (!sock.Connect((LPCSTR)getserver, getport))
  274.     {
  275.         if (sock.GetLastError() != WSAEWOULDBLOCK)
  276.         {
  277.             return RETRIEVE_ERROR;
  278.         }
  279.         else
  280.         {
  281.             sock.AsyncSelect(FD_CONNECT);
  282.             if (WaitFor(&sock.m_bConnect)) return RETRIEVE_ABORT;
  283.             if (redirection(sock, session, links) != NO_STOREERROR) return 0;
  284.             if (sock.m_bError) return STORE_ERROR;
  285.         }
  286.     }
  287.     
  288.     sock.SendRequest(line);
  289.     sock.AsyncSelect(FD_WRITE | FD_CLOSE);
  290.     
  291.     if (WaitFor(&sock.m_bSent))
  292.     {
  293.         return RETRIEVE_ABORT;
  294.     }
  295.     
  296.     else
  297.     {
  298. //        sock.AddLog("Before answer");
  299.         sock.m_recv = TRUE;
  300.         sock.AsyncSelect(FD_READ | FD_CLOSE);
  301.         if (WaitFor(&sock.m_bClose))
  302.             return RETRIEVE_ERROR;
  303. //        sock.AddLog("After answer");
  304.         if (sock.m_iCode != 200)
  305.         {
  306.             CString errorstr;
  307.             errorstr.Format("%03d", sock.m_iCode);
  308.             if (sock.m_iCode >= 300 && sock.m_iCode <= 302)
  309.                 sock.AddLog(errorstr, surl + "\r\n" + sock.location);
  310.             else
  311.             {
  312. /*                CString key;
  313.                 CString val;
  314.                 
  315.                 POSITION pos = sock.m_Header.GetStartPosition();
  316.                 while (pos != NULL)
  317.                 {
  318.                     sock.m_Header.GetNextAssoc(pos, key, val);
  319.                     line += "\r\n" + key + ": " + val;
  320.                 }
  321. */
  322.                 sock.AddLog(errorstr, surl + "\r\n\r\n" + line);
  323.             }
  324. //            errorstr.Format("Error: %d", sock.m_iCode);
  325. //            sock.AddLog(errorstr);
  326.         }
  327.         else
  328.         {
  329.             sock.AddLog("200", surl);
  330.         }
  331.         if (sock.m_iCode == 400 || sock.m_iCode == 503)
  332.         {
  333.             visitedlinks.RemoveTail();
  334.             links.AddTail(surl);
  335.             m_numFiles--;
  336.         }
  337.         if (redirection(sock, session, links) != NO_STOREERROR) return 0;
  338.         if (sock.m_bError) return STORE_ERROR;
  339.     }
  340.     return RETRIEVE_DOCUMENT;
  341. }
  342.  
  343.  
  344. BOOL CDownLoadDlg::OnInitDialog() 
  345. {
  346.     CDialog::OnInitDialog();
  347.  
  348.  
  349.     return TRUE;  // return TRUE unless you set the focus to a control
  350.                   // EXCEPTION: OCX Property Pages should return FALSE
  351. }
  352.  
  353. int CDownLoadDlg::redirection(CHTTPSocket & sock, CSession & session, CStringList & links)
  354. {
  355.     if (sock.m_bRedirect && (
  356.          (sock.m_iCode == 300 && session.m_Multiple) ||
  357.          (sock.m_iCode == 301 && session.m_Permanent) ||
  358.          (sock.m_iCode == 302 && session.m_Temporary)))
  359.     {
  360.         CString surl(sock.location);
  361.         CURL url(sock.location);
  362.         return RetrieveDocument(surl, url, session, links);
  363.     }
  364.     return NO_STOREERROR;
  365. }
  366.  
  367. void CDownLoadDlg::OnSize(UINT nType, int cx, int cy) 
  368. {
  369.     CDialog::OnSize(nType, cx, cy);
  370.     
  371.     m_bMinimized = nType == SIZE_MINIMIZED;
  372.     if (!m_bMinimized)
  373.     {
  374.         CString caption;
  375.     
  376.         caption.LoadString(IDS_MIRRORINGDIALOG);
  377.         SetWindowText(caption);
  378.     }
  379. }
  380.  
  381. void CDownLoadDlg::CreateLog(CSession & session, CStringList & links)
  382. {
  383.     CStdioFile & log = ((CMirrorItApp *)AfxGetApp()) -> theLogFile;
  384.     CString logname = session.m_Directory + "MirrorIt.log";
  385.     if (log.Open(logname, CFile::modeReadWrite | CFile::typeText))
  386.     {
  387.         int ret = AfxMessageBox(IDS_CONTINUELOG, MB_YESNO);
  388.         if (ret == IDYES)
  389.         {
  390.             CString line;
  391.  
  392.             while (log.ReadString(line))
  393.             {
  394.                 CString type = line.Left(3),
  395.                         url = line.Mid(4);
  396.                 int code = atoi(type);
  397.  
  398.                 if (type == "ADD")
  399.                 {
  400.                     links.AddTail(url);
  401.                 }
  402.                 else
  403.                 if (code == 200)
  404.                 {
  405.                     visitedlinks.AddTail(url);
  406.                     POSITION p = links.Find(url);
  407.                     if (p)
  408.                         links.RemoveAt(p);
  409.                 }
  410.                 if (code >= 300 && code <= 302)
  411.                 {
  412.                     visitedlinks.AddTail(url);
  413.                     POSITION p = links.Find(url);
  414.                     if (p)
  415.                         links.RemoveAt(p);
  416.                     if ((code == 300 && session.m_Multiple) ||
  417.                         (code == 301 && session.m_Permanent) ||
  418.                         (code == 302 && session.m_Temporary))
  419.                     {
  420.                         log.ReadString(line);
  421.                         links.AddTail(line.Mid(4));
  422.                     }
  423.                 }
  424.             }
  425.             return;
  426.         }
  427.         else
  428.         {
  429.             log.Close();
  430.         }
  431.         if (ret == IDCANCEL) 
  432.         {
  433.             m_bAbort = true;
  434.             return;
  435.         }
  436.     }
  437.     log.Open(logname, CFile::modeCreate | CFile::modeWrite | CFile::typeText);
  438. }
  439.