GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/windows/serverdialog.cpp Lines: 205 450 45.6 %
Date: 2018-05-24 20:11:55 Branches: 252 738 34.1 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2018  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "gui/windows/serverdialog.h"
24
25
#include "chatlogger.h"
26
#include "client.h"
27
#include "configuration.h"
28
#include "main.h"
29
#include "settings.h"
30
31
#include "net/download.h"
32
33
#include "fs/paths.h"
34
35
#include "gui/widgets/checkbox.h"
36
#include "gui/widgets/createwidget.h"
37
#include "gui/widgets/desktop.h"
38
#include "gui/windows/editserverdialog.h"
39
#include "gui/windows/logindialog.h"
40
#include "gui/windows/serverinfowindow.h"
41
42
#include "gui/widgets/button.h"
43
#include "gui/widgets/label.h"
44
#include "gui/widgets/layout.h"
45
#include "gui/widgets/serverslistbox.h"
46
#include "gui/widgets/scrollarea.h"
47
48
#include "utils/delete2.h"
49
#include "utils/foreach.h"
50
#include "utils/langs.h"
51
52
#include "debug.h"
53
54
#ifdef WIN32
55
#undef ERROR
56
#endif  // WIN32
57
58
static const int MAX_SERVERLIST = 15;
59
60
static std::string serverTypeToString(const ServerTypeT type)
61
{
62
    switch (type)
63
    {
64
        case ServerType::TMWATHENA:
65
#ifdef TMWA_SUPPORT
66
            return "TmwAthena";
67
#else  // TMWA_SUPPORT
68
69
            return "";
70
#endif  // TMWA_SUPPORT
71
72
        case ServerType::EATHENA:
73
            return "eAthena";
74
        case ServerType::EVOL2:
75
            return "Evol2";
76
        default:
77
        case ServerType::UNKNOWN:
78
            return "";
79
    }
80
}
81
82
static uint16_t defaultPortForServerType(const ServerTypeT type)
83
{
84

60
    switch (type)
85
    {
86
        default:
87
        case ServerType::EATHENA:
88
        case ServerType::EVOL2:
89
            return 6900;
90
60
        case ServerType::UNKNOWN:
91
        case ServerType::TMWATHENA:
92
            return 6901;
93
    }
94
}
95
96
4
ServerDialog::ServerDialog(ServerInfo *const serverInfo,
97
4
                           const std::string &dir) :
98
    // TRANSLATORS: servers dialog name
99
4
    Window(_("Choose Your Server"), Modal_false, nullptr, "server.xml"),
100
    ActionListener(),
101
    KeyListener(),
102
    SelectionListener(),
103
    mMutex(),
104
    mServers(ServerInfos()),
105
    mDir(dir),
106

8
    mDescription(new Label(this, std::string())),
107
    // TRANSLATORS: servers dialog button
108

8
    mQuitButton(new Button(this, _("Quit"), "quit", BUTTON_SKIN, this)),
109
    // TRANSLATORS: servers dialog button
110
4
    mConnectButton(new Button(this, _("Connect"), "connect",
111

4
        BUTTON_SKIN, this)),
112
    // TRANSLATORS: servers dialog button
113

8
    mAddEntryButton(new Button(this, _("Add"), "addEntry", BUTTON_SKIN, this)),
114
    // TRANSLATORS: servers dialog button
115
4
    mEditEntryButton(new Button(this, _("Edit"), "editEntry",
116

4
        BUTTON_SKIN, this)),
117
    // TRANSLATORS: servers dialog button
118

8
    mDeleteButton(new Button(this, _("Delete"), "remove", BUTTON_SKIN, this)),
119
    // TRANSLATORS: servers dialog button
120

8
    mLoadButton(new Button(this, _("Load"), "load", BUTTON_SKIN, this)),
121
    // TRANSLATORS: servers dialog button
122

8
    mInfoButton(new Button(this, _("Info"), "info", BUTTON_SKIN, this)),
123

4
    mServersListModel(new ServersListModel(&mServers, this)),
124

4
    mServersList(CREATEWIDGETR(ServersListBox, this, mServersListModel)),
