arcsdownloader.cpp
1 /*
2  name: tools/pkg/arcsdownloader.cpp
3 
4  This file is part of ARCS - Augmented Reality Component System
5  (version 2-current), written by Jean-Yves Didier
6  for IBISC Laboratory (http://www.ibisc.univ-evry.fr)
7 
8  Copyright (C) 2013 Université d'Evry-Val d'Essonne
9 
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program. If not, see <http://www.gnu.org/licenses/>.
22 
23 
24  Please send bugreports with examples or suggestions to
25  jean-yves.didier__at__ibisc.univ-evry.fr
26 */
27 
28 
29 #include "arcsdownloader.h"
30 #include <QNetworkReply>
31 #include <QNetworkAccessManager>
32 #include <QNetworkRequest>
33 #include <QFileInfo>
34 #include <iostream>
35 #include <QAuthenticator>
36 #include <QSslCertificate>
37 #include <QEventLoop>
38 #include <getpasswd.h>
39 
40 #include <string>
41 
42 ARCSDownloader::ARCSDownloader(QObject *parent) :
43  QObject(parent)
44 {
45  manager = new QNetworkAccessManager(this);
46  eventLoop = new QEventLoop(this);
47  connect(manager,SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
48  this,SLOT(authenticateToProxy(QNetworkProxy,QAuthenticator*)));
49  connect(manager,SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
50  this,SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
51  connect(manager,SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
52  this,SLOT(authenticateToSite(QNetworkReply*,QAuthenticator*)));
53  connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
54 
55 }
56 
57 
58 void ARCSDownloader::replyFinished(QNetworkReply *reply)
59 {
60  if (!reply)
61  return ;
62  reply->deleteLater();
63  QString urlString = reply->request().url().toString();
64 
65  if (reply->error() != QNetworkReply::NoError)
66  {
67  std::cerr << "Downloader has encountered an error: "
68  << qPrintable(reply->errorString()) << std::endl;
69  std::cerr << "on url: " << qPrintable(urlString) << std::endl;
70  // should remove wrong file from downloads
71  eventLoop->quit();
72  return;
73  }
74 
75  QFile file(filename);
76  if (!file.open(QIODevice::WriteOnly))
77  {
78  std::cerr << "Failed to write down file: " << qPrintable(filename) << std::endl;
79  eventLoop->quit();
80  return;
81  }
82 
83  //std::cout << "Downloaded !" << std::endl; //<< qPrintable(filename) << std::endl;
84  file.write(reply->readAll());
85  eventLoop->quit();
86 }
87 
88 void ARCSDownloader::authenticateToSite(QNetworkReply * reply, QAuthenticator * auth)
89 {
90  std::cout << "The site you try to connect requires you to authenticate yourself." << std::endl;
91  authenticate(auth);
92 }
93 
94 void ARCSDownloader::authenticateToProxy(const QNetworkProxy &proxy, QAuthenticator *auth)
95 {
96  std::cout << "Your network proxy requires you to authenticate yourself." << std::endl;
97  authenticate(auth);
98 }
99 
100 void ARCSDownloader::sslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
101 {
102  std::cerr << "Your ssl connection has encountered the following errors " << std::endl;
103  for (int i=0; i < errors.count(); i++)
104  {
105  std::cerr << " " << qPrintable(errors[i].errorString()) << std::endl;
106  QSslCertificate cert = errors[i].certificate();
107  std::cerr << " Certificate issued by " << qPrintable(cert.subjectInfo(QSslCertificate::CommonName))
108  << ", " << qPrintable(cert.subjectInfo(QSslCertificate::Organization))
109  << ", " << qPrintable(cert.subjectInfo(QSslCertificate::OrganizationalUnitName))
110  << ", " << qPrintable(cert.subjectInfo(QSslCertificate::LocalityName))
111  << ", " << qPrintable(cert.subjectInfo(QSslCertificate::CountryName))
112  << std::endl;
113 
114  }
115  std::cerr << "Do you wish to continue (y/N) ?";
116  std::string r;
117  std::cin >> r;
118  if (r.at(0) == 'y')
119  {
120  reply->ignoreSslErrors();//errors);
121  cachedSslErrors = errors;
122  }
123  else
124  {
125  std::cerr << "Ssl transaction has been dropped" << std::endl;
126  eventLoop->quit();
127  }
128 }
129 
130 void ARCSDownloader::setProgress(qint64 received, qint64 total)
131 {
132  qint64 frac=received*40/total;
133  qint64 percent = received*100/total;
134 
135  std::cout << "\rDownloading " << qPrintable(filename) << "\t[";
136  for (int i=0; i<40; i++)
137  {
138  if (i < frac)
139  std::cout << '=';
140  else
141  {
142  if (i == frac)
143  std::cout << "+";
144  else
145  std::cout << "-";
146  }
147  }
148  std::cout << "] " << percent << "%\t" << std::flush;
149  if (frac==40) std::cout << std::endl;
150 }
151 
152 void ARCSDownloader::authenticate(QAuthenticator *auth)
153 {
154  std::cout << "Username: " ;
155  std::string uname;
156  std::cin >> uname;
157  std::string pwd;
158  pwd = getpasswd("Password: ");
159  auth->setUser(uname.data());
160  auth->setPassword(pwd.data());
161 }
162 
163 void ARCSDownloader::download(QString s)
164 {
165  QNetworkReply* reply = manager->get(QNetworkRequest(s));
166  reply->ignoreSslErrors(cachedSslErrors);
167  filename = QFileInfo(reply->request().url().path()).fileName();
168  std::cout << "Trying to download " << qPrintable(filename) << std::endl;
169  connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this, SLOT(setProgress(qint64,qint64)));
170  eventLoop->exec();
171 }