Skip to content

Commit

Permalink
Read gzip/zip file.
Browse files Browse the repository at this point in the history
  • Loading branch information
pnemonic78 committed Feb 2, 2025
1 parent 9bd52ba commit e605785
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 16 deletions.
50 changes: 35 additions & 15 deletions app/src/main/java/org/gnucash/android/importer/GncXmlImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
*/
package org.gnucash.android.importer;

import static java.util.zip.GZIPInputStream.GZIP_MAGIC;

import androidx.annotation.NonNull;

import org.gnucash.android.db.adapter.TransactionsDbAdapter;
import org.gnucash.android.model.Book;
import org.gnucash.android.util.PreferencesHelper;
Expand All @@ -26,8 +30,9 @@
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
Expand All @@ -42,6 +47,9 @@
*/
public class GncXmlImporter {

private static final byte GZIP_MAGIC_HI = (byte) ((GZIP_MAGIC >> 8) & 0xFF);
private static final byte GZIP_MAGIC_LO = GZIP_MAGIC & 0xFF;

/**
* Parse GnuCash XML input and populates the database
*
Expand All @@ -59,26 +67,17 @@ public static String parse(InputStream gncXmlInputStream) throws ParserConfigura
* @return the book into which the XML was imported
*/
public static Book parseBook(InputStream gncXmlInputStream) throws ParserConfigurationException, SAXException, IOException {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();

BufferedInputStream bos;
PushbackInputStream pb = new PushbackInputStream(gncXmlInputStream, 2); //we need a pushbackstream to look ahead
byte[] signature = new byte[2];
pb.read(signature); //read the signature
pb.unread(signature); //push back the signature to the stream
if (signature[0] == (byte) 0x1f && signature[1] == (byte) 0x8b) //check if matches standard gzip magic number
bos = new BufferedInputStream(new GZIPInputStream(pb));
else
bos = new BufferedInputStream(pb);
InputStream input = getInputStream(gncXmlInputStream);

//TODO: Set an error handler which can log errors
Timber.d("Start import");
GncXmlHandler handler = new GncXmlHandler();
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
xr.setContentHandler(handler);
long startTime = System.nanoTime();
xr.parse(new InputSource(bos));
xr.parse(new InputSource(input));
long endTime = System.nanoTime();
Timber.d("%d ns spent on importing the file", endTime - startTime);

Expand All @@ -91,4 +90,25 @@ public static Book parseBook(InputStream gncXmlInputStream) throws ParserConfigu

return book;
}

@NonNull
private static InputStream getInputStream(InputStream inputStream) throws IOException {
byte[] signature = new byte[4];
BufferedInputStream bos = new BufferedInputStream(inputStream);
bos.mark(4);
bos.read(signature); //read the signature
bos.reset(); //push back the signature to the stream
//check if matches standard gzip magic number
if (signature[0] == GZIP_MAGIC_LO && signature[1] == GZIP_MAGIC_HI) {
return new GZIPInputStream(bos);
}
if (signature[0] == 'P' && signature[1] == 'K' && ((signature[2] == 0x03 && signature[3] == 0x04) || (signature[2] == 0x05 && signature[3] == 0x06))) {
ZipInputStream zis = new ZipInputStream(bos);
ZipEntry entry = zis.getNextEntry();
if (entry != null) {
return zis;
}
}
return bos;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,15 @@ protected String doInBackground(Uri... uris) {
if (mBackup) {
BackupManager.backupActiveBook();
}
if (isCancelled()) {
return null;
}

Uri uri = uris[0];
ContentResolver contentResolver = mContext.getContentResolver();
Book book;
String bookUID;
try {
ContentResolver contentResolver = mContext.getContentResolver();
InputStream accountInputStream = contentResolver.openInputStream(uri);
book = GncXmlImporter.parseBook(accountInputStream);
book.setSourceUri(uri);
Expand Down

0 comments on commit e605785

Please sign in to comment.