125
    mDownload(nullptr),
126
    mServerInfo(serverInfo),
127
    mPersistentIPCheckBox(nullptr),
128
    mDownloadProgress(-1.0F),
129








260
    mDownloadStatus(ServerDialogDownloadStatus::UNKNOWN)
130
{
131
4
    if (isSafeMode)
132
    {
133
        // TRANSLATORS: servers dialog name
134
        setCaption(_("Choose Your Server  *** SAFE MODE ***"));
135
    }
136
#ifdef USE_OPENGL
137

16
    else if (config.getIntValue("opengl") == RENDER_SOFTWARE)
138
    {
139
        // TRANSLATORS: servers dialog name
140
20
        setCaption(_("Choose Your Server  *** SOFTWARE RENDER MODE ***"));
141
    }
142
#endif  // USE_OPENGL
143
144
20
    setWindowName("ServerDialog");
145
146
4
    setCloseButton(true);
147
148

36
    mPersistentIPCheckBox = new CheckBox(this,
149
        // TRANSLATORS: servers dialog checkbox
150
4
        _("Use same ip for game sub servers"),
151

16
        config.getBoolValue("usePersistentIP"),
152

4
        this, "persitent ip");
153
154
4
    loadCustomServers();
155
156
4
    mServersList->addMouseListener(this);
157
158
4
    ScrollArea *const usedScroll = new ScrollArea(this, mServersList,
159

16
        fromBool(getOptionBool("showbackground", false), Opaque),
160

20
        "server_background.xml");
161
4
    usedScroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
162
163
4
    mServersList->addSelectionListener(this);
164
4
    usedScroll->setVerticalScrollAmount(0);
165
166
8
    place(0, 0, usedScroll, 8, 5).setPadding(3);
167
4
    place(0, 5, mDescription, 8, 1);
168
4
    place(0, 6, mPersistentIPCheckBox, 8, 1);
169
4
    place(0, 7, mInfoButton, 1, 1);
170
4
    place(1, 7, mAddEntryButton, 1, 1);
171
4
    place(2, 7, mEditEntryButton, 1, 1);
172
4
    place(3, 7, mLoadButton, 1, 1);
173
4
    place(4, 7, mDeleteButton, 1, 1);
174
4
    place(6, 7, mQuitButton, 1, 1);
175
4
    place(7, 7, mConnectButton, 1, 1);
176
177
    // Make sure the list has enough height
178

4
    getLayout().setRowHeight(0, 80);
179
180
    // Do this manually instead of calling reflowLayout so we can enforce a
181
    // minimum width.
182
4
    int width = 500;
183
4
    int height = 350;
184
185

4
    getLayout().reflow(width, height);
186
4
    setContentSize(width, height);
187
188
4
    setMinWidth(310);
189
4
    setMinHeight(220);
190
12
    setDefaultSize(getWidth(), getHeight(), ImagePosition::CENTER, 0, 0);
191
192
4
    setResizable(true);
193
4
    addKeyListener(this);
194
195
4
    loadWindowState();
196
4
}
197
198
4
void ServerDialog::postInit()
199
{
200
4
    Window::postInit();
201
4
    setVisible(Visible_true);
202
203
4
    mConnectButton->requestFocus();
204
205
4
    loadServers(true);
206
207
4
    mServersList->setSelected(0);  // Do this after for the Delete button
208
209
4
    if (needUpdateServers())
210
1
        downloadServerList();
211
    else
212
3
        logger->log("Skipping servers list update");
213
4
}
214
215
28
ServerDialog::~ServerDialog()
216
{
217
4
    if (mDownload != nullptr)
218
    {
219
1
        mDownload->cancel();
220
1
        delete2(mDownload)
221
    }
222
8
    delete2(mServersListModel);
223
8
}
224
225
void ServerDialog::connectToSelectedServer()
226
{
227
    if (client->getState() == State::CONNECT_SERVER)
228
        return;
229
230
    const int index = mServersList->getSelected();
231
    if (index < 0)
232
        return;
233
234
    if (mDownload != nullptr)
235
        mDownload->cancel();
236
237
    mQuitButton->setEnabled(false);
238
    mConnectButton->setEnabled(false);
239
    mLoadButton->setEnabled(false);
240
241
    ServerInfo server = mServers.at(index);
242
    mServerInfo->hostname = server.hostname;
243
    mServerInfo->althostname = server.althostname;
244
    mServerInfo->port = server.port;
245
    mServerInfo->type = server.type;
246
    mServerInfo->name = server.name;
247
    mServerInfo->description = server.description;
248
    mServerInfo->registerUrl = server.registerUrl;
249
    mServerInfo->onlineListUrl = server.onlineListUrl;
250
    mServerInfo->supportUrl = server.supportUrl;
251
    mServerInfo->defaultHostName = server.defaultHostName;
252
    mServerInfo->save = true;
253
    mServerInfo->persistentIp = server.persistentIp;
254
    mServerInfo->freeType = server.freeType;
255
    mServerInfo->updateMirrors = server.updateMirrors;
256
    mServerInfo->packetVersion = server.packetVersion;
257
    mServerInfo->updateHosts = server.updateHosts;
258
    mServerInfo->freeSources = server.freeSources;
259
    mServerInfo->nonFreeSources = server.nonFreeSources;
260
    mServerInfo->docs = server.docs;
261
    mServerInfo->serverUrl = server.serverUrl;
262
263
    settings.persistentIp = mServerInfo->persistentIp;
264
    settings.supportUrl = mServerInfo->supportUrl;
265
    settings.updateMirrors = mServerInfo->updateMirrors;
266
267
    if (chatLogger != nullptr)
268
        chatLogger->setServerName(mServerInfo->hostname);
269
270
    saveCustomServers(*mServerInfo,
271
        -1);
272
273
    if (!LoginDialog::savedPasswordKey.empty())
274
    {
275
        if (mServerInfo->hostname != LoginDialog::savedPasswordKey)
276
        {
277
            LoginDialog::savedPassword.clear();
278
            if (desktop != nullptr)
279
                desktop->reloadWallpaper();
280
        }
281
    }
282
283
    config.setValue("usePersistentIP",
284
        mPersistentIPCheckBox->isSelected());
285
    client->setState(State::CONNECT_SERVER);
286
}
287
288
void ServerDialog::action(const ActionEvent &event)
289
{
290
    const std::string &eventId = event.getId();
291
    if (eventId == "connect")
292
    {
293
        connectToSelectedServer();
294
    }
295
    else if (eventId == "quit")
296
    {
297
        close();
298
    }
299
    else if (eventId == "load")
300
    {
301
        downloadServerList();
302
    }
303
    else if (eventId == "addEntry")
304
    {
305
        CREATEWIDGET(EditServerDialog, this, ServerInfo(), -1);
306
    }
307
    else if (eventId == "editEntry")
308
    {
309
        const int index = mServersList->getSelected();
310
        if (index >= 0)
311
        {
312
            CREATEWIDGET(EditServerDialog,
313
                this,
314
                mServers.at(index),
315
                index);
316
        }
317
    }
318
    else if (eventId == "remove")
319
    {
320
        const int index = mServersList->getSelected();
321
        if (index >= 0)
322
        {
323
            mServersList->setSelected(0);
324
            mServers.erase(mServers.begin() + index);
325
            saveCustomServers(ServerInfo(),
326
                -1);
327
        }
328
    }
329
    else if (eventId == "info")
330
    {
331
        const int index = mServersList->getSelected();
332
        if (index >= 0)
333
        {
334
            if (serverInfoWindow != nullptr)
335
                serverInfoWindow->scheduleDelete();
336
            serverInfoWindow = CREATEWIDGETR(ServerInfoWindow,
337
                mServers.at(index));
338
        }
339
    }
340
}
341
342
void ServerDialog::keyPressed(KeyEvent &event)
343
{
344
    PRAGMA45(GCC diagnostic push)
345
    PRAGMA45(GCC diagnostic ignored "-Wswitch-enum")
346
    switch (event.getActionId())
347
    {
348
        case InputAction::GUI_CANCEL:
349
            event.consume();
350
            client->setState(State::EXIT);
351
            return;
352
353
        case InputAction::GUI_SELECT:
354
        case InputAction::GUI_SELECT2:
355
            event.consume();
356
            action(ActionEvent(nullptr,
357
                mConnectButton->getActionEventId()));
358
            return;
359
360
        case InputAction::GUI_INSERT:
361
            CREATEWIDGET(EditServerDialog, this, ServerInfo(), -1);
362
            return;
363
364
        case InputAction::GUI_DELETE:
365
        {
366
            const int index = mServersList->getSelected();
367
            if (index >= 0)
368
            {
369
                mServersList->setSelected(0);
370
                mServers.erase(mServers.begin() + index);
371
                saveCustomServers(ServerInfo(),
372
                    -1);
373
            }
374
            return;
375
        }
376
377
        case InputAction::GUI_BACKSPACE:
378
        {
379
            const int index = mServersList->getSelected();
380
            if (index >= 0)
381
            {
382
                CREATEWIDGET(EditServerDialog, this, mServers.at(index),
383
                    index);
384
            }
385
            return;
386
        }
387
388
        default:
389
            break;
390
    }
391
    PRAGMA45(GCC diagnostic pop)
392
    if (!event.isConsumed())
393
        mServersList->keyPressed(event);
394
}
395
396
8
void ServerDialog::valueChanged(const SelectionEvent &event A_UNUSED)
397
{
398
16
    const int index = mServersList->getSelected();
399
8
    if (index == -1)
400
    {
401
        mDeleteButton->setEnabled(false);
402
        return;
403
    }
404
8
    mDeleteButton->setEnabled(true);
405
}
406
407
void ServerDialog::mouseClicked(MouseEvent &event)
408
{
409
    if (event.getButton() == MouseButton::LEFT)
410
    {
411
        event.consume();
412
        if (event.getClickCount() == 2 &&
413
            event.getSource() == mServersList)
414
        {
415
            action(ActionEvent(mConnectButton,
416
                mConnectButton->getActionEventId()));
417
        }
418
    }
419
}
420
421
void ServerDialog::logic()
422
{
423
    BLOCK_START("ServerDialog::logic")
424
    {
425
        MutexLocker tempLock(&mMutex);
426
        if (mDownloadStatus == ServerDialogDownloadStatus::COMPLETE)
427
        {
428
            loadServers(true);
429
            mDownloadStatus = ServerDialogDownloadStatus::OVER;
430
            mDescription->setCaption(std::string());
431
            logger->log("Servers list updated");
432
        }
433
        else if (mDownloadStatus == ServerDialogDownloadStatus::IN_PROGRESS)
434
        {
435
            // TRANSLATORS: servers dialog label
436
            mDescription->setCaption(strprintf(_("Downloading server list..."
437
                "%2.2f%%"), static_cast<double>(mDownloadProgress * 100)));
438
        }
439
        else if (mDownloadStatus == ServerDialogDownloadStatus::IDLE)
440
        {
441
            // TRANSLATORS: servers dialog label
442
            mDescription->setCaption(_("Waiting for server..."));
443
        }
444
        else if (mDownloadStatus == ServerDialogDownloadStatus::PREPARING)
445
        {
446
            // TRANSLATORS: servers dialog label
447
            mDescription->setCaption(_("Preparing download"));
448
        }
449
        else if (mDownloadStatus == ServerDialogDownloadStatus::ERROR)
450
        {
451
            // TRANSLATORS: servers dialog label
452
            mDescription->setCaption(_("Error retreiving server list!"));
453
            logger->log("Error: servers list updating error");
454
        }
455
    }
456
457
    Window::logic();
458
    BLOCK_END("ServerDialog::logic")
459
}
460
461
1
void ServerDialog::downloadServerList()
462
{
463
    // Try to load the configuration value for the onlineServerList
464

5
    std::string listFile = branding.getStringValue("onlineServerList");
465

5
    std::string listFile2 = branding.getStringValue("onlineServerList2");
466
467
    // Fall back to manaplus.org when neither branding
468
    // nor config set it
469
1
    if (listFile.empty())
470
        listFile = "http://manaplus.org/serverlist.xml";
471
472
1
    if (mDownload != nullptr)
473
    {
474
        mDownload->cancel();
475
        delete2(mDownload)
476
    }
477
478
1
    mDownload = new Net::Download(this, listFile,
479

1
        &downloadUpdate, false, false, true);
480

4
    mDownload->setFile(pathJoin(mDir,
481

5
        branding.getStringValue("onlineServerFile")),
482
        -1);
483
1
    if (!listFile2.empty())
484
1
        mDownload->addMirror(listFile2);
485
1
    mDownload->start();
486
487

5
    config.setValue("serverslistupdate", getDateString());
488
1
}
489
490
4
static void loadHostsGroup(XmlNodeConstPtr node,
491
                           ServerInfo &server)
