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