FreeCAD

Форк
0
/
NetworkRetriever.cpp 
556 строк · 17.4 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23

24
#include "PreCompiled.h"
25

26
#ifndef _PreComp_
27
# include <QApplication>
28
# include <QDir>
29
# include <QFileInfo>
30
# include <QMessageBox>
31
# include <QTimer>
32
#endif
33

34
#include <App/Application.h>
35
#include <Base/Console.h>
36

37
#include "NetworkRetriever.h"
38
#include "Action.h"
39
#include "BitmapFactory.h"
40
#include "FileDialog.h"
41
#include "MainWindow.h"
42
#include "ui_DlgAuthorization.h"
43

44

45
using namespace Gui;
46
using namespace Gui::Dialog;
47

48
namespace Gui {
49

50
struct NetworkRetrieverP
51
{
52
    // wget options
53
    int tries;
54
    int level;
55
    QString outputFile;
56
    QString user;
57
    QString passwd;
58
    bool timeStamp;
59
    bool img;
60
    bool convert;
61
    bool recurse;
62
    bool folRel;
63
    bool html;
64
    bool nop;
65
    // wget argument
66
    QString startUrl;
67

68
    QString proxy;
69
    QString dir;
70
    bool fail;
71
};
72

73
} // namespace Gui
74

75
/* TRANSLATOR Gui::NetworkRetriever */
76

77
NetworkRetriever::NetworkRetriever( QObject * parent )
78
  : QObject( parent )
79
{
80
    d = new NetworkRetrieverP;
81
    d->tries = 3;
82
    d->level = 1;
83
    d->timeStamp = false;
84
    d->img = false;
85
    d->html = false;
86
    d->convert = true;
87
    d->recurse = false;
88
    d->folRel = false;
89
    d->nop = false;
90

91
    wget = new QProcess(this);
92

93
    // if wgets exits emit signal
94
    connect(wget, qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
95
            this, &NetworkRetriever::wgetFinished);
96

97
    // if application quits kill wget immediately to avoid dangling processes
98
    connect(qApp, &QApplication::lastWindowClosed, wget, &QProcess::kill);
99
}
100

101
NetworkRetriever::~NetworkRetriever()
102
{
103
    delete wget;
104
    delete d;
105
}
106

107
/**
108
 * This method is connected to QTimer::singleShot() and executed after 5 seconds. If wget then is still running
109
 * we can assume that everything is fine.
110
 * \note This test is necessary since \a wget writes all its output on stderr and we cannot determine surely
111
 * if an error occurred or not.
112
 *
113
 * There is still a problem that is not solved so far. If wget requires the proxy settings and if these
114
 * are not set, wget could take more than 5 seconds without downloading anything.
115
 */
116
void NetworkRetriever::testFailure()
117
{
118
    if ( wget->state() == QProcess::Running )
119
    {
120
        d->fail = false;
121
        QString msg = tr("Download started...");
122
        Base::Console().Message("%s\n", msg.toUtf8().constData());
123
    }
124
}
125

126
/**
127
 * Sets the number of retries to \a tries. If \a tries is 0 the number of tries
128
 * is unlimited. The default value of the tries property is set to 3.
129
 */
130
void NetworkRetriever::setNumberOfTries( int tries )
131
{
132
    d->tries = tries;
133
}
134

135
/**
136
 * Sets output file to \a out where documents are written to.
137
 */
138
void NetworkRetriever::setOutputFile( const QString& out )
139
{
140
    d->outputFile = out;
141
}
142

143
/**
144
 * If \a ts is true the timestamping is enabled, otherwise timestamping is
145
 * disabled. If timestamping is enabled files are no more re-retrieved unless
146
 * they are newer than the local files. As default the timestamping property is disabled.
147
 */
148
void NetworkRetriever::setEnableTimestamp(bool ts)
149
{
150
    d->timeStamp = ts;
151
}
152

153
/**
154
 * If you are behind a proxy server then you have to specify your proxy url with \a proxy.
155
 * Moreover, if the proxy requires user authentication then you can specify the username
156
 * with \a user and the password with \a passwd.
157
 */
158
void NetworkRetriever::setProxy( const QString& proxy, const QString& user, const QString& passwd )
159
{
160
    d->proxy = proxy;
161
    d->user = user;
162
    d->passwd = passwd;
163
}
164

165
/**
166
 * If \a recursive is true all referenced files are downloaded recursively.
167
 * As default recursion is disabled. \a level specifies the maximum recursion
168
 * depth. If \a level is 0 the recursion depth is infinite. As default the level
169
 * property is 1.
170
 * \note: Use this with care!
171
 */