492
{
493
8
    HostsGroup group;
494

20
    group.name = XML::langProperty(node,
495
        "name",
496
        // TRANSLATORS: unknown hosts group name
497
4
        _("Unknown"));
498
16
    for_each_xml_child_node(hostNode, node)
499
    {
500

24
        if (!xmlNameEqual(hostNode, "host") ||
501
8
            !XmlHaveChildContent(hostNode))
502
        {
503
16
            continue;
504
        }
505
16
        const std::string host = XmlChildContent(hostNode);
506
4
        if (host.empty())
507
            continue;
508

4
        if (!checkPath(host))
509
        {
510
            logger->log1("Warning: incorrect update server name");
511
            continue;
512
        }
513
514
4
        group.hosts.push_back(host);
515
    }
516
4
    if (!group.hosts.empty())
517
4
        server.updateHosts.push_back(group);
518
4
}
519
520
static void loadServerSourcesList(XmlNodeConstPtr node,
521
                                  STD_VECTOR<ServerUrlInfo> &list)
522
{
523
    for_each_xml_child_node(urlNode, node)
524
    {
525
        if (!xmlNameEqual(urlNode, "url") ||
526
            !XmlHaveChildContent(urlNode))
527
        {
528
            continue;
529
        }
530
        const std::string name = XML::langProperty(urlNode,
531
            "name",
532
            "");
533
        if (name.empty())
534
            continue;
535
        const std::string url = XmlChildContent(urlNode);
536
        if (url.empty())
537
            continue;
538
        list.push_back(ServerUrlInfo(name, url));
539
    }
540
}
541
542
static void loadServerSources(XmlNodeConstPtr node,
543
                              ServerInfo &server)
