home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 March / CMCD0304.ISO / Software / Freeware / Programare / nullsoft / nsis20.exe / Contrib / NSISdl / nsisdl.cpp < prev    next >
C/C++ Source or Header  |  2004-02-01  |  14KB  |  487 lines

  1. /*
  2.   NSIS-DL 1.3 - http downloading DLL for NSIS
  3.   Copyright (C) 2001-2002 Yaroslav Faybishenko & Justin Frankel
  4.  
  5.   This software is provided 'as-is', without any express or implied
  6.   warranty.  In no event will the authors be held liable for any damages
  7.   arising from the use of this software.
  8.  
  9.   Permission is granted to anyone to use this software for any purpose,
  10.   including commercial applications, and to alter it and redistribute it
  11.   freely, subject to the following restrictions:
  12.  
  13.   1. The origin of this software must not be misrepresented; you must not
  14.      claim that you wrote the original software. If you use this software
  15.      in a product, an acknowledgment in the product documentation would be
  16.      appreciated but is not required.
  17.   2. Altered source versions must be plainly marked as such, and must not be
  18.      misrepresented as being the original software.
  19.   3. This notice may not be removed or altered from any source distribution.
  20. */
  21. #include <windows.h>
  22. #include <stdio.h>
  23. #include <commctrl.h>
  24.  
  25. #include "netinc.h"
  26. #include "util.h"
  27. #include "httpget.h"
  28. #include "../exdll/exdll.h"
  29.  
  30. void *operator new( unsigned int num_bytes )
  31. {
  32.   return GlobalAlloc(GPTR,num_bytes);
  33. }
  34. void operator delete( void *p ) { if (p) GlobalFree(p); }
  35.  
  36.  
  37. HMODULE     hModule;
  38. HWND        g_hwndProgressBar;
  39. HWND        g_hwndStatic;
  40. static int  g_cancelled;
  41. static void *lpWndProcOld;
  42.  
  43. static UINT uMsgCreate;
  44.  
  45. HWND childwnd;
  46. HWND hwndL;
  47. HWND hwndB;
  48.  
  49. static LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  50. {
  51.   if (uMsgCreate && message == uMsgCreate)
  52.   {
  53.     static HWND hwndPrevFocus;
  54.     static BOOL fCancelDisabled;
  55.  
  56.     if (wParam)
  57.     {
  58.       childwnd = FindWindowEx((HWND) lParam, NULL, "#32770", NULL);
  59.       hwndL = GetDlgItem(childwnd, 1016);
  60.       hwndB = GetDlgItem(childwnd, 1027);
  61.       HWND hwndP = GetDlgItem(childwnd, 1004);
  62.       HWND hwndS = GetDlgItem(childwnd, 1006);
  63.       if (childwnd && hwndP && hwndS)
  64.       {
  65.         // Where to restore focus to before we disable the cancel button
  66.         hwndPrevFocus = GetFocus();
  67.         if (!hwndPrevFocus)
  68.           hwndPrevFocus = hwndP;
  69.  
  70.         if (IsWindowVisible(hwndL))
  71.           ShowWindow(hwndL, SW_HIDE);
  72.         else
  73.           hwndL = NULL;
  74.         if (IsWindowVisible(hwndB))
  75.           ShowWindow(hwndB, SW_HIDE);
  76.         else
  77.           hwndB = NULL;
  78.  
  79.         RECT wndRect, ctlRect;
  80.  
  81.         GetClientRect(childwnd, &wndRect);
  82.  
  83.         GetWindowRect(hwndS, &ctlRect);
  84.  
  85.         HWND s = g_hwndStatic = CreateWindow(
  86.           "STATIC",
  87.           "",
  88.           WS_CHILD | WS_CLIPSIBLINGS | SS_CENTER,
  89.           0,
  90.           wndRect.bottom / 2 - (ctlRect.bottom - ctlRect.top) / 2,
  91.           wndRect.right,
  92.           ctlRect.bottom - ctlRect.top,
  93.           childwnd,
  94.           NULL,
  95.           hModule,
  96.           NULL
  97.         );
  98.  
  99.         DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
  100.         dwStyle |= GetWindowLong(hwndP, GWL_STYLE) & PBS_SMOOTH;
  101.  
  102.         GetWindowRect(hwndP, &ctlRect);
  103.  
  104.         HWND pb = g_hwndProgressBar = CreateWindow(
  105.           "msctls_progress32",
  106.           "",
  107.           dwStyle,
  108.           0,
  109.           wndRect.bottom / 2 + (ctlRect.bottom - ctlRect.top) / 2,
  110.           wndRect.right,
  111.           ctlRect.bottom - ctlRect.top,
  112.           childwnd,
  113.           NULL,
  114.           hModule,
  115.           NULL
  116.         );
  117.  
  118.         long c;
  119.  
  120.         c = SendMessage(hwndP, PBM_SETBARCOLOR, 0, 0);
  121.         SendMessage(hwndP, PBM_SETBARCOLOR, 0, c);
  122.         SendMessage(pb, PBM_SETBARCOLOR, 0, c);
  123.  
  124.         c = SendMessage(hwndP, PBM_SETBKCOLOR, 0, 0);
  125.         SendMessage(hwndP, PBM_SETBKCOLOR, 0, c);
  126.         SendMessage(pb, PBM_SETBKCOLOR, 0, c);
  127.  
  128.         // set font
  129.         long hFont = SendMessage((HWND) lParam, WM_GETFONT, 0, 0);
  130.         SendMessage(pb, WM_SETFONT, hFont, 0);
  131.         SendMessage(s, WM_SETFONT, hFont, 0);
  132.  
  133.         ShowWindow(pb, SW_SHOWNA);
  134.         ShowWindow(s, SW_SHOWNA);
  135.  
  136.         fCancelDisabled = EnableWindow(GetDlgItem(hwnd, IDCANCEL), TRUE);
  137.         SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDCANCEL), TRUE);
  138.       }
  139.       else
  140.         childwnd = NULL;
  141.     }
  142.     else if (childwnd)
  143.     {
  144.       if (hwndB)
  145.       {
  146.         ShowWindow(hwndB, SW_SHOWNA);
  147.         hwndB = NULL;
  148.       }
  149.       if (hwndL)
  150.       {
  151.         ShowWindow(hwndL, SW_SHOWNA);
  152.         hwndL = NULL;
  153.       }
  154.  
  155.       // Prevent wierd stuff happening if the cancel button happens to be
  156.       // pressed at the moment we are finishing and restore the previous focus
  157.       // and cancel button states
  158.       SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)hwndPrevFocus, TRUE);
  159.       SendMessage(GetDlgItem(hwnd, IDCANCEL), BM_SETSTATE, FALSE, 0);
  160.       if (fCancelDisabled)
  161.         EnableWindow(GetDlgItem(hwnd, IDCANCEL), FALSE);
  162.  
  163.       if (g_hwndStatic)
  164.       {
  165.         DestroyWindow(g_hwndStatic);
  166.         g_hwndStatic = NULL;
  167.       }
  168.       if (g_hwndProgressBar)
  169.       {
  170.         DestroyWindow(g_hwndProgressBar);
  171.         g_hwndProgressBar = NULL;
  172.       }
  173.       childwnd = NULL;
  174.     }
  175.   }
  176.   else if (message == WM_COMMAND && LOWORD(wParam) == IDCANCEL)
  177.   {
  178.     g_cancelled = 1;
  179.   }
  180.   else
  181.   {
  182.     return CallWindowProc(
  183.       (WNDPROC) lpWndProcOld,
  184.       hwnd,
  185.       message,
  186.       wParam,
  187.       lParam
  188.     );
  189.   }
  190.   return 0;
  191. }
  192.  
  193. BOOL APIENTRY DllMain(HINSTANCE _hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
  194. {
  195.   hModule = _hModule;
  196.   return TRUE;
  197. }
  198.  
  199. static int g_file_size;
  200. static DWORD g_dwLastTick = 0;
  201. void progress_callback(char *msg, int read_bytes)
  202. {
  203.   // flicker reduction by A. Schiffler
  204.   DWORD dwLastTick = g_dwLastTick;
  205.   DWORD dwThisTick = GetTickCount();
  206.   if (childwnd)
  207.   {
  208.     if (dwThisTick - dwLastTick > 500)
  209.     {
  210.       SetWindowText(g_hwndStatic, msg);
  211.       dwLastTick = dwThisTick;
  212.     }
  213.     if (g_file_size)
  214.       SendMessage(g_hwndProgressBar, PBM_SETPOS, (WPARAM) MulDiv(read_bytes, 30000, g_file_size), 0);
  215.     g_dwLastTick = dwLastTick;
  216.   }
  217. }
  218.  
  219. extern char *_strstr(char *i, char *s);
  220. #define strstr _strstr
  221.  
  222. extern "C"
  223. {
  224.  
  225. __declspec(dllexport) void download (HWND   parent,
  226.               int    string_size,
  227.               char   *variables,
  228.               stack_t **stacktop)
  229. {
  230.   char buf[1024];
  231.   char url[1024];
  232.   char filename[1024];
  233.   BOOL bSuccess=FALSE;
  234.   int timeout_ms=30000;
  235.  
  236.   char *error=NULL;
  237.  
  238.   static char szDownloading[1024];//= "Downloading %s";
  239.   static char szConnecting[1024];//= "Connecting ...";
  240.   static char szSecond[1024];//= "second";
  241.   static char szMinute[1024];//= "minute";
  242.   static char szHour[1024];//= "hour";
  243.   static char szPlural[1024];//= "s";
  244.   static char szProgress[1024];//= "%dkB (%d%%) of %dkB @ %d.%01dkB/s";
  245.   static char szRemaining[1024];//= " (%d %s%s remaining)";
  246.  
  247.   EXDLL_INIT();
  248.  
  249.   popstring(url);
  250.   if (!lstrcmpi(url, "/TRANSLATE")) {
  251.     popstring(szDownloading);
  252.     popstring(szConnecting);
  253.     popstring(szSecond);
  254.     popstring(szMinute);
  255.     popstring(szHour);
  256.     popstring(szPlural);
  257.     popstring(szProgress);
  258.     popstring(szRemaining);
  259.     popstring(url);
  260.   }
  261.   else {
  262.     lstrcpy(szDownloading, "Downloading %s");
  263.     lstrcpy(szConnecting, "Connecting ...");
  264.     lstrcpy(szSecond, "second");
  265.     lstrcpy(szMinute, "minute");
  266.     lstrcpy(szHour, "hour");
  267.     lstrcpy(szPlural, "s");
  268.     lstrcpy(szProgress, "%dkB (%d%%) of %dkB @ %d.%01dkB/s");
  269.     lstrcpy(szRemaining, " (%d %s%s remaining)");
  270.   }
  271.   lstrcpyn(buf, url, 10);
  272.   if (!lstrcmpi(buf, "/TIMEOUT=")) {
  273.     timeout_ms=my_atoi(url+9);
  274.     popstring(url);
  275.   }
  276.   popstring(filename);
  277.  
  278.   HANDLE hFile = CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,0,NULL);
  279.  
  280.   if (hFile == INVALID_HANDLE_VALUE)
  281.   {
  282.     wsprintf(buf, "Unable to open %s", filename);
  283.     error = buf;
  284.   }
  285.   else
  286.   {
  287.     if (parent)
  288.     {
  289.       uMsgCreate = RegisterWindowMessage("nsisdl create");
  290.  
  291.       lpWndProcOld = (void *)SetWindowLong(parent,GWL_WNDPROC,(long)ParentWndProc);
  292.  
  293.       SendMessage(parent, uMsgCreate, TRUE, (LPARAM) parent);
  294.  
  295.       // set initial text
  296.       char *p = filename;
  297.       while (*p) p++;
  298.       while (*p != '\\' && p != filename) p = CharPrev(filename, p);
  299.       wsprintf(buf, szDownloading, p != filename ? p + 1 : p);
  300.       SetDlgItemText(childwnd, 1006, buf);
  301.       SetWindowText(g_hwndStatic, szConnecting);
  302.     }
  303.     {
  304.       WSADATA wsaData;
  305.       WSAStartup(MAKEWORD(1, 1), &wsaData);
  306.  
  307.       JNL_HTTPGet *get = 0;
  308.  
  309.       static char main_buf[8192];
  310.       char *buf=main_buf;
  311.       char *p=NULL;
  312.  
  313.       HKEY hKey;
  314.       if (RegOpenKeyEx(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",0,KEY_READ,&hKey) == ERROR_SUCCESS)
  315.       {
  316.         DWORD l = 4;
  317.         DWORD t;
  318.         DWORD v;
  319.         if (RegQueryValueEx(hKey,"ProxyEnable",NULL,&t,(unsigned char *)&v,&l) == ERROR_SUCCESS && t == REG_DWORD && v)
  320.         {
  321.           l=8192;
  322.           if (RegQueryValueEx(hKey,"ProxyServer",NULL,&t,(unsigned char *)buf,&l ) == ERROR_SUCCESS && t == REG_SZ)
  323.           {
  324.             p=strstr(buf,"http=");
  325.             if (!p) p=buf;
  326.             else {
  327.               p+=5;
  328.             }
  329.             char *tp=strstr(p,";");
  330.             if (tp) *tp=0;
  331.             char *p2=strstr(p,"=");
  332.             if (p2) p=0; // we found the wrong proxy
  333.           }
  334.         }
  335.         buf[8192-1]=0;
  336.         RegCloseKey(hKey);
  337.       }
  338.  
  339.       DWORD start_time=GetTickCount();
  340.       get=new JNL_HTTPGet(JNL_CONNECTION_AUTODNS,16384,(p&&p[0])?p:NULL);
  341.       int         st;
  342.       int         has_printed_headers = 0;
  343.       int         cl;
  344.       int         len;
  345.       int         sofar = 0;
  346.       DWORD last_recv_time=start_time;
  347.  
  348.       get->addheader ("User-Agent: NSISDL/1.2 (Mozilla)");
  349.       get->addheader ("Accept: */*");
  350.  
  351.       get->connect (url);
  352.  
  353.       while (1) {
  354.         if (g_cancelled)
  355.             error = "cancel";
  356.  
  357.         if (error)
  358.         {
  359.           if (parent)
  360.           {
  361.             SendMessage(parent, uMsgCreate, FALSE, (LPARAM) parent);
  362.             SetWindowLong(parent, GWL_WNDPROC, (long)lpWndProcOld);
  363.           }
  364.           break;
  365.         }
  366.  
  367.         Sleep(25);
  368.  
  369.         st = get->run ();
  370.  
  371.         if (st == -1) {
  372.           lstrcpyn(url, get->geterrorstr(), sizeof(url));
  373.           error = url;
  374.         } else if (st == 1) {
  375.           if (sofar < cl)
  376.             error="download incomplete";
  377.           else
  378.           {
  379.             bSuccess=TRUE;
  380.             error = "success";
  381.           }
  382.         } else {
  383.  
  384.           if (get->get_status () == 0) {
  385.             // progressFunc ("Connecting ...", 0);
  386.             if (last_recv_time+timeout_ms < GetTickCount())
  387.               error = "Timed out on connecting.";
  388.  
  389.           } else if (get->get_status () == 1) {
  390.  
  391.             progress_callback("Reading headers", 0);
  392.             if (last_recv_time+timeout_ms < GetTickCount())
  393.               error = "Timed out on getting headers.";
  394.  
  395.           } else if (get->get_status () == 2) {
  396.  
  397.             if (! has_printed_headers) {
  398.               has_printed_headers = 1;
  399.               last_recv_time=GetTickCount();
  400.  
  401.               cl = get->content_length ();
  402.               if (cl == 0)
  403.                 error = "Server did not specify content length.";
  404.               else if (g_hwndProgressBar) {
  405.                 SendMessage(g_hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 30000));
  406.                 g_file_size = cl;
  407.               }
  408.             }
  409.  
  410.             while ((len = get->bytes_available ()) > 0) {
  411.               if (len > 8192)
  412.                 len = 8192;
  413.               len = get->get_bytes (buf, len);
  414.               if (len > 0) {
  415.                 last_recv_time=GetTickCount();
  416.                 DWORD dw;
  417.                 WriteFile(hFile,buf,len,&dw,NULL);
  418.                 sofar += len;
  419.                 int time_sofar=(GetTickCount()-start_time)/1000;
  420.                 int bps=sofar/(time_sofar?time_sofar:1);
  421.                 int remain=MulDiv(time_sofar,cl,sofar) - time_sofar;
  422.                 char *rtext=szSecond;
  423.                 if (remain >= 60)
  424.                 {
  425.                   remain/=60;
  426.                   rtext=szMinute;
  427.                   if (remain >= 60)
  428.                   {
  429.                     remain/=60;
  430.                     rtext=szHour;
  431.                   }
  432.                 }
  433.                 wsprintf (buf,
  434.                       szProgress,
  435.                       sofar/1024,
  436.                       MulDiv(100,sofar,cl),
  437.                       cl/1024,
  438.                       bps/1024,((bps*10)/1024)%10
  439.                       );
  440.                 if (remain) wsprintf(buf+lstrlen(buf),szRemaining,
  441.                       remain,
  442.                       rtext,
  443.                       remain==1?"":szPlural
  444.                       );
  445.                 progress_callback(buf, sofar);
  446.               } else {
  447.                 if (sofar < cl)
  448.                   error = "Server aborted.";
  449.               }
  450.             }
  451.             if (GetTickCount() > last_recv_time+timeout_ms)
  452.               error = "Downloading timed out.";
  453.  
  454.           } else {
  455.             error = "Bad response status.";
  456.           }
  457.         }
  458.  
  459.       }
  460.  
  461.       // Clean up the connection then release winsock
  462.       if (get) delete get;
  463.       WSACleanup();
  464.     }
  465.  
  466.     CloseHandle(hFile);
  467.   }
  468.  
  469.   if (g_cancelled || !bSuccess) {
  470.     DeleteFile(filename);
  471.   }
  472.  
  473.   pushstring(error);
  474. }
  475.  
  476.  
  477. __declspec(dllexport) void download_quiet(HWND   parent,
  478.               int    stringsize,
  479.               char   *variables,
  480.               stack_t **stacktop)
  481. {
  482.   g_hwndProgressBar=0;
  483.   download(NULL,stringsize,variables,stacktop);
  484. }
  485.  
  486. } //extern "C"
  487.