package com.zegoggles.smssync.mail;
import android.provider.CallLog;
import android.provider.Telephony;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.MessagingException;
import org.jetbrains.annotations.NotNull;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import static com.zegoggles.smssync.utils.Sanitizer.sanitize;
/**
* Generates headers for SMS, MMS, Call logs
*/
class HeaderGenerator {
private static final String REFERENCE_UID_TEMPLATE = "<%s.%s@sms-backup-plus.local>";
private static final String MSG_ID_TEMPLATE = "<%s@sms-backup-plus.local>";
private static final String UTF_8 = "UTF-8";
private final String reference;
private final String version;
public HeaderGenerator(String reference, String version) {
this.version = version;
this.reference = reference;
}
public void setHeaders(final Message message,
final Map<String, String> msgMap,
final DataType dataType,
final String address,
final @NotNull PersonRecord contact,
final Date sentDate,
final int status) throws MessagingException {
// Threading by contact ID, not by thread ID. I think this value is more stable.
message.setHeader(Headers.REFERENCES, String.format(REFERENCE_UID_TEMPLATE, reference, contact.getId()));
message.setHeader(Headers.MESSAGE_ID, createMessageId(sentDate, address, status));
message.setHeader(Headers.ADDRESS, sanitize(address));
message.setHeader(Headers.DATATYPE, dataType.toString());
message.setHeader(Headers.BACKUP_TIME, toGMTString(new Date()));
message.setHeader(Headers.VERSION, version);
message.setSentDate(sentDate, false);
message.setInternalDate(sentDate);
switch (dataType) {
case SMS: setSmsHeaders(message, msgMap); break;
case MMS: setMmsHeaders(message, msgMap); break;
case CALLLOG: setCallLogHeaders(message, msgMap); break;
}
}
private void setSmsHeaders(Message message, Map<String,String> msgMap) throws MessagingException {
message.setHeader(Headers.ID, msgMap.get(Telephony.BaseMmsColumns._ID));
message.setHeader(Headers.TYPE, msgMap.get(Telephony.TextBasedSmsColumns.TYPE));
message.setHeader(Headers.DATE, msgMap.get(Telephony.TextBasedSmsColumns.DATE));
message.setHeader(Headers.THREAD_ID, msgMap.get(Telephony.TextBasedSmsColumns.THREAD_ID));
message.setHeader(Headers.READ, msgMap.get(Telephony.TextBasedSmsColumns.READ));
message.setHeader(Headers.STATUS, msgMap.get(Telephony.TextBasedSmsColumns.STATUS));
message.setHeader(Headers.PROTOCOL, msgMap.get(Telephony.TextBasedSmsColumns.PROTOCOL));
message.setHeader(Headers.SERVICE_CENTER, msgMap.get(Telephony.TextBasedSmsColumns.SERVICE_CENTER));
}
private void setMmsHeaders(Message message, Map<String,String> msgMap) throws MessagingException {
message.setHeader(Headers.ID, msgMap.get(Telephony.BaseMmsColumns._ID));
message.setHeader(Headers.TYPE, msgMap.get(Telephony.BaseMmsColumns.MESSAGE_TYPE));
message.setHeader(Headers.DATE, msgMap.get(Telephony.BaseMmsColumns.DATE));
message.setHeader(Headers.THREAD_ID, msgMap.get(Telephony.BaseMmsColumns.THREAD_ID));
message.setHeader(Headers.READ, msgMap.get(Telephony.BaseMmsColumns.READ));
}
private void setCallLogHeaders(Message message, Map<String,String> msgMap) throws MessagingException {
message.setHeader(Headers.ID, msgMap.get(CallLog.Calls._ID));
message.setHeader(Headers.TYPE, msgMap.get(CallLog.Calls.TYPE));
message.setHeader(Headers.DATE, msgMap.get(CallLog.Calls.DATE));
message.setHeader(Headers.DURATION, msgMap.get(CallLog.Calls.DURATION));
}
private static String toGMTString(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("d MMM y HH:mm:ss 'GMT'", Locale.US);
TimeZone gmtZone = TimeZone.getTimeZone("GMT");
sdf.setTimeZone(gmtZone);
GregorianCalendar gc = new GregorianCalendar(gmtZone);
gc.setTimeInMillis(date.getTime());
return sdf.format(date);
}
/**
* Create a message-id based on message date, phone number and message
* type.
*
* @param sent email send date
* @param address the email address
* @param type the type
* @return the message-id
*/
private static String createMessageId(Date sent, String address, int type) {
try {
final MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(Long.toString(sent.getTime()).getBytes(UTF_8));
if (address != null) {
digest.update(address.getBytes(UTF_8));
}
digest.update(Integer.toString(type).getBytes(UTF_8));
final StringBuilder sb = new StringBuilder();
for (byte b : digest.digest()) {
sb.append(String.format(Locale.ENGLISH, "%02x", b));
}
return String.format(Locale.ENGLISH, MSG_ID_TEMPLATE, sb.toString());
} catch (java.io.UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (java.security.NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
}