GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/chatlogger.cpp Lines: 1 101 1.0 %
Date: 2021-03-17 Branches: 0 104 0.0 %

Line Branch Exec Source
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
43
ChatLogger *chatLogger = nullptr;
44
45
ChatLogger::ChatLogger() :
46
    mLogFile(),
47
    mLogDir(),
48
    mBaseLogDir(),
49
    mServerName(),
50
    mLogFileName()
51
{
52
}
53
54
ChatLogger::~ChatLogger()
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
185
    secureName(mServerName);
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
228
void ChatLogger::clear()
229
{
230
    mLogDir.clear();
231
    mServerName.clear();
232
    mLogFileName.clear();
233
2
}