Logo Search packages:      
Sourcecode: earth3d version File versions  Download package

urlDownload.cpp

#include "urlDownload.h"
#include "urlTools.h"
#include <string.h>
#include <iostream>
#include <qnetwork.h>
#include <qnetworkprotocol.h>
#include <qdatetime.h>
#include <stdio.h>
#include "statusObserverQT.h"
#include <qfile.h>
#include "formview.h"
#include "downloadFinishedEvent.h"

#ifndef WIN32
#include <alloc.h>
#endif

using namespace std;

URLDownload::URLDownload(const char *url, DataReceivedListener *drl, void *userdata, bool allowCache) : ProxyUrlOperator(url, allowCache), StopableDownload() {
  connect(this, SIGNAL(finished(QNetworkOperation *)), this, SLOT(finished_download(QNetworkOperation *)));
  connect(this, SIGNAL(data(const QByteArray &, QNetworkOperation *)), this, SLOT(data_received(const QByteArray &, QNetworkOperation *)));

  content = (char *) malloc(1000);
  contentsize = 0;

#ifdef EARTH3DDEBUG
  cout << "URL: " << url << endl;
#endif

  thisurl = new char[strlen(url)+1];
  strcpy(thisurl, url);

  this->drl = drl;
  this->userdata = userdata;
  this->retrynr = 0;

  registerWithDownloadable(drl);
}

URLDownload::~URLDownload() {
  if (thisurl) delete[](thisurl);
//   if (content) free(content);
}

void URLDownload::run() {
#ifdef EARTH3DDEBUG
  printf("URLDownload::run\n");
#endif

  // QT has problems with file://-URLs, download them via normal File IO:
  if (QString(thisurl).left(8)==QString("file:///")) {
#ifdef EARTH3DDEBUG
    printf("URLDownload::run file:\n");
#endif
    QString filename = QString(thisurl).mid(8);
    QFile datafile(filename);
    if (!datafile.exists()) {
//       drl->dataReceived(NULL, 0, thisurl, 0, NULL, userdata, NULL, this);
//       deregisterWithDownloadable(drl);
      return;
    }
    datafile.open(IO_ReadOnly);
    printf("File size: %i\n", datafile.size());
    data_received(datafile.readAll(), NULL);
    datafile.close();

    qApp->postEvent(formview, new DownloadFinishedEvent(this));
  }
  else {
#ifdef EARTH3DDEBUG
    printf("URLDownload::run get\n");
#endif
    get();
  }
  // #else
//   get();
// #endif
}

void URLDownload::finished(QNetworkOperation *qno) {
//   std::cout << QTime::currentTime().toString("hh:mm:ss:zzz") << ": download finished: " << thisurl << std::endl;
//   std::cout << "error code=" << qno->errorCode() << std::endl;a
#ifdef EARTH3DDEBUG
  printf("URLDownload::finished\n");
#endif
//   char formatline[256];
//   sprintf(formatline, "%%%is\\n", contentsize);
//   printf(formatline, content);

  if (contentsize<=0) {
    // the download was not successful
    drl->dataReceived(NULL, 0, thisurl, 0, NULL, userdata, NULL, this);
    return;
  }  

  /* parse contents of file into header and parts */
  char *cur = (char *) content, *cr;
  int countParts;
  struct part_t *parts;
  
  cr = strchr(cur, '\n');
  countParts = atoi(cur);

  if (countParts==0) { // try to parse it as single XML document
    parts = new part_t[1];

    parts[0].content = (char *) content;
    parts[0].size = contentsize;
    countParts = 1;
  }
  else {
    parts = new part_t[countParts];
    
    if (cr) {
      cur = cr+1;
      for(int partnr = 0; partnr<countParts; partnr++) {
      parts[partnr].size = atoi(cur);
      cr = strchr(cur, '\n');
      if (cr) {
        cur = cr+1;
        parts[partnr].content = new char[parts[partnr].size+1];
        
        memcpy(parts[partnr].content, cur, parts[partnr].size);
        parts[partnr].content[parts[partnr].size]=0;
        cur += parts[partnr].size;
      }
      else {
        parts[partnr].content = NULL;
      }
      }
    }

    free(content);
    content = NULL;
  }    
//   std::cout << QTime::currentTime().toString("hh:mm:ss:zzz") << ": Parse finished: " << thisurl << std::endl;

  /* rewrite relative URLs */
  UrlTools::rewriteRelativeURLs(&(parts[0].content), &(parts[0].size), thisurl);
//   std::cout << QTime::currentTime().toString("hh:mm:ss:zzz") << ": Rewrite finished: " << thisurl << std::endl;
  
  /* call DataReceivedListener */
  drl->dataReceived(parts[0].content, parts[0].size, thisurl, countParts, parts, userdata, NULL, this);
//  content, contentsize, NULL, 1, NULL, userdata);
  std::cout << QTime::currentTime().toString("hh:mm:ss:zzz") << ": DataReceived finished: " << thisurl << std::endl;

  /* clean up */
  for(int partnr=0; partnr<countParts; partnr++) {
    if (parts[partnr].content) delete[](parts[partnr].content);
  }
  delete[](parts);
//   std::cout << QTime::currentTime().toString("hh:mm:ss:zzz") << ": Delete finished: " << thisurl << std::endl;

  // delete this object
  if (thisurl) {
    delete[](thisurl);
    thisurl = NULL;
  }
//   if (content) {
//     free(content);
//     content = NULL;
//   }
}

void URLDownload::finished_download(QNetworkOperation *qno) {
  if (!downloadStopped) {
    // try again, 5 times
    if (qno!=NULL && qno->state()==QNetworkProtocol::StFailed) { //qno->errorCode()) {
      cout << "retry: " << thisurl << endl;
      retrynr++;
      if (retrynr<5) {
      get();
      return;
      }
      else {
      drl->dataReceived(NULL, 0, thisurl, 0, NULL, userdata, NULL, this);
      deregisterWithDownloadable(drl);
      /* try to delete self */
      //       delete(this);
      }
    }
    else {
      statusobserver.changeMemoryOffset(StatusObserver::MEM_URLDOWNLOAD, contentsize);
      
      finished(qno);
      deregisterWithDownloadable(drl);
    }
  }

#ifndef WIN32
  /* try to delete self */
  delete(this);
#endif
}

void URLDownload::data_received(const QByteArray &array, QNetworkOperation *qno) {
//   char formatline[256];
//   sprintf(formatline, "%%%is\\n", array.size());
//   printf(formatline, array.data());
#ifdef EARTH3DDEBUG
  printf("data_received %i\n", array.size());
#endif
  contentsize += array.size();
  content = (char *) realloc(content, contentsize);
  memcpy(content + contentsize - array.size(), array.data(), array.size());
}



Generated by  Doxygen 1.6.0   Back to index