Git commit 050ee10c64bbeb92d8df1d6af228053e2d26d707 by Montel Laurent. Committed on 02/04/2016 at 17:28. Pushed by mlaurent into branch 'master'.
Remove nntp too M +0 -1 kioslave/docs/CMakeLists.txt D +0 -3 kioslave/docs/nntp/CMakeLists.txt D +0 -48 kioslave/docs/nntp/index.docbook M +0 -1 kioslave/src/CMakeLists.txt D +0 -22 kioslave/src/nntp/CMakeLists.txt D +0 -16 kioslave/src/nntp/LICENSE D +0 -1 kioslave/src/nntp/Mainpage.dox D +0 -2 kioslave/src/nntp/Messages.sh D +0 -1043 kioslave/src/nntp/nntp.cpp D +0 -148 kioslave/src/nntp/nntp.h D +0 -11 kioslave/src/nntp/nntp.protocol D +0 -11 kioslave/src/nntp/nntps.protocol http://commits.kde.org/kdepimlibs/050ee10c64bbeb92d8df1d6af228053e2d26d707 diff --git a/kioslave/docs/CMakeLists.txt b/kioslave/docs/CMakeLists.txt index 87b341a..e61902c 100644 --- a/kioslave/docs/CMakeLists.txt +++ b/kioslave/docs/CMakeLists.txt @@ -1,6 +1,5 @@ add_subdirectory(imap) add_subdirectory(ldap) -add_subdirectory(nntp) add_subdirectory(pop3) add_subdirectory(smtp) add_subdirectory(sieve) diff --git a/kioslave/docs/nntp/CMakeLists.txt b/kioslave/docs/nntp/CMakeLists.txt deleted file mode 100644 index e7d671b..0000000 --- a/kioslave/docs/nntp/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -########### install files ############### -kdoctools_create_handbook(index.docbook INSTALL_DESTINATION ${KDE_INSTALL_DOCBUNDLEDIR}/en SUBDIR kioslave5/nntp) - diff --git a/kioslave/docs/nntp/index.docbook b/kioslave/docs/nntp/index.docbook deleted file mode 100644 index 535fa9b..0000000 --- a/kioslave/docs/nntp/index.docbook +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE article PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN" -"dtd/kdedbx45.dtd" [ -<!ENTITY % addindex "IGNORE"> -<!ENTITY % English "INCLUDE" > <!-- change language only here --> -]> - -<article lang="&language;" id="nntp"> -<title>nntp</title> -<articleinfo> -<authorgroup> -<author>&Lauri.Watts; &Lauri.Watts.mail;</author> -<!-- TRANS:ROLES_OF_TRANSLATORS --> -</authorgroup> -</articleinfo> -<para>The nntp kioslave accesses <acronym>NNTP</acronym> servers -directly.</para> - -<para>This kioslave can not be used with servers that do not implement -the <command>GROUP</command> command, including some versions of the -popular <application>INN</application> news server which is often used -by <acronym>ISP</acronym>s. It does work with -<application>leafnode</application>, which many people use to keep an -offline cache of news articles on their own hard drive or within their -<acronym>LAN</acronym>.</para> - -<para>You can use the nntp kioslave by typing -<userinput>nntp://yourserver/groupname</userinput> into the &konqueror; -<acronym>URL</acronym> bar.</para> - -<para>If you enter a group name, as above, and the group is available, -you will see the messages stored for that group as icons in -&konqueror;.</para> - -<para>Clicking on a message will display it as plain text, including all -headers. This could be useful for debugging a news client to news -server connection, for example, to ensure that your new -<application>leafnode</application> server is working correctly.</para> - -<para>If you don't enter a group name, and only the server name, you -will see a list of available groups. </para> - -<para>Please be aware that this could take an enormous amount of time, and -will cause a lot of network traffic. Some commercial usenet servers -have 60,000 or more groups available, and doing such a thing may -cause your desktop to freeze.</para> - -</article> diff --git a/kioslave/src/CMakeLists.txt b/kioslave/src/CMakeLists.txt index de3ea2c..b630c8f 100644 --- a/kioslave/src/CMakeLists.txt +++ b/kioslave/src/CMakeLists.txt @@ -1,7 +1,6 @@ #remove it remove_definitions(-DQT_NO_CAST_FROM_BYTEARRAY) add_subdirectory(ldap) -add_subdirectory(nntp) add_subdirectory(sieve) add_subdirectory(smtp) diff --git a/kioslave/src/nntp/CMakeLists.txt b/kioslave/src/nntp/CMakeLists.txt deleted file mode 100644 index 7b0e8a0..0000000 --- a/kioslave/src/nntp/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ - - - - -########### next target ############### - -set(kio_nntp_PART_SRCS nntp.cpp ) - - -add_library(kio_nntp MODULE ${kio_nntp_PART_SRCS}) - - -target_link_libraries(kio_nntp KF5::KIOCore KF5::I18n) -set_target_properties(kio_nntp PROPERTIES OUTPUT_NAME "nntp") - -install(TARGETS kio_nntp DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf5/kio/ ) - - -########### install files ############### - -install( FILES nntp.protocol nntps.protocol DESTINATION ${KDE_INSTALL_KSERVICES5DIR} ) - diff --git a/kioslave/src/nntp/LICENSE b/kioslave/src/nntp/LICENSE deleted file mode 100644 index d28a48f..0000000 --- a/kioslave/src/nntp/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/kioslave/src/nntp/Mainpage.dox b/kioslave/src/nntp/Mainpage.dox deleted file mode 100644 index 57b7f27..0000000 --- a/kioslave/src/nntp/Mainpage.dox +++ /dev/null @@ -1 +0,0 @@ -// DOXYGEN_REFERENCES = kdecore kdeui kio diff --git a/kioslave/src/nntp/Messages.sh b/kioslave/src/nntp/Messages.sh deleted file mode 100644 index c778166..0000000 --- a/kioslave/src/nntp/Messages.sh +++ /dev/null @@ -1,2 +0,0 @@ -#! /usr/bin/env bash -$XGETTEXT *.cpp -o $podir/kio_nntp.pot diff --git a/kioslave/src/nntp/nntp.cpp b/kioslave/src/nntp/nntp.cpp deleted file mode 100644 index f76dcc2..0000000 --- a/kioslave/src/nntp/nntp.cpp +++ /dev/null @@ -1,1043 +0,0 @@ -/* This file is part of KDE - Copyright (C) 2000 by Wolfram Diestel <wolf...@steloj.de> - Copyright (C) 2005 by Tim Way <t...@way.hrcoxmail.com> - Copyright (C) 2005 by Volker Krause <vkra...@kde.org> - - This is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. -*/ - -#include "nntp.h" - -#include <sys/stat.h> -#include <stdio.h> -#include <cmath> -#include <QUrl> - -#include <QDir> -#include <QHash> -#include <QRegExp> -#include <QUrlQuery> -#include <KLocalizedString> -#include <QCoreApplication> -#include <QDataStream> - -#include <kio/ioslave_defaults.h> - -#define DBG_AREA 7114 -//#define DBG kDebug(DBG_AREA) -#define DBG qDebug() - -#undef ERR -//#define ERR kError(DBG_AREA) -#define ERR qCritical() - -using namespace KIO; - -extern "C" { - int Q_DECL_EXPORT kdemain(int argc, char **argv); -} - -int kdemain(int argc, char **argv) -{ - QCoreApplication app(argc, argv); // needed for QSocketNotifier - app.setApplicationName(QStringLiteral("kio_nntp")); - - if (argc != 4) { - fprintf(stderr, "Usage: kio_nntp protocol domain-socket1 domain-socket2\n"); - exit(-1); - } - - NNTPProtocol *slave; - - // Are we going to use SSL? - if (strcasecmp(argv[1], "nntps") == 0) { - slave = new NNTPProtocol(argv[2], argv[3], true); - } else { - slave = new NNTPProtocol(argv[2], argv[3], false); - } - - slave->dispatchLoop(); - delete slave; - - return 0; -} - -/****************** NNTPProtocol ************************/ - -NNTPProtocol::NNTPProtocol(const QByteArray &pool, const QByteArray &app, bool isSSL) - : TCPSlaveBase((isSSL ? "nntps" : "nntp"), pool, app, isSSL) - , isAuthenticated(false) -{ - DBG << "=============> NNTPProtocol::NNTPProtocol"; - - readBufferLen = 0; - m_defaultPort = isSSL ? DEFAULT_NNTPS_PORT : DEFAULT_NNTP_PORT; - m_port = m_defaultPort; -} - -NNTPProtocol::~NNTPProtocol() -{ - DBG << "<============= NNTPProtocol::~NNTPProtocol"; - - // close connection - nntp_close(); -} - -void NNTPProtocol::setHost(const QString &host, quint16 port, const QString &user, - const QString &pass) -{ - DBG << (! user.isEmpty() ? (user + QLatin1Char('@')) : QStringLiteral("")) - << host << ":" << ((port == 0) ? m_defaultPort : port); - - if (isConnected() && (mHost != host || m_port != port || - mUser != user || mPass != pass)) { - nntp_close(); - } - - mHost = host; - m_port = ((port == 0) ? m_defaultPort : port); - mUser = user; - mPass = pass; -} - -void NNTPProtocol::get(const QUrl &url) -{ - DBG << url.toDisplayString(); - QString path = QDir::cleanPath(url.path()); - - // path should be like: /group/<msg_id> or /group/<serial number> - if (path.startsWith(QLatin1Char('/'))) { - path.remove(0, 1); - } - int pos = path.indexOf(QLatin1Char('/')); - QString group; - QString msg_id; - if (pos > 0) { - group = path.left(pos); - msg_id = path.mid(pos + 1); - } - - if (group.isEmpty() || msg_id.isEmpty()) { - error(ERR_DOES_NOT_EXIST, path); - return; - } - - int res_code; - DBG << "group:" << group << "msg:" << msg_id; - - if (!nntp_open()) { - return; - } - - // select group if necessary - if (mCurrentGroup != group && !group.isEmpty()) { - infoMessage(i18n("Selecting group %1...", group)); - res_code = sendCommand(QLatin1String("GROUP ") + group); - if (res_code == 411) { - error(ERR_DOES_NOT_EXIST, path); - mCurrentGroup.clear(); - return; - } else if (res_code != 211) { - unexpected_response(res_code, QStringLiteral("GROUP")); - mCurrentGroup.clear(); - return; - } - mCurrentGroup = group; - } - - // get article - infoMessage(i18n("Downloading article...")); - res_code = sendCommand(QLatin1String("ARTICLE ") + msg_id); - if (res_code == 423 || res_code == 430) { - error(ERR_DOES_NOT_EXIST, path); - return; - } else if (res_code != 220) { - unexpected_response(res_code, QStringLiteral("ARTICLE")); - return; - } - - // read and send data - char tmp[MAX_PACKET_LEN]; - while (true) { - if (!waitForResponse(readTimeout())) { - error(ERR_SERVER_TIMEOUT, mHost); - nntp_close(); - return; - } - int len = readLine(tmp, MAX_PACKET_LEN); - const char *buffer = tmp; - if (len <= 0) { - break; - } - if (len == 3 && tmp[0] == '.' && tmp[1] == '\r' && tmp[2] == '\n') { - break; - } - if (len > 1 && tmp[0] == '.' && tmp[1] == '.') { - ++buffer; - --len; - } - data(QByteArray::fromRawData(buffer, len)); - } - - // end of data - data(QByteArray()); - - // finish - finished(); -} - -void NNTPProtocol::put(const QUrl &url, int permissions, KIO::JobFlags flags) -{ - if (!nntp_open()) { - return; - } - if (post_article()) { - finished(); - } -} - -void NNTPProtocol::special(const QByteArray &data) -{ - // 1 = post article - int cmd; - QDataStream stream(data); - - if (!nntp_open()) { - return; - } - - stream >> cmd; - if (cmd == 1) { - if (post_article()) { - finished(); - } - } else { - error(ERR_UNSUPPORTED_ACTION, i18n("Invalid special command %1", cmd)); - } -} - -bool NNTPProtocol::post_article() -{ - DBG; - - // send post command - infoMessage(i18n("Sending article...")); - int res_code = sendCommand(QStringLiteral("POST")); - if (res_code == 440) { // posting not allowed - error(ERR_WRITE_ACCESS_DENIED, mHost); - return false; - } else if (res_code != 340) { // 340: ok, send article - unexpected_response(res_code, QStringLiteral("POST")); - return false; - } - - // send article now - int result; - bool last_chunk_had_line_ending = true; - do { - QByteArray buffer; - dataReq(); - result = readData(buffer); - DBG << "receiving data:" << buffer; - // treat the buffer data - if (result > 0) { - // translate "\r\n." to "\r\n.." - int pos = 0; - if (last_chunk_had_line_ending && buffer[0] == '.') { - buffer.insert(0, '.'); - pos += 2; - } - last_chunk_had_line_ending = (buffer.endsWith("\r\n")); //krazy:exclude=strings - while ((pos = buffer.indexOf("\r\n.", pos)) > 0) { - buffer.insert(pos + 2, '.'); - pos += 4; - } - - // send data to socket, write() doesn't send the terminating 0 - write(buffer, buffer.length()); - DBG << "writing:" << buffer; - } - } while (result > 0); - - // error occurred? - if (result < 0) { - ERR << "error while getting article data for posting"; - nntp_close(); - return false; - } - - // send end mark - write("\r\n.\r\n", 5); - - // get answer - res_code = evalResponse(readBuffer, readBufferLen); - if (res_code == 441) { // posting failed - error(ERR_COULD_NOT_WRITE, mHost); - return false; - } else if (res_code != 240) { - unexpected_response(res_code, QStringLiteral("POST")); - return false; - } - - return true; -} - -void NNTPProtocol::stat(const QUrl &url) -{ - DBG << url.toDisplayString(); - UDSEntry entry; - QString path = QDir::cleanPath(url.path()); - QRegExp regGroup = QRegExp(QStringLiteral("^\\/?[a-z0-9\\.\\-_]+\\/?$"), Qt::CaseInsensitive); - QRegExp regMsgId = QRegExp(QStringLiteral("^\\/?[a-z0-9\\.\\-_]+\\/<\\S+>$"), Qt::CaseInsensitive); - int pos; - QString group; - QString msg_id; - - // / = group list - if (path.isEmpty() || path == QLatin1String("/")) { - DBG << "root"; - fillUDSEntry(entry, QString(), 0, false, (S_IWUSR | S_IWGRP | S_IWOTH)); - - // /group = message list - } else if (regGroup.indexIn(path) == 0) { - if (path.startsWith(QLatin1Char('/'))) { - path.remove(0, 1); - } - if ((pos = path.indexOf(QLatin1Char('/'))) > 0) { - group = path.left(pos); - } else { - group = path; - } - DBG << "group:" << group; - // postingAllowed should be ored here with "group not moderated" flag - // as size the num of messages (GROUP cmd) could be given - fillUDSEntry(entry, group, 0, false, (S_IWUSR | S_IWGRP | S_IWOTH)); - - // /group/<msg_id> = message - } else if (regMsgId.indexIn(path) == 0) { - pos = path.indexOf(QLatin1Char('<')); - group = path.left(pos); - msg_id = QUrl::fromPercentEncoding(path.right(path.length() - pos).toLatin1()); - if (group.startsWith(QLatin1Char('/'))) { - group.remove(0, 1); - } - if ((pos = group.indexOf(QLatin1Char('/'))) > 0) { - group = group.left(pos); - } - DBG << "group:" << group << "msg:" << msg_id; - fillUDSEntry(entry, msg_id, 0, true); - - // invalid url - } else { - error(ERR_DOES_NOT_EXIST, path); - return; - } - - statEntry(entry); - finished(); -} - -void NNTPProtocol::listDir(const QUrl &url) -{ - DBG << url.toDisplayString(); - if (!nntp_open()) { - return; - } - - QString path = QDir::cleanPath(url.path()); - - if (path.isEmpty()) { - QUrl newURL(url); - newURL.setPath(QStringLiteral("/")); - DBG << "redirecting to" << newURL.toDisplayString(); - redirection(newURL); - finished(); - return; - } else if (path == QLatin1String("/")) { - QUrl newUrl(url); - fetchGroups(QUrlQuery(newUrl).queryItemValue(QStringLiteral("since")), QUrlQuery(newUrl).queryItemValue(QStringLiteral("desc")) == QLatin1String("true")); - finished(); - } else { - // if path = /group - int pos; - QString group; - if (path.startsWith(QLatin1Char('/'))) { - path.remove(0, 1); - } - if ((pos = path.indexOf(QLatin1Char('/'))) > 0) { - group = path.left(pos); - } else { - group = path; - } - QUrl newUrl(url); - QString first = QUrlQuery(newUrl).queryItemValue(QStringLiteral("first")); - QString max = QUrlQuery(newUrl).queryItemValue(QStringLiteral("max")); - if (fetchGroup(group, first.toULong(), max.toULong())) { - finished(); - } - } -} - -void NNTPProtocol::fetchGroups(const QString &since, bool desc) -{ - int expected; - int res; - if (since.isEmpty()) { - // full listing - infoMessage(i18n("Downloading group list...")); - res = sendCommand(QStringLiteral("LIST")); - expected = 215; - } else { - // incremental listing - infoMessage(i18n("Looking for new groups...")); - res = sendCommand(QLatin1String("NEWGROUPS ") + since); - expected = 231; - } - if (res != expected) { - unexpected_response(res, QStringLiteral("LIST")); - return; - } - - // read newsgroups line by line - QByteArray line; - QString group; - int pos, pos2; - long msg_cnt; - long access; - UDSEntry entry; - QHash<QString, UDSEntry> entryMap; - - // read in data and process each group. one line at a time - while (true) { - if (! waitForResponse(readTimeout())) { - error(ERR_SERVER_TIMEOUT, mHost); - nntp_close(); - return; - } - readBufferLen = readLine(readBuffer, MAX_PACKET_LEN); - line = QByteArray(readBuffer, readBufferLen); - if (line == ".\r\n") { - break; - } - - // group name - if ((pos = line.indexOf(' ')) > 0) { - - group = QLatin1String(line.left(pos)); - - // number of messages - line.remove(0, pos + 1); - long last = 0; - access = 0; - if (((pos = line.indexOf(' ')) > 0 || (pos = line.indexOf('\t')) > 0) && - ((pos2 = line.indexOf(' ', pos + 1)) > 0 || (pos2 = line.indexOf('\t', pos + 1)) > 0)) { - last = line.left(pos).toLongLong(); - long first = line.mid(pos + 1, pos2 - pos - 1).toLongLong(); - msg_cnt = std::abs(last - first + 1); - // group access rights - switch (line[pos2 + 1]) { - case 'n': - access = 0; - break; - case 'm': - access = S_IWUSR | S_IWGRP; - break; - case 'y': - access = S_IWUSR | S_IWGRP | S_IWOTH; - break; - } - } else { - msg_cnt = 0; - } - - entry.clear(); - fillUDSEntry(entry, group, msg_cnt, false, access); - if (!desc) { - listEntry(entry); - } else { - entryMap.insert(group, entry); - } - } - } - - // handle group descriptions - QHash<QString, UDSEntry>::Iterator it = entryMap.begin(); - if (desc) { - infoMessage(i18n("Downloading group descriptions...")); - totalSize(entryMap.size()); - } - while (desc) { - // request all group descriptions - if (since.isEmpty()) { - res = sendCommand(QStringLiteral("LIST NEWSGROUPS")); - } else { - // request only descriptions for new groups - if (it == entryMap.end()) { - break; - } - res = sendCommand(QLatin1String("LIST NEWSGROUPS ") + it.key()); - ++it; - if (res == 503) { - // Information not available (RFC 2980 ยง2.1.6), try next group - continue; - } - } - if (res != 215) { - // No group description available or not implemented - break; - } - - // download group descriptions - while (true) { - if (! waitForResponse(readTimeout())) { - error(ERR_SERVER_TIMEOUT, mHost); - nntp_close(); - return; - } - readBufferLen = readLine(readBuffer, MAX_PACKET_LEN); - line = QByteArray(readBuffer, readBufferLen); - if (line == ".\r\n") { - break; - } - - //DBG << " fetching group description: " << QString( line ).trimmed(); - int pos = line.indexOf(' '); - pos = pos < 0 ? line.indexOf('\t') : qMin(pos, line.indexOf('\t')); - group = QLatin1String(line.left(pos)); - QString groupDesc = QLatin1String(line.right(line.length() - pos).trimmed()); - - if (entryMap.contains(group)) { - entry = entryMap.take(group); - entry.insert(KIO::UDSEntry::UDS_EXTRA, groupDesc); - listEntry(entry); - } - } - - if (since.isEmpty()) { - break; - } - } - // take care of groups without descriptions - for (QHash<QString, UDSEntry>::Iterator it = entryMap.begin(); it != entryMap.end(); ++it) { - listEntry(it.value()); - } - - entry.clear(); - finished(); -} - -bool NNTPProtocol::fetchGroup(QString &group, unsigned long first, unsigned long max) -{ - int res_code; - QString resp_line; - - // select group - infoMessage(i18n("Selecting group %1...", group)); - res_code = sendCommand(QLatin1String("GROUP ") + group); - if (res_code == 411) { - error(ERR_DOES_NOT_EXIST, group); - mCurrentGroup.clear(); - return false; - } else if (res_code != 211) { - unexpected_response(res_code, QStringLiteral("GROUP")); - mCurrentGroup.clear(); - return false; - } - mCurrentGroup = group; - - // repsonse to "GROUP <requested-group>" command is 211 then find the message count (cnt) - // and the first and last message followed by the group name - unsigned long firstSerNum, lastSerNum; - resp_line = QString::fromLatin1(readBuffer); - QRegExp re(QStringLiteral("211\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)")); - if (re.indexIn(resp_line) != -1) { - firstSerNum = re.cap(2).toLong(); - lastSerNum = re.cap(3).toLong(); - } else { - error(ERR_INTERNAL, i18n("Could not extract message serial numbers from server response:\n%1", - resp_line)); - return false; - } - - if (firstSerNum == 0) { - return true; - } - first = qMax(first, firstSerNum); - if (lastSerNum < first) { // No need to fetch anything - // note: this also ensure that "lastSerNum - first" is not negative - // in the next test (in "unsigned long" computation this leads to an overflow - return true; - } - if (max > 0 && lastSerNum - first > max) { - first = lastSerNum - max + 1; - } - - DBG << "Starting from serial number: " << first << " of " << firstSerNum << " - " << lastSerNum; - setMetaData(QStringLiteral("FirstSerialNumber"), QString::number(firstSerNum)); - setMetaData(QStringLiteral("LastSerialNumber"), QString::number(lastSerNum)); - - infoMessage(i18n("Downloading new headers...")); - totalSize(lastSerNum - first); - bool notSupported = true; - if (fetchGroupXOVER(first, notSupported)) { - return true; - } else if (notSupported) { - return fetchGroupRFC977(first); - } - return false; -} - -bool NNTPProtocol::fetchGroupRFC977(unsigned long first) -{ - UDSEntry entry; - - // set article pointer to first article and get msg-id of it - int res_code = sendCommand(QLatin1String("STAT ") + QString::number(first)); - QString resp_line = QLatin1String(readBuffer); - if (res_code != 223) { - unexpected_response(res_code, QStringLiteral("STAT")); - return false; - } - - //STAT res_line: 223 nnn <msg_id> ... - QString msg_id; - int pos, pos2; - if ((pos = resp_line.indexOf(QLatin1Char('<'))) > 0 && (pos2 = resp_line.indexOf(QLatin1Char('>'), pos + 1))) { - msg_id = resp_line.mid(pos, pos2 - pos + 1); - fillUDSEntry(entry, msg_id, 0, true); - listEntry(entry); - } else { - error(ERR_INTERNAL, i18n("Could not extract first message id from server response:\n%1", - resp_line)); - return false; - } - - // go through all articles - while (true) { - res_code = sendCommand(QStringLiteral("NEXT")); - if (res_code == 421) { - // last artice reached - entry.clear(); - finished(); - return true; - } else if (res_code != 223) { - unexpected_response(res_code, QStringLiteral("NEXT")); - return false; - } - - //res_line: 223 nnn <msg_id> ... - resp_line = QLatin1String(readBuffer); - if ((pos = resp_line.indexOf(QLatin1Char('<'))) > 0 && (pos2 = resp_line.indexOf(QLatin1Char('>'), pos + 1))) { - msg_id = resp_line.mid(pos, pos2 - pos + 1); - entry.clear(); - fillUDSEntry(entry, msg_id, 0, true); - listEntry(entry); - } else { - error(ERR_INTERNAL, i18n("Could not extract message id from server response:\n%1", - resp_line)); - return false; - } - } - return true; // Not reached -} - -bool NNTPProtocol::fetchGroupXOVER(unsigned long first, bool ¬Supported) -{ - notSupported = false; - - QString line; - QStringList headers; - - int res = sendCommand(QStringLiteral("LIST OVERVIEW.FMT")); - if (res == 215) { - while (true) { - if (! waitForResponse(readTimeout())) { - error(ERR_SERVER_TIMEOUT, mHost); - nntp_close(); - return false; - } - readBufferLen = readLine(readBuffer, MAX_PACKET_LEN); - line = QString::fromLatin1(readBuffer, readBufferLen); - if (line == QLatin1String(".\r\n")) { - break; - } - headers << line.trimmed(); - DBG << "OVERVIEW.FMT:" << line.trimmed(); - } - } else { - // fallback to defaults - headers << QStringLiteral("Subject:") << QStringLiteral("From:") << QStringLiteral("Date:") << QStringLiteral("Message-ID:") - << QStringLiteral("References:") << QStringLiteral("Bytes:") << QStringLiteral("Lines:"); - } - - res = sendCommand(QLatin1String("XOVER ") + QString::number(first) + QLatin1Char('-')); - if (res == 420) { - return true; // no articles selected - } - if (res == 500) { - notSupported = true; // unknwon command - } - if (res != 224) { - unexpected_response(res, QStringLiteral("XOVER")); - return false; - } - - long msgSize; - QString name; - UDSEntry entry; - int udsType; - - QStringList fields; - while (true) { - if (! waitForResponse(readTimeout())) { - error(ERR_SERVER_TIMEOUT, mHost); - nntp_close(); - return false; - } - readBufferLen = readLine(readBuffer, MAX_PACKET_LEN); - line = QString::fromLatin1(readBuffer, readBufferLen); - if (line == QLatin1String(".\r\n")) { - entry.clear(); - finished(); - return true; - } - - fields = line.split(QLatin1Char('\t'), QString::KeepEmptyParts); - msgSize = 0; - entry.clear(); - udsType = KIO::UDSEntry::UDS_EXTRA; - QStringList::ConstIterator it = headers.constBegin(); - QStringList::ConstIterator it2 = fields.constBegin(); - // first entry is the serial number - name = (*it2); - ++it2; - for (; it != headers.constEnd() && it2 != fields.constEnd(); ++it, ++it2) { - if ((*it) == QLatin1String("Bytes:")) { - msgSize = (*it2).toLong(); - continue; - } - QString atomStr; - if ((*it).endsWith(QLatin1String("full"))) { - if ((*it2).trimmed().isEmpty()) { - atomStr = (*it).left((*it).indexOf(QLatin1Char(':')) + 1); // strip of the 'full' suffix - } else { - atomStr = (*it2).trimmed(); - } - } else { - atomStr = (*it) + QLatin1Char(' ') + (*it2).trimmed(); - } - entry.insert(udsType++, atomStr); - if (udsType >= KIO::UDSEntry::UDS_EXTRA_END) { - break; - } - } - fillUDSEntry(entry, name, msgSize, true); - listEntry(entry); - } - return true; // not reached -} - -void NNTPProtocol::fillUDSEntry(UDSEntry &entry, const QString &name, long size, - bool is_article, long access) -{ - - long posting = 0; - - // entry name - entry.insert(KIO::UDSEntry::UDS_NAME, name); - - // entry size - entry.insert(KIO::UDSEntry::UDS_SIZE, size); - - // file type - entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, is_article ? S_IFREG : S_IFDIR); - - // access permissions - posting = postingAllowed ? access : 0; - long long accessVal = (is_article) ? (S_IRUSR | S_IRGRP | S_IROTH) : - (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH | posting); - entry.insert(KIO::UDSEntry::UDS_ACCESS, accessVal); - - entry.insert(KIO::UDSEntry::UDS_USER, mUser.isEmpty() ? QStringLiteral("root") : mUser); - - /* - entry->insert(UDS_GROUP, QString::fromLatin1("root")); - */ - - // MIME type - if (is_article) { - entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("message/news")); - } -} - -void NNTPProtocol::nntp_close() -{ - if (isConnected()) { - write("QUIT\r\n", 6); - disconnectFromHost(); - isAuthenticated = false; - } - mCurrentGroup.clear(); -} - -bool NNTPProtocol::nntp_open() -{ - // if still connected reuse connection - if (isConnected()) { - DBG << "reusing old connection"; - return true; - } - - DBG << " nntp_open -- creating a new connection to" << mHost << ":" << m_port; - // create a new connection (connectToHost() includes error handling) - infoMessage(i18n("Connecting to server...")); - if (connectToHost((isAutoSsl() ? QStringLiteral("nntps") : QStringLiteral("nntp")), mHost, m_port)) { - DBG << " nntp_open -- connection is open"; - - // read greeting - int res_code = evalResponse(readBuffer, readBufferLen); - - /* expect one of - 200 server ready - posting allowed - 201 server ready - no posting allowed - */ - if (!(res_code == 200 || res_code == 201)) { - unexpected_response(res_code, QStringLiteral("CONNECT")); - return false; - } - - DBG << " nntp_open -- greating was read res_code :" << res_code; - - res_code = sendCommand(QStringLiteral("MODE READER")); - - // TODO: not in RFC 977, so we should not abort here - if (!(res_code == 200 || res_code == 201)) { - unexpected_response(res_code, QStringLiteral("MODE READER")); - return false; - } - - // let local class know whether posting is allowed or not - postingAllowed = (res_code == 200); - - // activate TLS if requested - if (metaData(QStringLiteral("tls")) == QLatin1String("on")) { - if (sendCommand(QStringLiteral("STARTTLS")) != 382) { - error(ERR_COULD_NOT_CONNECT, i18n("This server does not support TLS")); - return false; - } - if (!startSsl()) { - error(ERR_COULD_NOT_CONNECT, i18n("TLS negotiation failed")); - return false; - } - } - - // *try* to authenticate now (see bug#167718) - authenticate(); - - return true; - } - - return false; -} - -int NNTPProtocol::sendCommand(const QString &cmd) -{ - int res_code = 0; - - if (!nntp_open()) { - ERR << "NOT CONNECTED, cannot send cmd" << cmd; - return 0; - } - - DBG << "cmd:" << cmd; - - write(cmd.toLatin1(), cmd.length()); - // check the command for proper termination - if (!cmd.endsWith(QLatin1String("\r\n"))) { - write("\r\n", 2); - } - res_code = evalResponse(readBuffer, readBufferLen); - - // if authorization needed send user info - if (res_code == 480) { - DBG << "auth needed, sending user info"; - - if (mUser.isEmpty() || mPass.isEmpty()) { - KIO::AuthInfo authInfo; - authInfo.username = mUser; - authInfo.password = mPass; - if (openPasswordDialog(authInfo)) { - mUser = authInfo.username; - mPass = authInfo.password; - } - } - if (mUser.isEmpty() || mPass.isEmpty()) { - return res_code; - } - - res_code = authenticate(); - if (res_code != 281) { - // error should be handled by invoking function - return res_code; - } - - // ok now, resend command - write(cmd.toLatin1(), cmd.length()); - if (!cmd.endsWith(QLatin1String("\r\n"))) { - write("\r\n", 2); - } - res_code = evalResponse(readBuffer, readBufferLen); - } - - return res_code; -} - -int NNTPProtocol::authenticate() -{ - int res_code = 0; - - if (isAuthenticated) { - // already authenticated - return 281; - } - - if (mUser.isEmpty() || mPass.isEmpty()) { - return 281; // failsafe : maybe add a "relax" mode to optionally ask user/pwd. - } - - // send username to server and confirm response - write("AUTHINFO USER ", 14); - write(mUser.toLatin1(), mUser.length()); - write("\r\n", 2); - res_code = evalResponse(readBuffer, readBufferLen); - - if (res_code == 281) { - // no password needed (RFC 2980 3.1.1 does not required one) - return res_code; - } - if (res_code != 381) { - // error should be handled by invoking function - return res_code; - } - - // send password - write("AUTHINFO PASS ", 14); - write(mPass.toLatin1(), mPass.length()); - write("\r\n", 2); - res_code = evalResponse(readBuffer, readBufferLen); - - if (res_code == 281) { - isAuthenticated = true; - } - - return res_code; -} - -void NNTPProtocol::unexpected_response(int res_code, const QString &command) -{ - ERR << "Unexpected response to" << command << "command: (" << res_code << ")" - << readBuffer; - - // See RFC 3977 appendix C "Summary of Response Codes" - switch (res_code) { - case 205: // connection closed by the server: this can happens, e.g. if the session timeout on the server side - // Not the same thing, but use the same message as code 400 anyway. - case 400: // temporary issue on the server - error(ERR_INTERNAL_SERVER, - i18n("The server %1 could not handle your request.\n" - "Please try again now, or later if the problem persists.", mHost)); - break; - case 480: // credential request - error(ERR_COULD_NOT_LOGIN, - i18n("You need to authenticate to access the requested resource.")); - break; - case 481: // wrong credential (TODO: place a specific message for this case) - error(ERR_COULD_NOT_LOGIN, - i18n("The supplied login and/or password are incorrect.")); - break; - case 502: - error(ERR_ACCESS_DENIED, mHost); - break; - default: - error(ERR_INTERNAL, i18n("Unexpected server response to %1 command:\n%2", command, QLatin1String(readBuffer))); - } - - nntp_close(); -} - -int NNTPProtocol::evalResponse(char *data, ssize_t &len) -{ - if (!waitForResponse(responseTimeout())) { - error(ERR_SERVER_TIMEOUT, mHost); - nntp_close(); - return -1; - } - len = readLine(data, MAX_PACKET_LEN); - - if (len < 3) { - return -1; - } - - // get the first three characters. should be the response code - int respCode = ((data[0] - 48) * 100) + ((data[1] - 48) * 10) + ((data[2] - 48)); - - DBG << "got:" << respCode; - - return respCode; -} - -/* not really necessary, because the slave has to - use the KIO::Error's instead, but let this here for - documentation of the NNTP response codes and may - by later use. -QString NNTPProtocol::errorStr(int resp_code) { - QString ret; - - switch (resp_code) { - case 100: ret = "help text follows"; break; - case 199: ret = "debug output"; break; - - case 200: ret = "server ready - posting allowed"; break; - case 201: ret = "server ready - no posting allowed"; break; - case 202: ret = "slave status noted"; break; - case 205: ret = "closing connection - goodbye!"; break; - case 211: ret = "group selected"; break; - case 215: ret = "list of newsgroups follows"; break; - case 220: ret = "article retrieved - head and body follow"; break; - case 221: ret = "article retrieved - head follows"; break; - case 222: ret = "article retrieved - body follows"; break; - case 223: ret = "article retrieved - request text separately"; break; - case 230: ret = "list of new articles by message-id follows"; break; - case 231: ret = "list of new newsgroups follows"; break; - case 235: ret = "article transferred ok"; break; - case 240: ret = "article posted ok"; break; - - case 335: ret = "send article to be transferred"; break; - case 340: ret = "send article to be posted"; break; - - case 400: ret = "service discontinued"; break; - case 411: ret = "no such news group"; break; - case 412: ret = "no newsgroup has been selected"; break; - case 420: ret = "no current article has been selected"; break; - case 421: ret = "no next article in this group"; break; - case 422: ret = "no previous article in this group"; break; - case 423: ret = "no such article number in this group"; break; - case 430: ret = "no such article found"; break; - case 435: ret = "article not wanted - do not send it"; break; - case 436: ret = "transfer failed - try again later"; break; - case 437: ret = "article rejected - do not try again"; break; - case 440: ret = "posting not allowed"; break; - case 441: ret = "posting failed"; break; - - case 500: ret = "command not recognized"; break; - case 501: ret = "command syntax error"; break; - case 502: ret = "access restriction or permission denied"; break; - case 503: ret = "program fault - command not performed"; break; - default: ret = QString("unknown NNTP response code %1").arg(resp_code); - } - - return ret; -} -*/ diff --git a/kioslave/src/nntp/nntp.h b/kioslave/src/nntp/nntp.h deleted file mode 100644 index b21dd3a..0000000 --- a/kioslave/src/nntp/nntp.h +++ /dev/null @@ -1,148 +0,0 @@ -/* This file is part of KDE - Copyright (C) 2000 by Wolfram Diestel <wolf...@steloj.de> - Copyright (C) 2005 by Tim Way <t...@way.hrcoxmail.com> - Copyright (C) 2005 by Volker Krause <vkra...@kde.org> - - This is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. -*/ - -#ifndef _NNTP_H -#define _NNTP_H - -#include <kio/tcpslavebase.h> - -#define MAX_PACKET_LEN 8192 - -/* TODO: - - test special post command - - progress information in get, and maybe post - - remove unnecessary debug stuff -*/ -/** - @brief NNTP KIO slave - - @par References - - RFC 850: Standard for interchange of USENET messages - - RFC 2980: Common NNTP Extensions (updated by RFC 3977) - - RFC 3977: Network News Transfer Protocol - - RFC 4643: Network News Transfer Protocol (NNTP) Extension for Authentication -*/ -class NNTPProtocol : public KIO::TCPSlaveBase -{ - -public: - /** Default Constructor - * @param isSSL is a true or false to indicate whether ssl is to be used - */ - NNTPProtocol(const QByteArray &pool, const QByteArray &app, bool isSSL); - virtual ~NNTPProtocol(); - - void get(const QUrl &url) Q_DECL_OVERRIDE; - void put(const QUrl &url, int permissions, KIO::JobFlags flags) Q_DECL_OVERRIDE; - void stat(const QUrl &url) Q_DECL_OVERRIDE; - void listDir(const QUrl &url) Q_DECL_OVERRIDE; - virtual void setHost(const QString &host, quint16 port, - const QString &user, const QString &pass) Q_DECL_OVERRIDE; - - /** - * Special command: 1 = post article - * it takes no other args, the article data are - * requested by dataReq() and should be valid - * as in RFC850. It's not checked for correctness here. - * @param data the special command for article - * @deprecated use put() for posting - */ - void special(const QByteArray &data) Q_DECL_OVERRIDE; - -protected: - - /** - * Send a command to the server. Returns the response code and - * the response line - * @param cmd the command to send to server - */ - int sendCommand(const QString &cmd); - - /** - * Attempt to properly shut down the NNTP connection by sending - * "QUIT\r\n" before closing the socket. - */ - void nntp_close(); - - /** - * Attempt to initiate a NNTP connection via a TCP socket, if no existing - * connection could be reused. - */ - bool nntp_open(); - - /** - * Post article. Invoked by special() and put() - */ - bool post_article(); - -private: - QString mHost, mUser, mPass; - quint16 m_port, m_defaultPort; - bool postingAllowed, isAuthenticated; - char readBuffer[MAX_PACKET_LEN]; - ssize_t readBufferLen; - /// Current selected newsgroup - QString mCurrentGroup; - - /** - * Fetch all new groups since the given date or (if the date is empty) - * all available groups. - * @param since Date as specified in RFC 977 for the NEWGROUPS command - * @param desc Fetch group description (needs more memory) - */ - void fetchGroups(const QString &since, bool desc); - /** - * Fetch message listing from the given newsgroup. - * This will use RFC2980 XOVER if available, plain RFC977 STAT/NEXT - * otherwise. - * @param group The newsgroup name - * @param first Serial number of the first message, 0 lists all messages. - * @param max Maximal number of returned messages, 0 means unlimited. - * @return true on success, false otherwise. - */ - bool fetchGroup(QString &group, unsigned long first = 0, unsigned long max = 0); - /** - * Fetch message listing from the current group using RFC977 STAT/NEXT - * commands. - * @param first message number of the first article - * @return true on success, false otherwise. - */ - bool fetchGroupRFC977(unsigned long first); - /** - * Fetch message listing from the current group using the RFC2980 XOVER - * command. - * Additional headers provided by XOVER are added as UDS_EXTRA entries - * to the listing. - * @param first message number of the first article - * @param notSupported boolean reference to indicate if command failed - * due to missing XOVER support on the server. - * @return true on success, false otherwise - */ - bool fetchGroupXOVER(unsigned long first, bool ¬Supported); - /// creates an UDSEntry with file information used in stat and listDir - void fillUDSEntry(KIO::UDSEntry &entry, const QString &name, long size, - bool is_article, long access = 0); - /// error handling for unexpected responses - void unexpected_response(int res_code, const QString &command); - /** - * grabs the response line from the server. used after most send_cmd calls. max - * length for the returned string ( char *data ) is 4096 characters including - * the "\r\n" terminator. - */ - int evalResponse(char *data, ssize_t &len); - /** - * Try to authenticate to the server. - * @return the response code from the server if the mUser/mPassword - * are available; 281 (successful authentication) otherwise. - */ - int authenticate(); -}; - -#endif diff --git a/kioslave/src/nntp/nntp.protocol b/kioslave/src/nntp/nntp.protocol deleted file mode 100644 index 8406bbe..0000000 --- a/kioslave/src/nntp/nntp.protocol +++ /dev/null @@ -1,11 +0,0 @@ -[Protocol] -exec=kf5/kio/nntp -protocol=nntp -input=none -output=filesystem -listing=Name,Type,Size -reading=true -writing=true -deleting=false -X-DocPath=kioslave5/nntp/index.html -Icon=message-news diff --git a/kioslave/src/nntp/nntps.protocol b/kioslave/src/nntp/nntps.protocol deleted file mode 100644 index de6700c..0000000 --- a/kioslave/src/nntp/nntps.protocol +++ /dev/null @@ -1,11 +0,0 @@ -[Protocol] -exec=kf5/kio/nntp -protocol=nntps -input=none -output=filesystem -listing=Name,Type,Size -reading=true -writing=true -deleting=false -X-DocPath=kioslave5/nntp/index.html -Icon=message-news _______________________________________________ kde-doc-english mailing list kde-doc-english@kde.org https://mail.kde.org/mailman/listinfo/kde-doc-english