Commit 1e0691c6 authored by Tracie Sucharski's avatar Tracie Sucharski
Browse files

Deleted ftpget and httpget, added resourceget, to fix in copy of v006LibraryV2 branch.

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/branches/v006LibrariesV2@6701 41f8697f-d340-4b68-9986-7bafba869bb8
parent 370d5d22
Loading
Loading
Loading
Loading
+209 −0
Original line number Diff line number Diff line
#include "ResourceGet.h"

#include <iostream>

#include <QtCore>
#include <QMessageBox>
#include <QtNetwork>

#include "Application.h"
#include "IException.h"
#include "Progress.h"


using namespace std;

namespace Isis {

  ResourceGet::ResourceGet(QObject *parent) : QObject(parent) {
    m_error = false;
    m_lastDone = -1;
    m_timeOut = 60000; // default timeout (ms) 
    m_reply = NULL;
    m_isInteractive = Application::GetUserInterface().IsInteractive();

    //tjw:  A timer for detecting network timeouts and exiting the application gracefully
    connect(&m_timer, SIGNAL(timeout()), 
            this, SLOT(connectionTimeout()));
  }



  /**
   * Destructor
   */
  ResourceGet::~ResourceGet() {
    // m_reply already scheduled for deletion in connectionFinished
  }



  /**
   * Initiates the request for the resource at the given url
   * 
   * @param url (const QUrl &) The resource's URL
   * @param topath (QString) Local destination for the downloaded resource
   * @param timeout (int) Time (in milliseconds) to try before timeout occurs
   * 
   * @return (bool) Indicates if there were any problems creating the local file to write to
   */
  bool ResourceGet::getResource(const QUrl &url, QString topath, int timeout) {
    //tjw:
    m_timeOut = timeout;

    // Need to setup output file 
    QString localFileName;
    if (topath.size() != 0) {
      localFileName += topath;
      localFileName += "/";
    }

    // The local file is named according to the external resource name
    // i.e. if there is no filename in the URL, we can't name our local file to write to
    localFileName +=  QFileInfo(url.path()).fileName();
    if (localFileName.isEmpty() ) {
      QString msg = QString("URL has no filename, can't create local output file");
      m_progress.SetText(msg);
      if (!m_isInteractive)
         cout << msg.toStdString() << endl;

      m_error = true;
      return m_error;
    }

    // Handle any problems with opening the local output file
    m_file.setFileName(localFileName);
    if (!m_file.open(QIODevice::WriteOnly) ) {
      QString msg = QString("Cannot open output file: ");
      msg += m_file.error();
      m_progress.SetText(msg);

      if (!m_isInteractive)
         cout << msg.toStdString() << endl;

      m_error =  true;
      return m_error;
    }

    // Establish the connection and start the GET request
    m_networkMgr.connectToHost(url.host(), url.port() );

    // We obtain ownership of the QNetworkReply *, so need to delete later
    m_reply = m_networkMgr.get(QNetworkRequest(url));

    connect(m_reply, SIGNAL(finished()),
            this, SLOT(connectionFinished()));
    connect(m_reply, SIGNAL(readyRead()),
            this, SLOT(downloadReadyRead()));
    connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
            this, SLOT(updateDownloadProgress(qint64, qint64)));

