aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/logview/LogFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/logview/LogFile.cpp')
-rw-r--r--src/modules/logview/LogFile.cpp249
1 files changed, 248 insertions, 1 deletions
diff --git a/src/modules/logview/LogFile.cpp b/src/modules/logview/LogFile.cpp
index be244077b..0c15b27be 100644
--- a/src/modules/logview/LogFile.cpp
+++ b/src/modules/logview/LogFile.cpp
@@ -24,12 +24,20 @@
#include "LogFile.h"
+#include "kvi_settings.h"
+#include "KviApplication.h"
+#include "KviControlCodes.h"
#include "KviQString.h"
#include "KviCString.h"
+#include "KviHtmlGenerator.h"
+#include "KviIconManager.h"
+#include "KviLocale.h"
#include "KviOptions.h"
#include "KviFileUtils.h"
#include <QFileInfo>
+#include <QDir>
+#include <QTextStream>
#include <QLocale>
#ifdef COMPILE_ZLIB_SUPPORT
@@ -144,7 +152,7 @@ LogFile::LogFile(const QString & szName)
}
}
-void LogFile::getText(QString & szText)
+void LogFile::getText(QString & szText) const
{
QString szLogName = fileName();
QFile logFile;
@@ -189,3 +197,242 @@ void LogFile::getText(QString & szText)
}
#endif
}
+
+void LogFile::createLog(ExportType exportType, QString szLog, QString * pszFile) const
+{
+ QRegExp rx;
+ QString szLogDir, szInputBuffer, szOutputBuffer, szLine, szTmp;
+ QString szDate = date().toString("yyyy.MM.dd");
+
+ /* Save export directory - this directory path is also used in the HTML export
+ * and info is used when working with pszFile */
+ QFileInfo info(szLog);
+ szLogDir = info.absoluteDir().absolutePath() + KVI_PATH_SEPARATOR_CHAR;
+
+ /* Reading in log file - LogFiles are read in as bytes, so '\r' isn't
+ * sanitised by default */
+ getText(szInputBuffer);
+ QStringList lines = szInputBuffer.replace('\r', "").split('\n');
+
+ switch(exportType)
+ {
+ case LogFile::PlainText:
+ {
+ /* Only append extension if it isn't there already (e.g. a specific
+ * file is to be overwritten) */
+ if(!szLog.endsWith(".txt"))
+ szLog += ".txt";
+
+ // Scan the file
+ for(auto & line : lines)
+ {
+ szTmp = line;
+ szLine = KviControlCodes::stripControlBytes(szTmp);
+
+ // Remove icons' code
+ rx.setPattern("^\\d{1,3}\\s");
+ szLine.replace(rx, "");
+
+ // Remove link from a user speaking, deal with (and keep) various ranks
+ // e.g.: <!ncHelLViS69> --> <HelLViS69>
+ rx.setPattern("\\s<([+%@&~!]?)!nc");
+ szLine.replace(rx, " <\\1");
+
+ // Remove link from a nick in a mask
+ // e.g.: !nFoo [~bar@!hfoo.bar] --> Foo [~bar@!hfoo.bar]
+ rx.setPattern("\\s!n");
+ szLine.replace(rx, " ");
+
+ // Remove link from a host in a mask
+ // e.g.: Foo [~bar@!hfoo.bar] --> Foo [~bar@foo.bar]
+ rx.setPattern("@!h");
+ szLine.replace(rx, "@");
+
+ // Remove link from a channel
+ // e.g.: !c#KVIrc --> #KVIrc
+ rx.setPattern("!c#");
+ szLine.replace(rx, "#");
+
+ szOutputBuffer += szLine;
+ szOutputBuffer += "\n";
+ }
+
+ break;
+ }
+ case LogFile::HTML:
+ {
+ /* Only append extension if it isn't there already (e.g. a specific
+ * file is to be overwritten) */
+ if(!szLog.endsWith(".html"))
+ szLog += ".html";
+
+ szTmp = QString("KVIrc %1 %2").arg(KVI_VERSION).arg(KVI_RELEASE_NAME);
+ QString szNick = "";
+ bool bFirstLine = true;
+
+ QString szTitle;
+ switch(type())
+ {
+ case LogFile::Channel:
+ szTitle = __tr2qs_ctx("Channel %1 on %2", "log").arg(name(), network());
+ break;
+ case LogFile::Console:
+ szTitle = __tr2qs_ctx("Console on %1", "log").arg(network());
+ break;
+ case LogFile::Query:
+ szTitle = __tr2qs_ctx("Query with: %1 on %2", "log").arg(name(), network());
+ break;
+ case LogFile::DccChat:
+ szTitle = __tr2qs_ctx("DCC Chat with: %1", "log").arg(name());
+ break;
+ case LogFile::Other:
+ szTitle = __tr2qs_ctx("Something on: %1", "log").arg(network());
+ break;
+ }
+
+ // Prepare HTML document
+ szOutputBuffer += "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n";
+ szOutputBuffer += "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n";
+ szOutputBuffer += "<head>\n";
+ szOutputBuffer += "\t<meta http-equiv=\"content-type\" content=\"application/xhtml+xml; charset=utf-8\" />\n";
+ szOutputBuffer += "\t<meta name=\"author\" content=\"" + szTmp + "\" />\n";
+ szOutputBuffer += "\t<title>" + szTitle + "</title>\n";
+ szOutputBuffer += "</head>\n<body>\n";
+ szOutputBuffer += "<h2>" + szTitle + "</h2>\n<h3>Date: " + szDate + "</h3>\n";
+
+ // Scan the file
+ for(auto & line : lines)
+ {
+ szTmp = line;
+
+ // Find who has talked
+ QString szTmpNick = szTmp.section(" ", 2, 2);
+ if((szTmpNick.left(1) != "<") && (szTmpNick.right(1) != ">"))
+ szTmpNick = "";
+
+ // locate msgtype
+ QString szNum = szTmp.section(' ', 0, 0);
+ bool bOk;
+ int iMsgType = szNum.toInt(&bOk);
+
+ // only human text for now...
+ if(iMsgType != 24 && iMsgType != 25 && iMsgType != 26)
+ continue;
+
+ // remove msgtype tag
+ szTmp = szTmp.remove(0, szNum.length() + 1);
+
+ szTmp = KviHtmlGenerator::convertToHtml(szTmp, true);
+
+ // insert msgtype icon at start of the current text line
+ KviMessageTypeSettings msg(KVI_OPTION_MSGTYPE(iMsgType));
+ QString szIcon = g_pIconManager->getSmallIconResourceName((KviIconManager::SmallIcon)msg.pixId());
+ szTmp.prepend("<img src=\"" + szIcon + R"(" alt="" /> )");
+
+ /*
+ * Check if the nick who has talked is the same of the above line.
+ * If so, we have to put the line as it is, otherwise we have to
+ * open a new paragraph
+ */
+ if(szTmpNick != szNick)
+ {
+ /*
+ * People is not the same, close the paragraph opened
+ * before and open a new one
+ */
+ if(!bFirstLine)
+ szOutputBuffer += "</p>\n";
+ szTmp.prepend("<p>");
+
+ szNick = szTmpNick;
+ }
+ else
+ {
+ // Break the line
+ szTmp.prepend("<br />\n");
+ }
+
+ // remove internal tags before nickname
+ rx.setPattern(">([+%@&~!]?)!nc");
+ szTmp.replace(rx, ">\\1");
+ szTmp.replace(">&amp;!nc", ">&amp;");
+
+ szOutputBuffer += szTmp;
+ bFirstLine = false;
+ }
+
+ // Close the last paragraph
+ szOutputBuffer += "</p>\n";
+
+ // regexp to search all embedded icons
+ rx.setPattern("<img src=\"smallicons:([^\"]+)");
+ int iIndex = szOutputBuffer.indexOf(rx);
+ QStringList szImagesList;
+
+ // search for icons
+ while(iIndex >= 0)
+ {
+ int iLength = rx.matchedLength();
+ QString szCap = rx.cap(1);
+
+ // if the icon isn't in the images list then add
+ if(szImagesList.indexOf(szCap) == -1)
+ szImagesList.append(szCap);
+ iIndex = szOutputBuffer.indexOf(rx, iIndex + iLength);
+ }
+
+ // get current theme path
+ QString szCurrentThemePath;
+ g_pApp->getLocalKvircDirectory(szCurrentThemePath, KviApplication::Themes, KVI_OPTION_STRING(KviOption_stringIconThemeSubdir));
+ szCurrentThemePath += KVI_PATH_SEPARATOR_CHAR;
+
+ // current coresmall path
+ szCurrentThemePath += "coresmall";
+ szCurrentThemePath += KVI_PATH_SEPARATOR_CHAR;
+
+ // check if coresmall exists in current theme
+ if(!KviFileUtils::directoryExists(szCurrentThemePath))
+ {
+ // get global coresmall path
+ g_pApp->getGlobalKvircDirectory(szCurrentThemePath, KviApplication::Pics, "coresmall");
+ KviQString::ensureLastCharIs(szCurrentThemePath, QChar(KVI_PATH_SEPARATOR_CHAR));
+ }
+
+ // copy all icons to the log destination folder
+ for(int i = 0; i < szImagesList.count(); i++)
+ {
+ QString szSourceFile = szCurrentThemePath + szImagesList.at(i);
+ QString szDestFile = szLogDir + szImagesList.at(i);
+ KviFileUtils::copyFile(szSourceFile, szDestFile);
+ }
+
+ // remove internal tags
+ rx.setPattern("<qt>|</qt>|smallicons:");
+ szOutputBuffer.replace(rx, "");
+
+ // Close the document
+ szOutputBuffer += "</body>\n</html>\n";
+
+ break;
+ }
+ }
+
+ // File overwriting already dealt with when file path was obtained
+ QFile log(szLog);
+ if(!log.open(QIODevice::WriteOnly | QIODevice::Text))
+ return;
+
+ if(pszFile)
+ {
+ *pszFile = "";
+ *pszFile = info.filePath();
+ }
+
+ // Ensure we're writing in UTF-8
+ QTextStream output(&log);
+ output.setCodec("UTF-8");
+ output << szOutputBuffer;
+
+ // Close file descriptors
+ log.close();
+}