1 /*
2 
3                           Firewall Builder
4 
5                  Copyright (C) 2008 NetCitadel, LLC
6 
7   Author:  Vadim Kurland <vadim@fwbuilder.org>
8 
9   $Id$
10 
11   This program is free software which we release under the GNU General Public
12   License. You may redistribute and/or modify this program under the terms
13   of that license as published by the Free Software Foundation; either
14   version 2 of the License, or (at your option) any later version.
15 
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20 
21   To get a copy of the GNU General Public License, write to the Free Software
22   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 
24 */
25 
26 #include "config.h"
27 #include "global.h"
28 #include "utils.h"
29 
30 #include "StartTipDialog.h"
31 #include "startup_tip_url.h"
32 #include "FWBSettings.h"
33 #include "FWWindow.h"
34 #include "Help.h"
35 
36 #include "fwbuilder/Constants.h"
37 
38 #include <QCheckBox>
39 #include <QLocale>
40 #include <QtDebug>
41 #include <QDesktopServices>
42 
43 #include <stdlib.h>
44 
45 
46 using namespace std;
47 using namespace libfwbuilder;
48 
StartTipDialog(QWidget * parent)49 StartTipDialog::StartTipDialog(QWidget *parent): QDialog(parent)
50 {
51     setAttribute(Qt::WA_DeleteOnClose);
52     setModal(false);
53 
54     http_getter = new HttpGet();
55     connect(http_getter, SIGNAL(done(const QString&)),
56             this, SLOT(downloadComplete(const QString&)));
57 
58     m_dialog = new Ui::StartTipDialog_q;
59     m_dialog->setupUi(this);
60 
61     QString pgm = m_dialog->program_name->text();
62     m_dialog->program_name->setText(pgm.arg(GENERATION));
63     m_dialog->program_version->setText(VERSION);
64 
65     QString locale = QLocale::system().name(); //"en_US";
66     QStringList paths;
67     paths.append(QString(Constants::getResourcesDirectory().c_str()) +
68                  "/help/" + locale);
69     paths.append(QString(Constants::getResourcesDirectory().c_str()) +
70                  "/help/" + "en_US");
71 
72     m_dialog->textview->setSearchPaths(paths);
73     m_dialog->textview->setOpenLinks(true);
74     m_dialog->textview->setOpenExternalLinks(true);
75 
76     current_tip = -1;
77 
78     // preload tips that come with the package
79 
80     // we use separate Help() object for the tip of the day becayse it should
81     // have different size and should not be persistent
82     Help *h = new Help(NULL, "");
83     int tip_no = 1;
84     while (true)
85     {
86         QString tip_file;
87         tip_file.sprintf("tip%02d.html", tip_no);
88         QString contents;
89         if (fwbdebug)
90 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
91             qDebug("Trying tip file %s", tip_file.toAscii().constData());
92 #else
93             qDebug("Trying tip file %s", tip_file.toLatin1().constData());
94 #endif
95 
96         QString help_file = h->findHelpFile(tip_file);
97         if (!help_file.isEmpty())
98         {
99             tips.append("file:" + tip_file);
100             tip_no++;
101         } else
102             break;
103     }
104     delete h;
105     current_tip = tips.size() - 1;
106 
107     if (fwbdebug) qDebug("Have %d tips", tips.size());
108 
109     first_run = st->getBool("UI/FirstRun");
110 }
111 
~StartTipDialog()112 StartTipDialog::~StartTipDialog()
113 {
114     delete m_dialog;
115     delete http_getter;
116 };
117 
118 /*
119  * disconnect signal in case dialog is closed before http query completes.
120  * This does happen in unit tests and might happen on slow machines or
121  * slow internet connections
122  */
closeEvent(QCloseEvent *)123 void StartTipDialog::closeEvent(QCloseEvent*)
124 {
125     disconnect(http_getter, SIGNAL(done(const QString&)),
126                this, SLOT(downloadComplete(const QString&)));
127 }
128 
129 /*
130  * Returns file name for a random tip
131  */
getRandomTip()132 QString StartTipDialog::getRandomTip()
133 {
134     if (tips.size())
135     {
136         int n = rand() % tips.size();
137         if (fwbdebug) qDebug("Showing tip %d", n);
138         return tips[n];
139     }
140     return "";
141 }
142 
run()143 void StartTipDialog::run()
144 {
145     if (first_run)
146     {
147         showTip(0);
148         st->setBool("UI/FirstRun", false);
149     } else
150     {
151         if (http_getter->get(QUrl(STARTUP_TIP_URL)))
152         {
153             start_time = time(NULL);
154         } else
155         {
156             if (fwbdebug) qDebug("Can not connect to the url %s", STARTUP_TIP_URL);
157             showTip(getRandomTip(), false);
158         }
159     }
160 }
161 
downloadComplete(const QString & txt)162 void StartTipDialog::downloadComplete(const QString &txt)
163 {
164     // Do not show dialog if download took too long (time out occurred)
165     if (time(NULL) - start_time < 15)
166     {
167         QString tip;
168         if (http_getter->getStatus())
169         {
170             showTip(txt);
171         } else
172         {
173             if (fwbdebug)
174             {
175                 qDebug() << "Error connecting to the url " <<  STARTUP_TIP_URL;
176                 qDebug() << http_getter->getLastError();
177             }
178             showTip(getRandomTip(), false);
179         }
180     } else
181     {
182         if (fwbdebug)
183             qDebug("Suppressing startup tip dialog because download took too long");
184     }
185 }
186 
showTip(const QString & txt,bool new_tip)187 void StartTipDialog::showTip(const QString &txt, bool new_tip)
188 {
189     if (fwbdebug) qDebug("Show tip  %s", txt.toStdString().c_str());
190     if (new_tip)
191     {
192         tips.append(txt);
193         current_tip = tips.size() - 1;
194     }
195 
196     QUrl url(txt);
197     if (url.isValid() && (url.scheme() == "file" || url.scheme() == "http"))
198         m_dialog->textview->setSource(url);
199     else
200         m_dialog->textview->setText(txt);
201 
202     show();
203     raise();
204 }
205 
showTip(int tip_idx)206 void StartTipDialog::showTip(int tip_idx)
207 {
208     if (fwbdebug) qDebug("Show tip #%d", tip_idx);
209     showTip(tips[tip_idx], false);
210 }
211 
close()212 void StartTipDialog::close()
213 {
214     if (m_dialog->donotshow->isChecked()) st->setBool("UI/NoStartTip", true);
215     QDialog::close();
216 }
217 
nextTip()218 void StartTipDialog::nextTip()
219 {
220     if (current_tip < (tips.size() - 1))
221     {
222         current_tip++;
223         showTip(current_tip);
224     } else
225         run();   // gets next tip, caches it and shows it
226 }
227 
prevTip()228 void StartTipDialog::prevTip()
229 {
230     current_tip--;
231     if (current_tip < 0) current_tip = 0;
232     showTip(current_tip);
233 }
234 
showGettingStartedTutorial()235 void StartTipDialog::showGettingStartedTutorial()
236 {
237     int ab_group = st->getABTestingGroup();
238     QString url("http://www.fwbuilder.org/4.0/quick_start_guide_%1.html");
239     QDesktopServices::openUrl(QUrl(url.arg(ab_group), QUrl::StrictMode));
240 }
241