    m_lastDone = -1;
    m_error = false;
    return m_error;
  }



   //tjw:  Timeout event handler monitors the ftp connection and gracefully
  //closes and exits the application if a timeout occurs.
  void ResourceGet::connectionTimeout() {
      QString timeoutSecs = QString("Timeout error:  GET request exceeded ") +
              QString::number(m_timeOut)+ QString(" ms.");

      m_progress.SetText(timeoutSecs);

      // Will let user know there was a timeout
      m_errorMessage = timeoutSecs;

      // Note that finished() SIGNAL will be emitted when aborting
      m_reply->abort();
  }



  //! Handles when the connection finishes
  void ResourceGet::connectionFinished() {
    // This will handle an abort() as well
    if (m_reply->error()) {
      // Error message is already set if we encountered a TIMEOUT
      if (m_errorMessage.isEmpty()) {
        m_errorMessage = m_reply->errorString();
      }
      
      if (m_errorMessage.contains("Timeout error")) {
        m_error = false;
        if (!m_isInteractive) {
          cout << m_errorMessage << endl;
        }
      }
      else {
        m_error = true;
      }

      removeLocalFile();
    }

    else {
      m_file.close();
      // this was added because final size may not match progress size so
      // you do not get 100% processed
      if (!m_isInteractive) {
        cout << "100% Processed" << endl;
      }
    }

    // QNetworkAccessManager::get gave us ownership of the QNetworkReply *
    m_reply->deleteLater();
    m_reply = NULL;

    emit done();
  }



  //! Slot that is invoked whenever there is data available to read over connection
  void ResourceGet::downloadReadyRead() {
    if (m_file.exists()) {
      m_file.write(m_reply->readAll());
    }
  }



  //! Removes the local file if there is an error with the download
  void ResourceGet::removeLocalFile() {
    bool fileExists = false;
    QString fileRemovedQStr;

    fileExists = m_file.exists();

    if (fileExists) {
      m_file.close();
      m_file.remove();
    }
  }



  // tjw:  ftpProgress uses the ISIS progress class to track progress
  void ResourceGet::updateDownloadProgress(qint64 read, qint64 total) {
    m_timer.start(m_timeOut);

    if (total == 0) return;
    if (total == -1) return;
    if (m_error) return;
    if (m_lastDone < 0) {        
      m_progress.SetText(QString("Downloading File ") + m_file.fileName());
      m_progress.SetMaximumSteps(total);
      m_progress.CheckStatus();
      m_lastDone = 1;
    }

    while (m_lastDone <= read) {
      m_progress.CheckStatus();
      m_lastDone++;
    }
   }

}
+66 −0
Original line number Diff line number Diff line
#ifndef RESOURCEGET_H
#define RESOURCEGET_H

#include <QFile>
#include <QNetworkAccessManager>
#include <QString>
#include <QTimer>

#include "Progress.h"

class QNetworkReply;
class QUrl;

namespace Isis {
  /**
   * @author ????-??-?? Unknown
   *
   * @internal
   *   @history 2016-02-08 Ian Humphrey - Replaced ftpget and httpget classes with ResourceGet
   *                           class to handle generic resource requests (Qt5). This was done
   *                           as the previous classes relied on QFtp and QHttp, which are 
   *                           deprecated in Qt5.
   */
  class ResourceGet : public QObject {
      Q_OBJECT

    public:
      ResourceGet(QObject *parent = 0);
      ~ResourceGet();

      bool getResource(const QUrl &url, QString topath, int timeout);

      inline bool error() const {
        return m_error;
      };
      inline QString errorMessage() const {
        return m_errorMessage;
      }

    signals:
      void done();

    private slots:
      //tjw
      void connectionTimeout();
      void connectionFinished();
      void downloadReadyRead();
      void updateDownloadProgress(qint64 read, qint64 total);
      

    private:
      void removeLocalFile();
      
      bool m_error;                       //!< Indicates if an error has occurred
      bool m_isInteractive;               //!< Indicates if application is interactive
      int m_lastDone;                     //!< Last read byte during download
      int m_timeOut;                      //!< Value (in milliseconds) before timeout occurs
      Progress m_progress;                //!< Keeps track of download progress
      QFile m_file;                       //!< Local file to write download data to
      QNetworkAccessManager m_networkMgr; //!< Manages the connection for the download
      QNetworkReply *m_reply;             //!< The reply that will contain data to read
      QString m_errorMessage;             //!< A string representation of an error that occurs
      QTimer m_timer;                     //!< Timer used to determine timeout
  };
}
#endif
+0 −223
Original line number Diff line number Diff line
#include  "Application.h"
#include "ftpget.h"
#include "IString.h"
#include "IException.h"
#include "Progress.h"


#include <iostream>
#include <QtCore>
#include <QtNetwork>


using namespace std;

namespace Isis {

