configurable local message retention period. (untested)
This commit is contained in:
parent
4c6ef3b24e
commit
9b6ae6d75f
|
@ -114,6 +114,8 @@ public final class Config {
|
|||
public static final ChatState DEFAULT_CHATSTATE = ChatState.ACTIVE;
|
||||
public static final int TYPING_TIMEOUT = 8;
|
||||
|
||||
public static final int EXPIRY_INTERVAL = 30 * 60 * 1000; // 30 minutes
|
||||
|
||||
public static final String ENABLED_CIPHERS[] = {
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA384",
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Collections;
|
|||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Locale;
|
||||
|
||||
import eu.siacs.conversations.Config;
|
||||
|
@ -930,6 +931,17 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
|||
account.getPgpDecryptionService().decrypt(messages);
|
||||
}
|
||||
|
||||
public void expireOldMessages(long timestamp) {
|
||||
synchronized (this.messages) {
|
||||
for(ListIterator<Message> iterator = this.messages.listIterator(); iterator.hasNext();) {
|
||||
if (iterator.next().getTimeSent() < timestamp) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
untieMessages();
|
||||
}
|
||||
}
|
||||
|
||||
public void sort() {
|
||||
synchronized (this.messages) {
|
||||
Collections.sort(this.messages, new Comparator<Message>() {
|
||||
|
|
|
@ -521,6 +521,12 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
}
|
||||
}
|
||||
|
||||
long deletionDate = mXmppConnectionService.getAutomaticMessageDeletionDate();
|
||||
if (deletionDate != 0 && message.getTimeSent() < deletionDate) {
|
||||
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": skipping message from "+message.getCounterpart().toString()+" because it was sent prior to our deletion date");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean checkForDuplicates = query != null
|
||||
|| (isTypeGroupChat && packet.hasChild("delay","urn:xmpp:delay"))
|
||||
|| message.getType() == Message.TYPE_PRIVATE;
|
||||
|
@ -570,9 +576,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
|||
conversation.endOtrIfNeeded();
|
||||
}
|
||||
|
||||
if (message.getEncryption() == Message.ENCRYPTION_NONE || mXmppConnectionService.saveEncryptedMessages()) {
|
||||
mXmppConnectionService.databaseBackend.createMessage(message);
|
||||
}
|
||||
final HttpConnectionManager manager = this.mXmppConnectionService.getHttpConnectionManager();
|
||||
if (message.trusted() && message.treatAsDownloadable() != Message.Decision.NEVER && manager.getAutoAcceptFileSize() > 0) {
|
||||
manager.createNewDownloadConnection(message);
|
||||
|
|
|
@ -769,6 +769,13 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
|||
db.delete(Message.TABLENAME, Message.CONVERSATION + "=?", args);
|
||||
}
|
||||
|
||||
public boolean expireOldMessages(long timestamp) {
|
||||
String where = Message.TIME_SENT+"<?";
|
||||
String[] whereArgs = {String.valueOf(timestamp)};
|
||||
SQLiteDatabase db = this.getReadableDatabase();
|
||||
return db.delete(Message.TABLENAME,where,whereArgs) > 0;
|
||||
}
|
||||
|
||||
public Pair<Long, String> getLastMessageReceived(Account account) {
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
|
|
|
@ -56,6 +56,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
|||
startCatchup = lastClearDate.first;
|
||||
reference = null;
|
||||
}
|
||||
startCatchup = Math.max(startCatchup,mXmppConnectionService.getAutomaticMessageDeletionDate());
|
||||
long endCatchup = account.getXmppConnection().getLastSessionEstablished();
|
||||
final Query query;
|
||||
if (startCatchup == 0) {
|
||||
|
@ -107,12 +108,15 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
|||
|
||||
public Query query(Conversation conversation, long start, long end) {
|
||||
synchronized (this.queries) {
|
||||
if (start > end) {
|
||||
return null;
|
||||
}
|
||||
final Query query = new Query(conversation, start, end,PagingOrder.REVERSE);
|
||||
if (start==0) {
|
||||
query.reference = conversation.getFirstMamReference();
|
||||
Log.d(Config.LOGTAG,"setting mam reference");
|
||||
}
|
||||
Log.d(Config.LOGTAG,"checking max of "+start+" end "+mXmppConnectionService.getAutomaticMessageDeletionDate());
|
||||
query.start = Math.max(start,mXmppConnectionService.getAutomaticMessageDeletionDate());
|
||||
if (start > end) {
|
||||
return null;
|
||||
}
|
||||
this.queries.add(query);
|
||||
this.execute(query);
|
||||
|
@ -222,7 +226,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded {
|
|||
query.getConversation().setFirstMamReference(first == null ? null : first.getContent());
|
||||
}
|
||||
if (complete || relevant == null || abort) {
|
||||
final boolean done = (complete || query.getMessageCount() == 0) && query.getStart() == 0;
|
||||
final boolean done = (complete || query.getMessageCount() == 0) && query.getStart() <= mXmppConnectionService.getAutomaticMessageDeletionDate();
|
||||
this.finalizeQuery(query, done);
|
||||
Log.d(Config.LOGTAG,query.getAccount().getJid().toBareJid()+": finished mam after "+query.getTotalCount()+" messages. messages left="+Boolean.toString(!done));
|
||||
if (query.getWith() == null && query.getMessageCount() > 0) {
|
||||
|
|
|
@ -59,6 +59,7 @@ import java.util.ListIterator;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import de.duenndns.ssl.MemorizingTrustManager;
|
||||
import eu.siacs.conversations.Config;
|
||||
|
@ -265,6 +266,7 @@ public class XmppConnectionService extends Service {
|
|||
private int mucRosterChangedListenerCount = 0;
|
||||
private OnKeyStatusUpdated mOnKeyStatusUpdated = null;
|
||||
private int keyStatusUpdatedListenerCount = 0;
|
||||
private AtomicLong mLastExpiryRun = new AtomicLong(0);
|
||||
private SecureRandom mRandom;
|
||||
private LruCache<Pair<String,String>,ServiceDiscoveryResult> discoCache = new LruCache<>(20);
|
||||
private final OnBindListener mOnBindListener = new OnBindListener() {
|
||||
|
@ -645,6 +647,9 @@ public class XmppConnectionService extends Service {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (SystemClock.elapsedRealtime() - mLastExpiryRun.get() >= Config.EXPIRY_INTERVAL) {
|
||||
expireOldMessages();
|
||||
}
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
|
@ -854,6 +859,20 @@ public class XmppConnectionService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
private void expireOldMessages() {
|
||||
mLastExpiryRun.set(SystemClock.elapsedRealtime());
|
||||
synchronized (this.conversations) {
|
||||
long timestamp = getAutomaticMessageDeletionDate();
|
||||
if (timestamp > 0) {
|
||||
databaseBackend.expireOldMessages(timestamp);
|
||||
for (Conversation conversation : this.conversations) {
|
||||
conversation.expireOldMessages(timestamp);
|
||||
}
|
||||
updateConversationUi();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasInternetConnection() {
|
||||
ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
|
@ -1232,13 +1251,11 @@ public class XmppConnectionService extends Service {
|
|||
if (addToConversation) {
|
||||
conversation.add(message);
|
||||
}
|
||||
if (message.getEncryption() == Message.ENCRYPTION_NONE || saveEncryptedMessages()) {
|
||||
if (saveInDb) {
|
||||
databaseBackend.createMessage(message);
|
||||
} else if (message.edited()) {
|
||||
databaseBackend.updateMessage(message, message.getEditedId());
|
||||
}
|
||||
}
|
||||
updateConversationUi();
|
||||
}
|
||||
if (packet != null) {
|
||||
|
@ -1347,6 +1364,12 @@ public class XmppConnectionService extends Service {
|
|||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long deletionDate = getAutomaticMessageDeletionDate();
|
||||
mLastExpiryRun.set(SystemClock.elapsedRealtime());
|
||||
if (deletionDate > 0) {
|
||||
Log.d(Config.LOGTAG, "deleting messages that are older than "+AbstractGenerator.getTimestamp(deletionDate));
|
||||
databaseBackend.expireOldMessages(deletionDate);
|
||||
}
|
||||
Log.d(Config.LOGTAG, "restoring roster");
|
||||
for (Account account : accounts) {
|
||||
databaseBackend.readRoster(account.getRoster());
|
||||
|
@ -1518,8 +1541,11 @@ public class XmppConnectionService extends Service {
|
|||
MessageArchiveService.Query query = getMessageArchiveService().query(conversation, 0, timestamp);
|
||||
if (query != null) {
|
||||
query.setCallback(callback);
|
||||
}
|
||||
callback.informUser(R.string.fetching_history_from_server);
|
||||
} else {
|
||||
callback.informUser(R.string.not_fetching_history_retention_period);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3046,6 +3072,15 @@ public class XmppConnectionService extends Service {
|
|||
.getDefaultSharedPreferences(getApplicationContext());
|
||||
}
|
||||
|
||||
public long getAutomaticMessageDeletionDate() {
|
||||
try {
|
||||
final long timeout = Long.parseLong(getPreferences().getString(SettingsActivity.AUTOMATIC_MESSAGE_DELETION, "0")) * 1000;
|
||||
return timeout == 0 ? timeout : System.currentTimeMillis() - timeout;
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean confirmMessages() {
|
||||
return getPreferences().getBoolean("confirm_messages", true);
|
||||
}
|
||||
|
@ -3058,10 +3093,6 @@ public class XmppConnectionService extends Service {
|
|||
return getPreferences().getBoolean("chat_states", false);
|
||||
}
|
||||
|
||||
public boolean saveEncryptedMessages() {
|
||||
return !getPreferences().getBoolean("dont_save_encrypted", false);
|
||||
}
|
||||
|
||||
private boolean respectAutojoin() {
|
||||
return getPreferences().getBoolean("autojoin", true);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ public class SettingsActivity extends XmppActivity implements
|
|||
public static final String TREAT_VIBRATE_AS_SILENT = "treat_vibrate_as_silent";
|
||||
public static final String MANUALLY_CHANGE_PRESENCE = "manually_change_presence";
|
||||
public static final String BLIND_TRUST_BEFORE_VERIFICATION = "btbv";
|
||||
public static final String AUTOMATIC_MESSAGE_DELETION = "automatic_message_deletion";
|
||||
|
||||
public static final int REQUEST_WRITE_LOGS = 0xbf8701;
|
||||
private SettingsFragment mSettingsFragment;
|
||||
|
|
|
@ -52,6 +52,7 @@ import eu.siacs.conversations.entities.Message;
|
|||
import eu.siacs.conversations.entities.Message.FileParams;
|
||||
import eu.siacs.conversations.entities.Transferable;
|
||||
import eu.siacs.conversations.persistance.FileBackend;
|
||||
import eu.siacs.conversations.services.MessageArchiveService;
|
||||
import eu.siacs.conversations.services.NotificationService;
|
||||
import eu.siacs.conversations.ui.ConversationActivity;
|
||||
import eu.siacs.conversations.ui.text.DividerSpan;
|
||||
|
@ -565,8 +566,12 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
|||
timestamp = System.currentTimeMillis();
|
||||
}
|
||||
activity.setMessagesLoaded();
|
||||
activity.xmppConnectionService.getMessageArchiveService().query(conversation, 0, timestamp);
|
||||
MessageArchiveService.Query query = activity.xmppConnectionService.getMessageArchiveService().query(conversation, 0, timestamp);
|
||||
if (query != null) {
|
||||
Toast.makeText(activity, R.string.fetching_history_from_server, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(activity,R.string.not_fetching_history_retention_period, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -103,4 +103,18 @@
|
|||
<item>610</item>
|
||||
<item>2584</item>
|
||||
</string-array>
|
||||
<string-array name="automatic_message_deletion_values">
|
||||
<item>0</item>
|
||||
<item>86400</item>
|
||||
<item>604800</item>
|
||||
<item>2592000</item>
|
||||
<item>15811200</item>
|
||||
</string-array>
|
||||
<string-array name="automatic_message_deletion">
|
||||
<item>@string/never</item>
|
||||
<item>@string/timeout_24_hours</item>
|
||||
<item>@string/timeout_7_days</item>
|
||||
<item>@string/timeout_30_days</item>
|
||||
<item>@string/timeout_6_months</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
|
|
@ -724,5 +724,12 @@
|
|||
<string name="hide_inactive_devices">Hide inactive devices</string>
|
||||
<string name="distrust_omemo_key">Distrust device</string>
|
||||
<string name="distrust_omemo_key_text">Are you sure you want to remove the verification for this device?\nThis device and messages coming from that device will be marked as untrusted.</string>
|
||||
<string name="timeout_24_hours">24 hours</string>
|
||||
<string name="timeout_7_days">7 days</string>
|
||||
<string name="timeout_30_days">30 days</string>
|
||||
<string name="timeout_6_months">6 months</string>
|
||||
<string name="pref_automatically_delete_messages">Automatic message deletion</string>
|
||||
<string name="pref_automatically_delete_messages_description">Automatically delete messages from this device that are older than the configured time frame.</string>
|
||||
<string name="encrypting_message">Encrypting message</string>
|
||||
<string name="not_fetching_history_retention_period">Overstepping local retention period.</string>
|
||||
</resources>
|
||||
|
|
|
@ -170,11 +170,13 @@
|
|||
android:key="btbv"
|
||||
android:title="@string/pref_blind_trust_before_verification"
|
||||
android:summary="@string/pref_blind_trust_before_verification_summary"/>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="dont_save_encrypted"
|
||||
android:summary="@string/pref_dont_save_encrypted_summary"
|
||||
android:title="@string/pref_dont_save_encrypted"/>
|
||||
<ListPreference
|
||||
android:key="automatic_message_deletion"
|
||||
android:title="@string/pref_automatically_delete_messages"
|
||||
android:summary="@string/pref_automatically_delete_messages_description"
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/automatic_message_deletion"
|
||||
android:entryValues="@array/automatic_message_deletion_values" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="dont_trust_system_cas"
|
||||
|
|
Loading…
Reference in a new issue