~s-cecilio/lenmus/v5.3

« back to all changes in this revision

Viewing changes to src/updater/lenmus_updater.cpp

  • Committer: cecilios
  • Date: 2007-05-19 11:39:03 UTC
  • Revision ID: svn-v4:2587a929-2f0e-0410-ae78-fe6f687d5efe:trunk:236

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//---------------------------------------------------------------------------------------
2
 
//    LenMus Phonascus: The teacher of music
3
 
//    Copyright (c) 2002-2012 LenMus project
4
 
//
5
 
//    This program is free software; you can redistribute it and/or modify it under the
6
 
//    terms of the GNU General Public License as published by the Free Software Foundation,
7
 
//    either version 3 of the License, or (at your option) any later version.
8
 
//
9
 
//    This program is distributed in the hope that it will be useful, but WITHOUT ANY
10
 
//    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
11
 
//    PARTICULAR PURPOSE.  See the GNU General Public License for more details.
12
 
//
13
 
//    You should have received a copy of the GNU General Public License along with this
14
 
//    program. If not, see <http://www.gnu.org/licenses/>.
15
 
//
16
 
//    For any comment, suggestion or feature request, please contact the manager of
17
 
//    the project at cecilios@users.sourceforge.net
18
 
//
19
 
//---------------------------------------------------------------------------------------
20
 
 
21
 
//lenmus headers
22
 
#include "lenmus_updater.h"
23
 
 
24
 
#include "lenmus_msg_box.h"
25
 
#include "lenmus_updater_dlg.h"
26
 
#include "lenmus_paths.h"
27
 
 
28
 
//wxWidgets headers
29
 
#include <wx/dialup.h>
30
 
#include <wx/wfstream.h>
31
 
#include <wx/protocol/http.h>
32
 
#include <wx/mstream.h>         //to use files in memory
33
 
#include <wx/url.h>
34
 
#include <wx/datetime.h>        //to get and save the date of last successful check
35
 
#include <wx/mimetype.h>
36
 
#include <wx/filename.h>
37
 
 
38
 
namespace lenmus
39
 
