Content Addressable Media Storage (Cheogram)

This commit is contained in:
Arne 2023-05-20 01:54:21 +02:00
parent dcac523a07
commit df15eb3b93
5 changed files with 120 additions and 10 deletions

View file

@ -29,8 +29,8 @@ allprojects {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
jcenter()
maven { url "https://jitpack.io" }
}
configurations {

View file

@ -210,9 +210,19 @@ public class HttpDownloadConnection implements Transferable {
if (message.getEncryption() == Message.ENCRYPTION_PGP) {
notify = message.getConversation().getAccount().getPgpDecryptionService().decrypt(message, notify);
}
DownloadableFile file;
final DownloadableFile tmp = mXmppConnectionService.getFileBackend().getFile(message);
final String extension = MimeUtils.extractRelevantExtension(tmp.getName());
try {
mXmppConnectionService.getFileBackend().setupRelativeFilePath(message, new FileInputStream(tmp), extension);
file = mXmppConnectionService.getFileBackend().getFile(message);
tmp.renameTo(file);
} catch (final IOException e) {
file = tmp;
}
mXmppConnectionService.updateMessage(message);
mHttpConnectionManager.updateConversationUi(true);
final boolean notifyAfterScan = notify;
final DownloadableFile file = mXmppConnectionService.getFileBackend().getFile(message, true);
FileBackend.updateMediaScanner(mXmppConnectionService, file, () -> {
if (notifyAfterScan) {
mXmppConnectionService.getNotificationService().push(message);

View file

@ -264,6 +264,16 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.execSQL("PRAGMA monocles.user_version = 3");
}
if(monoclesVersion < 4) {
db.execSQL(
"CREATE TABLE monocles.cids (" +
"cid TEXT NOT NULL PRIMARY KEY," +
"path TEXT NOT NULL" +
")"
);
db.execSQL("PRAGMA monocles.user_version = 4");
}
db.setTransactionSuccessful();
} finally {

View file

@ -706,7 +706,7 @@ public class FileBackend {
extension = "oga";
}
String filename = "Sent" + File.separator + fileDateFormat.format(new Date(message.getTimeSent())) + "_" + message.getUuid().substring(0, 4);
setupRelativeFilePath(message, String.format("%s.%s", filename, extension));
setupRelativeFilePath(message, uri, extension);
copyFileToPrivateStorage(mXmppConnectionService.getFileBackend().getFile(message), uri);
}
@ -871,8 +871,42 @@ public class FileBackend {
throw new IllegalStateException("Unknown image format");
}
setupRelativeFilePath(message, filename);
copyImageToPrivateStorage(getFile(message), image);
updateFileParams(message);
final File tmp = getFile(message);
copyImageToPrivateStorage(tmp, image);
final String extension = MimeUtils.extractRelevantExtension(filename);
try {
setupRelativeFilePath(message, new FileInputStream(tmp), extension);
} catch (final FileNotFoundException e) {
throw new FileCopyException(R.string.error_file_not_found);
} catch (final IOException e) {
throw new FileCopyException(R.string.error_io_exception);
}
tmp.renameTo(getFile(message));
updateFileParams(message, null, false);
}
public void setupRelativeFilePath(final Message message, final Uri uri, final String extension) throws FileCopyException {
try {
setupRelativeFilePath(message, mXmppConnectionService.getContentResolver().openInputStream(uri), extension);
} catch (final FileNotFoundException e) {
throw new FileCopyException(R.string.error_file_not_found);
} catch (final IOException e) {
throw new FileCopyException(R.string.error_io_exception);
}
}
public void setupRelativeFilePath(final Message message, final InputStream is, final String extension) throws IOException {
Cid[] cids = calculateCids(is);
setupRelativeFilePath(message, String.format("%s.%s", cids[0], extension));
File file = getFile(message);
for (int i = 0; i < cids.length; i++) {
try {
mXmppConnectionService.saveCid(cids[i], file);
} catch (XmppConnectionService.BlockedMediaException e) {
throw new RuntimeException(e);
}
}
}
public void setupRelativeFilePath(final Message message, final String filename) {
@ -1598,7 +1632,8 @@ public class FileBackend {
public void updateFileParams(final Message message, final String url) {
updateFileParams(message, url, true);
}
public void updateFileParams(final Message message, String url, boolean updateCids) {
public void updateFileParams(final Message message, final String url, boolean updateCids) {
final boolean encrypted =
message.getEncryption() == Message.ENCRYPTION_PGP
|| message.getEncryption() == Message.ENCRYPTION_DECRYPTED;
@ -1684,6 +1719,17 @@ public class FileBackend {
message.setFileParams(fileParams);
message.setFileDeleted(false);
message.setType(privateMessage ? Message.TYPE_PRIVATE_FILE : (image ? Message.TYPE_IMAGE : Message.TYPE_FILE));
if (updateCids) {
try {
Cid[] cids = calculateCids(new FileInputStream(getFile(message)));
for (int i = 0; i < cids.length; i++) {
mXmppConnectionService.saveCid(cids[i], file);
}
} catch (final IOException e) { } catch (
XmppConnectionService.BlockedMediaException e) {
throw new RuntimeException(e);
}
}
}
private Dimensions getPDFDimensions(final File file) {
@ -1958,6 +2004,34 @@ public class FileBackend {
throw new AssertionError(e);
}
}
public void updateMediaScanner(File file) {
updateMediaScanner(file, null);
}
public void updateMediaScanner(File file, final Runnable callback) {
MediaScannerConnection.scanFile(
mXmppConnectionService,
new String[] {file.getAbsolutePath()},
null,
new MediaScannerConnection.MediaScannerConnectionClient() {
@Override
public void onMediaScannerConnected() {}
@Override
public void onScanCompleted(String path, Uri uri) {
if (callback != null && file.getAbsolutePath().equals(path)) {
callback.run();
} else {
Log.d(Config.LOGTAG, "media scanner scanned wrong file");
if (callback != null) {
callback.run();
}
}
}
});
}
private static class Dimensions {
public final int width;
public final int height;

View file

@ -54,6 +54,8 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
import eu.siacs.conversations.xmpp.jingle.stanzas.S5BTransportInfo;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import eu.siacs.conversations.utils.MimeUtils;
public class JingleFileTransferConnection extends AbstractJingleConnection implements Transferable {
private final SimpleDateFormat fileDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US);
@ -117,6 +119,8 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
@Override
public void onFileTransmitted(DownloadableFile file) {
DownloadableFile finalFile;
if (responding()) {
if (expectedHash.length > 0) {
if (Arrays.equals(expectedHash, file.getSha1Sum())) {
@ -128,7 +132,17 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": other party did not include file hash in file transfer");
}
sendSuccess();
xmppConnectionService.getFileBackend().updateFileParams(message);
final String extension = MimeUtils.extractRelevantExtension(file.getName());
try {
xmppConnectionService.getFileBackend().setupRelativeFilePath(message, new FileInputStream(file), extension);
finalFile = xmppConnectionService.getFileBackend().getFile(message);
file.renameTo(finalFile);
} catch (final IOException e) {
finalFile = file;
}
xmppConnectionService.getFileBackend().updateFileParams(message, null, false);
xmppConnectionService.databaseBackend.createMessage(message);
xmppConnectionService.markMessage(message, Message.STATUS_RECEIVED);
if (acceptedAutomatically) {
@ -145,6 +159,8 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
id.account.getPgpDecryptionService().decrypt(message, true);
}
} else {
finalFile = file;
if (description.getVersion() == FileTransferDescription.Version.FT_5) { //older Conversations will break when receiving a session-info
sendHash();
}
@ -152,13 +168,13 @@ public class JingleFileTransferConnection extends AbstractJingleConnection imple
id.account.getPgpDecryptionService().decrypt(message, false);
}
if (message.getEncryption() == Message.ENCRYPTION_PGP || message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
file.delete();
finalFile.delete();
}
disconnectSocks5Connections();
}
Log.d(Config.LOGTAG, "successfully transmitted file:" + file.getAbsolutePath() + " (" + CryptoHelper.bytesToHex(file.getSha1Sum()) + ")");
Log.d(Config.LOGTAG, "successfully transmitted file:" + finalFile.getAbsolutePath() + " (" + CryptoHelper.bytesToHex(file.getSha1Sum()) + ")");
if (message.getEncryption() != Message.ENCRYPTION_PGP) {
FileBackend.updateMediaScanner(xmppConnectionService, file);
xmppConnectionService.getFileBackend().updateMediaScanner(finalFile);
}
}