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