File indexing completed on 2023-09-24 07:58:41
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 #include "kbookmarkmanager.h" 0013 #include "kbookmarks_debug.h" 0014 0015 #include <KCharsets> 0016 0017 #include <QFileDialog> 0018 #include <QMessageBox> 0019 #include <QApplication> 0020 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0021 #include <QTextCodec> 0022 #else 0023 #include <QStringConverter> 0024 #endif 0025 0026 QString KNSBookmarkImporterImpl::toUnicode(const QByteArray &data) const 0027 { 0028 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0029 QTextCodec *codec = m_utf8 ? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale(); 0030 Q_ASSERT(codec); 0031 if (!codec) { 0032 return {}; 0033 } 0034 return codec->toUnicode(data); 0035 #else 0036 auto codec = QStringDecoder(m_utf8 ? QStringDecoder::Utf8 : QStringDecoder::System); 0037 return codec.decode(data); 0038 #endif 0039 } 0040 0041 void KNSBookmarkImporterImpl::parse() 0042 { 0043 QFile f(m_fileName); 0044 0045 if (f.open(QIODevice::ReadOnly)) { 0046 static const int g_lineLimit = 16 * 1024; 0047 QByteArray s(g_lineLimit, 0); 0048 // skip header 0049 while (f.readLine(s.data(), g_lineLimit) >= 1 && !s.contains("<DL>")) { 0050 ; 0051 } 0052 0053 while (int size = f.readLine(s.data(), g_lineLimit) >= 1) { 0054 if (size == g_lineLimit) { // Gosh, this line is longer than g_lineLimit. Skipping. 0055 qCWarning(KBOOKMARKS_LOG) << "Netscape bookmarks contain a line longer than " << g_lineLimit << ". Skipping."; 0056 continue; 0057 } 0058 QByteArray t = s.trimmed(); 0059 0060 if (t.left(4).toUpper() == "<HR>") { 0061 Q_EMIT newSeparator(); 0062 t = t.mid(4).trimmed(); 0063 if (t.isEmpty()) { 0064 continue; 0065 } 0066 } 0067 0068 if (t.left(12).toUpper() == "<DT><A HREF=" || t.left(16).toUpper() == "<DT><H3><A HREF=") { 0069 int firstQuotes = t.indexOf('"') + 1; 0070 int secondQuotes = t.indexOf('"', firstQuotes); 0071 if (firstQuotes != -1 && secondQuotes != -1) { 0072 QByteArray link = t.mid(firstQuotes, secondQuotes - firstQuotes); 0073 int endTag = t.indexOf('>', secondQuotes + 1); 0074 0075 int closeTag = t.indexOf('<', endTag + 1); 0076 0077 QByteArray name = t.mid(endTag + 1, closeTag - endTag - 1); 0078 QString qname = KCharsets::resolveEntities(toUnicode(name)); 0079 0080 Q_EMIT newBookmark(qname, toUnicode(link), QString()); 0081 } 0082 } else if (t.left(7).toUpper() == "<DT><H3") { 0083 int endTag = t.indexOf('>', 7); 0084 QByteArray name = t.mid(endTag + 1); 0085 name = name.left(name.indexOf('<')); 0086 QString qname = KCharsets::resolveEntities(toUnicode(name)); 0087 QByteArray additionalInfo = t.mid(8, endTag - 8); 0088 bool folded = (additionalInfo.left(6) == "FOLDED"); 0089 if (folded) { 0090 additionalInfo.remove(0, 7); 0091 } 0092 0093 Q_EMIT newFolder(qname, !folded, QString()); 0094 } else if (t.left(8).toUpper() == "</DL><P>") { 0095 Q_EMIT endFolder(); 0096 } 0097 } 0098 0099 f.close(); 0100 } 0101 } 0102 0103 QString KNSBookmarkImporterImpl::findDefaultLocation(bool forSaving) const 0104 { 0105 if (m_utf8) { 0106 const QString mozillaHomePath = QDir::homePath() + QLatin1String("/.mozilla"); 0107 if (forSaving) { 0108 return QFileDialog::getSaveFileName(QApplication::activeWindow(), QString(), mozillaHomePath, tr("HTML Files (*.html)")); 0109 } else { 0110 return QFileDialog::getOpenFileName(QApplication::activeWindow(), QString(), mozillaHomePath, tr("*.html|HTML Files (*.html)")); 0111 } 0112 } else { 0113 return QDir::homePath() + QLatin1String("/.netscape/bookmarks.html"); 0114 } 0115 } 0116 0117 //////////////////////////////////////////////////////////////// 0118 0119 void KNSBookmarkExporterImpl::setUtf8(bool utf8) 0120 { 0121 m_utf8 = utf8; 0122 } 0123 0124 void KNSBookmarkExporterImpl::write(const KBookmarkGroup &parent) 0125 { 0126 if (!QFile::exists(m_fileName)) { 0127 QString errorMsg = KNSBookmarkImporterImpl::tr( 0128 "Could not find %1. Netscape is probably not installed. " 0129 "Aborting the export.") 0130 .arg(m_fileName); 0131 QMessageBox::critical(nullptr, KNSBookmarkImporterImpl::tr("Netscape not found"), errorMsg); 0132 return; 0133 } 0134 if (QFile::exists(m_fileName)) { 0135 (void)QFile::rename(m_fileName, m_fileName + QLatin1String(".beforekde")); 0136 } 0137 0138 QFile file(m_fileName); 0139 0140 if (!file.open(QIODevice::WriteOnly)) { 0141 qCCritical(KBOOKMARKS_LOG) << "Can't write to file " << m_fileName; 0142 return; 0143 } 0144 0145 QTextStream fstream(&file); 0146 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0147 // NOTE: QStringConverter::System assumes the encoding is UTF-8 for Unix based systems 0148 fstream.setEncoding(m_utf8 ? QStringConverter::Utf8 : QStringConverter::System); 0149 QString charset = QString::fromUtf8(QStringConverter::nameForEncoding(m_utf8 ? QStringConverter::Utf8 : QStringConverter::System)); 0150 #else 0151 fstream.setCodec(m_utf8 ? QTextCodec::codecForName("UTF-8") : QTextCodec::codecForLocale()); 0152 QString charset = m_utf8 ? QStringLiteral("UTF-8") : QString::fromLatin1(QTextCodec::codecForLocale()->name()).toUpper(); 0153 #endif 0154 0155 fstream << "<!DOCTYPE NETSCAPE-Bookmark-file-1>\n" 0156 << KNSBookmarkImporterImpl::tr("<!-- This file was generated by Konqueror -->") << "\n" 0157 << "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=" << charset << "\">\n" 0158 << "<TITLE>" << KNSBookmarkImporterImpl::tr("Bookmarks") << "</TITLE>\n" 0159 << "<H1>" << KNSBookmarkImporterImpl::tr("Bookmarks") << "</H1>\n" 0160 << "<DL><p>\n" 0161 << folderAsString(parent) << "</DL><P>\n"; 0162 } 0163 0164 QString KNSBookmarkExporterImpl::folderAsString(const KBookmarkGroup &parent) const 0165 { 0166 QString str; 0167 QTextStream fstream(&str, QIODevice::WriteOnly); 0168 0169 for (KBookmark bk = parent.first(); !bk.isNull(); bk = parent.next(bk)) { 0170 if (bk.isSeparator()) { 0171 fstream << "<HR>\n"; 0172 fstream.flush(); 0173 continue; 0174 } 0175 0176 QString text = bk.fullText().toHtmlEscaped(); 0177 0178 if (bk.isGroup()) { 0179 fstream << "<DT><H3 " << (!bk.toGroup().isOpen() ? "FOLDED " : "") << bk.internalElement().attribute(QStringLiteral("netscapeinfo")) << ">" << text 0180 << "</H3>\n" 0181 << "<DL><P>\n" 0182 << folderAsString(bk.toGroup()) << "</DL><P>\n"; 0183 fstream.flush(); 0184 continue; 0185 0186 } else { 0187 // note - netscape seems to use local8bit for url... 0188 fstream << "<DT><A HREF=\"" << bk.url().toString() << "\"" << bk.internalElement().attribute(QStringLiteral("netscapeinfo")) << ">" << text 0189 << "</A>\n"; 0190 fstream.flush(); 0191 continue; 0192 } 0193 } 0194 0195 return str; 0196 } 0197 0198 //// 0199 0200 #include "moc_kbookmarkimporter_ns.cpp"