1package eu.siacs.conversations.services;
2
3import android.app.NotificationManager;
4import android.app.Service;
5import android.content.Context;
6import android.content.Intent;
7import android.os.IBinder;
8import android.support.v4.app.NotificationCompat;
9import java.io.BufferedWriter;
10import java.io.File;
11import java.io.FileWriter;
12import java.io.IOException;
13import java.text.SimpleDateFormat;
14import java.util.Date;
15import java.util.List;
16import java.util.concurrent.atomic.AtomicBoolean;
17
18import eu.siacs.conversations.R;
19import eu.siacs.conversations.entities.Account;
20import eu.siacs.conversations.entities.Conversation;
21import eu.siacs.conversations.entities.Message;
22import eu.siacs.conversations.persistance.DatabaseBackend;
23import eu.siacs.conversations.persistance.FileBackend;
24import rocks.xmpp.addr.Jid;
25
26public class ExportLogsService extends Service {
27
28 private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
29 private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsLogsDirectory() + "/logs/%s";
30 private static final String MESSAGE_STRING_FORMAT = "(%s) %s: %s\n";
31 private static final int NOTIFICATION_ID = 1;
32 private static AtomicBoolean running = new AtomicBoolean(false);
33 private DatabaseBackend mDatabaseBackend;
34 private List<Account> mAccounts;
35
36 @Override
37 public void onCreate() {
38 mDatabaseBackend = DatabaseBackend.getInstance(getBaseContext());
39 mAccounts = mDatabaseBackend.getAccounts();
40 }
41
42 @Override
43 public int onStartCommand(Intent intent, int flags, int startId) {
44 if (running.compareAndSet(false, true)) {
45 new Thread(() -> {
46 export();
47 stopForeground(true);
48 running.set(false);
49 stopSelf();
50 }).start();
51 }
52 return START_NOT_STICKY;
53 }
54
55 private void export() {
56 List<Conversation> conversations = mDatabaseBackend.getConversations(Conversation.STATUS_AVAILABLE);
57 conversations.addAll(mDatabaseBackend.getConversations(Conversation.STATUS_ARCHIVED));
58 NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
59 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext());
60 mBuilder.setContentTitle(getString(R.string.notification_export_logs_title))
61 .setSmallIcon(R.drawable.ic_import_export_white_24dp)
62 .setProgress(conversations.size(), 0, false);
63 startForeground(NOTIFICATION_ID, mBuilder.build());
64
65 int progress = 0;
66 for (Conversation conversation : conversations) {
67 writeToFile(conversation);
68 progress++;
69 mBuilder.setProgress(conversations.size(), progress, false);
70 mNotifyManager.notify(NOTIFICATION_ID, mBuilder.build());
71 }
72 }
73
74 private void writeToFile(Conversation conversation) {
75 Jid accountJid = resolveAccountUuid(conversation.getAccountUuid());
76 Jid contactJid = conversation.getJid();
77
78 File dir = new File(String.format(DIRECTORY_STRING_FORMAT,accountJid.asBareJid().toString()));
79 dir.mkdirs();
80
81 BufferedWriter bw = null;
82 try {
83 for (Message message : mDatabaseBackend.getMessagesIterable(conversation)) {
84 if (message == null)
85 continue;
86 if (message.getType() == Message.TYPE_TEXT || message.hasFileOnRemoteHost()) {
87 String date = simpleDateFormat.format(new Date(message.getTimeSent()));
88 if (bw == null) {
89 bw = new BufferedWriter(new FileWriter(
90 new File(dir, contactJid.asBareJid().toString() + ".txt")));
91 }
92 String jid = null;
93 switch (message.getStatus()) {
94 case Message.STATUS_RECEIVED:
95 jid = getMessageCounterpart(message);
96 break;
97 case Message.STATUS_SEND:
98 case Message.STATUS_SEND_RECEIVED:
99 case Message.STATUS_SEND_DISPLAYED:
100 jid = accountJid.asBareJid().toString();
101 break;
102 }
103 if (jid != null) {
104 String body = message.hasFileOnRemoteHost() ? message.getFileParams().url.toString() : message.getBody();
105 bw.write(String.format(MESSAGE_STRING_FORMAT, date, jid,
106 body.replace("\\\n", "\\ \n").replace("\n", "\\ \n")));
107 }
108 }
109 }
110 } catch (IOException e) {
111 e.printStackTrace();
112 } finally {
113 try {
114 if (bw != null) {
115 bw.close();
116 }
117 } catch (IOException e1) {
118 e1.printStackTrace();
119 }
120 }
121 }
122
123 private Jid resolveAccountUuid(String accountUuid) {
124 for (Account account : mAccounts) {
125 if (account.getUuid().equals(accountUuid)) {
126 return account.getJid();
127 }
128 }
129 return null;
130 }
131
132 private String getMessageCounterpart(Message message) {
133 String trueCounterpart = (String) message.getContentValues().get(Message.TRUE_COUNTERPART);
134 if (trueCounterpart != null) {
135 return trueCounterpart;
136 } else {
137 return message.getCounterpart().toString();
138 }
139 }
140
141 @Override
142 public IBinder onBind(Intent intent) {
143 return null;
144 }
145}