172
void NetworkRetriever::setEnableRecursive( bool recursive, int level )
173
{
174
    d->recurse = recursive;
175
    d->level = level;
176
}
177

178
/**
179
 * If \a folRel is true wget follows relative links only. As default
180
 * the follows relative property is false.
181
 */
182
void NetworkRetriever::setFollowRelative( bool folRel )
183
{
184
    d->folRel = folRel;
185
}
186

187
/**
188
 * If \a convert is true all non-relative links are converted to
189
 * relative links. As default the convert property is true.
190
 */
191
void NetworkRetriever::setEnableConvert( bool convert )
192
{
193
    d->convert = convert;
194
}
195

196
/**
197
 * If \a img is true wget tries to get all needed image files
198
 * to display the HTML page. As default this behaviour is disabled..
199
 */
200
void NetworkRetriever::setFetchImages( bool img )
201
{
202
    d->img = img;
203
}
204

205
/**
206
 * Saves all text/html documents with .html extionsion if \a html is true.
207
 * As default the html property is false.
208
 */
209
void NetworkRetriever::setEnableHTMLExtension( bool html )
210
{
211
    d->html = html;
212
}
213

214
/**
215
 * Do not ever ascend to the parent directory when retrieving recursively.
216
 */
217
void NetworkRetriever::setNoParent( bool nop )
218
{
219
    d->nop = nop;
220
}
221

222
/**
223
 * Sets the output directory to \a dir where all downloaded are written into.
224
 */
225
void NetworkRetriever::setOutputDirectory( const QString& dir )
226
{
227
    d->dir = dir;
228
}
229

230
/**
231
 * wget starts to download \a startUrl and all referenced pages.
232
 */
233
bool NetworkRetriever::startDownload( const QString& startUrl )
234
{
235
    if ( !testWget() )
236
        return false;
237

238
    d->startUrl = startUrl;
239

240
    // proxy as environment variable
241
    if ( !d->proxy.isEmpty() )
242
    {
243
        QStringList env = wget->environment();
244
        env << QString::fromLatin1("http_proxy=%1").arg(d->proxy);
245
        env << QString::fromLatin1("ftp_proxy=%1").arg(d->proxy);
246
        wget->setEnvironment(env);
247
    }
248
    else
249
    {
250
        QStringList env = wget->environment();
251
        env.removeAll(QString::fromLatin1("http_proxy=%1").arg(d->proxy));
252
        env.removeAll(QString::fromLatin1("ftp_proxy=%1").arg(d->proxy));
253
        wget->setEnvironment(env);
254
    }
255

256
    QStringList wgetArguments;
257

258
    // since the wget option '--directory-prefix' seems not to work as expected
259
    // and QProcess::setWorkingDirectory() fails if the 'doc' directory doesn't
260
    // exist we must check for this and create it if needed.
261
    if ( !d->dir.isEmpty() )
262
    {
263
        QDir dir(d->dir);
264
        if (!dir.exists(d->dir))
265
        {
266
            if (!dir.mkdir(d->dir))
267
            {
268
                Base::Console().Error("Directory '%s' could not be created.", (const char*)d->dir.toLatin1());
269
                return true; // please, no error message
270
            }
271
        }
272

273
        wget->setWorkingDirectory( dir.path() );
274
    }
275

276
    // user authentication
277
    if ( !d->proxy.isEmpty() )
278
    {
279
        if ( !d->user.isEmpty() )
280
        {
281
            wgetArguments << QString::fromLatin1("--proxy-user=%1").arg( d->user );
282
            if ( !d->passwd.isEmpty() )
283
            {
284
                wgetArguments << QString::fromLatin1("--proxy-passwd=%1").arg( d->passwd );
285
            }
286
        }
287
    }
288

289
    // output file
290
    if ( !d->outputFile.isEmpty() )
291
        wgetArguments << QString::fromLatin1("--output-document=%1").arg( d->outputFile );
292
    // timestamping enabled -> update newer files only
293
    if ( d->timeStamp )
294
        wgetArguments << QString::fromLatin1("-N");
295
    // get all needed image files
296
    if ( d->img )
297
        wgetArguments << QString::fromLatin1("-p");
298
    // follow relative links only
299
    if ( d->folRel )
300
        wgetArguments<< QString::fromLatin1("-L");
301
    if ( d->recurse )
302
    {
303
        wgetArguments << QString::fromLatin1("-r");
304
        wgetArguments << QString::fromLatin1("--level=%1").arg( d->level );
305
    }
306

307
    if ( d->nop )
308
        wgetArguments << QString::fromLatin1("-np");
309

310
    // convert absolute links in to relative
311
    if ( d->convert )
312
        wgetArguments << QString::fromLatin1("-k");
313
    // number of tries
314
    wgetArguments << QString::fromLatin1("--tries=%1").arg( d->tries );
315
    // use HTML file extension
316
    if ( d->html )
317
        wgetArguments << QString::fromLatin1("-E");
318

319
    // start URL
320
    wgetArguments << startUrl;
321

322
#ifdef FC_OS_LINUX
323
    // on Linux it seems that we have to change cwd
324
    QString cwd = QDir::currentPath ();
325
    if ( !d->dir.isEmpty() )
326
    {
327
        QDir::setCurrent(d->dir);
328
    }
329

330
    wget->start(QString::fromLatin1("wget"), wgetArguments);
331
    QDir::setCurrent( cwd );
332
#else
333
    wget->start(QString::fromLatin1("wget"), wgetArguments);
334
#endif
335

336
    return wget->state() == QProcess::Running;
337
}
338

