1 /***************************************************************************
2                          kofxdirectconnectdlg.cpp
3                              -------------------
4     begin                : Sat Nov 13 2004
5     copyright            : (C) 2002 by Ace Jones
6     email                : acejones@users.sourceforge.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "kofxdirectconnectdlg.h"
19 #include "kmymoneysettings.h"
20 
21 // ----------------------------------------------------------------------------
22 // QT Includes
23 
24 #include <QLabel>
25 #include <QFile>
26 #include <QTextStream>
27 #include <QTemporaryFile>
28 #include <QDebug>
29 
30 // ----------------------------------------------------------------------------
31 // KDE Includes
32 
33 #include <kio/job_base.h>
34 #include <KJobUiDelegate>
35 #include <KIO/TransferJob>
36 #include <KMessageBox>
37 #include <KLocalizedString>
38 
39 // ----------------------------------------------------------------------------
40 // Project Includes
41 
42 #include "mymoneyofxconnector.h"
43 
44 class KOfxDirectConnectDlg::Private
45 {
46 public:
Private()47   Private() : m_firstData(true) {}
48   QFile    m_fpTrace;
49   bool     m_firstData;
50 };
51 
KOfxDirectConnectDlg(const MyMoneyAccount & account,QWidget * parent)52 KOfxDirectConnectDlg::KOfxDirectConnectDlg(const MyMoneyAccount& account, QWidget *parent) :
53     KOfxDirectConnectDlgDecl(parent),
54     d(new Private),
55     m_tmpfile(0),
56     m_connector(account),
57     m_job(0)
58 {
59 }
60 
~KOfxDirectConnectDlg()61 KOfxDirectConnectDlg::~KOfxDirectConnectDlg()
62 {
63   if (d->m_fpTrace.isOpen()) {
64     d->m_fpTrace.close();
65   }
66   delete m_tmpfile;
67   delete d;
68 }
69 
init()70 bool KOfxDirectConnectDlg::init()
71 {
72   show();
73 
74   QByteArray request = m_connector.statementRequest();
75   if (request.isEmpty()) {
76     hide();
77     return false;
78   }
79 
80   // For debugging, dump out the request
81 #if 0
82   QFile g("request.ofx");
83   g.open(QIODevice::WriteOnly);
84   QTextStream(&g) << m_connector.url() << "\n" << QString(request);
85   g.close();
86 #endif
87 
88   if (KMyMoneySettings::logOfxTransactions()) {
89     QString logPath = KMyMoneySettings::logPath();
90     d->m_fpTrace.setFileName(QString("%1/ofxlog.txt").arg(logPath));
91     d->m_fpTrace.open(QIODevice::WriteOnly | QIODevice::Append);
92   }
93 
94   if (d->m_fpTrace.isOpen()) {
95     QByteArray connectorData = m_connector.url().toUtf8();
96     d->m_fpTrace.write("url: ", 5);
97     d->m_fpTrace.write(connectorData, strlen(connectorData));
98     d->m_fpTrace.write("\n", 1);
99     d->m_fpTrace.write("request:\n", 9);
100     QByteArray trcData(request);  // make local copy
101     trcData.replace('\r', ""); // krazy:exclude=doublequote_chars
102     d->m_fpTrace.write(trcData, trcData.size());
103     d->m_fpTrace.write("\n", 1);
104     d->m_fpTrace.write("response:\n", 10);
105   }
106 
107   qDebug("creating job");
108   m_job = KIO::http_post(QUrl(m_connector.url()), request, KIO::HideProgressInfo);
109 
110   // open the temp file. We come around here twice if init() is called twice
111   if (m_tmpfile) {
112     qDebug() << "Already connected, using " << m_tmpfile->fileName();
113     delete m_tmpfile; //delete otherwise we mem leak
114   }
115   m_tmpfile = new QTemporaryFile();
116   // for debugging purposes one might want to leave the temp file around
117   // in order to achieve this, please uncomment the next line
118   // m_tmpfile->setAutoRemove(false);
119   if (!m_tmpfile->open()) {
120     qWarning("Unable to open tempfile '%s' for download.", qPrintable(m_tmpfile->fileName()));
121     return false;
122   }
123 
124   m_job->addMetaData("content-type", "Content-type: application/x-ofx");
125 
126   connect(m_job, SIGNAL(result(KJob*)), this, SLOT(slotOfxFinished(KJob*)));
127   connect(m_job, SIGNAL(data(KIO::Job*,QByteArray)), this, SLOT(slotOfxData(KIO::Job*,QByteArray)));
128 
129   setStatus(QString("Contacting %1...").arg(m_connector.url()));
130   kProgress1->setMaximum(3);
131   kProgress1->setValue(1);
132   return true;
133 }
134 
setStatus(const QString & _status)135 void KOfxDirectConnectDlg::setStatus(const QString& _status)
136 {
137   textLabel1->setText(_status);
138   qDebug() << "STATUS:" << _status;
139 }
140 
setDetails(const QString & _details)141 void KOfxDirectConnectDlg::setDetails(const QString& _details)
142 {
143   qDebug() << "DETAILS: " << _details;
144 }
145 
slotOfxData(KIO::Job *,const QByteArray & _ba)146 void KOfxDirectConnectDlg::slotOfxData(KIO::Job*, const QByteArray& _ba)
147 {
148   qDebug("Got %d bytes of data", _ba.size());
149   if (d->m_firstData) {
150     setStatus("Connection established, retrieving data...");
151     setDetails(QString("Downloading data to %1...").arg(m_tmpfile->fileName()));
152     kProgress1->setValue(kProgress1->value() + 1);
153     d->m_firstData = false;
154   }
155   m_tmpfile->write(_ba);
156 
157   setDetails(QString("Got %1 bytes").arg(_ba.size()));
158 
159   if (d->m_fpTrace.isOpen()) {
160     QByteArray trcData(_ba);
161     trcData.replace('\r', ""); // krazy:exclude=doublequote_chars
162     d->m_fpTrace.write(trcData, trcData.size());
163   }
164 }
165 
slotOfxFinished(KJob *)166 void KOfxDirectConnectDlg::slotOfxFinished(KJob* /* e */)
167 {
168   qDebug("Job finished");
169   kProgress1->setValue(kProgress1->value() + 1);
170   setStatus("Completed.");
171 
172   if (d->m_fpTrace.isOpen()) {
173     d->m_fpTrace.write("\nCompleted\n\n\n\n", 14);
174   }
175 
176   int error = m_job->error();
177 
178   if (m_tmpfile) {
179     qDebug("Closing tempfile");
180     m_tmpfile->close();
181   }
182   qDebug("Tempfile closed");
183 
184   if (error) {
185     qDebug("Show error message");
186     m_job->uiDelegate()->showErrorMessage();
187   } else if (m_job->isErrorPage()) {
188     qDebug("Process error page");
189     QString details;
190     if (m_tmpfile) {
191       QFile f(m_tmpfile->fileName());
192       if (f.open(QIODevice::ReadOnly)) {
193         QTextStream stream(&f);
194         while (!stream.atEnd()) {
195           details += stream.readLine(); // line of text excluding '\n'
196         }
197         f.close();
198 
199         qDebug() << "The HTTP request failed: " << details;
200       }
201     }
202     KMessageBox::detailedSorry(this, i18n("The HTTP request failed."), details, i18nc("The HTTP request failed", "Failed"));
203   } else if (m_tmpfile) {
204     qDebug("Emit statementReady signal with '%s'", qPrintable(m_tmpfile->fileName()));
205     emit statementReady(m_tmpfile->fileName());
206     qDebug("Return from signal statementReady() processing");
207   }
208   delete m_tmpfile;
209   m_tmpfile = 0;
210   hide();
211   qDebug("Finishing slotOfxFinished");
212 }
213 
reject()214 void KOfxDirectConnectDlg::reject()
215 {
216   if (m_job)
217     m_job->kill();
218   if (m_tmpfile) {
219     m_tmpfile->close();
220     delete m_tmpfile;
221     m_tmpfile = 0;
222   }
223   QDialog::reject();
224 }
225