mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 10:22:48 +00:00
kioslave: reimplement ftp and sftp slaves via curl
the sftp KIO slave is in the kde-workspace repo and the module for finding libssh was for it. tested ftp and sftp - both work with user and password authentication as intended (in read-only mode, put() not implemented) Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
5064d34b04
commit
a5132853b0
15 changed files with 380 additions and 3203 deletions
|
@ -40,7 +40,6 @@ set(cmakeFiles
|
||||||
FindLibLZMA.cmake
|
FindLibLZMA.cmake
|
||||||
FindLIBPARTED.cmake
|
FindLIBPARTED.cmake
|
||||||
FindLibSpectre.cmake
|
FindLibSpectre.cmake
|
||||||
FindLibSSH.cmake
|
|
||||||
FindLibTorrent.cmake
|
FindLibTorrent.cmake
|
||||||
FindLibUSB.cmake
|
FindLibUSB.cmake
|
||||||
FindLightDM.cmake
|
FindLightDM.cmake
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
# Try to find LibSSH, once done this will define:
|
|
||||||
#
|
|
||||||
# LIBSSH_FOUND - system has LibSSH
|
|
||||||
# LIBSSH_INCLUDE_DIRS - the LibSSH include directory
|
|
||||||
# LIBSSH_LIBRARIES - the libraries needed to use LibSSH
|
|
||||||
# LIBSSH_DEFINITIONS - compiler switches required for using LibSSH
|
|
||||||
#
|
|
||||||
# Copyright (c) 2020 Ivailo Monev <xakepa10@gmail.com>
|
|
||||||
#
|
|
||||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
|
||||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
|
||||||
pkg_check_modules(PC_LIBSSH QUIET libssh)
|
|
||||||
|
|
||||||
set(LIBSSH_INCLUDE_DIR ${PC_LIBSSH_INCLUDE_DIRS})
|
|
||||||
set(LIBSSH_LIBRARIES ${PC_LIBSSH_LIBRARIES})
|
|
||||||
set(LIBSSH_VERSION ${PC_LIBSSH_VERSION})
|
|
||||||
set(LIBSSH_DEFINITIONS ${PC_LIBSSH_CFLAGS_OTHER})
|
|
||||||
|
|
||||||
if(NOT LIBSSH_INCLUDE_DIR OR NOT LIBSSH_LIBRARIES)
|
|
||||||
find_path(LIBSSH_INCLUDE_DIR
|
|
||||||
NAMES libssh/libssh.h
|
|
||||||
HINTS $ENV{LIBSSHDIR}/include
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(LIBSSH_LIBRARIES
|
|
||||||
NAMES ssh
|
|
||||||
HINTS $ENV{LIBSSHDIR}/lib
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(LibSSH
|
|
||||||
VERSION_VAR LIBSSH_VERSION
|
|
||||||
REQUIRED_VARS LIBSSH_LIBRARIES LIBSSH_INCLUDE_DIR
|
|
||||||
)
|
|
||||||
|
|
||||||
mark_as_advanced(LIBSSH_INCLUDE_DIR LIBSSH_LIBRARIES)
|
|
|
@ -65,7 +65,7 @@
|
||||||
7050 kio (KHTTP)
|
7050 kio (KHTTP)
|
||||||
7101 kio_file
|
7101 kio_file
|
||||||
7102 kio_ftp
|
7102 kio_ftp
|
||||||
7103 kio_http
|
7103 kio_curl
|
||||||
7104 kidletime
|
7104 kidletime
|
||||||
51003 kexiv2
|
51003 kexiv2
|
||||||
51004 kpasswdstore
|
51004 kpasswdstore
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
add_subdirectory( file )
|
add_subdirectory( file )
|
||||||
add_subdirectory( http )
|
add_subdirectory( curl )
|
||||||
add_subdirectory( ftp )
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
project(kioslave-http)
|
project(kioslave-curl)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${KDE4_KIO_INCLUDES}
|
${KDE4_KIO_INCLUDES}
|
||||||
|
@ -7,19 +7,19 @@ include_directories(
|
||||||
|
|
||||||
########### next target ###############
|
########### next target ###############
|
||||||
|
|
||||||
add_executable(kio_http http.cpp)
|
add_executable(kio_curl kio_curl.cpp)
|
||||||
|
|
||||||
target_link_libraries(kio_http
|
target_link_libraries(kio_curl
|
||||||
${CURL_LIBRARIES}
|
${CURL_LIBRARIES}
|
||||||
kdecore
|
kdecore
|
||||||
kio
|
kio
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS kio_http DESTINATION ${KDE4_LIBEXEC_INSTALL_DIR})
|
install(TARGETS kio_curl DESTINATION ${KDE4_LIBEXEC_INSTALL_DIR})
|
||||||
|
|
||||||
########### install files ###############
|
########### install files ###############
|
||||||
|
|
||||||
install(
|
install(
|
||||||
FILES http.protocol https.protocol
|
FILES http.protocol https.protocol ftp.protocol sftp.protocol
|
||||||
DESTINATION ${KDE4_SERVICES_INSTALL_DIR}
|
DESTINATION ${KDE4_SERVICES_INSTALL_DIR}
|
||||||
)
|
)
|
17
kioslave/curl/ftp.protocol
Normal file
17
kioslave/curl/ftp.protocol
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[Protocol]
|
||||||
|
exec=kio_curl
|
||||||
|
protocol=ftp
|
||||||
|
copyToFile=false
|
||||||
|
copyFromFile=false
|
||||||
|
listing=true
|
||||||
|
reading=true
|
||||||
|
writing=false
|
||||||
|
makedir=false
|
||||||
|
deleting=false
|
||||||
|
moving=false
|
||||||
|
ProxiedBy=http
|
||||||
|
Icon=folder-remote
|
||||||
|
maxInstances=20
|
||||||
|
maxInstancesPerHost=5
|
||||||
|
X-DocPath=kioslave/curl/index.html
|
||||||
|
Class=:internet
|
|
@ -1,11 +1,11 @@
|
||||||
[Protocol]
|
[Protocol]
|
||||||
exec=kio_http
|
exec=kio_curl
|
||||||
protocol=http
|
protocol=http
|
||||||
copyToFile=false
|
copyToFile=false
|
||||||
copyFromFile=false
|
copyFromFile=false
|
||||||
listing=false
|
listing=false
|
||||||
reading=true
|
reading=true
|
||||||
writing=true
|
writing=false
|
||||||
makedir=false
|
makedir=false
|
||||||
deleting=false
|
deleting=false
|
||||||
moving=false
|
moving=false
|
||||||
|
@ -15,5 +15,5 @@ maxInstances=20
|
||||||
maxInstancesPerHost=5
|
maxInstancesPerHost=5
|
||||||
defaultMimetype=application/octet-stream
|
defaultMimetype=application/octet-stream
|
||||||
determineMimetypeFromExtension=false
|
determineMimetypeFromExtension=false
|
||||||
X-DocPath=kioslave/http/index.html
|
X-DocPath=kioslave/curl/index.html
|
||||||
Class=:internet
|
Class=:internet
|
|
@ -1,11 +1,11 @@
|
||||||
[Protocol]
|
[Protocol]
|
||||||
exec=kio_http
|
exec=kio_curl
|
||||||
protocol=https
|
protocol=https
|
||||||
copyToFile=false
|
copyToFile=false
|
||||||
copyFromFile=false
|
copyFromFile=false
|
||||||
listing=false
|
listing=false
|
||||||
reading=true
|
reading=true
|
||||||
writing=true
|
writing=false
|
||||||
makedir=false
|
makedir=false
|
||||||
deleting=false
|
deleting=false
|
||||||
moving=false
|
moving=false
|
||||||
|
@ -15,5 +15,5 @@ maxInstances=20
|
||||||
maxInstancesPerHost=5
|
maxInstancesPerHost=5
|
||||||
defaultMimetype=application/octet-stream
|
defaultMimetype=application/octet-stream
|
||||||
determineMimetypeFromExtension=false
|
determineMimetypeFromExtension=false
|
||||||
X-DocPath=kioslave/http/index.html
|
X-DocPath=kioslave/curl/index.html
|
||||||
Class=:internet
|
Class=:internet
|
|
@ -16,17 +16,112 @@
|
||||||
Boston, MA 02110-1301, USA.
|
Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "http.h"
|
#include "kio_curl.h"
|
||||||
#include "kdebug.h"
|
|
||||||
#include "kcomponentdata.h"
|
#include "kcomponentdata.h"
|
||||||
|
#include "kmimetype.h"
|
||||||
|
#include "kdebug.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define KIO_CURL_ERROR(CODE) \
|
||||||
|
const QString curlerror = QString::fromAscii(curl_easy_strerror(CODE)); \
|
||||||
|
kWarning(7103) << "curl error" << curlerror; \
|
||||||
|
error(KIO::ERR_SLAVE_DEFINED, curlerror);
|
||||||
|
|
||||||
|
// for reference:
|
||||||
|
// https://linux.die.net/man/3/strmode
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc959
|
||||||
|
// https://curl.se/libcurl/c/pop3-stat.html
|
||||||
|
|
||||||
|
// TODO: what is the limit?
|
||||||
|
static const int filepathmax = 1024;
|
||||||
|
|
||||||
|
static inline int ftpUserModeFromChar(const char modechar, const int rmode, const int wmode, const int xmode)
|
||||||
|
{
|
||||||
|
mode_t result = 0;
|
||||||
|
switch (modechar) {
|
||||||
|
case '-': {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'r': {
|
||||||
|
result |= rmode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'w': {
|
||||||
|
result |= wmode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'x': {
|
||||||
|
result |= xmode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
kWarning(7103) << "Invalid FTP mode char" << modechar;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline mode_t ftpModeFromString(const char* modestring)
|
||||||
|
{
|
||||||
|
mode_t result = 0;
|
||||||
|
switch (modestring[0]) {
|
||||||
|
case '-': {
|
||||||
|
result |= S_IFREG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b': {
|
||||||
|
result |= S_IFBLK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'c': {
|
||||||
|
result |= S_IFCHR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'd': {
|
||||||
|
result |= S_IFDIR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'l': {
|
||||||
|
result |= S_IFLNK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'p': {
|
||||||
|
result |= S_IFIFO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's': {
|
||||||
|
result |= S_IFSOCK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
kWarning(7103) << "Invalid FTP mode string" << modestring;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result |= ftpUserModeFromChar(modestring[1], S_IRUSR, S_IWUSR, S_IXUSR);
|
||||||
|
result |= ftpUserModeFromChar(modestring[2], S_IRUSR, S_IWUSR, S_IXUSR);
|
||||||
|
result |= ftpUserModeFromChar(modestring[3], S_IRUSR, S_IWUSR, S_IXUSR);
|
||||||
|
|
||||||
|
result |= ftpUserModeFromChar(modestring[4], S_IRGRP, S_IWGRP, S_IXGRP);
|
||||||
|
result |= ftpUserModeFromChar(modestring[5], S_IRGRP, S_IWGRP, S_IXGRP);
|
||||||
|
result |= ftpUserModeFromChar(modestring[6], S_IRGRP, S_IWGRP, S_IXGRP);
|
||||||
|
|
||||||
|
result |= ftpUserModeFromChar(modestring[7], S_IROTH, S_IWOTH, S_IXOTH);
|
||||||
|
result |= ftpUserModeFromChar(modestring[8], S_IROTH, S_IWOTH, S_IXOTH);
|
||||||
|
result |= ftpUserModeFromChar(modestring[9], S_IROTH, S_IWOTH, S_IXOTH);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static inline QByteArray curlProxyBytes(const QString &proxy)
|
static inline QByteArray curlProxyBytes(const QString &proxy)
|
||||||
{
|
{
|
||||||
const KUrl proxyurl(proxy);
|
const KUrl proxyurl(proxy);
|
||||||
|
@ -171,68 +266,52 @@ static inline KIO::Error curlToKIOError(const CURLcode curlcode, CURL *curl)
|
||||||
|
|
||||||
size_t curlWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata)
|
size_t curlWriteCallback(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||||
{
|
{
|
||||||
HttpProtocol* httpprotocol = static_cast<HttpProtocol*>(userdata);
|
CurlProtocol* curlprotocol = static_cast<CurlProtocol*>(userdata);
|
||||||
if (!httpprotocol) {
|
if (!curlprotocol) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// size should always be 1
|
// size should always be 1
|
||||||
Q_ASSERT(size == 1);
|
Q_ASSERT(size == 1);
|
||||||
httpprotocol->slotData(ptr, nmemb);
|
curlprotocol->slotData(ptr, nmemb);
|
||||||
return nmemb;
|
return nmemb;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t curlReadCallback(char *ptr, size_t size, size_t nmemb, void *userdata)
|
|
||||||
{
|
|
||||||
HttpProtocol* httpprotocol = static_cast<HttpProtocol*>(userdata);
|
|
||||||
if (!httpprotocol) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
httpprotocol->dataReq();
|
|
||||||
QByteArray kioreadbuffer;
|
|
||||||
const int kioreadresult = httpprotocol->readData(kioreadbuffer);
|
|
||||||
if (kioreadbuffer.size() > nmemb) {
|
|
||||||
kWarning(7103) << "Request data size larger than the buffer size";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
::memcpy(ptr, kioreadbuffer.constData(), kioreadbuffer.size() * sizeof(char));
|
|
||||||
return kioreadresult;
|
|
||||||
}
|
|
||||||
|
|
||||||
int curlXFERCallback(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
int curlXFERCallback(void *userdata, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
||||||
{
|
{
|
||||||
HttpProtocol* httpprotocol = static_cast<HttpProtocol*>(userdata);
|
CurlProtocol* curlprotocol = static_cast<CurlProtocol*>(userdata);
|
||||||
if (!httpprotocol) {
|
if (!curlprotocol) {
|
||||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
}
|
}
|
||||||
if (httpprotocol->aborttransfer) {
|
if (curlprotocol->aborttransfer) {
|
||||||
return CURLE_HTTP_RETURNED_ERROR;
|
return CURLE_HTTP_RETURNED_ERROR;
|
||||||
}
|
}
|
||||||
httpprotocol->slotProgress(KIO::filesize_t(dlnow), KIO::filesize_t(dltotal));
|
curlprotocol->slotProgress(KIO::filesize_t(dlnow), KIO::filesize_t(dltotal));
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
KComponentData componentData("kio_http", "kdelibs4");
|
KComponentData componentData("kio_curl", "kdelibs4");
|
||||||
|
|
||||||
kDebug(7103) << "Starting" << ::getpid();
|
kDebug(7103) << "Starting" << ::getpid();
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
::fprintf(stderr, "Usage: kio_http app-socket\n");
|
::fprintf(stderr, "Usage: kio_curl app-socket\n");
|
||||||
::exit(-1);
|
::exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpProtocol slave(argv[1]);
|
CurlProtocol slave(argv[1]);
|
||||||
slave.dispatchLoop();
|
slave.dispatchLoop();
|
||||||
|
|
||||||
kDebug(7103) << "Done";
|
kDebug(7103) << "Done";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpProtocol::HttpProtocol(const QByteArray &app)
|
CurlProtocol::CurlProtocol(const QByteArray &app)
|
||||||
: SlaveBase("http", app),
|
: SlaveBase("curl", app),
|
||||||
aborttransfer(false), m_emitmime(true),
|
aborttransfer(false),
|
||||||
|
m_emitmime(true), m_ishttp(false), m_isftp(false), m_issftp(false), m_collectdata(false),
|
||||||
m_curl(nullptr), m_curlheaders(nullptr)
|
m_curl(nullptr), m_curlheaders(nullptr)
|
||||||
{
|
{
|
||||||
m_curl = curl_easy_init();
|
m_curl = curl_easy_init();
|
||||||
|
@ -242,7 +321,7 @@ HttpProtocol::HttpProtocol(const QByteArray &app)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpProtocol::~HttpProtocol()
|
CurlProtocol::~CurlProtocol()
|
||||||
{
|
{
|
||||||
if (m_curlheaders) {
|
if (m_curlheaders) {
|
||||||
curl_slist_free_all(m_curlheaders);
|
curl_slist_free_all(m_curlheaders);
|
||||||
|
@ -252,9 +331,9 @@ HttpProtocol::~HttpProtocol()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpProtocol::stat(const KUrl &url)
|
void CurlProtocol::stat(const KUrl &url)
|
||||||
{
|
{
|
||||||
kDebug(7103) << "URL" << url.prettyUrl();
|
kDebug(7103) << "Stat URL" << url.prettyUrl();
|
||||||
|
|
||||||
if (redirectUrl(url)) {
|
if (redirectUrl(url)) {
|
||||||
return;
|
return;
|
||||||
|
@ -264,9 +343,18 @@ void HttpProtocol::stat(const KUrl &url)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: do not set CURLOPT_NOBODY, server may not send some headers
|
CURLcode curlresult = CURLE_OK;
|
||||||
CURLcode curlresult = curl_easy_perform(m_curl);
|
// NOTE: do not set CURLOPT_NOBODY for HTTP, server may not send some headers
|
||||||
kDebug(7103) << "Transfer result" << curlresult;
|
if (m_isftp || m_issftp) {
|
||||||
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_NOBODY, 1L);
|
||||||
|
if (curlresult != CURLE_OK) {
|
||||||
|
KIO_CURL_ERROR(curlresult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curlresult = curl_easy_perform(m_curl);
|
||||||
|
kDebug(7103) << "Stat result" << curlresult;
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
const KIO::Error kioerror = curlToKIOError(curlresult, m_curl);
|
const KIO::Error kioerror = curlToKIOError(curlresult, m_curl);
|
||||||
if (kioerror == KIO::ERR_COULD_NOT_LOGIN) {
|
if (kioerror == KIO::ERR_COULD_NOT_LOGIN) {
|
||||||
|
@ -279,12 +367,14 @@ void HttpProtocol::stat(const KUrl &url)
|
||||||
}
|
}
|
||||||
|
|
||||||
QString httpmimetype;
|
QString httpmimetype;
|
||||||
char *curlcontenttype = nullptr;
|
if (m_ishttp) {
|
||||||
curlresult = curl_easy_getinfo(m_curl, CURLINFO_CONTENT_TYPE, &curlcontenttype);
|
char *curlcontenttype = nullptr;
|
||||||
if (curlresult == CURLE_OK) {
|
curlresult = curl_easy_getinfo(m_curl, CURLINFO_CONTENT_TYPE, &curlcontenttype);
|
||||||
httpmimetype = HTTPMIMEType(QString::fromAscii(curlcontenttype));
|
if (curlresult == CURLE_OK) {
|
||||||
} else {
|
httpmimetype = HTTPMIMEType(QString::fromAscii(curlcontenttype));
|
||||||
kWarning(7103) << "Could not get content type info" << curl_easy_strerror(curlresult);
|
} else {
|
||||||
|
kWarning(7103) << "Could not get content type info" << curl_easy_strerror(curlresult);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
curl_off_t curlfiletime = 0;
|
curl_off_t curlfiletime = 0;
|
||||||
|
@ -300,9 +390,9 @@ void HttpProtocol::stat(const KUrl &url)
|
||||||
}
|
}
|
||||||
|
|
||||||
KIO::UDSEntry kioudsentry;
|
KIO::UDSEntry kioudsentry;
|
||||||
kDebug(7103) << "HTTP last-modified" << curlfiletime;
|
kDebug(7103) << "File time" << curlfiletime;
|
||||||
kDebug(7103) << "HTTP content-length" << curlcontentlength;
|
kDebug(7103) << "Content length" << curlcontentlength;
|
||||||
kDebug(7103) << "HTTP content-type" << httpmimetype;
|
kDebug(7103) << "MIME type" << httpmimetype;
|
||||||
kioudsentry.insert(KIO::UDSEntry::UDS_NAME, url.fileName());
|
kioudsentry.insert(KIO::UDSEntry::UDS_NAME, url.fileName());
|
||||||
kioudsentry.insert(KIO::UDSEntry::UDS_SIZE, qlonglong(curlcontentlength));
|
kioudsentry.insert(KIO::UDSEntry::UDS_SIZE, qlonglong(curlcontentlength));
|
||||||
kioudsentry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, qlonglong(curlfiletime));
|
kioudsentry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, qlonglong(curlfiletime));
|
||||||
|
@ -314,9 +404,111 @@ void HttpProtocol::stat(const KUrl &url)
|
||||||
finished();
|
finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpProtocol::get(const KUrl &url)
|
void CurlProtocol::listDir(const KUrl &url)
|
||||||
{
|
{
|
||||||
kDebug(7103) << "URL" << url.prettyUrl();
|
kDebug(7103) << "List URL" << url.prettyUrl();
|
||||||
|
|
||||||
|
KUrl urlhack(url);
|
||||||
|
urlhack = KUrl(url.url(KUrl::AddTrailingSlash));
|
||||||
|
if (redirectUrl(urlhack)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!setupCurl(urlhack)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_isftp && !m_issftp) {
|
||||||
|
// only for FTP or SFTP
|
||||||
|
error(KIO::ERR_INTERNAL, url.prettyUrl());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_collectdata = true;
|
||||||
|
|
||||||
|
CURLcode curlresult = curl_easy_perform(m_curl);
|
||||||
|
kDebug(7103) << "List result" << curlresult;
|
||||||
|
if (curlresult != CURLE_OK) {
|
||||||
|
const KIO::Error kioerror = curlToKIOError(curlresult, m_curl);
|
||||||
|
if (kioerror == KIO::ERR_COULD_NOT_LOGIN) {
|
||||||
|
if (authUrl(url)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error(kioerror, url.prettyUrl());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KIO::UDSEntry statentry;
|
||||||
|
char ftpmode[11];
|
||||||
|
int ftpint1 = 0;
|
||||||
|
char ftpowner[128];
|
||||||
|
char ftpgroup[128];
|
||||||
|
int ftpsize = 0;
|
||||||
|
char ftpmonth[4];
|
||||||
|
int ftpday = 0;
|
||||||
|
char ftpyearortime[6];
|
||||||
|
char ftpfilepath[filepathmax];
|
||||||
|
char ftplinkpath[filepathmax];
|
||||||
|
foreach(const QByteArray &line, m_writedata.split('\n')) {
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
::memset(ftpmode, 0, sizeof(ftpmode) * sizeof(char));
|
||||||
|
ftpint1 = 0;
|
||||||
|
::memset(ftpowner, 0, sizeof(ftpowner) * sizeof(char));
|
||||||
|
::memset(ftpgroup, 0, sizeof(ftpgroup) * sizeof(char));
|
||||||
|
ftpsize = 0;
|
||||||
|
::memset(ftpmonth, 0, sizeof(ftpmonth) * sizeof(char));
|
||||||
|
ftpday = 0;
|
||||||
|
::memset(ftpyearortime, 0, sizeof(ftpyearortime) * sizeof(char));
|
||||||
|
::memset(ftpfilepath, 0, filepathmax * sizeof(char));
|
||||||
|
::memset(ftplinkpath, 0, filepathmax * sizeof(char));
|
||||||
|
const int sscanfresult = ::sscanf(
|
||||||
|
line.constData(),
|
||||||
|
"%s %d %s %s %d %s %d %s %s -> %s",
|
||||||
|
ftpmode, &ftpint1, ftpowner, ftpgroup, &ftpsize, ftpmonth, &ftpday, ftpyearortime, ftpfilepath, ftplinkpath
|
||||||
|
);
|
||||||
|
// qDebug() << Q_FUNC_INFO << ftpmode << ftpint1 << ftpowner << ftpgroup << ftpsize << ftpmonth << ftpday << ftpyearortime << ftpfilepath << ftplinkpath;
|
||||||
|
if (sscanfresult == 10) {
|
||||||
|
const mode_t stdmode = ftpModeFromString(ftpmode);
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_NAME, QFile::decodeName(ftpfilepath));
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_FILE_TYPE, stdmode & S_IFMT);
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_ACCESS, stdmode & 07777);
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_SIZE, ftpsize);
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_USER, QString::fromLatin1(ftpowner));
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_GROUP, QString::fromLatin1(ftpgroup));
|
||||||
|
// link paths to current path causes KIO to do strange things
|
||||||
|
if (ftplinkpath[0] != '.' && ftplinkpath[1] != 0) {
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_LINK_DEST, QFile::decodeName(ftplinkpath));
|
||||||
|
}
|
||||||
|
if (ftpsize <= 0) {
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_GUESSED_MIME_TYPE, QString::fromLatin1("application/x-zerosize"));
|
||||||
|
}
|
||||||
|
listEntry(statentry, false);
|
||||||
|
} else if (sscanfresult == 9) {
|
||||||
|
const mode_t stdmode = ftpModeFromString(ftpmode);
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_NAME, QFile::decodeName(ftpfilepath));
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_FILE_TYPE, stdmode & S_IFMT);
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_ACCESS, stdmode & 07777);
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_SIZE, ftpsize);
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_USER, QString::fromLatin1(ftpowner));
|
||||||
|
statentry.insert(KIO::UDSEntry::UDS_GROUP, QString::fromLatin1(ftpgroup));
|
||||||
|
listEntry(statentry, false);
|
||||||
|
} else {
|
||||||
|
kWarning(7103) << "Invalid FTP data line" << line << sscanfresult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statentry.clear();
|
||||||
|
listEntry(statentry, true);
|
||||||
|
|
||||||
|
finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurlProtocol::get(const KUrl &url)
|
||||||
|
{
|
||||||
|
kDebug(7103) << "Get URL" << url.prettyUrl();
|
||||||
|
|
||||||
if (redirectUrl(url)) {
|
if (redirectUrl(url)) {
|
||||||
return;
|
return;
|
||||||
|
@ -327,7 +519,7 @@ void HttpProtocol::get(const KUrl &url)
|
||||||
}
|
}
|
||||||
|
|
||||||
CURLcode curlresult = curl_easy_perform(m_curl);
|
CURLcode curlresult = curl_easy_perform(m_curl);
|
||||||
kDebug(7103) << "Transfer result" << curlresult;
|
kDebug(7103) << "Get result" << curlresult;
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
const KIO::Error kioerror = curlToKIOError(curlresult, m_curl);
|
const KIO::Error kioerror = curlToKIOError(curlresult, m_curl);
|
||||||
if (kioerror == KIO::ERR_COULD_NOT_LOGIN) {
|
if (kioerror == KIO::ERR_COULD_NOT_LOGIN) {
|
||||||
|
@ -342,74 +534,46 @@ void HttpProtocol::get(const KUrl &url)
|
||||||
finished();
|
finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CurlProtocol::slotData(const char* curldata, const size_t curldatasize)
|
||||||
void HttpProtocol::put(const KUrl &url, int permissions, KIO::JobFlags flags)
|
|
||||||
{
|
|
||||||
kDebug(7103) << "URL" << url.prettyUrl();
|
|
||||||
|
|
||||||
// no permissions to set, it is POST
|
|
||||||
Q_UNUSED(permissions);
|
|
||||||
Q_UNUSED(flags);
|
|
||||||
|
|
||||||
if (redirectUrl(url)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!setupCurl(url)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CURLcode curlresult = curl_easy_setopt(m_curl, CURLOPT_POST, 1L);
|
|
||||||
if (curlresult != CURLE_OK) {
|
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
curlresult = curl_easy_perform(m_curl);
|
|
||||||
kDebug(7103) << "Transfer result" << curlresult;
|
|
||||||
if (curlresult != CURLE_OK) {
|
|
||||||
const KIO::Error kioerror = curlToKIOError(curlresult, m_curl);
|
|
||||||
if (kioerror == KIO::ERR_COULD_NOT_LOGIN) {
|
|
||||||
if (authUrl(url)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
error(kioerror, url.prettyUrl());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
finished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void HttpProtocol::slotData(const char* curldata, const size_t curldatasize)
|
|
||||||
{
|
{
|
||||||
if (aborttransfer) {
|
if (aborttransfer) {
|
||||||
kDebug(7103) << "Transfer still in progress";
|
kDebug(7103) << "Transfer still in progress";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QByteArray bytedata = QByteArray::fromRawData(curldata, curldatasize);
|
||||||
|
|
||||||
if (m_emitmime) {
|
if (m_emitmime) {
|
||||||
m_emitmime = false;
|
m_emitmime = false;
|
||||||
|
|
||||||
// if it's HTTP error do not send data and MIME, abort transfer
|
if (m_ishttp) {
|
||||||
const long httpcode = HTTPCode(m_curl);
|
// if it's HTTP error do not send data and MIME, abort transfer
|
||||||
if (httpcode >= 400) {
|
const long httpcode = HTTPCode(m_curl);
|
||||||
aborttransfer = true;
|
if (httpcode >= 400) {
|
||||||
return;
|
aborttransfer = true;
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QString httpmimetype = QString::fromLatin1("application/octet-stream");
|
QString httpmimetype = QString::fromLatin1("application/octet-stream");
|
||||||
char *curlcontenttype = nullptr;
|
char *curlcontenttype = nullptr;
|
||||||
CURLcode curlresult = curl_easy_getinfo(m_curl, CURLINFO_CONTENT_TYPE, &curlcontenttype);
|
CURLcode curlresult = curl_easy_getinfo(m_curl, CURLINFO_CONTENT_TYPE, &curlcontenttype);
|
||||||
if (curlresult == CURLE_OK) {
|
if (curlresult == CURLE_OK) {
|
||||||
httpmimetype = HTTPMIMEType(QString::fromAscii(curlcontenttype));
|
httpmimetype = HTTPMIMEType(QString::fromAscii(curlcontenttype));
|
||||||
|
} else {
|
||||||
|
kWarning(7103) << "Could not get content type info" << curl_easy_strerror(curlresult);
|
||||||
|
}
|
||||||
|
mimeType(httpmimetype);
|
||||||
} else {
|
} else {
|
||||||
kWarning(7103) << "Could not get content type info" << curl_easy_strerror(curlresult);
|
KMimeType::Ptr kmimetype = KMimeType::findByNameAndContent(m_url.url(), bytedata);
|
||||||
|
mimeType(kmimetype->name());
|
||||||
}
|
}
|
||||||
mimeType(httpmimetype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data(QByteArray::fromRawData(curldata, curldatasize));
|
if (m_collectdata) {
|
||||||
|
m_writedata.append(bytedata);
|
||||||
|
} else {
|
||||||
|
data(bytedata);
|
||||||
|
}
|
||||||
|
|
||||||
curl_off_t curlspeeddownload = 0;
|
curl_off_t curlspeeddownload = 0;
|
||||||
CURLcode curlresult = curl_easy_getinfo(m_curl, CURLINFO_SPEED_DOWNLOAD_T, &curlspeeddownload);
|
CURLcode curlresult = curl_easy_getinfo(m_curl, CURLINFO_SPEED_DOWNLOAD_T, &curlspeeddownload);
|
||||||
|
@ -421,7 +585,7 @@ void HttpProtocol::slotData(const char* curldata, const size_t curldatasize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpProtocol::slotProgress(KIO::filesize_t received, KIO::filesize_t total)
|
void CurlProtocol::slotProgress(KIO::filesize_t received, KIO::filesize_t total)
|
||||||
{
|
{
|
||||||
kDebug(7103) << "Received" << received << "from" << total;
|
kDebug(7103) << "Received" << received << "from" << total;
|
||||||
processedSize(received);
|
processedSize(received);
|
||||||
|
@ -430,7 +594,7 @@ void HttpProtocol::slotProgress(KIO::filesize_t received, KIO::filesize_t total)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpProtocol::redirectUrl(const KUrl &url)
|
bool CurlProtocol::redirectUrl(const KUrl &url)
|
||||||
{
|
{
|
||||||
// curl cannot verify certs if the host is address, CURLOPT_USE_SSL set to CURLUSESSL_TRY
|
// curl cannot verify certs if the host is address, CURLOPT_USE_SSL set to CURLUSESSL_TRY
|
||||||
// does not bypass such cases so resolving it manually
|
// does not bypass such cases so resolving it manually
|
||||||
|
@ -452,7 +616,7 @@ bool HttpProtocol::redirectUrl(const KUrl &url)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpProtocol::setupCurl(const KUrl &url)
|
bool CurlProtocol::setupCurl(const KUrl &url)
|
||||||
{
|
{
|
||||||
if (Q_UNLIKELY(!m_curl)) {
|
if (Q_UNLIKELY(!m_curl)) {
|
||||||
error(KIO::ERR_OUT_OF_MEMORY, QString::fromLatin1("Null context"));
|
error(KIO::ERR_OUT_OF_MEMORY, QString::fromLatin1("Null context"));
|
||||||
|
@ -461,6 +625,13 @@ bool HttpProtocol::setupCurl(const KUrl &url)
|
||||||
|
|
||||||
aborttransfer = false;
|
aborttransfer = false;
|
||||||
m_emitmime = true;
|
m_emitmime = true;
|
||||||
|
const QString urlprotocol = url.protocol();
|
||||||
|
m_ishttp = (urlprotocol == QLatin1String("http") || urlprotocol == QLatin1String("https"));
|
||||||
|
m_isftp = (urlprotocol == QLatin1String("ftp"));
|
||||||
|
m_issftp = (urlprotocol == QLatin1String("sftp"));
|
||||||
|
m_collectdata = false;
|
||||||
|
m_writedata.clear();
|
||||||
|
m_url = url;
|
||||||
curl_easy_reset(m_curl);
|
curl_easy_reset(m_curl);
|
||||||
curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1L);
|
curl_easy_setopt(m_curl, CURLOPT_NOSIGNAL, 1L);
|
||||||
curl_easy_setopt(m_curl, CURLOPT_FILETIME, 1L);
|
curl_easy_setopt(m_curl, CURLOPT_FILETIME, 1L);
|
||||||
|
@ -470,46 +641,47 @@ bool HttpProtocol::setupCurl(const KUrl &url)
|
||||||
// curl_easy_setopt(m_curl, CURLOPT_IGNORE_CONTENT_LENGTH, 1L); // breaks XFER info, fixes transfer of chunked content
|
// curl_easy_setopt(m_curl, CURLOPT_IGNORE_CONTENT_LENGTH, 1L); // breaks XFER info, fixes transfer of chunked content
|
||||||
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);
|
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);
|
||||||
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
|
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, curlWriteCallback);
|
||||||
curl_easy_setopt(m_curl, CURLOPT_READDATA, this);
|
|
||||||
curl_easy_setopt(m_curl, CURLOPT_READFUNCTION, curlReadCallback);
|
|
||||||
curl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 0L); // otherwise the XFER info callback is not called
|
curl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 0L); // otherwise the XFER info callback is not called
|
||||||
curl_easy_setopt(m_curl, CURLOPT_XFERINFODATA, this);
|
curl_easy_setopt(m_curl, CURLOPT_XFERINFODATA, this);
|
||||||
curl_easy_setopt(m_curl, CURLOPT_XFERINFOFUNCTION, curlXFERCallback);
|
curl_easy_setopt(m_curl, CURLOPT_XFERINFOFUNCTION, curlXFERCallback);
|
||||||
curl_easy_setopt(m_curl, CURLOPT_FAILONERROR, 1L);
|
curl_easy_setopt(m_curl, CURLOPT_FAILONERROR, 1L);
|
||||||
|
// TODO: option for this, warning?
|
||||||
|
curl_easy_setopt(m_curl, CURLOPT_USE_SSL, (long)CURLUSESSL_TRY);
|
||||||
// curl_easy_setopt(m_curl, CURLOPT_VERBOSE, 1L); // debugging
|
// curl_easy_setopt(m_curl, CURLOPT_VERBOSE, 1L); // debugging
|
||||||
|
|
||||||
const QByteArray urlbytes = url.prettyUrl().toLocal8Bit();
|
const QByteArray urlbytes = url.prettyUrl().toLocal8Bit();
|
||||||
CURLcode curlresult = curl_easy_setopt(m_curl, CURLOPT_URL, urlbytes.constData());
|
CURLcode curlresult = curl_easy_setopt(m_curl, CURLOPT_URL, urlbytes.constData());
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CURL_AT_LEAST_VERSION(7, 85, 0)
|
#if CURL_AT_LEAST_VERSION(7, 85, 0)
|
||||||
static const char* const curlprotocols = "http,https";
|
static const char* const curlprotocols = "http,https,ftp,sftp";
|
||||||
|
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROTOCOLS_STR, curlprotocols);
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROTOCOLS_STR, curlprotocols);
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_REDIR_PROTOCOLS_STR, curlprotocols);
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_REDIR_PROTOCOLS_STR, curlprotocols);
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// deprecated since v7.85.0
|
// deprecated since v7.85.0
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
|
static const long const curlprotocols = (CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP | CURLPROTO_SFTP);
|
||||||
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROTOCOLS, curlprotocols);
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_REDIR_PROTOCOLS, curlprotocols);
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -520,7 +692,7 @@ bool HttpProtocol::setupCurl(const KUrl &url)
|
||||||
const QByteArray useragentbytes = metaData("UserAgent").toAscii();
|
const QByteArray useragentbytes = metaData("UserAgent").toAscii();
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_USERAGENT, useragentbytes.constData());
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_USERAGENT, useragentbytes.constData());
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -533,12 +705,12 @@ bool HttpProtocol::setupCurl(const KUrl &url)
|
||||||
kDebug(7103) << "Proxy" << proxybytes << curlproxytype;
|
kDebug(7103) << "Proxy" << proxybytes << curlproxytype;
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROXY, proxybytes.constData());
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROXY, proxybytes.constData());
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROXYTYPE, curlproxytype);
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROXYTYPE, curlproxytype);
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,31 +718,32 @@ bool HttpProtocol::setupCurl(const KUrl &url)
|
||||||
kDebug(7103) << "No proxy auth" << noproxyauth;
|
kDebug(7103) << "No proxy auth" << noproxyauth;
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROXYAUTH, noproxyauth ? CURLAUTH_NONE : CURLAUTH_ANY);
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_PROXYAUTH, noproxyauth ? CURLAUTH_NONE : CURLAUTH_ANY);
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool nowwwauth = (noauth || metaData("no-www-auth") == QLatin1String("true"));
|
const bool nowwwauth = (noauth || metaData("no-www-auth") == QLatin1String("true"));
|
||||||
kDebug(7103) << "No WWW auth" << nowwwauth;
|
kDebug(7103) << "No WWW auth" << nowwwauth;
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_HTTPAUTH, nowwwauth ? CURLAUTH_NONE : CURLAUTH_ANY);
|
if (m_ishttp) {
|
||||||
if (curlresult != CURLE_OK) {
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_HTTPAUTH, nowwwauth ? CURLAUTH_NONE : CURLAUTH_ANY);
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
if (curlresult != CURLE_OK) {
|
||||||
return false;
|
KIO_CURL_ERROR(curlresult);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nowwwauth) {
|
if (!nowwwauth) {
|
||||||
const QByteArray urlusername = url.userName().toAscii();
|
const QByteArray urlusername = url.userName().toAscii();
|
||||||
const QByteArray urlpassword = url.password().toAscii();
|
const QByteArray urlpassword = url.password().toAscii();
|
||||||
if (!urlusername.isEmpty() && !urlpassword.isEmpty()) {
|
if (!urlusername.isEmpty() && !urlpassword.isEmpty()) {
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_USERNAME, urlusername.constData());
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_USERNAME, urlusername.constData());
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_PASSWORD, urlpassword.constData());
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_PASSWORD, urlpassword.constData());
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,7 +754,7 @@ bool HttpProtocol::setupCurl(const KUrl &url)
|
||||||
const qlonglong resumeoffset = metaData(QLatin1String("resume")).toLongLong();
|
const qlonglong resumeoffset = metaData(QLatin1String("resume")).toLongLong();
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_RESUME_FROM_LARGE, curl_off_t(resumeoffset));
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_RESUME_FROM_LARGE, curl_off_t(resumeoffset));
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
canResume();
|
canResume();
|
||||||
|
@ -593,34 +766,36 @@ bool HttpProtocol::setupCurl(const KUrl &url)
|
||||||
m_curlheaders = nullptr;
|
m_curlheaders = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasMetaData(QLatin1String("Languages"))) {
|
if (m_ishttp) {
|
||||||
m_curlheaders = curl_slist_append(m_curlheaders, QByteArray("Accept-Language: ") + metaData("Languages").toAscii());
|
if (hasMetaData(QLatin1String("Languages"))) {
|
||||||
}
|
m_curlheaders = curl_slist_append(m_curlheaders, QByteArray("Accept-Language: ") + metaData("Languages").toAscii());
|
||||||
|
}
|
||||||
|
|
||||||
if (hasMetaData(QLatin1String("Charsets"))) {
|
if (hasMetaData(QLatin1String("Charsets"))) {
|
||||||
m_curlheaders = curl_slist_append(m_curlheaders, QByteArray("Accept-Charset: ") + metaData("Charsets").toAscii());
|
m_curlheaders = curl_slist_append(m_curlheaders, QByteArray("Accept-Charset: ") + metaData("Charsets").toAscii());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasMetaData(QLatin1String("accept"))) {
|
if (hasMetaData(QLatin1String("accept"))) {
|
||||||
m_curlheaders = curl_slist_append(m_curlheaders, QByteArray("Accept: ") + metaData("accept").toAscii());
|
m_curlheaders = curl_slist_append(m_curlheaders, QByteArray("Accept: ") + metaData("accept").toAscii());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasMetaData(QLatin1String("Authorization"))) {
|
if (hasMetaData(QLatin1String("Authorization"))) {
|
||||||
m_curlheaders = curl_slist_append(m_curlheaders, QByteArray("Authorization: ") + metaData("Authorization").toAscii());
|
m_curlheaders = curl_slist_append(m_curlheaders, QByteArray("Authorization: ") + metaData("Authorization").toAscii());
|
||||||
}
|
}
|
||||||
|
|
||||||
curlresult = curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_curlheaders);
|
curlresult = curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_curlheaders);
|
||||||
if (curlresult != CURLE_OK) {
|
if (curlresult != CURLE_OK) {
|
||||||
curl_slist_free_all(m_curlheaders);
|
curl_slist_free_all(m_curlheaders);
|
||||||
m_curlheaders = nullptr;
|
m_curlheaders = nullptr;
|
||||||
error(KIO::ERR_SLAVE_DEFINED, curl_easy_strerror(curlresult));
|
KIO_CURL_ERROR(curlresult);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HttpProtocol::authUrl(const KUrl &url)
|
bool CurlProtocol::authUrl(const KUrl &url)
|
||||||
{
|
{
|
||||||
KIO::AuthInfo kioauthinfo;
|
KIO::AuthInfo kioauthinfo;
|
||||||
kioauthinfo.url = url;
|
kioauthinfo.url = url;
|
|
@ -24,15 +24,15 @@
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
class HttpProtocol : public KIO::SlaveBase
|
class CurlProtocol : public KIO::SlaveBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HttpProtocol(const QByteArray &app);
|
CurlProtocol(const QByteArray &app);
|
||||||
~HttpProtocol();
|
~CurlProtocol();
|
||||||
|
|
||||||
void stat(const KUrl &url) final;
|
void stat(const KUrl &url) final;
|
||||||
|
void listDir(const KUrl &url) final;
|
||||||
void get(const KUrl &url) final;
|
void get(const KUrl &url) final;
|
||||||
void put(const KUrl &url, int permissions, KIO::JobFlags flags) final;
|
|
||||||
|
|
||||||
void slotData(const char* curldata, const size_t curldatasize);
|
void slotData(const char* curldata, const size_t curldatasize);
|
||||||
void slotProgress(KIO::filesize_t received, KIO::filesize_t total);
|
void slotProgress(KIO::filesize_t received, KIO::filesize_t total);
|
||||||
|
@ -45,6 +45,12 @@ private:
|
||||||
bool authUrl(const KUrl &url);
|
bool authUrl(const KUrl &url);
|
||||||
|
|
||||||
bool m_emitmime;
|
bool m_emitmime;
|
||||||
|
bool m_ishttp;
|
||||||
|
bool m_isftp;
|
||||||
|
bool m_issftp;
|
||||||
|
bool m_collectdata;
|
||||||
|
QByteArray m_writedata;
|
||||||
|
KUrl m_url;
|
||||||
CURL* m_curl;
|
CURL* m_curl;
|
||||||
struct curl_slist *m_curlheaders;
|
struct curl_slist *m_curlheaders;
|
||||||
};
|
};
|
17
kioslave/curl/sftp.protocol
Normal file
17
kioslave/curl/sftp.protocol
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[Protocol]
|
||||||
|
exec=kio_curl
|
||||||
|
protocol=sftp
|
||||||
|
copyToFile=false
|
||||||
|
copyFromFile=false
|
||||||
|
listing=true
|
||||||
|
reading=true
|
||||||
|
writing=false
|
||||||
|
makedir=false
|
||||||
|
deleting=false
|
||||||
|
moving=false
|
||||||
|
ProxiedBy=http
|
||||||
|
Icon=folder-remote
|
||||||
|
maxInstances=20
|
||||||
|
maxInstancesPerHost=5
|
||||||
|
X-DocPath=kioslave/curl/index.html
|
||||||
|
Class=:internet
|
|
@ -1,15 +0,0 @@
|
||||||
project(kioslave-ftp)
|
|
||||||
|
|
||||||
include_directories(${KDE4_KIO_INCLUDES})
|
|
||||||
|
|
||||||
########### next target ###############
|
|
||||||
|
|
||||||
add_executable(kio_ftp ftp.cpp)
|
|
||||||
|
|
||||||
target_link_libraries(kio_ftp kdecore kio)
|
|
||||||
|
|
||||||
install(TARGETS kio_ftp DESTINATION ${KDE4_LIBEXEC_INSTALL_DIR})
|
|
||||||
|
|
||||||
########### install files ###############
|
|
||||||
|
|
||||||
install(FILES ftp.protocol DESTINATION ${KDE4_SERVICES_INSTALL_DIR})
|
|
2539
kioslave/ftp/ftp.cpp
2539
kioslave/ftp/ftp.cpp
File diff suppressed because it is too large
Load diff
|
@ -1,426 +0,0 @@
|
||||||
// -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*-
|
|
||||||
/* This file is part of the KDE libraries
|
|
||||||
Copyright (C) 2000 David Faure <faure@kde.org>
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public License
|
|
||||||
along with this library; see the file COPYING.LIB. If not, write to
|
|
||||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
||||||
Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef KDELIBS_FTP_H
|
|
||||||
#define KDELIBS_FTP_H
|
|
||||||
|
|
||||||
#include <config.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
#include <kurl.h>
|
|
||||||
#include <kio/slavebase.h>
|
|
||||||
|
|
||||||
#include <QTcpServer>
|
|
||||||
#include <QTcpSocket>
|
|
||||||
|
|
||||||
struct FtpEntry
|
|
||||||
{
|
|
||||||
QString name;
|
|
||||||
QString owner;
|
|
||||||
QString group;
|
|
||||||
QString link;
|
|
||||||
|
|
||||||
KIO::filesize_t size;
|
|
||||||
mode_t type;
|
|
||||||
mode_t access;
|
|
||||||
time_t date;
|
|
||||||
};
|
|
||||||
|
|
||||||
//===============================================================================
|
|
||||||
// Ftp
|
|
||||||
//===============================================================================
|
|
||||||
class Ftp : public QObject, public KIO::SlaveBase
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
Ftp( const QByteArray &app );
|
|
||||||
virtual ~Ftp();
|
|
||||||
|
|
||||||
virtual void setHost( const QString& host, quint16 port, const QString& user, const QString& pass );
|
|
||||||
|
|
||||||
virtual void stat( const KUrl &url );
|
|
||||||
|
|
||||||
virtual void listDir( const KUrl & url );
|
|
||||||
virtual void mkdir( const KUrl & url, int permissions );
|
|
||||||
virtual void rename( const KUrl & src, const KUrl & dst, KIO::JobFlags flags );
|
|
||||||
virtual void del( const KUrl & url, bool isfile );
|
|
||||||
virtual void chmod( const KUrl & url, int permissions );
|
|
||||||
|
|
||||||
virtual void get( const KUrl& url );
|
|
||||||
virtual void put( const KUrl& url, int permissions, KIO::JobFlags flags );
|
|
||||||
//virtual void mimetype( const KUrl& url );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the case that one side of the job is a local file
|
|
||||||
*/
|
|
||||||
virtual void copy( const KUrl &src, const KUrl &dest, int permissions, KIO::JobFlags flags );
|
|
||||||
|
|
||||||
private:
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All the methods named ftpXyz are lowlevel methods that are not exported.
|
|
||||||
// The implement functionality used by the public high-level methods. Some
|
|
||||||
// low-level methods still use error() to emit errors. This behaviour is not
|
|
||||||
// recommended - please return a boolean status or an error code instead!
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status Code returned from ftpPut() and ftpGet(), used to select
|
|
||||||
* source or destination url for error messages
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
statusSuccess,
|
|
||||||
statusClientError,
|
|
||||||
statusServerError
|
|
||||||
} StatusCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login Mode for ftpOpenConnection
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
loginDefered,
|
|
||||||
loginExplicit,
|
|
||||||
loginImplicit
|
|
||||||
} LoginMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect and login to the FTP server.
|
|
||||||
*
|
|
||||||
* @param loginMode controls if login info should be sent<br>
|
|
||||||
* loginDefered - must not be logged on, no login info is sent<br>
|
|
||||||
* loginExplicit - must not be logged on, login info is sent<br>
|
|
||||||
* loginImplicit - login info is sent if not logged on
|
|
||||||
*
|
|
||||||
* @return true on success (a login failure would return false).
|
|
||||||
*/
|
|
||||||
bool ftpOpenConnection (LoginMode loginMode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the connection
|
|
||||||
*/
|
|
||||||
void ftpCloseConnection();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by ftpOpenConnection. It logs us in.
|
|
||||||
* m_initialPath is set to the current working directory
|
|
||||||
* if logging on was successful.
|
|
||||||
*
|
|
||||||
* @param userChanged if not NULL, will be set to true if the user name
|
|
||||||
* was changed during login.
|
|
||||||
* @return true on success.
|
|
||||||
*/
|
|
||||||
bool ftpLogin(bool* userChanged = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ftpSendCmd - send a command (@p cmd) and read response
|
|
||||||
*
|
|
||||||
* @param maxretries number of time it should retry. Since it recursively
|
|
||||||
* calls itself if it can't read the answer (this happens especially after
|
|
||||||
* timeouts), we need to limit the recursiveness ;-)
|
|
||||||
*
|
|
||||||
* return true if any response received, false on error
|
|
||||||
*/
|
|
||||||
bool ftpSendCmd( const QByteArray& cmd, int maxretries = 1 );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the SIZE command to get the file size.
|
|
||||||
* @param mode the size depends on the transfer mode, hence this arg.
|
|
||||||
* @return true on success
|
|
||||||
* Gets the size into m_size.
|
|
||||||
*/
|
|
||||||
bool ftpSize( const QString & path, char mode );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the SIZE command to the server and returns the response.
|
|
||||||
* @param path the path to file whose size is to be retrieved.
|
|
||||||
* @return response from the server
|
|
||||||
*/
|
|
||||||
const char* ftpSendSizeCmd(const QString& path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the file exists.
|
|
||||||
* Implemented using the SIZE command.
|
|
||||||
*/
|
|
||||||
bool ftpFileExists(const QString& path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the current working directory, but only if not yet current
|
|
||||||
*/
|
|
||||||
bool ftpFolder(const QString& path, bool bReportError);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs a command on the ftp server like "list" or "retr". In contrast to
|
|
||||||
* ftpSendCmd a data connection is opened. The corresponding socket
|
|
||||||
* sData is available for reading/writing on success.
|
|
||||||
* The connection must be closed afterwards with ftpCloseCommand.
|
|
||||||
*
|
|
||||||
* @param mode is 'A' or 'I'. 'A' means ASCII transfer, 'I' means binary transfer.
|
|
||||||
* @param errorcode the command-dependent error code to emit on error
|
|
||||||
*
|
|
||||||
* @return true if the command was accepted by the server.
|
|
||||||
*/
|
|
||||||
bool ftpOpenCommand( const char *command, const QString & path, char mode,
|
|
||||||
int errorcode, KIO::fileoffset_t offset = 0 );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The counterpart to openCommand.
|
|
||||||
* Closes data sockets and then reads line sent by server at
|
|
||||||
* end of command.
|
|
||||||
* @return false on error (line doesn't start with '2')
|
|
||||||
*/
|
|
||||||
bool ftpCloseCommand();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send "TYPE I" or "TYPE A" only if required, see m_cDataMode.
|
|
||||||
*
|
|
||||||
* Use 'A' to select ASCII and 'I' to select BINARY mode. If
|
|
||||||
* cMode is '?' the m_bTextMode flag is used to choose a mode.
|
|
||||||
*/
|
|
||||||
bool ftpDataMode(char cMode);
|
|
||||||
|
|
||||||
//void ftpAbortTransfer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by ftpOpenCommand, return 0 on success or an error code
|
|
||||||
*/
|
|
||||||
int ftpOpenDataConnection();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* closes a data connection, see ftpOpenDataConnection()
|
|
||||||
*/
|
|
||||||
void ftpCloseDataConnection();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for ftpOpenDataConnection
|
|
||||||
*/
|
|
||||||
int ftpOpenPASVDataConnection();
|
|
||||||
/**
|
|
||||||
* Helper for ftpOpenDataConnection
|
|
||||||
*/
|
|
||||||
int ftpOpenEPSVDataConnection();
|
|
||||||
/**
|
|
||||||
* Helper for ftpOpenDataConnection
|
|
||||||
*/
|
|
||||||
int ftpOpenPortDataConnection();
|
|
||||||
|
|
||||||
bool ftpChmod( const QString & path, int permissions );
|
|
||||||
|
|
||||||
// used by listDir
|
|
||||||
bool ftpOpenDir( const QString & path );
|
|
||||||
/**
|
|
||||||
* Called to parse directory listings, call this until it returns false
|
|
||||||
*/
|
|
||||||
bool ftpReadDir(FtpEntry& ftpEnt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to fill an UDSEntry
|
|
||||||
*/
|
|
||||||
void ftpCreateUDSEntry( const QString & filename, const FtpEntry& ftpEnt, KIO::UDSEntry& entry, bool isDir );
|
|
||||||
|
|
||||||
void ftpShortStatAnswer( const QString& filename, bool isDir );
|
|
||||||
|
|
||||||
void ftpStatAnswerNotFound( const QString & path, const QString & filename );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the internal implementation of rename() - set put().
|
|
||||||
*
|
|
||||||
* @return true on success.
|
|
||||||
*/
|
|
||||||
bool ftpRename( const QString & src, const QString & dst, KIO::JobFlags flags );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by ftpOpenConnection. It opens the control connection to the ftp server.
|
|
||||||
*
|
|
||||||
* @return true on success.
|
|
||||||
*/
|
|
||||||
bool ftpOpenControlConnection();
|
|
||||||
bool ftpOpenControlConnection( const QString & host, int port );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* closes the socket holding the control connection (see ftpOpenControlConnection)
|
|
||||||
*/
|
|
||||||
void ftpCloseControlConnection();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* read a response from the server (a trailing CR gets stripped)
|
|
||||||
* @param iOffset -1 to read a new line from the server<br>
|
|
||||||
* 0 to return the whole response string
|
|
||||||
* >0 to return the response with iOffset chars skipped
|
|
||||||
* @return the reponse message with iOffset chars skipped (or "" if iOffset points
|
|
||||||
* behind the available data)
|
|
||||||
*/
|
|
||||||
const char* ftpResponse(int iOffset);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the internal implementation of get() - see copy().
|
|
||||||
*
|
|
||||||
* IMPORTANT: the caller should call ftpCloseCommand() on return.
|
|
||||||
* The function does not call error(), the caller should do this.
|
|
||||||
*
|
|
||||||
* @param iError set to an ERR_xxxx code on error
|
|
||||||
* @param iCopyFile -1 -or- handle of a local destination file
|
|
||||||
* @param hCopyOffset local file only: non-zero for resume
|
|
||||||
* @return 0 for success, -1 for server error, -2 for client error
|
|
||||||
*/
|
|
||||||
StatusCode ftpGet(int& iError, int iCopyFile, const KUrl& url, KIO::fileoffset_t hCopyOffset);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the internal implementation of put() - see copy().
|
|
||||||
*
|
|
||||||
* IMPORTANT: the caller should call ftpCloseCommand() on return.
|
|
||||||
* The function does not call error(), the caller should do this.
|
|
||||||
*
|
|
||||||
* @param iError set to an ERR_xxxx code on error
|
|
||||||
* @param iCopyFile -1 -or- handle of a local source file
|
|
||||||
* @return 0 for success, -1 for server error, -2 for client error
|
|
||||||
*/
|
|
||||||
StatusCode ftpPut(int& iError, int iCopyFile, const KUrl& url, int permissions, KIO::JobFlags flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* helper called from copy() to implement FILE -> FTP transfers
|
|
||||||
*
|
|
||||||
* @param iError set to an ERR_xxxx code on error
|
|
||||||
* @param iCopyFile [out] handle of a local source file
|
|
||||||
* @param sCopyFile path of the local source file
|
|
||||||
* @return 0 for success, -1 for server error, -2 for client error
|
|
||||||
*/
|
|
||||||
StatusCode ftpCopyPut(int& iError, int& iCopyFile, const QString &sCopyFile, const KUrl& url, int permissions, KIO::JobFlags flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* helper called from copy() to implement FTP -> FILE transfers
|
|
||||||
*
|
|
||||||
* @param iError set to an ERR_xxxx code on error
|
|
||||||
* @param iCopyFile [out] handle of a local source file
|
|
||||||
* @param sCopyFile path of the local destination file
|
|
||||||
* @return 0 for success, -1 for server error, -2 for client error
|
|
||||||
*/
|
|
||||||
StatusCode ftpCopyGet(int& iError, int& iCopyFile, const QString &sCopyFile, const KUrl& url, int permissions, KIO::JobFlags flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the mime type of the content to retrieved.
|
|
||||||
*
|
|
||||||
* @param iError set to an ERR_xxxx code on error
|
|
||||||
* @return 0 for success, -1 for server error, -2 for client error
|
|
||||||
*/
|
|
||||||
StatusCode ftpSendMimeType(int& iError, const KUrl& url);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fixes up an entry name so that extraneous whitespaces do not cause
|
|
||||||
* problems. See bug# 88575 and bug# 300988.
|
|
||||||
*/
|
|
||||||
void fixupEntryName(FtpEntry* ftpEnt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls @ref statEntry.
|
|
||||||
*/
|
|
||||||
bool maybeEmitStatEntry(FtpEntry& ftpEnt, const QString& search, const QString& filename, bool isDir);
|
|
||||||
|
|
||||||
private: // data members
|
|
||||||
|
|
||||||
QString m_host;
|
|
||||||
int m_port;
|
|
||||||
QString m_user;
|
|
||||||
QString m_pass;
|
|
||||||
/**
|
|
||||||
* Where we end up after connecting
|
|
||||||
*/
|
|
||||||
QString m_initialPath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the current working directory - see ftpFolder
|
|
||||||
*/
|
|
||||||
QString m_currentPath;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the status returned by the FTP protocol, set in ftpResponse()
|
|
||||||
*/
|
|
||||||
int m_iRespCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the status/100 returned by the FTP protocol, set in ftpResponse()
|
|
||||||
*/
|
|
||||||
int m_iRespType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This flag is maintained by ftpDataMode() and contains I or A after
|
|
||||||
* ftpDataMode() has successfully set the mode.
|
|
||||||
*/
|
|
||||||
char m_cDataMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* true if logged on (m_control should also be non-NULL)
|
|
||||||
*/
|
|
||||||
bool m_bLoggedOn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* true if a "textmode" metadata key was found by ftpLogin(). This
|
|
||||||
* switches the ftp data transfer mode from binary to ASCII.
|
|
||||||
*/
|
|
||||||
bool m_bTextMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* true if a data stream is open, used in ftpCloseConnection().
|
|
||||||
*
|
|
||||||
* When the user cancels a get or put command the Ftp dtor will be called,
|
|
||||||
* which in turn calls ftpCloseConnection(). The later would try to send QUIT
|
|
||||||
* which won't work until timeout. ftpOpenCommand sets the m_bBusy flag so
|
|
||||||
* that the sockets will be closed immedeately - the server should be
|
|
||||||
* capable of handling this and return an error code on thru the control
|
|
||||||
* connection. The m_bBusy gets cleared by the ftpCloseCommand() routine.
|
|
||||||
*/
|
|
||||||
bool m_bBusy;
|
|
||||||
|
|
||||||
bool m_bPasv;
|
|
||||||
|
|
||||||
KIO::filesize_t m_size;
|
|
||||||
static KIO::filesize_t UnknownSize;
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
epsvUnknown = 0x01,
|
|
||||||
epsvAllUnknown = 0x02,
|
|
||||||
eprtUnknown = 0x04,
|
|
||||||
epsvAllSent = 0x10,
|
|
||||||
pasvUnknown = 0x20,
|
|
||||||
chmodUnknown = 0x100
|
|
||||||
};
|
|
||||||
int m_extControl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* control connection socket, only set if openControl() succeeded
|
|
||||||
*/
|
|
||||||
QTcpSocket *m_control;
|
|
||||||
QByteArray m_lastControlLine;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* data connection socket
|
|
||||||
*/
|
|
||||||
QTcpSocket *m_data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* active mode server socket
|
|
||||||
*/
|
|
||||||
QTcpServer *m_server;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // KDELIBS_FTP_H
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
[Protocol]
|
|
||||||
exec=kio_ftp
|
|
||||||
protocol=ftp
|
|
||||||
copyToFile=true
|
|
||||||
copyFromFile=true
|
|
||||||
listing=true
|
|
||||||
reading=true
|
|
||||||
writing=true
|
|
||||||
makedir=true
|
|
||||||
deleting=true
|
|
||||||
moving=true
|
|
||||||
ProxiedBy=http
|
|
||||||
Icon=folder-remote
|
|
||||||
maxInstances=20
|
|
||||||
maxInstancesPerHost=5
|
|
||||||
X-DocPath=kioslave/ftp/index.html
|
|
||||||
Class=:internet
|
|
Loading…
Add table
Reference in a new issue