339
/**
340
 * Returns true if wget is still downloading, otherwise returns false.
341
 */
342
bool NetworkRetriever::isDownloading() const
343
{
344
    return wget->state() == QProcess::Running;
345
}
346

347
/**
348
 * Kills wget if it is still running.
349
 */
350
void NetworkRetriever::abort()
351
{
352
    if ( wget->state() == QProcess::Running)
353
    {
354
        QTimer::singleShot( 2000, wget, &QProcess::kill);
355
    }
356
}
357

358
void NetworkRetriever::wgetFinished(int exitCode, QProcess::ExitStatus status)
359
{
360
    Q_UNUSED(exitCode);
361
    Q_UNUSED(status);
362
    wget->setReadChannel(QProcess::StandardError);
363
    if (wget->canReadLine()) {
364
        QByteArray data = wget->readAll();
365
        Base::Console().Warning(data);
366
    }
367
    Q_EMIT wgetExited();
368
}
369

370
/**
371
 * This is a test if wget is in PATH environment or not.
372
 * If the test succeeds true is returned, false otherwise.
373
 */
374
bool NetworkRetriever::testWget()
375
{
376
    QProcess proc;
377
    proc.setProgram(QString::fromLatin1("wget"));
378
    proc.start();
379
    bool ok = proc.state() == QProcess::Running;
380
    proc.kill();
381
    proc.waitForFinished();
382
    return ok;
383
}
384

385
// --------------------------------------------------------------------
386

387
StdCmdDownloadOnlineHelp::StdCmdDownloadOnlineHelp( QObject * parent)
388
  : QObject(parent), Command("Std_DownloadOnlineHelp")
389
{
390
    sGroup        ="Help";
391
    sMenuText     = QT_TR_NOOP("Download online help");
392
    sToolTipText  = QT_TR_NOOP("Download %1's online help");
393
    sWhatsThis    = "Std_DownloadOnlineHelp";
394
    sStatusTip    = QT_TR_NOOP("Download %1's online help");
395
    sPixmap       = "help";
396

397
    wget = new NetworkRetriever( this );
398
    // downloading recursively and depth 5
399
    wget->setEnableRecursive( true, 5 );
400
    wget->setNumberOfTries( 3 );
401
    wget->setEnableHTMLExtension( true );
402
    wget->setEnableConvert( true );
403

404
    wget->setEnableTimestamp( true );
405
    wget->setFetchImages( true );
406
    wget->setFollowRelative( false );
407
    wget->setNoParent( true );
408

409
    connect(wget, &NetworkRetriever::wgetExited, this, &StdCmdDownloadOnlineHelp::wgetFinished);
410
}
411

412
StdCmdDownloadOnlineHelp::~StdCmdDownloadOnlineHelp()
413
{
414
    delete wget;
415
}
416

417
Action * StdCmdDownloadOnlineHelp::createAction()
418
{
419
    Action *pcAction;
420

421
    QString exe = QString::fromStdString(App::Application::getExecutableName());
422
    pcAction = new Action(this,getMainWindow());
423
    pcAction->setText(QCoreApplication::translate(
424
        this->className(), getMenuText()));
425
    pcAction->setToolTip(QCoreApplication::translate(
426
        this->className(), getToolTipText()).arg(exe));
427
    pcAction->setStatusTip(QCoreApplication::translate(
428
        this->className(), getStatusTip()).arg(exe));
429
    pcAction->setWhatsThis(QCoreApplication::translate(
430
        this->className(), getWhatsThis()).arg(exe));
431
    pcAction->setIcon(Gui::BitmapFactory().pixmap(getPixmap()));
432
    pcAction->setShortcut(QString::fromLatin1(getAccel()));
433

434
    return pcAction;
435
}
436

