Fix
[ryzomcore.git] / nelns / login_system / nel_launcher_windows / nel_launcherDlg.cpp
blobf1e28ce2963445f1389bc193e620354fe069abee
1 // nel_launcherDlg.cpp : implementation file
2 //
4 #include "stdafx.h"
5 #include "nel_launcher.h"
6 #include "nel_launcherDlg.h"
7 #include <string>
8 #include <vector>
9 #include <process.h>
10 #include <direct.h>
11 #include "mshtml.h"
13 #include "nel/misc/config_file.h"
14 #include "nel/misc/path.h"
16 #include "patch.h"
18 using namespace std;
19 using namespace NLMISC;
21 CConfigFile ConfigFile;
23 /*#ifdef _DEBUG
24 #define new DEBUG_NEW
25 #undef THIS_FILE
26 static char THIS_FILE[] = __FILE__;
27 #endif*/
29 const char *PleaseWaitFilename = "pleasewait.html";
31 void CNel_launcherDlg::openUrl (const std::string &url)
33 m_explore.Navigate(url.c_str(), NULL, NULL, NULL, NULL);
36 /////////////////////////////////////////////////////////////////////////////
37 // CNel_launcherDlg dialog
39 CNel_launcherDlg::CNel_launcherDlg(CWnd* pParent /*=NULL*/)
40 : CDialog(CNel_launcherDlg::IDD, pParent)
42 //{{AFX_DATA_INIT(CNel_launcherDlg)
43 // NOTE: the ClassWizard will add member initialization here
44 //}}AFX_DATA_INIT
45 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
46 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
49 void CNel_launcherDlg::DoDataExchange(CDataExchange* pDX)
51 CDialog::DoDataExchange(pDX);
52 //{{AFX_DATA_MAP(CNel_launcherDlg)
53 DDX_Control(pDX, IDC_EXPLORER1, m_explore);
54 //}}AFX_DATA_MAP
57 BEGIN_MESSAGE_MAP(CNel_launcherDlg, CDialog)
58 //{{AFX_MSG_MAP(CNel_launcherDlg)
59 ON_WM_PAINT()
60 ON_WM_QUERYDRAGICON()
61 ON_WM_SIZE()
62 ON_WM_TIMER()
63 //}}AFX_MSG_MAP
64 END_MESSAGE_MAP()
66 /////////////////////////////////////////////////////////////////////////////
67 // CNel_launcherDlg message handlers
69 BOOL CNel_launcherDlg::OnInitDialog()
71 NLMISC::CApplicationContext ApplicationContext;
73 CDialog::OnInitDialog();
75 // Set the icon for this dialog. The framework does this automatically
76 // when the application's main window is not a dialog
77 SetIcon(m_hIcon, TRUE); // Set big icon
78 SetIcon(m_hIcon, FALSE); // Set small icon
80 //CWebBrowser2 m_browser - member variable
82 // downloadFile ();
83 // return TRUE;
85 ConfigFile.load ("nel_launcher.cfg");
87 // get the working path
88 string workingPath = CPath::getFullPath (ConfigFile.getVar ("Application").asString(2));
90 if (!NLMISC::CFile::isExists (workingPath))
92 nlerror ("Working path '%s' doesn't exists", workingPath.c_str ());
95 // load the pleasewait html page if available in the nel_launcher directory
96 bool PleaseWaitLoaded = false;
97 string PleaseWaitFullPath;
98 PleaseWaitFullPath = CPath::getFullPath (PleaseWaitFilename, false);
99 if (NLMISC::CFile::isExists (PleaseWaitFullPath))
101 openUrl(PleaseWaitFullPath.c_str());
102 PleaseWaitLoaded = true;
105 _chdir (workingPath.c_str ());
107 // load the pleasewait html page if available in the client directory
108 PleaseWaitFullPath = CPath::getFullPath (PleaseWaitFilename, false);
109 if (!PleaseWaitLoaded && NLMISC::CFile::isExists (PleaseWaitFullPath))
111 openUrl(PleaseWaitFullPath.c_str());
114 // remove temp files
115 if (NLMISC::CFile::fileExists ("update_nel_launcher.bat"))
116 NLMISC::CFile::deleteFile ("update_nel_launcher.bat");
118 string Version = getVersion ();
120 string url = "http://"+ConfigFile.getVar ("StartupHost").asString()+ConfigFile.getVar ("StartupPage").asString();
121 url += "?newClientVersion=" + Version;
122 url += "&newClientApplication=" + ConfigFile.getVar ("Application").asString(0);
124 openUrl (url);
126 return TRUE; // return TRUE unless you set the focus to a control
129 // If you add a minimize button to your dialog, you will need the code below
130 // to draw the icon. For MFC applications using the document/view model,
131 // this is automatically done for you by the framework.
133 void CNel_launcherDlg::OnPaint()
135 if (IsIconic())
137 CPaintDC dc(this); // device context for painting
139 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
141 // Center icon in client rectangle
142 int cxIcon = GetSystemMetrics(SM_CXICON);
143 int cyIcon = GetSystemMetrics(SM_CYICON);
144 CRect rect;
145 GetClientRect(&rect);
146 int x = (rect.Width() - cxIcon + 1) / 2;
147 int y = (rect.Height() - cyIcon + 1) / 2;
149 // Draw the icon
150 dc.DrawIcon(x, y, m_hIcon);
152 else
154 CDialog::OnPaint();
158 // The system calls this to obtain the cursor to display while the user drags
159 // the minimized window.
160 HCURSOR CNel_launcherDlg::OnQueryDragIcon()
162 return (HCURSOR) m_hIcon;
165 BEGIN_EVENTSINK_MAP(CNel_launcherDlg, CDialog)
166 //{{AFX_EVENTSINK_MAP(CNel_launcherDlg)
167 ON_EVENT(CNel_launcherDlg, IDC_EXPLORER1, 250 /* BeforeNavigate2 */, OnBeforeNavigate2Explorer1, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL)
168 ON_EVENT(CNel_launcherDlg, IDC_EXPLORER1, 259 /* DocumentComplete */, OnDocumentCompleteExplorer1, VTS_DISPATCH VTS_PVARIANT)
169 //}}AFX_EVENTSINK_MAP
170 END_EVENTSINK_MAP()
172 void CNel_launcherDlg::OnBeforeNavigate2Explorer1(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel)
174 // set the user agent to nel_launcher changing the header
175 CString strHeader(Headers->bstrVal);
176 if (strHeader == "")
178 IWebBrowser2 *pBrowser;
179 LPDISPATCH pWebDisp;
181 pDisp->QueryInterface(IID_IWebBrowser2, (void**) &pBrowser);
182 pBrowser->get_Container(&pWebDisp);
184 BSTR bstr = SysAllocString(L"User-Agent: nel_launcher\r\n");
185 Headers->bstrVal = bstr;
187 pBrowser->Navigate2(URL, Flags, TargetFrameName, PostData, Headers);
189 if (!pWebDisp)
190 (*Cancel) = true;
192 if (pWebDisp)
193 pWebDisp->Release();
194 if (pBrowser)
195 pBrowser->Release();
197 SysFreeString (bstr);
199 return;
203 /* CString cstr = URL->bstrVal;
204 string str = string((const char*)cstr);
206 if (str.find ("clientVersion=") == string::npos)
208 string Version;
210 FILE *fp = fopen ("VERSION", "rb");
211 if (fp!=NULL)
213 char ver[1000];
214 if (fgets (ver, 1000, fp) != NULL)
216 Version = ver;
218 fclose (fp);
221 string url = str;
223 if (url.find ("?") != string::npos)
225 url += "&";
227 else
229 url += "?";
231 // url += "clientVersion=" + Version;
232 // url += "&clientApplication=" + ConfigFile.getVar ("Application").asString(0);
233 url += "toto=10";
234 *Cancel = TRUE;
235 m_explore.Navigate(url.c_str(), Flags, TargetFrameName, PostData, Headers);
238 VARIANT vurl;
239 VariantInit (&vurl);
240 vurl.vt = VT_BSTR;
241 vector<unsigned short> v;
242 for (uint i = 0; i < url.size (); i++)
243 v.push_back ((unsigned short)url[i]);
244 v.push_back (0);
245 BSTR bstr = SysAllocString((const unsigned short *)&(v[0]));
246 vurl.bstrVal = bstr;
248 OnBeforeNavigate2Explorer1(pDisp, &vurl, Flags, TargetFrameName, PostData, Headers, Cancel);
250 SysFreeString (bstr);
252 /* }
253 else
255 nlinfo ("coucou");
258 /* if (str.find("?nel_quit=1") != string::npos)
260 exit(0);
263 string token ("nel_exe=");
265 int spos = str.find (token);
266 if (spos == string::npos) return;
268 int spos2 = str.find ("&", spos+token.size ()+1);
269 if (spos == string::npos) return;
271 string path;
272 string exe = str.substr (spos+token.size (), spos2-spos-token.size ());
274 CConfigFile::CVar *var = ConfigFile.getVarPtr (exe);
275 if (var == NULL)
277 char str[1024];
278 smprintf (str, 1024, "Don't know the executable filename for the application '%s'", exe.c_str ());
279 MessageBox (str, "nel_launcher error");
280 exit(0);
282 else
284 exe = var->asString (0);
285 path = var->asString (1);
288 token = "nel_args=";
289 spos = str.find (token);
290 if (spos == string::npos) return;
292 string rawargs = str.substr (spos+token.size ());
294 // decode arguments (%20 -> space)
296 vector<string> vargs;
297 const char *args[50];
298 int argspos = 0;
300 int pos1 = 0, pos2 = 0;
301 while (true)
303 pos2 = rawargs.find("%20", pos1);
304 if (pos2==string::npos)
306 if(pos1!=rawargs.size())
308 string res = rawargs.substr (pos1);
309 vargs.push_back (res);
311 break;
313 if(pos1 != pos2)
315 string res = rawargs.substr (pos1, pos2-pos1);
316 vargs.push_back (res);
318 pos1 = pos2+3;
321 int i;
322 int size;
323 if(vargs.size()>47) size = 47;
324 else size = vargs.size();
326 args[0] = exe.c_str ();
327 for(i = 0; i < size; i++)
329 args[i+1] = vargs[i].c_str ();
331 args[i+1] = NULL;
334 // execute, should better use CreateProcess()
336 _chdir (path.c_str());
337 _execvp (exe.c_str(), args);
338 exit(0);
340 /* string cmd;
342 cmd=exe+" "+rawargs;
343 while (true)
345 int pos = cmd.find ("%20");
346 if (pos == string::npos)
347 break;
349 cmd.replace (pos, 3, " ");
352 WinExec (cmd.c_str(), SW_SHOWNORMAL);
356 void CNel_launcherDlg::OnSize(UINT nType, int cx, int cy)
358 CDialog::OnSize(nType, cx, cy);
360 if (m_explore.m_hWnd == NULL) return;
361 CRect rect;
362 GetClientRect (&rect);
363 m_explore.SetWindowPos ((CWnd* )HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, SWP_SHOWWINDOW);
366 string getValue (const string &str, const string &token)
368 string realtoken = token+"=\"";
369 uint spos = str.find (realtoken);
370 if (spos == string::npos) return "";
372 uint spos2 = str.find ("\"", spos+realtoken.size ());
373 if (spos == string::npos) return "";
375 return str.substr (spos+realtoken.size (), spos2-spos-realtoken.size ());
379 void CNel_launcherDlg::launch (const string &str)
381 string exe = ConfigFile.getVar ("Application").asString(1);
382 string path;
384 if (ConfigFile.getVar ("Application").size() == 4)
385 path = ConfigFile.getVar ("Application").asString(3);
387 string rawargs = getValue (str, "nelArgs");
389 nlinfo ("extracting string '%s'", str.c_str ());
391 // convert the command line in an array of string for the _execvp() function
393 vector<string> vargs;
394 const char *args[50];
395 int argspos = 0;
397 uint pos1 = 0, pos2 = 0;
398 while (true)
400 pos2 = rawargs.find(" ", pos1);
401 if (pos2==string::npos)
403 if(pos1!=rawargs.size())
405 string res = rawargs.substr (pos1);
406 vargs.push_back (res);
408 break;
410 if(pos1 != pos2)
412 string res = rawargs.substr (pos1, pos2-pos1);
413 vargs.push_back (res);
415 pos1 = pos2+1;
418 int i;
419 int size;
420 if(vargs.size()>47) size = 47;
421 else size = vargs.size();
423 args[0] = exe.c_str ();
424 for(i = 0; i < size; i++)
426 args[i+1] = vargs[i].c_str ();
428 args[i+1] = NULL;
430 // go in the good path before launching
431 if (!path.empty())
432 _chdir (path.c_str ());
434 // execute, should better use CreateProcess()
435 if (_execvp (exe.c_str(), args) == -1)
437 // error occurs during the launch
438 string str = toString("Can't execute '%s': code=%d %s", exe.c_str(), errno, strerror(errno));
439 MessageBox (str.c_str(), "Error");
441 exit(0);
444 void CNel_launcherDlg::patch (const string &str)
446 string url = "http://"+ConfigFile.getVar ("StartupHost").asString();
448 string serverVersion = getValue (str, "serverVersion");
450 string urlok = url;
451 urlok += getValue (str, "nelUrl");
452 urlok += "&newClientVersion=";
453 urlok += serverVersion;
455 string urlfailed = url;
456 urlfailed += getValue (str, "nelUrlFailed");
457 urlfailed += "&reason=";
459 startPatchThread (getValue (str, "nelServerPath"), serverVersion, urlok, urlfailed, "<br>");
461 SetTimer(0,100,NULL);
463 /* try
465 string serverVersion = getValue (str, "serverVersion");
466 patchVersion (getValue (str, "nelServerPath"), serverVersion);
468 // this url is where we have to go after patching success
469 url += getValue (str, "nelUrl");
470 url += "&newClientVersion=";
471 url += serverVersion;
473 catch (Exception &e)
475 nlwarning ("Patching failed '%s'", e.what());
477 url += getValue (str, "nelUrlFailed");
478 url += "&reason=";
479 url += e.what ();
482 // go to the next url
483 openUrl (url.c_str());*/
486 void CNel_launcherDlg::OnTimer(UINT nIDEvent)
488 string state, log;
489 if (patchState(state, log))
491 LPDISPATCH lpDispatch;
492 lpDispatch = m_explore.GetDocument();
493 if (lpDispatch == NULL) return;
495 IHTMLDocument2* pHTMLDocument2;
496 HRESULT hr;
497 hr = lpDispatch->QueryInterface(IID_IHTMLDocument2, (LPVOID*) &pHTMLDocument2);
498 lpDispatch->Release();
499 if (FAILED(hr)) return;
500 if (pHTMLDocument2 == NULL) return;
502 IHTMLElement* pBody;
503 hr = pHTMLDocument2->get_body(&pBody);
504 if (FAILED(hr)) return;
505 if (pBody == NULL) return;
507 BSTR bstr;
508 pBody->get_innerHTML(&bstr);
509 CString csourceCode( bstr );
510 string htmlCode( (LPCSTR)csourceCode );
511 SysFreeString(bstr);
513 string tokenStart = "<!--nel_start_state-->";
514 string tokenEnd = "<!--nel_end_state-->";
516 int pos = csourceCode.Find (tokenStart.c_str());
517 if (pos == -1) return;
518 int pos2 = csourceCode.Find (tokenEnd.c_str());
519 if (pos2 == -1) return;
521 CString oldstate = csourceCode.Mid (pos, pos2-pos);
523 if (csourceCode.Replace (oldstate, string(tokenStart+state).c_str ()) == 0)
524 return;
526 string tokenStartLog = "<!--nel_start_log-->";
527 string tokenEndLog = "<!--nel_end_log-->";
529 int pos3 = csourceCode.Find (tokenStartLog.c_str());
530 if (pos3 == -1) return;
532 int pos4 = csourceCode.Find (tokenEndLog.c_str());
533 if (pos4 == -1) return;
535 CString oldlog = csourceCode.Mid (pos3, pos4-pos3);
537 if (csourceCode.Replace (oldlog, string(tokenStartLog+log).c_str ()) == 0)
538 return;
540 pBody->put_innerHTML(csourceCode.AllocSysString ()); //insert the html
542 pBody->Release();
545 string url;
546 bool res;
547 if (patchEnded(url, res))
549 nlinfo ("finnish");
550 KillTimer (0);
551 if (res)
552 MessageBox ("Patch completed succesfuly.", "patch");
553 else
554 MessageBox ("Patch could not be completed due to an error.", "patch");
555 openUrl (url.c_str());
560 void CNel_launcherDlg::OnDocumentCompleteExplorer1(LPDISPATCH pDisp, VARIANT FAR* URL)
562 IHTMLDocument2* pHTMLDocument2;
563 LPDISPATCH lpDispatch;
564 lpDispatch = m_explore.GetDocument();
566 if (lpDispatch)
568 HRESULT hr;
569 hr = lpDispatch->QueryInterface(IID_IHTMLDocument2, (LPVOID*) &pHTMLDocument2);
570 lpDispatch->Release();
572 if (FAILED(hr))
573 return;
575 if (pHTMLDocument2 == NULL)
576 return;
578 IHTMLElement* pBody;
579 hr = pHTMLDocument2->get_body(&pBody);
581 if (FAILED(hr))
582 return;
584 if (pBody == NULL)
585 return;
587 BSTR bstr;
588 pBody->get_innerHTML(&bstr);
589 CString csourceCode( bstr );
590 string str( (LPCSTR)csourceCode );
592 SysFreeString(bstr);
593 pBody->Release();
596 // now I have the web page, look if there's something interesting in it.
598 // if something start with <!--nel it s cool
599 string action = getValue (str, "<!--nel");
601 if (action.empty ())
602 return;
604 string token = "<!--nel";
605 uint spos = str.find (token);
606 uint spos2 = str.find ("-->", spos+token.size ()+1);
607 string comment = str.substr (spos+token.size (), spos2-spos-token.size ());
609 if (action=="launch")
610 launch (comment);
611 else if (action=="patch")
612 patch (comment);
613 return;