  FtpGet::FtpGet(QObject *parent) : QObject(parent) {



    //connect the Qftp done signal to the ftpDone function
    connect(&p_ftp, SIGNAL(done(bool)), this, SLOT(ftpDone(bool) ) );

    //tjw:  connect the QFtp progress signal to the ftpProgress function(ISIS progress)
    connect(&p_ftp, SIGNAL(dataTransferProgress(qint64, qint64)),
            this, SLOT(ftpProgress(qint64, qint64)));

    //tjw:  A timer for detecting network timeouts and exiting the application gracefully
    connect(&p_timer, SIGNAL(timeout()),this,SLOT(ftpTimeout() ) );


  }

  //*************************************************************************
  // getFile function will check URL, if URL is good, getFile will connect,
  // login, and get the file.  This function returns p_error.
  //*************************************************************************

  bool FtpGet::getFile(const QUrl &url, QString topath, int timeout) {


      //tjw:
      p_timeOut = timeout;




    //next four if check the URL and return true is there is error.
    if (!url.isValid() ) {

     //tested
     QString msg = QString("Invalid URL");
      p_progress.SetText(msg);
      if (!Application::GetUserInterface().IsInteractive() )
         cout << msg.toStdString() << endl;

      p_error = true;
      return p_error;
    }

    //Dead code:  This condition is already checked before the function is hit
    //if (url.scheme().toLower() != "ftp") {
    //  QString msg = QString("URL must start with 'ftp:'");
    //  p_progress.SetText(msg);

    //  if (!Application::GetUserInterface().IsInteractive() )
    //     cout << msg.toStdString() << endl;

    //  p_error =  true;
    //  return p_error;
    //}
    //tested
    if (url.path().isEmpty() ) {
      QString msg = QString("URL has no path");
      p_progress.SetText(msg);

      if (!Application::GetUserInterface().IsInteractive() )
         cout << msg.toStdString() << endl;

      p_error =  true;
      return p_error;
    }

    QString localFileName;
    if (topath.size() != 0) {
      localFileName += topath;
      localFileName += "/";
    }
    //tested
    localFileName +=  QFileInfo(url.path()).fileName();
    if (localFileName.isEmpty() ) {
      QString msg = QString("URL has no filename");
      p_progress.SetText(msg);
      if (!Application::GetUserInterface().IsInteractive() )
         cout << msg.toStdString() << endl;

      p_error = true;
      return p_error;
    }
    // check local file.
    p_file.setFileName(localFileName);
    if (!p_file.open(QIODevice::WriteOnly) ) {
      QString msg = QString("Cannot open output file");
      p_progress.SetText(msg);

      if (!Application::GetUserInterface().IsInteractive() )
         cout << msg.toStdString() << endl;

      p_error =  true;
      return p_error;
    }

    p_ftp.connectToHost(url.host(), url.port() );
    p_ftp.login();
    p_ftp.get(url.path(), &p_file);

    p_lastDone = -1;
    p_error = false;
    return p_error;
  }


  void FtpGet::ftpDone(bool error) {

    if (error) {
      p_error = true;
      QString msg = p_ftp.errorString();
      msg.remove("\n");

    }
    else {
      p_error = false;
    }
    if (!p_error) {
      p_file.close();

      // this was added because final size may not match progress size so
      // you do not get 100% processed
      if (!Application::GetUserInterface().IsInteractive() ) {
        cout << "100% Processed" << endl;
      }
    }
    emit done();
    return;

  }



  //tjw:  Timeout event handler monitors the ftp connection and gracefully
  //closes and exits the application if a timeout occurs.
  void FtpGet::ftpTimeout() {

      bool fileExists = false;
      bool fileRemoved = false;
      QString fileRemovedQStr;

      QString timeoutSecs = QString("Timeout error:  An ftp get request exceeded ") +
              QString::number(p_timeOut)+ QString(" ms.");

      p_progress.SetText(timeoutSecs);

      if (!Application::GetUserInterface().IsInteractive() )
        cout << timeoutSecs.toStdString() << endl;


      p_ftp.abort();
      p_ftp.close();

      fileExists = p_file.exists();

      if (fileExists) {
          fileRemoved = p_file.remove();
      }


      if (!fileExists || fileRemoved)
          fileRemovedQStr = p_file.fileName() + QString(" successfully deleted.");



      if (!Application::GetUserInterface().IsInteractive() )
        cout << fileRemovedQStr.toStdString() << endl;



      emit done();
      return;
  }