544
{
545
    for_each_xml_child_node(subNode, node)
546
    {
547
        if (xmlNameEqual(subNode, "free"))
548
        {
549
            loadServerSourcesList(subNode, server.freeSources);
550
        }
551
        else if (xmlNameEqual(subNode, "nonfree"))
552
        {
553
            loadServerSourcesList(subNode, server.nonFreeSources);
554
        }
555
    }
556
}
557
558
4
void ServerDialog::loadServers(const bool addNew)
559
{
560
16
    XML::Document doc(pathJoin(mDir,
561

20
        branding.getStringValue("onlineServerFile")),
562
        UseVirtFs_false,
563
8
        SkipError_true);
564
4
    XmlNodeConstPtr rootNode = doc.rootNode();
565
566

8
    if (rootNode == nullptr ||
567
4
        !xmlNameEqual(rootNode, "serverlist"))
568
    {
569
        logger->log1("Error loading server list!");
570
        return;
571
    }
572
573
4
    const int ver = XML::getProperty(rootNode, "version", 0);
574
4
    if (ver != 1)
575
    {
576
        logger->log("Error: unsupported online server list version: %d",
577
                    ver);
578
        return;
579
    }
580
581
8
    const std::string lang = getLangShort();
582
8
    const std::string description2("description_" + lang);
583
584
72
    for_each_xml_child_node(serverNode, rootNode)
585
    {
586

68
        if (!xmlNameEqual(serverNode, "server"))
587
80
            continue;
588
589
        const std::string type = XML::getProperty(
590

140
            serverNode, "type", "unknown");
591
56
        ServerInfo server;
592
28
        server.type = ServerInfo::parseType(type);
593
        const std::string licenseType = XML::getProperty(
594

140
            serverNode, "licenseType", "notset");
595
28
        server.freeType = ServerInfo::parseFreeType(licenseType);
596
597
        // Ignore unknown server types
598
28
        if (server.type == ServerType::UNKNOWN)
599
        {
600
            logger->log("Ignoring server entry with unknown type: %s",
601
                        type.c_str());
602
            continue;
603
        }
604
605
84
        server.name = XML::getProperty(serverNode, "name", std::string());
606
        std::string version = XML::getProperty(serverNode, "minimumVersion",
607
84
                                               std::string());
608
609

112
        const bool meetsMinimumVersion = (compareStrI(version, SMALL_VERSION)
610
28
                                   <= 0);
611
612
        // For display in the list
613
28
        if (meetsMinimumVersion)
614
            version.clear();
615
        else if (version.empty())
616
        {
617
            // TRANSLATORS: servers dialog label
618
            version = _("requires a newer version");
619
        }
620
        else
621
        {
622
            // TRANSLATORS: servers dialog label
623
            version = strprintf(_("requires v%s"), version.c_str());
624
        }
625
626
56
        const Font *const font = gui->getFont();
627
628
1048
        for_each_xml_child_node(subNode, serverNode)
629
        {
630

1020
            if (xmlNameEqual(subNode, "connection"))
631
            {
632

140
                server.hostname = XML::getProperty(subNode, "hostname", "");
633

140
                server.althostname = XML::getProperty(
634
                    subNode, "althostname", "");
635
28
                server.port = CAST_U16(
636
28
                    XML::getProperty(subNode, "port", 0));
637
28
                server.packetVersion = XML::getProperty(subNode,
638
                    "packetVersion", 0);
639
640
28
                if (server.port == 0)
641
                {
642
                    // If no port is given, use the default for the given type
643
                    server.port = defaultPortForServerType(server.type);
644
                }
645
            }
646

992
            else if (XmlHaveChildContent(subNode))
647
            {
648
464
                if ((xmlNameEqual(subNode, "description")
649

928
                    && server.description.empty()) || (!lang.empty()
650

436
                    && xmlNameEqual(subNode, description2.c_str())))
651
                {
652
52
                    server.description = XmlChildContent(subNode);
653
                }
654

412
                else if (xmlNameEqual(subNode, "registerurl"))
655
                {
656
4
                    server.registerUrl = XmlChildContent(subNode);
657
                }
658

408
                else if (xmlNameEqual(subNode, "onlineListUrl"))
659
                {
660
4
                    server.onlineListUrl = XmlChildContent(subNode);
661
                }
662

404
                else if (xmlNameEqual(subNode, "support"))
663
                {
664
20
                    server.supportUrl = XmlChildContent(subNode);
665
                }
666

384
                else if (xmlNameEqual(subNode, "persistentIp"))
667
                {
668
                    std::string text = XmlChildContent(subNode);
669
                    server.persistentIp = (text == "1" || text == "true");
670
                }
671

384
                else if (xmlNameEqual(subNode, "updateMirror"))
672
                {
673
80
                    server.updateMirrors.push_back(XmlChildContent(subNode));
674
                }
675

368
                else if (xmlNameEqual(subNode, "site"))
676
                {
677
28
                    server.serverUrl = XmlChildContent(subNode);
678
                }
679
            }
680

1020
            if (xmlNameEqual(subNode, "updates"))
681
            {
682
4
                loadHostsGroup(subNode, server);
683
            }
684

1016
            else if (xmlNameEqual(subNode, "defaultUpdateHost"))
685
            {
686

20
                server.defaultHostName = XML::langProperty(
687
                    // TRANSLATORS: default hosts group name
688
4
                    subNode, "name", _("default"));
689
            }
690

1012
            else if (xmlNameEqual(subNode, "sources"))
691
            {
692
                loadServerSources(subNode, server);
693
            }
694

1012
            else if (xmlNameEqual(subNode, "docs"))
695
            {
696
                loadServerSourcesList(subNode, server.docs);
697
            }
698
        }
699
700
28
        server.version.first = font->getWidth(version);
701
28
        server.version.second = version;
702
703
84
        MutexLocker tempLock(&mMutex);
704
        // Add the server to the local list if it's not already present
705
28
        bool found = false;
706
112
        for (unsigned int i = 0, fsz = CAST_U32(
707
56
             mServers.size()); i < fsz; i++)
708
        {
709
168
            if (mServers[i] == server)
710
            {
711
                // Use the name listed in the server list
712
                mServers[i].name = server.name;
713
                mServers[i].type = server.type;
714
                mServers[i].freeType = server.freeType;
715
                mServers[i].version = server.version;
716
                mServers[i].description = server.description;
717
                mServers[i].registerUrl = server.registerUrl;
718
                mServers[i].onlineListUrl = server.onlineListUrl;
719
                mServers[i].supportUrl = server.supportUrl;
720
                mServers[i].serverUrl = server.serverUrl;
721
                mServers[i].althostname = server.althostname;
722
                mServers[i].persistentIp = server.persistentIp;
723
                mServers[i].updateMirrors = server.updateMirrors;
724
                mServers[i].defaultHostName = server.defaultHostName;
725
                mServers[i].updateHosts = server.updateHosts;
726
                mServers[i].packetVersion = server.packetVersion;
727
                mServers[i].freeSources = server.freeSources;
728
                mServers[i].nonFreeSources = server.nonFreeSources;
729
                mServers[i].docs = server.docs;
730
                mServersListModel->setVersionString(i, version);
731
                found = true;
732
                break;
733
            }
734
        }
735
28
        if (!found && addNew)
736
28
            mServers.push_back(server);
737
    }
738
8
    if (mServersList->getSelected() < 0)
739
4
        mServersList->setSelected(0);
740
}
741
742
4
void ServerDialog::loadCustomServers()
743
{
744
64
    for (int i = 0; i < MAX_SERVERLIST; ++i)
745
    {
746
60
        const std::string index = toString(i);
747
60
        const std::string nameKey("MostUsedServerDescName" + index);
748
60
        const std::string descKey("MostUsedServerDescription" + index);
749
60
        const std::string hostKey("MostUsedServerName" + index);
750
60
        const std::string typeKey("MostUsedServerType" + index);
751
60
        const std::string portKey("MostUsedServerPort" + index);
752
        const std::string onlineListUrlKey
753
60
            ("MostUsedServerOnlineList" + index);
754
60
        const std::string persistentIpKey("persistentIp" + index);
755
        const std::string packetVersionKey
756
60
            ("MostUsedServerPacketVersion" + index);
757
758
60
        ServerInfo server;
759

300
        server.name = config.getValue(nameKey, "");
760

300
        server.description = config.getValue(descKey, "");
761

300
        server.onlineListUrl = config.getValue(onlineListUrlKey, "");
762

300
        server.hostname = config.getValue(hostKey, "");
763

300
        server.type = ServerInfo::parseType(config.getValue(typeKey, ""));
764
120
        server.persistentIp = config.getValue(
765
60
            persistentIpKey, 0) != 0 ? true : false;
766
60
        server.packetVersion = config.getValue(packetVersionKey, 0);
767
768
120
        const int defaultPort = defaultPortForServerType(server.type);
769
60
        server.port = CAST_U16(
770
60
            config.getValue(portKey, defaultPort));
771
772
        // skip invalid server
773
60
        if (!server.isValid())
774
60
            continue;
775
776
        server.save = true;
777
        mServers.push_back(server);
778
    }
779
4
}
780
781
void ServerDialog::saveCustomServers(const ServerInfo &currentServer,
782
                                     const int index)
