Divelogs.de: improve prepare_dives_for_divelogs()

prepare_dives_for_divelogs() is based on GTK / C code
where we used GLib methods to generate a temp zip file.
Qt has QTemporaryFile, but it seems there is some sort
of a problem when using with with zip_open
(ZIP_CREATE considered) or at least in this particular case.

To workaround that, we generate a random name ourself with qrand()
and simply pass it to zip_open (with ZIP_CREATE) and then return
the filename.

Also (!), there is memory corruption when trying to return
'tempfile'. This wasn't the case with the C compiler,
to my knowledge. Regardless of this fact the generated
zip does not look corrupt.

Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
This commit is contained in:
Lubomir I. Ivanov 2013-12-07 16:43:28 +02:00
parent 231e02f97d
commit 5514499867

View file

@ -112,15 +112,20 @@ static char *prepare_dives_for_divelogs(const bool selected)
struct zip_source *s[dive_table.nr];
struct zip *zip;
char *error = NULL;
char *parsed = NULL, *endat = NULL;
QTemporaryFile zipFile;
zipFile.setFileTemplate(QDir::tempPath() + "/import-XXXXXX.dld");
tempfile = zipFile.fileName().toLocal8Bit().data();
/* generate a random filename and create/open that file with zip_open */
QString tempfileQ = QDir::tempPath() + "/import-" + QString::number(qrand() % 99999999) + ".dld";
tempfile = tempfileQ.toLocal8Bit().data();
zip = zip_open(tempfile, ZIP_CREATE, NULL);
if (!zip || !amount_selected)
if (!zip) {
fprintf(stderr, "divelog.de-upload: cannot open file as zip\n");
return NULL;
}
if (!amount_selected) {
fprintf(stderr, "divelog.de-upload: no dives selected\n");
return NULL;
}
/* walk the dive list in chronological order */
for (i = 0; i < dive_table.nr; i++) {
@ -130,15 +135,19 @@ static char *prepare_dives_for_divelogs(const bool selected)
if (selected && !dive->selected)
continue;
f = tmpfile();
if (!f)
if (!f) {
fprintf(stderr, "divelog.de-upload: cannot create temp file\n");
return NULL;
}
save_dive(f, dive);
fseek(f, 0, SEEK_END);
streamsize = ftell(f);
rewind(f);
membuf = (char *)malloc(streamsize + 1);
if (!membuf || !fread(membuf, streamsize, 1, f))
if (!membuf || !fread(membuf, streamsize, 1, f)) {
fprintf(stderr, "divelog.de-upload: memory error\n");
return NULL;
}
membuf[streamsize] = 0;
fclose(f);
/*
@ -147,12 +156,17 @@ static char *prepare_dives_for_divelogs(const bool selected)
* the XML into a character buffer.
*/
doc = xmlReadMemory(membuf, strlen(membuf), "divelog", NULL, 0);
if (!doc)
if (!doc) {
fprintf(stderr, "divelog.de-upload: xml error\n");
continue;
}
free((void *)membuf);
// this call is overriding our local variable tempfile! not a good sign!
xslt = get_stylesheet("divelogs-export.xslt");
if (!xslt)
if (!xslt) {
fprintf(stderr, "divelog.de-upload: missing stylesheet\n");
return NULL;
}
transformed = xsltApplyStylesheet(xslt, doc, NULL);
xsltFreeStylesheet(xslt);
xmlDocDumpMemory(transformed, (xmlChar **) &membuf, (int *)&streamsize);
@ -166,10 +180,12 @@ static char *prepare_dives_for_divelogs(const bool selected)
if (s[i]) {
int64_t ret = zip_add(zip, filename, s[i]);
if (ret == -1)
fprintf(stderr, "failed to include dive %d\n", i);
fprintf(stderr, "divelog.de-upload: failed to include dive %d\n", i);
}
}
zip_close(zip);
/* let's call this again */
tempfile = tempfileQ.toLocal8Bit().data();
return tempfile;
}
@ -523,14 +539,17 @@ void DivelogsDeWebServices::downloadDives()
void DivelogsDeWebServices::prepareDivesForUpload()
{
char *file = prepare_dives_for_divelogs(true);
if (file) {
QFile f(file);
free(file);
uploadDives((QIODevice *)&f);
return;
char *filename = prepare_dives_for_divelogs(true);
if (filename) {
QFile f(filename);
if (f.exists()) {
uploadDives((QIODevice *)&f);
f.close();
f.remove();
return;
}
mainWindow()->showError(QString("Cannot create file: ").append(filename));
}
// FIXME: show error
}
void DivelogsDeWebServices::uploadDives(QIODevice *dldContent)
@ -725,6 +744,7 @@ void DivelogsDeWebServices::uploadFinished()
// an error condition, such as a failed login
QByteArray xmlData = reply->readAll();
char *resp = xmlData.data();
// qDebug() << resp;
if (resp) {
char *parsed = strstr(resp, "<Login>");
// char *endat = strstr(resp, "</divelogsDataImport>");
@ -795,4 +815,3 @@ void DivelogsDeWebServices::buttonClicked(QAbstractButton* button)
break;
}
}