  // tjw:  ftpProgress uses the ISIS progress class to track progress
  void FtpGet::ftpProgress(qint64 done, qint64 total) {

    p_timer.start(p_timeOut);

    //double percentDone = 0;
    //percentDone = 100*((double)done/total);
    //cout << percentDone << endl;

    if (total == 0) return;
    if (total == -1) return;
    if (p_error) return;
    if (p_lastDone < 0) {        
      p_progress.SetText(QString("Downloading File ") + p_file.fileName());
      p_progress.SetMaximumSteps(total);
      p_progress.CheckStatus();
      p_lastDone = 1;

    }

    while (p_lastDone <= done) {

      p_progress.CheckStatus();
      p_lastDone++;

    }


   }

}
+0 −59
Original line number Diff line number Diff line
#ifndef FTPGET_H
#define FTPGET_H

#include <QFile>
#include <QFtp>
#include <QTimer>
#include "Progress.h"

class QUrl;
namespace Isis {
  /**
   * @author ????-??-?? Unknown
   *
   * @internal
   */
  class FtpGet : public QObject {
      Q_OBJECT

    public:
      FtpGet(QObject *parent = 0);

      bool getFile(const QUrl &url, QString topath,int timeout);

      bool error() const {
        return p_error;
      };



    signals:
      void done();

      //tjw
      void dataTransferProgress(qint64, qint64);


    private slots:
      void ftpDone(bool error);
      void ftpProgress(qint64 done, qint64 total);

      //tjw
      void ftpTimeout();


    private:

      QFtp p_ftp;
      QFile p_file;
      bool p_error;
      int p_lastDone;
      Progress p_progress;


      int p_timeOut;
      QTimer p_timer;

  };
}
#endif
+0 −219
Original line number Diff line number Diff line
#include "Application.h"
#include "httpget.h"
#include "IException.h"
#include "IString.h"
#include "Progress.h"


#include <iostream>
#include <QtCore>
#include <QtNetwork>




using namespace std;

namespace Isis {

  HttpGet::HttpGet(QObject *parent) : QObject(parent) {


    //connect the QHttp done signal to the httpDone function
    connect(&p_http, SIGNAL(done(bool)), this, SLOT(httpDone(bool)));
    //connect the QHttp progress signal to the httpProgress function(Isis progress)
    connect(&p_http, SIGNAL(dataReadProgress(int, int)),
            this, SLOT(httpProgress(int, int)));

    //tjw:  A timer for detecting network timeouts and exiting
    //      the application gracefully
    connect(&p_timer, SIGNAL(timeout()),this,SLOT(httpTimeout() ) );

  }
  //****************************************************************************
  // getFile function will check URL, if URL is good the function will connect,
  // login, and get the file.  This function returns p_error
  //****************************************************************************

