ManaPlus
chatlogger.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2009-2010 The Mana Developers
4  * Copyright (C) 2011-2019 The ManaPlus Developers
5  * Copyright (C) 2009-2021 Andrei Karas
6  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "chatlogger.h"
24 
25 #include "configuration.h"
26 
27 #include "fs/mkdir.h"
28 
29 #include "utils/cast.h"
30 
31 #include <dirent.h>
32 #include <iostream>
33 
34 #ifdef WIN32
35 #include <windows.h>
36 #include <sys/time.h>
37 #elif defined __APPLE__
38 #include <Carbon/Carbon.h>
39 #endif // WIN32
40 
41 #include "debug.h"
42 
44 
46  mLogFile(),
47  mLogDir(),
48  mBaseLogDir(),
49  mServerName(),
50  mLogFileName()
51 {
52 }
53 
55 {
56  if (mLogFile.is_open())
57  mLogFile.close();
58 }
59 
60 void ChatLogger::setLogFile(const std::string &logFilename)
61 {
62  if (mLogFile.is_open())
63  mLogFile.close();
64 
65  mLogFile.open(logFilename.c_str(),
66  std::ios_base::app);
67  mLogFileName = logFilename;
68 
69  if (!mLogFile.is_open())
70  {
71  std::cout << "Warning: error while opening " <<
72  logFilename <<
73  " for writing.\n";
74  }
75 }
76 
77 void ChatLogger::setLogDir(const std::string &logDir)
78 {
79  mLogDir = logDir;
80 
81  if (mLogFile.is_open())
82  mLogFile.close();
83 
84  DIR *const dir = opendir(mLogDir.c_str());
85  if (dir == nullptr)
86  mkdir_r(mLogDir.c_str());
87  else
88  closedir(dir);
89 }
90 
91 void ChatLogger::log(std::string str)
92 {
93  const std::string &dateStr = getDir();
94  const std::string logFileName = strprintf(
95  "%s/#General.log", dateStr.c_str());
96  if (!mLogFile.is_open() ||
97  logFileName != mLogFileName)
98  {
99  setLogDir(dateStr);
100  setLogFile(logFileName);
101  }
102 
103  str = removeColors(str);
104  writeTo(mLogFile, str);
105 }
106 
107 void ChatLogger::log(std::string name,
108  std::string str)
109 {
110  const std::string &dateStr = getDir();
111  const std::string logFileName = strprintf("%s/%s.log",
112  dateStr.c_str(), secureName(name).c_str());
113 
114  if (!mLogFile.is_open() || logFileName != mLogFileName)
115  {
116  setLogDir(dateStr);
117  setLogFile(logFileName);
118  }
119 
120  str = removeColors(str);
121  writeTo(mLogFile, str);
122 }
123 
124 std::string ChatLogger::getDir() const
125 {
126  std::string date;
127 
128  time_t rawtime;
129  char buffer [81];
130 
131  time(&rawtime);
132  tm *const timeinfo = localtime(&rawtime);
133 
134  strftime(buffer, 79, "%Y-%m/%d", timeinfo);
135 
136  date = strprintf("%s/%s/%s",
137  mBaseLogDir.c_str(),
138  mServerName.c_str(),
139  buffer);
140 
141  return date;
142 }
143 
144 std::string ChatLogger::secureName(std::string &name)
145 {
146  const size_t sz = name.length();
147  for (size_t f = 0; f < sz; f ++)
148  {
149  const unsigned char ch = name[f];
150  if ((ch < '0' || ch > '9') &&
151  (ch < 'a' || ch > 'z') &&
152  (ch < 'A' || ch > 'Z') &&
153  ch != '-' &&
154  ch != '+' &&
155  ch != '=' &&
156  ch != '.' &&
157  ch != ',' &&
158  ch != ')' &&
159  ch != '(' &&
160  ch != '[' &&
161  ch != ']' &&
162  ch != '#')
163  {
164  name[f] = '_';
165  }
166  }
167  return name;
168 }
169 
170 void ChatLogger::writeTo(std::ofstream &file,
171  const std::string &str)
172 {
173  file << str << std::endl;
174 }
175 
176 void ChatLogger::setServerName(const std::string &serverName)
177 {
178  mServerName = serverName;
179  if (mServerName.empty())
180  mServerName = config.getStringValue("MostUsedServerName0");
181 
182  if (mLogFile.is_open())
183  mLogFile.close();
184 
186  if (!mLogDir.empty())
187  {
188  const std::string name = pathJoin(mLogDir, mServerName);
189  DIR *const dir = opendir(name.c_str());
190  if (dir == nullptr)
191  mkdir_r(name.c_str());
192  else
193  closedir(dir);
194  }
195 }
196 
197 void ChatLogger::loadLast(std::string name,
198  std::list<std::string> &list,
199  const unsigned int n) const
200 {
201  std::ifstream logFile;
202  std::string fileName = strprintf("%s/%s.log",
203  getDir().c_str(),
204  secureName(name).c_str());
205 
206  logFile.open(fileName.c_str(), std::ios::in);
207 
208  if (!logFile.is_open())
209  return;
210 
211  char line[710];
212  unsigned sz = CAST_U32(list.size());
213  while (logFile.getline(line, 700))
214  {
215  list.push_back(line);
216  sz ++;
217  if (sz > n)
218  {
219  list.pop_front();
220  sz --;
221  }
222  }
223 
224  if (logFile.is_open())
225  logFile.close();
226 }
227 
229 {
230  mLogDir.clear();
231  mServerName.clear();
232  mLogFileName.clear();
233 }
#define CAST_U32
Definition: cast.h:31
ChatLogger * chatLogger
Definition: chatlogger.cpp:43
std::string mLogFileName
Definition: chatlogger.h:83
void setServerName(const std::string &serverName)
Definition: chatlogger.cpp:176
void loadLast(std::string name, std::list< std::string > &list, const unsigned int n) const
Definition: chatlogger.cpp:197
void setLogFile(const std::string &logFilename)
Definition: chatlogger.cpp:60
void clear()
Definition: chatlogger.cpp:228
static void writeTo(std::ofstream &file, const std::string &str)
Definition: chatlogger.cpp:170
std::string mBaseLogDir
Definition: chatlogger.h:81
static std::string secureName(std::string &str)
Definition: chatlogger.cpp:144
std::string getDir() const
Definition: chatlogger.cpp:124
std::string mServerName
Definition: chatlogger.h:82
void setLogDir(const std::string &logDir)
Definition: chatlogger.cpp:77
std::string mLogDir
Definition: chatlogger.h:80
void log(std::string str)
Definition: chatlogger.cpp:91
std::ofstream mLogFile
Definition: chatlogger.h:79
std::string getStringValue(const std::string &key) const
Configuration config
int mkdir_r(const char *const pathname)
Create a directory, making leading components first if necessary.
Definition: mkdir.cpp:109
std::string removeColors(std::string msg)
std::string strprintf(const char *const format,...)
std::string pathJoin(std::string str1, const std::string &str2)
std::string fileName
Definition: testmain.cpp:39