783
{
784
    // Make sure the current server is mentioned first
785
    if (currentServer.isValid())
786
    {
787
        if (index >= 0 && CAST_SIZE(index) < mServers.size())
788
        {
789
            mServers[index] = currentServer;
790
        }
791
        else
792
        {
793
            FOR_EACH (ServerInfos::iterator, i, mServers)
794
            {
795
                if (*i == currentServer)
796
                {
797
                    mServers.erase(i);
798
                    break;
799
                }
800
            }
801
            mServers.insert(mServers.begin(), currentServer);
802
        }
803
    }
804
805
    int savedServerCount = 0;
806
807
    for (unsigned i = 0, fsz = CAST_U32(mServers.size());
808
         i < fsz && savedServerCount < MAX_SERVERLIST; ++ i)
809
    {
810
        const ServerInfo &server = mServers.at(i);
811
812
        // Only save servers that were loaded from settings
813
        if (!(server.save && server.isValid()))
814
            continue;
815
816
        const std::string num = toString(savedServerCount);
817
        const std::string nameKey("MostUsedServerDescName" + num);
818
        const std::string descKey("MostUsedServerDescription" + num);
819
        const std::string hostKey("MostUsedServerName" + num);
820
        const std::string typeKey("MostUsedServerType" + num);
821
        const std::string portKey("MostUsedServerPort" + num);
822
        const std::string onlineListUrlKey
823
            ("MostUsedServerOnlineList" + num);
824
        const std::string persistentIpKey("persistentIp" + num);
825
        const std::string packetVersionKey
826
            ("MostUsedServerPacketVersion" + num);
827
828
        config.setValue(nameKey, server.name);
829
        config.setValue(descKey, server.description);
830
        config.setValue(onlineListUrlKey, server.onlineListUrl);
831
        config.setValue(hostKey, server.hostname);
832
        config.setValue(typeKey, serverTypeToString(server.type));
833
        config.setValue(portKey, toString(server.port));
834
        config.setValue(persistentIpKey, server.persistentIp);
835
        config.setValue(packetVersionKey, server.packetVersion);
836
        ++ savedServerCount;
837
    }
838
839
    // Insert an invalid entry at the end to make the loading stop there
840
    if (savedServerCount < MAX_SERVERLIST)
841
        config.setValue("MostUsedServerName" + toString(savedServerCount), "");
842
}
843
844
int ServerDialog::downloadUpdate(void *ptr,
845
                                 const DownloadStatusT status,
846
                                 size_t total,
847
                                 const size_t remaining)