  bool HttpGet::getFile(const QUrl &url, QString topath,int timeout) {

      p_timeOut = timeout;

    //tested
    // The next four ifs will check the URL and return error is bad
    if (!url.isValid() ) {
      QString msg = "Invalid URL";
      p_progress.SetText(msg);
      if (!Application::GetUserInterface().IsInteractive() )
         cout << msg.toStdString() << endl;

//       iException::Message(iException::User, msg, _FILEINFO_);
      p_error = true;
      return p_error;
    }

    //Dead code:  this condition is already checked before this function is entered
    //if (url.scheme().toLower() != "http") {
    //  QString msg = "URL must start with 'http:'";
    //  p_progress.SetText(msg);
    //  if (!Application::GetUserInterface().IsInteractive() )
    //     cout << msg.toStdString() << endl;

//       iException::Message(iException::User, msg, _FILEINFO_);
    //p_error = true;
    //  return p_error;
    //}

    //tested
    if (url.path().isEmpty() ) {
      QString msg = "URL has no path";
      p_progress.SetText(msg);
      if (!Application::GetUserInterface().IsInteractive() )
         cout << msg.toStdString() << endl;

//       iException::Message(iException::User, msg, _FILEINFO_);
      p_error = true;
      return p_error;
    }

    QString localFileName;
    if (topath.size() != 0) {
      localFileName += topath;
      localFileName += "/";
    }
    localFileName +=  QFileInfo(url.path()).fileName();
    //tested
    if (localFileName.isEmpty() ) {
      QString msg = "URL has no filename";
      p_progress.SetText(msg);
      if (!Application::GetUserInterface().IsInteractive() )
         cout << msg.toStdString() << endl;

//       iException::Message(iException::User, msg, _FILEINFO_);
      p_error = true;
      return p_error;
    }
    // check the local file.
    p_file.setFileName(localFileName);
    if (!p_file.open(QIODevice::WriteOnly) ) {
      QString msg = "Cannot open output file";
      p_progress.SetText(msg);
      if (!Application::GetUserInterface().IsInteractive() )
         cout << msg.toStdString() << endl;

//       iException::Message(iException::User, msg, _FILEINFO_);
      p_error = true;
      return p_error;
    }
    p_http.setHost(url.host(), url.port() );
    p_http.get(url.path(), &p_file);

    p_lastDone = -1;
    p_error = false;
    return p_error;
  }


  //tjw:  Timeout event handler monitors the http connection and gracefully
  //closes and exits the application if a timeout occurs.
  void HttpGet::httpTimeout() {

      bool fileExists = false;
      bool fileRemoved = false;
      QString fileRemovedQStr;


      QString timeoutSecs = QString("Timeout error:  An http get request exceeded ") +
              QString::number(p_timeOut)+ QString(" ms.");

      p_progress.SetText(timeoutSecs);

      if (!Application::GetUserInterface().IsInteractive() )
        cout << timeoutSecs.toStdString() << endl;

      p_http.close();

      fileExists = p_file.exists();

      if (fileExists) {
          fileRemoved = p_file.remove();
      }


      if (!fileExists || fileRemoved)
          fileRemovedQStr = p_file.fileName() + QString(" successfully deleted.");


      p_progress.SetText(fileRemovedQStr);

      if (!Application::GetUserInterface().IsInteractive() )
        cout << fileRemovedQStr.toStdString() << endl;


      emit done();
      return;
  }


  void HttpGet::httpDone(bool error) {
    map <int, QString> errLUT;
    errLUT [204] = "No content";
    errLUT [301] = "Moved Permanently";
    errLUT [302] = "Moved Temporarily";
    errLUT [400] = "Bad Request";
    errLUT [401] = "Unauthorized";
    errLUT [403] = "Forbidden";
    errLUT [404] = "File Not Found";
    errLUT [500] = "Internal server Error";
    errLUT [502] = "Bad GateWay";
    errLUT [503] = "service Unavailable";

    if (error) {
      p_error =  true;
      QString msg = p_http.errorString();
//       iException::Message(iException::User, msg, _FILEINFO_);
    }
    else if (p_http.lastResponse().statusCode()  != 200 &&
             p_http.lastResponse().statusCode()  != 0) {
      p_error = true;
      QString msg = "error code: [" + errLUT[p_http.lastResponse().statusCode()] + "]";
//       iException::Message(iException::User, msg, _FILEINFO_);
    }
    else {
      p_error = false;
    }
    if (!p_error) {

      if (!Application::GetUserInterface().IsInteractive() ) {
          cout << "100% Processed" << endl;
      }
      p_file.close();

     }

    emit done();
    return;
  }
  // This function setsup and useses Isis progress classs to track progress.
  void HttpGet::httpProgress(int done, int total) {

      p_timer.start(p_timeOut);
      //double percentDone = 0;
      //percentDone = 100*((double)done/total);



    if (total == 0) return;
    if (p_error) return;
    if (p_lastDone < 0) {
      p_progress.SetText(QString("Downloading File ") + p_file.fileName());
      p_progress.SetMaximumSteps(total);
      p_progress.CheckStatus();
      p_lastDone = 1;
    }
    while (p_lastDone <= done) {
      p_progress.CheckStatus();
      p_lastDone++;
    }
  }
}
Loading