437
void StdCmdDownloadOnlineHelp::languageChange()
438
{
439
    if (_pcAction) {
440
        QString exe = QString::fromStdString(App::Application::getExecutableName());
441
        _pcAction->setText(QCoreApplication::translate(
442
            this->className(), getMenuText()));
443
        _pcAction->setToolTip(QCoreApplication::translate(
444
            this->className(), getToolTipText()).arg(exe));
445
        _pcAction->setStatusTip(QCoreApplication::translate(
446
            this->className(), getStatusTip()).arg(exe));
447
        _pcAction->setWhatsThis(QCoreApplication::translate(
448
            this->className(), getWhatsThis()).arg(exe));
449
    }
450
}
451

452
void StdCmdDownloadOnlineHelp::activated(int iMsg)
453
{
454
    Q_UNUSED(iMsg);
455
    if (!wget->isDownloading()) {
456
        ParameterGrp::handle hGrp = App::GetApplication().GetUserParameter().GetGroup("BaseApp");
457
        hGrp = hGrp->GetGroup("Preferences")->GetGroup("OnlineHelp");
458
        std::string url = hGrp->GetASCII("DownloadURL", "www.freecad.org/wiki/");
459
        std::string prx = hGrp->GetASCII("ProxyText", "");
460
        bool bUseProxy  = hGrp->GetBool ("UseProxy", false);
461
        bool bAuthor    = hGrp->GetBool ("Authorize", false);
462

463
        if (bUseProxy) {
464
            QString username;
465
            QString password;
466

467
            if (bAuthor) {
468
                QDialog dlg(getMainWindow());
469
                dlg.setModal(true);
470
                Ui_DlgAuthorization ui;
471
                ui.setupUi(&dlg);
472

473
                if (dlg.exec() == QDialog::Accepted) {
474
                    username = ui.username->text();
475
                    password = ui.password->text();
476
                }
477
            }
478

479
            wget->setProxy(QString::fromLatin1(prx.c_str()), username, password);
480
        }
481

482
        int loop=3;
483
        bool canStart = false;
484

485
        // set output directory
486
        QString path = QString::fromStdString(App::Application::getHomePath());
487
        path += QString::fromLatin1("/doc/");
488
        ParameterGrp::handle hURLGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/OnlineHelp");
489
        path = QString::fromUtf8(hURLGrp->GetASCII( "DownloadLocation", path.toLatin1() ).c_str());
490

491
        while (loop > 0) {
492
            loop--;
493
            QFileInfo fi( path);
494
            if (!fi.exists()) {
495
                if (QMessageBox::critical(getMainWindow(), tr("Non-existing directory"),
496
                     tr("The directory '%1' does not exist.\n\n"
497
                        "Do you want to specify an existing directory?").arg(fi.filePath()),
498
                     QMessageBox::Yes | QMessageBox::No) !=
499
                     QMessageBox::Yes)
500
                {
501
                    // exit the command
502
                    return;
503
                }
504
                else
505
                {
506
                    path = FileDialog::getExistingDirectory();
507
                    if ( path.isEmpty() )
508
                        return;
509
                }
510
            }
511

512
            if (!fi.permission( QFile::WriteUser)) {
513
                if (QMessageBox::critical(getMainWindow(), tr("Missing permission"),
514
                     tr("You don't have write permission to '%1'\n\n"
515
                        "Do you want to specify another directory?").arg(fi.filePath()),
516
                     QMessageBox::Yes | QMessageBox::No) !=
517
                     QMessageBox::Yes)
518
                {
519
                    // exit the command
520
                    return;
521
                }
522
                else {
523
                    path = FileDialog::getExistingDirectory();
524
                    if ( path.isEmpty() )
525
                        return;
526
                }
527
            }
528
            else {
529
                wget->setOutputDirectory( path );
530
                canStart = true;
531
                break;
532
            }
533
        }
534

535
        if (canStart) {
536
            bool ok = wget->startDownload(QString::fromLatin1(url.c_str()));
537
            if (!ok)
538
                Base::Console().Error("The tool 'wget' couldn't be found. Please check your installation.");
539
            else if ( wget->isDownloading() && _pcAction )
540
                _pcAction->setText(tr("Stop downloading"));
541
        }
542
    }
543
    else // kill the process now
544
    {
545
        wget->abort();
546
    }
547
}
548

549
void StdCmdDownloadOnlineHelp::wgetFinished()
550
{
551
    if (_pcAction)
552
        _pcAction->setText(QCoreApplication::translate(
553
            this->className(), getMenuText()));
554
}
555

556
#include "moc_NetworkRetriever.cpp"
557

558

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.