848
{
849
    if ((ptr == nullptr) || status == DownloadStatus::Cancelled)
850
        return -1;
851
852
    ServerDialog *const sd = reinterpret_cast<ServerDialog*>(ptr);
853
    bool finished = false;
854
855
    if (sd->mDownload == nullptr)
856
        return -1;
857
858
    if (status == DownloadStatus::Complete)
859
    {
860
        finished = true;
861
    }
862
    else if (CAST_S32(status) < 0)
863
    {
864
        logger->log("Error retreiving server list: %s\n",
865
                    sd->mDownload->getError());
866
        sd->mDownloadStatus = ServerDialogDownloadStatus::ERROR;
867
    }
868
    else
869
    {
870
        float progress = static_cast<float>(remaining);
871
        if (total != 0u)
872
            progress /= static_cast<float>(total);
873
874
        if (progress != progress || progress < 0.0F)
875
            progress = 0.0f;
876
        else if (progress > 1.0F)
877
            progress = 1.0F;
878
879
        MutexLocker lock1(&sd->mMutex);
880
        sd->mDownloadStatus = ServerDialogDownloadStatus::IN_PROGRESS;
881
        sd->mDownloadProgress = progress;
882
    }
883
884
    if (finished)
885
    {
886
        MutexLocker lock1(&sd->mMutex);
887
        sd->mDownloadStatus = ServerDialogDownloadStatus::COMPLETE;
888
    }
889
890
    return 0;
891
}
892
893
void ServerDialog::updateServer(const ServerInfo &server, const int index)
894
{
895
    saveCustomServers(server, index);
896
}
897
898
4
bool ServerDialog::needUpdateServers() const
899
{
900




32
    if (mServers.empty() || config.getStringValue("serverslistupdate")
901

16
        != getDateString())
902
    {
903
        return true;
904
    }
905
906
3
    return false;
907
}
908
909
void ServerDialog::close()
910
{
911
    if (mDownload != nullptr)
912
        mDownload->cancel();
913
    client->setState(State::FORCE_QUIT);
914
    Window::close();
915

6
}