File indexing completed on 2024-04-28 05:49:59

0001 //  -*- c-basic-offset:4; indent-tabs-mode:nil -*-
0002 /*
0003     This file is part of the KDE libraries
0004     SPDX-FileCopyrightText: 1996-1998 Martin R. Jones <mjones@kde.org>
0005     SPDX-FileCopyrightText: 2000 David Faure <faure@kde.org>
0006     SPDX-FileCopyrightText: 2003 Alexander Kellett <lypanov@kde.org>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-only
0009 */
0010 
0011 #include "kbookmarkimporter_ns.h"
0012 
0013 #include <KCharsets>
0014 
0015 #include <QApplication>
0016 #include <QDebug>
0017 #include <QFileDialog>
0018 #include <QMessageBox>
0019 #include <QStringConverter>
0020 #include <QTextStream>
0021 
0022 QString NSBookmarkImporterImpl::toUnicode(const QByteArray &data) const
0023 {
0024     auto codec = QStringDecoder(m_utf8 ? QStringDecoder::Utf8 : QStringDecoder::System);
0025     return codec.decode(data);
0026 }
0027 
0028 void NSBookmarkImporterImpl::parse()
0029 {
0030     QFile f(m_fileName);
0031 
0032     if (f.open(QIODevice::ReadOnly)) {
0033         static const int g_lineLimit = 16 * 1024;
0034         QByteArray s(g_lineLimit, 0);
0035         // skip header
0036         while (f.readLine(s.data(), g_lineLimit) >= 1 && !s.contains("<DL>")) {
0037             ;
0038         }
0039 
0040         while (int size = f.readLine(s.data(), g_lineLimit) >= 1) {
0041             if (size == g_lineLimit) { // Gosh, this line is longer than g_lineLimit. Skipping.
0042                 qWarning() << "Netscape bookmarks contain a line longer than " << g_lineLimit << ". Skipping.";
0043                 continue;
0044             }
0045             QByteArray t = s.trimmed();
0046 
0047             if (t.left(4).toUpper() == "<HR>") {
0048                 Q_EMIT newSeparator();
0049                 t = t.mid(4).trimmed();
0050                 if (t.isEmpty()) {
0051                     continue;
0052                 }
0053             }
0054 
0055             if (t.left(12).toUpper() == "<DT><A HREF=" || t.left(16).toUpper() == "<DT><H3><A HREF=") {
0056                 int firstQuotes = t.indexOf('"') + 1;
0057                 int secondQuotes = t.indexOf('"', firstQuotes);
0058                 if (firstQuotes != -1 && secondQuotes != -1) {
0059                     QByteArray link = t.mid(firstQuotes, secondQuotes - firstQuotes);
0060                     int endTag = t.indexOf('>', secondQuotes + 1);
0061 
0062                     int closeTag = t.indexOf('<', endTag + 1);
0063 
0064                     QByteArray name = t.mid(endTag + 1, closeTag - endTag - 1);
0065                     QString qname = KCharsets::resolveEntities(toUnicode(name));
0066 
0067                     Q_EMIT newBookmark(qname, toUnicode(link), QString());
0068                 }
0069             } else if (t.left(7).toUpper() == "<DT><H3") {
0070                 int endTag = t.indexOf('>', 7);
0071                 QByteArray name = t.mid(endTag + 1);
0072                 name = name.left(name.indexOf('<'));
0073                 QString qname = KCharsets::resolveEntities(toUnicode(name));
0074                 QByteArray additionalInfo = t.mid(8, endTag - 8);
0075                 bool folded = (additionalInfo.left(6) == "FOLDED");
0076                 if (folded) {
0077                     additionalInfo.remove(0, 7);
0078                 }
0079 
0080                 Q_EMIT newFolder(qname, !folded, QString());
0081             } else if (t.left(8).toUpper() == "</DL><P>") {
0082                 Q_EMIT endFolder();
0083             }
0084         }
0085 
0086         f.close();
0087     }
0088 }
0089 
0090 QString NSBookmarkImporterImpl::findDefaultLocation(bool forSaving) const
0091 {
0092     if (m_utf8) {
0093         const QString mozillaHomePath = QDir::homePath() + QLatin1String("/.mozilla");
0094         if (forSaving) {
0095             return QFileDialog::getSaveFileName(QApplication::activeWindow(), QString(), mozillaHomePath, tr("HTML Files (*.html)"));
0096         } else {
0097             return QFileDialog::getOpenFileName(QApplication::activeWindow(), QString(), mozillaHomePath, tr("*.html|HTML Files (*.html)"));
0098         }
0099     } else {
0100         return QDir::homePath() + QLatin1String("/.netscape/bookmarks.html");
0101     }
0102 }
0103 
0104 ////////////////////////////////////////////////////////////////
0105 
0106 void KNSBookmarkExporterImpl::setUtf8(bool utf8)
0107 {
0108     m_utf8 = utf8;
0109 }
0110 
0111 void KNSBookmarkExporterImpl::write(const KBookmarkGroup &parent)
0112 {
0113     if (!QFile::exists(m_fileName)) {
0114         QString errorMsg = NSBookmarkImporterImpl::tr(
0115                                "Could not find %1. Netscape is probably not installed. "
0116                                "Aborting the export.")
0117                                .arg(m_fileName);
0118         QMessageBox::critical(nullptr, NSBookmarkImporterImpl::tr("Netscape not found"), errorMsg);
0119         return;
0120     }
0121     if (QFile::exists(m_fileName)) {
0122         (void)QFile::rename(m_fileName, m_fileName + QLatin1String(".beforekde"));
0123     }
0124 
0125     QFile file(m_fileName);
0126 
0127     if (!file.open(QIODevice::WriteOnly)) {
0128         qCritical() << "Can't write to file " << m_fileName;
0129         return;
0130     }
0131 
0132     QTextStream fstream(&file);
0133     // NOTE: QStringConverter::System assumes the encoding is UTF-8 for Unix based systems
0134     fstream.setEncoding(m_utf8 ? QStringConverter::Utf8 : QStringConverter::System);
0135     QString charset = QString::fromUtf8(QStringConverter::nameForEncoding(m_utf8 ? QStringConverter::Utf8 : QStringConverter::System));
0136 
0137     fstream << "<!DOCTYPE NETSCAPE-Bookmark-file-1>\n"
0138             << NSBookmarkImporterImpl::tr("<!-- This file was generated by Konqueror -->") << "\n"
0139             << "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=" << charset << "\">\n"
0140             << "<TITLE>" << NSBookmarkImporterImpl::tr("Bookmarks") << "</TITLE>\n"
0141             << "<H1>" << NSBookmarkImporterImpl::tr("Bookmarks") << "</H1>\n"
0142             << "<DL><p>\n"
0143             << folderAsString(parent) << "</DL><P>\n";
0144 }
0145 
0146 QString KNSBookmarkExporterImpl::folderAsString(const KBookmarkGroup &parent) const
0147 {
0148     QString str;
0149     QTextStream fstream(&str, QIODevice::WriteOnly);
0150 
0151     for (KBookmark bk = parent.first(); !bk.isNull(); bk = parent.next(bk)) {
0152         if (bk.isSeparator()) {
0153             fstream << "<HR>\n";
0154             fstream.flush();
0155             continue;
0156         }
0157 
0158         QString text = bk.fullText().toHtmlEscaped();
0159 
0160         if (bk.isGroup()) {
0161             fstream << "<DT><H3 " << (!bk.toGroup().isOpen() ? "FOLDED " : "") << bk.internalElement().attribute(QStringLiteral("netscapeinfo")) << ">" << text
0162                     << "</H3>\n"
0163                     << "<DL><P>\n"
0164                     << folderAsString(bk.toGroup()) << "</DL><P>\n";
0165             fstream.flush();
0166             continue;
0167 
0168         } else {
0169             // note - netscape seems to use local8bit for url...
0170             fstream << "<DT><A HREF=\"" << bk.url().toString() << "\"" << bk.internalElement().attribute(QStringLiteral("netscapeinfo")) << ">" << text
0171                     << "</A>\n";
0172             fstream.flush();
0173             continue;
0174         }
0175     }
0176 
0177     return str;
0178 }
0179 
0180 ////
0181 
0182 #include "moc_kbookmarkimporter_ns.cpp"