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