1 //////////////////////////////////////////////////////////////////////
2 //
3 // BeeBEEP Copyright (C) 2010-2021 Marco Mastroddi
4 //
5 // BeeBEEP is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published
7 // by the Free Software Foundation, either version 3 of the License,
8 // or (at your option) any later version.
9 //
10 // BeeBEEP is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with BeeBEEP. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // Author: Marco Mastroddi <marco.mastroddi(AT)gmail.com>
19 //
20 // $Id: MessageManager.cpp 1455 2020-12-23 10:17:53Z mastroddi $
21 //
22 //////////////////////////////////////////////////////////////////////
23
24 #include "MessageManager.h"
25 #include "Protocol.h"
26 #include "SaveChatList.h"
27 #include "Settings.h"
28
29
30 MessageManager* MessageManager::mp_instance = Q_NULLPTR;
31
MessageManager()32 MessageManager::MessageManager()
33 : m_messagesToSend()
34 {
35 }
36
addMessageToSend(VNumber to_user_id,VNumber chat_id,const Message & m)37 void MessageManager::addMessageToSend( VNumber to_user_id, VNumber chat_id, const Message& m )
38 {
39 addMessageRecord( MessageRecord( to_user_id, chat_id, m ) );
40 }
41
takeMessagesToSendToUserId(VNumber user_id)42 QList<MessageRecord> MessageManager::takeMessagesToSendToUserId( VNumber user_id )
43 {
44 QList<MessageRecord> message_list;
45 QList<MessageRecord>::iterator it = m_messagesToSend.begin();
46 while( it != m_messagesToSend.end() )
47 {
48 if( (*it).toUserId() == user_id )
49 {
50 message_list.append( *it );
51 it = m_messagesToSend.erase( it );
52 }
53 else
54 ++it;
55 }
56 if( !message_list.isEmpty() )
57 saveUnsentMessages( true );
58 return message_list;
59 }
60
countMessagesToSendToUserId(VNumber user_id)61 int MessageManager::countMessagesToSendToUserId( VNumber user_id )
62 {
63 int counter = 0;
64 foreach( MessageRecord mr, m_messagesToSend )
65 {
66 if( mr.toUserId() == user_id )
67 counter++;
68 }
69 return counter;
70 }
71
countMessagesToSendInChatId(VNumber chat_id)72 int MessageManager::countMessagesToSendInChatId( VNumber chat_id )
73 {
74 int counter = 0;
75 foreach( MessageRecord mr, m_messagesToSend )
76 {
77 if( mr.chatId() == chat_id )
78 counter++;
79 }
80 return counter;
81 }
82
unsentMessagesCanBeSaved() const83 bool MessageManager::unsentMessagesCanBeSaved() const
84 {
85 QFileInfo file_info( Settings::instance().unsentMessagesFilePath() );
86 if( file_info.exists() )
87 return file_info.isWritable();
88
89 QFile file( Settings::instance().unsentMessagesFilePath() );
90 if( file.open( QIODevice::WriteOnly ) )
91 {
92 file.close();
93 file.remove();
94 return true;
95 }
96 else
97 return false;
98 }
99
saveUnsentMessages(bool silent_mode)100 bool MessageManager::saveUnsentMessages( bool silent_mode )
101 {
102 QString file_name = Settings::instance().unsentMessagesFilePath();
103 QFile file( file_name );
104 if( !Settings::instance().enableSaveData() || !Settings::instance().chatSaveUnsentMessages() )
105 {
106 if( !silent_mode )
107 qDebug() << "Unsent chat messages are not saved because you have disabled this option";
108 if( file.exists() )
109 {
110 if( !silent_mode )
111 qDebug() << "Unsent messages file removed:" << qPrintable( file_name );
112 file.remove();
113 }
114 return false;
115 }
116
117 if( !Settings::instance().saveUserList() || !Settings::instance().saveGroupList() )
118 {
119 qWarning() << "Saving unsent messages fails because 'Save users' and 'Save groups' options are disabled";
120 return false;
121 }
122
123 if( !file.open( QIODevice::WriteOnly ) )
124 {
125 qWarning() << "Unable to open file" << qPrintable( file_name ) << ": saving unsent messages aborted";
126 return false;
127 }
128
129 if( !silent_mode )
130 qDebug() << "Saving unsent messages in" << qPrintable( file_name );
131 QDataStream stream( &file );
132 stream.setVersion( Settings::instance().dataStreamVersion( false ) );
133
134 QStringList file_header;
135 file_header << Settings::instance().programName();
136 file_header << Settings::instance().version( false, false, false );
137 file_header << QString::number( Settings::instance().protocolVersion() );
138 file_header << m_savedMessagesAuthCode;
139 stream << file_header;
140 if( stream.status() != QDataStream::Ok )
141 {
142 qWarning() << "Datastream error: unable to save file header in" << qPrintable( file_name );
143 file.close();
144 return false;
145 }
146
147 QStringList sl_smr;
148 if( !m_messagesToSend.isEmpty() )
149 {
150 foreach( MessageRecord mr, m_messagesToSend )
151 {
152 QString smr = Protocol::instance().saveMessageRecord( mr );
153 if( !smr.isEmpty() )
154 sl_smr.append( Settings::instance().simpleEncrypt( smr ) );
155 }
156 }
157 qint32 sl_smr_size = sl_smr.size();
158 stream << sl_smr_size;
159 if( stream.status() != QDataStream::Ok )
160 {
161 qWarning() << "Datastream error: unable to save number of unsent messages in" << qPrintable( file_name );
162 file.close();
163 return false;
164 }
165 if( sl_smr_size > 0 )
166 {
167 int sl_smr_counter = 0;
168 foreach( QString smr, sl_smr )
169 {
170 sl_smr_counter++;
171 stream << smr;
172 if( stream.status() != QDataStream::Ok )
173 {
174 qWarning() << "Datastream error: unable to save unsent message" << sl_smr_counter << "in" << qPrintable( file_name );
175 file.close();
176 return false;
177 }
178 }
179 }
180 file.close();
181 if( !silent_mode )
182 qDebug() << sl_smr_size << "unsent messages saved";
183 return true;
184 }
185
addMessageRecord(const MessageRecord & mr)186 void MessageManager::addMessageRecord( const MessageRecord& mr )
187 {
188 m_messagesToSend.append( mr );
189 saveUnsentMessages( true );
190 }
191
addMessageRecords(const QList<MessageRecord> & mr_list)192 void MessageManager::addMessageRecords( const QList<MessageRecord>& mr_list )
193 {
194 if( mr_list.isEmpty() )
195 return;
196 if( m_messagesToSend.isEmpty() )
197 m_messagesToSend = mr_list;
198 else
199 m_messagesToSend.append( mr_list );
200 saveUnsentMessages( true );
201 }
202
loadSavedMessagesAuthCode()203 void MessageManager::loadSavedMessagesAuthCode()
204 {
205 QString s = Settings::instance().saveMessagesTimestamp().toString( Qt::ISODate );
206 s += Settings::instance().localUser().name();
207 QByteArray ba = s.toUtf8().toBase64();
208 QByteArray auth_code = QCryptographicHash::hash( ba, QCryptographicHash::Sha1 );
209 m_savedMessagesAuthCode = QString::fromLatin1( auth_code.toHex() );
210 }
211
generateSaveMessagesAuthCode()212 void MessageManager::generateSaveMessagesAuthCode()
213 {
214 Settings::instance().setSaveMessagesTimestamp( QDateTime::currentDateTime() );
215 Settings::instance().save();
216 loadSavedMessagesAuthCode();
217 }
218
chatMessageCanBeSaved() const219 bool MessageManager::chatMessageCanBeSaved() const
220 {
221 return SaveChatList::canBeSaved();
222 }
223
saveMessages(bool save_unsent_messages_also)224 bool MessageManager::saveMessages( bool save_unsent_messages_also )
225 {
226 bool unsent_chat_messages_saved;
227 generateSaveMessagesAuthCode();
228 if( save_unsent_messages_also )
229 unsent_chat_messages_saved = saveUnsentMessages( false );
230 else
231 unsent_chat_messages_saved = true;
232 SaveChatList scl;
233 return scl.save() && unsent_chat_messages_saved;
234 }
235