{
40
 
 
41
 
//=======================================================================================
42
 
// Updater implementation
43
 
//=======================================================================================
44
 
Updater::Updater(ApplicationScope& appScope)
45
 
    : m_appScope(appScope)
46
 
{
47
 
}
48
 
 
49
 
//---------------------------------------------------------------------------------------
50
 
Updater::~Updater()
51
 
{
52
 
}
53
 
 
54
 
//---------------------------------------------------------------------------------------
55
 
void Updater::LoadUserPreferences()
56
 
{
57
 
    //load settings form user congiguration data or default values
58
 
    wxConfigBase* pPrefs = m_appScope.get_preferences();
59
 
    pPrefs->Read(_T("/Internet/CheckForUpdates"), &m_fCheckForUpdates, true );
60
 
 
61
 
}
62
 
 
63
 
//---------------------------------------------------------------------------------------
64
 
void Updater::SaveUserPreferences()
65
 
{
66
 
    //save settings in user congiguration data
67
 
    wxConfigBase* pPrefs = m_appScope.get_preferences();
68
 
    pPrefs->Write(_T("/Internet/CheckForUpdates"), m_fCheckForUpdates );
69
 
 
70
 
}
71
 
 
72
 
//---------------------------------------------------------------------------------------
73
 
//true if errors in conection or update information download
74
 
bool Updater::DoCheck(wxString sPlatform, bool fSilent)
75
 
{
76
 
    m_sPlatform = sPlatform;
77
 
 
78
 
    wxXmlDocument oDoc;
79
 
 
80
 
    //for developing and testing do not connect to internet (it implies firewall
81
 
    //rules modification each time I recompile) unless explicitly selected 'Release
82
 
    //behaviour' in Debug menu.
83
 
    if (m_appScope.is_release_behaviour())
84
 
    {
85
 
        //Release behaviour. Access to internet
86
 
 
87
 
        //verify if internet is available
88
 
        if (!CheckInternetConnection())
89
 
        {
90
 
            if (!fSilent)
91
 
            {
92
 
                wxString sEmpty = _T("");
93
 
                wxString sMsg = sEmpty +
94
 
                        _("You are not connected to internet!") + _T("\n\n") +
95
 
                        _("To check for updates LenMus needs internet connection.") + _T("\n") +
96
 
                        _("Please, connect to internet and then retry.");
97
 
                ErrorBox oEB(sMsg, _T("Close this error window"));
98
 
                oEB.ShowModal();
99
 
            }
100
 
            return true;
101
 
        }
102
 
 
103
 
        //wxString sUrl = _T("http://localhost/sw/UpdateData.xml");
104
 
#if (LENMUS_PLATFORM_UNIX == 1)
105
 
        wxString sUrl = _T("http://www.lenmus.org/sw/UpdateData.xml");
106
 
#else
107
 
        wxString sUrl = _T("http://www.lenmus.org/sw/UpdateData-linux.xml");
108
 
#endif
109
 
 
110
 
//-----------------------------------
111
 
     ////Old code using wxHTTP
112
 
 
113
 
     //   // ensure we can build a wxURL object from the given URL
114
 
     //   wxURL oURL(sUrl);
115
 
     //   wxASSERT( oURL.GetError() == wxURL_NOERR);
116
 
     //
117
 
     //   //Setup user-agent string to be identified not as a bot but as a browser
118
 
     //   wxProtocol& oProt = oURL.GetProtocol();
119
 
     //   wxHTTP* pHTTP = (wxHTTP*)&oProt;
120
 
     //   pHTTP->SetHeader(_T("User-Agent"), _T("LenMus Phonascus updater"));
121
 
     //   oProt.SetTimeout(10);              // 90 sec
122
 
 
123
 
     //   //create the input stream by establishing http connection
124
 
     //   wxInputStream* pInput = oURL.GetInputStream();
125
 
 
126
 
//-----------------------------------
127
 
    //// New code using wxHttpEngine
128
 
 
129
 
    //    wxHTTPBuilder oHttp;
130
 
    //    oHttp.InitContentTypes(); // Initialise the content types on the page
131
 
 
132
 
    //    //get proxy options
133
 
    //    ProxySettings* pSettings = GetProxySettings();
134
 
 
135
 
    //    if (pSettings->fUseProxy) {
136
 
    //        oHttp.HttpProxy(pSettings->sProxyHostname, pSettings->nProxyPort );
137
 
    //        if (pSettings->fRequiresAuth)
138
 
    //            oHttp.HttpProxyAuth( pSettings->sProxyUsername, pSettings->sProxyPassword);
139
 
    //    }
140
 
 
141
 
    //    //Setup user-agent string to be identified not as a bot but as a browser
142
 
    //    oHttp.SetHeader(_T("User-Agent"), _T("LenMus Phonascus updater"));
143
 
    //    oHttp.SetTimeout(10);              // 10 sec
144
 
 
145
 
    //    wxInputStream* pInput = oHttp.GetInputStream( sUrl );
146
 
 
147
 
//-----------------------------------
148
 
    // New code using wxHTTP
149
 
 
150
 
        // ensure we can build a wxURL object from the given URL
151
 
        wxURL oURL(sUrl);
152
 
        wxASSERT( oURL.GetError() == wxURL_NOERR);
153
 
 
154
 
        //Setup user-agent string to be identified not as a bot but as a browser
155
 
        wxProtocol& oProt = oURL.GetProtocol();
156
 
        wxHTTP* pHTTP = (wxHTTP*)&oProt;
157
 
        pHTTP->SetHeader(_T("User-Agent"), _T("LenMus_updater"));
158
 
        oProt.SetTimeout(10);              // 10 secs.
159
 
 
160
 
        //get proxy options
161
 
        ProxySettings* pSettings = m_appScope.get_proxy_settings();
162
 
 
163
 
        // If a proxy is used, set it
164
 
        if (pSettings->fUseProxy)
165
 
        {
166
 
            pHTTP->SetProxyMode(true);
167
 
            // user:pass@host:port
168
 
            wxString sProxyUrl = _T("http://");
169
 
            if (pSettings->fRequiresAuth)
170
 
            {
171
 
                sProxyUrl += pSettings->sProxyUsername + _T(":") +
172
 
                             pSettings->sProxyPassword + _T("@");
173
 
            }
174
 
            sProxyUrl += pSettings->sProxyHostname  +
175
 
                wxString::Format( _T(":%d"), pSettings->nProxyPort );
176
 
            oURL.SetProxy( sProxyUrl );
177
 
        }
178
 
 
179
 
        //create the input stream by establishing http connection
180
 
        wxInputStream* pInput = oURL.GetInputStream();
181
 
 
182
 
 
183
 
//-----------------------------------
184
 
        if (!pInput || !pInput->IsOk())
185
 
        {
186
 
            if (pInput)
187
 
                delete pInput;
188
 
            //wxLogMessage( oHttp.GetLastError() );
189
 
            wxString sEmpty = _T("");
190
 
            wxString sMsg = sEmpty + _("Error checking for updates") + _T("\n\n") +
191
 
_("A connection with the server could not be established. \
192
 
Check that you are connected to the internet and that no firewalls are blocking \
193
 
this program; then try again. If problems persist, the server \
194
 
may be down. Please, try again later.");
195
 
            ErrorBox oEB(sMsg, _T("Close this error window"));
196
 
            oEB.ShowModal();
197
 
            return true;
198
 
        }
199
 
 
200
 
        //download updates data file and analyze it
201
 
        if (!oDoc.Load(*pInput))
202
 
        {
203
 
            wxLogMessage(_T("[Updater::DoCheck] Problem: Error loading XML file "));
204
 
            return true;
205
 
        }
206
 
 
207
 
    }
208
 
 
209
 
    else
210
 
    {
211
 
        //Debug behaviour. Instead of accesing Internet use local files
212
 
        wxFileName oFN(m_appScope.get_paths()->GetRootPath(), _T("TestUpdateData.xml"));
213
 
        wxString sFilename = oFN.GetFullPath();
214
 
        if (!oDoc.Load(sFilename) )
215
 
        {
216
 
            wxLogMessage(_T("[Updater::DoCheck] Problem: Error loading XML file "));
217
 
            return true;
218
 
        }
219
 
    }
220
 
 
221
 
    //Verify type of document. Must be <UpdateData>
222
 
    wxXmlNode *pRoot = oDoc.GetRoot();
223
 
    if (pRoot->GetName() != _T("UpdateData"))
224
 
    {
225
 
        wxLogMessage(_T("[Updater::DoCheck] Error. <%s> files are not supported"), pRoot->GetName().c_str() );
226
 
        return true;
227
 
    }
228
 
 
229
 
    //analyze document and extract information for this platform
230
 
    ParseDocument(pRoot);
231
 
 
232
 
    m_fNeedsUpdate = (m_sVersion != _T("") &&
233
 
                      m_sVersion != m_appScope.get_version_string());
234
 
 
235
 
    return false;       //no errors
236
 
}
237
 
 
238
 
//---------------------------------------------------------------------------------------
239
 
bool Updater::CheckInternetConnection()
240
 
{
241
 
    bool fConnected = false;    //assume not connected
242
 
 
243
 
    // check connection
244
 
    wxDialUpManager* pManager = wxDialUpManager::Create();
245
 
    if (pManager->IsOk()) {
246
 
        fConnected = pManager->IsOnline();
247
 
    }
248
 
 
249
 
    delete pManager;
250
 
    return fConnected;
251
 
}
252
 
 
253
 
//---------------------------------------------------------------------------------------
254
 
void Updater::ParseDocument(wxXmlNode* pNode)
255
 
{
256
 
    //initialize results
257
 
    m_sVersion = _T("");
258
 
    m_sDescription = _T("");
259
 
    m_sPackage = _T("No package!");
260
 
 
261
 
    //start parsing. Loop to find <platform> tag for this platform
262
 
    wxLogMessage(_T("[Updater::ParseDocument] Trace: Starting the parser"));
263
 
    pNode = GetFirstChild(pNode);
264
 
    wxXmlNode* pElement = pNode;
265
 
 
266
 
    while (pElement) {
267
 
        if (pElement->GetName() != _T("platform")) {
268
 
            wxLogMessage(_T("[Updater::ParseDocument] Error: Expected tag <platform> but found <%s>"),
269
 
                pElement->GetName().c_str() );
270
 
            return;
271
 
        }
272
 
        else {
273
 
            //if this platform found analyze it and finish
274
 
            if (GetAttribute(pElement, _T("name"), _T("")) == m_sPlatform) {
275
 
                wxLogMessage(_T("[Updater::ParseDocument] Trace: Analyzing data for <platform name='%s'>"),
276
 
                    m_sPlatform.c_str() );
277
 
 
278
 
                //find first child
279
 
                pNode = GetFirstChild(pNode);
280
 
                pElement = pNode;
281
 
 
282
 
                while (pElement) {
283
 
                    if (pElement->GetName() == _T("version")) {
284
 
                        m_sVersion = GetText(pElement);
285
 
                    }
286
 
                    else if (pElement->GetName() == _T("package")) {
287
 
                        m_sPackage = GetText(pElement);
288
 
                    }
289
 
                    else if (pElement->GetName() == _T("description")) {
290
 
                        m_sDescription = GetText(pElement);
291
 
                    }
292
 
                    else if (pElement->GetName() == _T("download_url")) {
293
 
                        m_sUrl = GetText(pElement);
294
 
                    }
295
 
                    else {
296
 
                        wxLogMessage(_T("[Updater::ParseDocument] Error: Expected tag <version> or <description> but found <%s>"),
297
 
                            pElement->GetName().c_str() );
298
 
                    }
299
 
 
300
 
                    // Find next sibling
301
 
                    pNode = GetNextSibling(pNode);
302
 
                    pElement = pNode;
303
 
                }
304
 
                return;     //done
305
 
            }
306
 
            //it is not this platform. Continue with next <platform> tag
307
 
        }
308
 
 
309
 
        // Find next next <platform> tag
310
 
        pNode = GetNextSibling(pNode);
311
 
        pElement = pNode;
312
 
 
313
 
    }
314
 
 
315
 
}
316
 
 
317
 
//---------------------------------------------------------------------------------------
318
 
void Updater::check_for_updates(wxFrame* pParent, bool fSilent)
319
 
{
320
 
    if (!m_fCheckForUpdates) return;
321
 
 
322
 
    //initializations
323
 
    m_pParent = pParent;
324
 
    m_fNeedsUpdate = false;
325
 
    ::wxBeginBusyCursor();
326
 
 
327
 
    //Inform user and ask permision to proceed
328
 
    if (!fSilent) {
329
 
        UpdaterDlgStart dlgStart(m_pParent);
330
 
        if (dlgStart.ShowModal() == wxID_CANCEL) {
331
 
            ::wxEndBusyCursor();
332
 
            return;  //updater canceled
333
 
        }
334
 
    }
335
 
 
336
 
    //conect to server and get information about updates
337
 
#if (LENMUS_PLATFORM_WIN32 == 1)
338
 
    if (DoCheck(_T("Win32"), fSilent)) {
339
 
#else
340
 
    if (DoCheck(_T("Linux"), fSilent)) {
341
 
#endif
342
 
        ::wxEndBusyCursor();
343
 
        return;  //Error. Not posible to do check
344
 
    }
345
 
 
346
 
    //inform about results and remove busy cursor
347
 
    if (!m_fNeedsUpdate) {
348
 
        //no updates available
349
 
        ::wxEndBusyCursor();
350
 
        if (!fSilent) wxMessageBox(_T("No updates available."));
351
 
   }
352
 
    else {
353
 
        //update available. Create and show informative dialog
354
 
        UpdaterDlgInfo dlg(m_pParent, this);
355
 
        dlg.AddPackage(GetPackage(), GetDescription());
356
 
        ::wxEndBusyCursor();
357
 
        dlg.ShowModal();
358
 
    }
359
 
 
360
 
    //save the date of last successful check
361
 
    wxString sLastCheckDate = (wxDateTime::Now()).Format(_T("%x"));
362
 
    wxConfigBase* pPrefs = m_appScope.get_preferences();
363
 
    pPrefs->Write(_T("/Options/CheckForUpdates/LastCheck"), sLastCheckDate);
364
 
 
365
 
}
366
 
 
367
 
//---------------------------------------------------------------------------------------
368
 
bool Updater::DownloadFiles()
369
 
{
370
 
    ::wxLaunchDefaultBrowser(m_sUrl);
371
 
    return false;
372
 
}
373
 
 
374
 
//---------------------------------------------------------------------------------------
375
 
wxString Updater::GetText(wxXmlNode* pElement)
376
 
{
377
 
    //    Receives node of type ELEMENT and returns its text content
378
 
    wxASSERT(pElement->GetType() == wxXML_ELEMENT_NODE);
379
 
 
380
 
    wxXmlNode* pNode = pElement->GetChildren();
381
 
    wxString sName = pElement->GetName();
382
 
    wxString sValue = _T("");
383
 
 
384
 
    if (pNode->GetType() == wxXML_TEXT_NODE) {
385
 
        sValue = pNode->GetContent();
386
 
    }
387
 
    return sValue;
388
 
}
389
 
 
390
 
//---------------------------------------------------------------------------------------
391
 
wxString Updater::GetAttribute(wxXmlNode* pNode, wxString sName, wxString sDefault)
392
 
{
393
 
    wxXmlProperty* pAttrib = pNode->GetProperties();
394
 
    while(pAttrib) {
395
 
        if (pAttrib->GetName() == sName)
396
 
            return pAttrib->GetValue();
397
 
        pAttrib = pAttrib->GetNext();
398
 
    }
399
 
 
400
 
    return sDefault;
401
 
}
402
 
 
403
 
//---------------------------------------------------------------------------------------
404
 
wxXmlNode* Updater::GetNextSibling(wxXmlNode* pNode)
405
 
{
406
 
    // Return next sibling element or NULL if no more
407
 
    pNode = pNode->GetNext();
408
 
    while (pNode && pNode->GetType() != wxXML_ELEMENT_NODE)
409
 
        pNode = pNode->GetNext();
410
 
    return pNode;
411
 
 
412
 
}
413
 
//---------------------------------------------------------------------------------------
414
 
wxXmlNode* Updater::GetFirstChild(wxXmlNode* pNode)
415
 
{
416
 
    // Return first child element or NULL if no more
417
 
    pNode = pNode->GetChildren();
418
 
    while (pNode && pNode->GetType() != wxXML_ELEMENT_NODE)
419
 
        pNode = pNode->GetNext();
420
 
    return pNode;
421
 
}
422
 
 
423
 
 
424
 
}   //namespace lenmus