summaryrefslogtreecommitdiffstats
path: root/kioslave
diff options
context:
space:
mode:
Diffstat (limited to 'kioslave')
-rw-r--r--kioslave/CMakeLists.txt18
-rw-r--r--kioslave/Mainpage.dox9
-rw-r--r--kioslave/Makefile.am27
-rw-r--r--kioslave/bzip2/CMakeLists.txt42
-rw-r--r--kioslave/bzip2/Makefile.am11
-rw-r--r--kioslave/bzip2/configure.in.in11
-rw-r--r--kioslave/bzip2/kbzip2filter.cpp187
-rw-r--r--kioslave/bzip2/kbzip2filter.desktop86
-rw-r--r--kioslave/bzip2/kbzip2filter.h54
-rw-r--r--kioslave/file/CMakeLists.txt55
-rw-r--r--kioslave/file/Makefile.am22
-rw-r--r--kioslave/file/file.cc1831
-rw-r--r--kioslave/file/file.h98
-rw-r--r--kioslave/file/file.protocol15
-rw-r--r--kioslave/ftp/CMakeLists.txt44
-rw-r--r--kioslave/ftp/Makefile.am16
-rw-r--r--kioslave/ftp/configure.in.in5
-rw-r--r--kioslave/ftp/ftp.cc2675
-rw-r--r--kioslave/ftp/ftp.h603
-rw-r--r--kioslave/ftp/ftp.protocol18
-rw-r--r--kioslave/gzip/CMakeLists.txt41
-rw-r--r--kioslave/gzip/Makefile.am12
-rw-r--r--kioslave/gzip/kgzipfilter.cpp336
-rw-r--r--kioslave/gzip/kgzipfilter.desktop86
-rw-r--r--kioslave/gzip/kgzipfilter.h52
-rw-r--r--kioslave/http/CMakeLists.txt69
-rw-r--r--kioslave/http/Makefile.am31
-rw-r--r--kioslave/http/README.http_cache_cleaner20
-rw-r--r--kioslave/http/README.webdav184
-rw-r--r--kioslave/http/THOUGHTS28
-rw-r--r--kioslave/http/TODO45
-rw-r--r--kioslave/http/configure.in.bot10
-rw-r--r--kioslave/http/configure.in.in110
-rw-r--r--kioslave/http/http.cc6108
-rw-r--r--kioslave/http/http.h577
-rw-r--r--kioslave/http/http.protocol12
-rw-r--r--kioslave/http/http_cache_cleaner.cpp284
-rw-r--r--kioslave/http/http_cache_cleaner.desktop168
-rw-r--r--kioslave/http/https.protocol12
-rw-r--r--kioslave/http/kcookiejar/CMakeLists.txt63
-rw-r--r--kioslave/http/kcookiejar/Makefile.am31
-rw-r--r--kioslave/http/kcookiejar/domain_info1
-rw-r--r--kioslave/http/kcookiejar/kcookiejar.cpp1558
-rw-r--r--kioslave/http/kcookiejar/kcookiejar.desktop157
-rw-r--r--kioslave/http/kcookiejar/kcookiejar.h365
-rw-r--r--kioslave/http/kcookiejar/kcookiescfg.upd16
-rw-r--r--kioslave/http/kcookiejar/kcookieserver.cpp606
-rw-r--r--kioslave/http/kcookiejar/kcookieserver.h98
-rw-r--r--kioslave/http/kcookiejar/kcookiewin.cpp382
-rw-r--r--kioslave/http/kcookiejar/kcookiewin.h84
-rw-r--r--kioslave/http/kcookiejar/main.cpp92
-rw-r--r--kioslave/http/kcookiejar/netscape_cookie_spec.html331
-rw-r--r--kioslave/http/kcookiejar/rfc21091179
-rw-r--r--kioslave/http/kcookiejar/rfc29651459
-rw-r--r--kioslave/http/kcookiejar/tests/Makefile.am18
-rw-r--r--kioslave/http/kcookiejar/tests/cookie.test162
-rw-r--r--kioslave/http/kcookiejar/tests/cookie_rfc.test148
-rw-r--r--kioslave/http/kcookiejar/tests/cookie_saving.test430
-rw-r--r--kioslave/http/kcookiejar/tests/cookie_settings.test116
-rw-r--r--kioslave/http/kcookiejar/tests/kcookiejartest.cpp270
-rw-r--r--kioslave/http/rfc2518.txt1
-rw-r--r--kioslave/http/rfc2616.txt1
-rw-r--r--kioslave/http/rfc2617.txt1
-rw-r--r--kioslave/http/rfc2817.txt1
-rw-r--r--kioslave/http/rfc2818.txt1
-rw-r--r--kioslave/http/rfc3229.txt1
-rw-r--r--kioslave/http/rfc3253.txt1
-rw-r--r--kioslave/http/shoutcast-icecast.txt605
-rw-r--r--kioslave/http/webdav.protocol18
-rw-r--r--kioslave/http/webdavs.protocol18
-rw-r--r--kioslave/iso/CMakeLists.txt51
-rw-r--r--kioslave/iso/Makefile.am67
-rw-r--r--kioslave/iso/iso.cpp525
-rw-r--r--kioslave/iso/iso.h51
-rw-r--r--kioslave/iso/iso.protocol11
-rw-r--r--kioslave/iso/isoservice.desktop14
-rw-r--r--kioslave/iso/kio_iso.desktop13
-rw-r--r--kioslave/iso/kio_isorc2
-rw-r--r--kioslave/iso/kiso.cpp460
-rw-r--r--kioslave/iso/kiso.h112
-rw-r--r--kioslave/iso/kisodirectory.cpp31
-rw-r--r--kioslave/iso/kisodirectory.h40
-rw-r--r--kioslave/iso/kisofile.cpp53
-rw-r--r--kioslave/iso/kisofile.h49
-rw-r--r--kioslave/iso/libisofs/CMakeLists.txt23
-rw-r--r--kioslave/iso/libisofs/COPYING280
-rw-r--r--kioslave/iso/libisofs/ChangeLog6
-rw-r--r--kioslave/iso/libisofs/Makefile.am18
-rw-r--r--kioslave/iso/libisofs/README24
-rw-r--r--kioslave/iso/libisofs/bswap.h94
-rw-r--r--kioslave/iso/libisofs/el_torito.h63
-rw-r--r--kioslave/iso/libisofs/iso_fs.h219
-rw-r--r--kioslave/iso/libisofs/isofs.c876
-rw-r--r--kioslave/iso/libisofs/isofs.h161
-rw-r--r--kioslave/iso/libisofs/rock.h127
-rw-r--r--kioslave/iso/qfilehack.cpp40
-rw-r--r--kioslave/iso/qfilehack.h38
-rw-r--r--kioslave/metainfo/CMakeLists.txt43
-rw-r--r--kioslave/metainfo/Makefile.am24
-rw-r--r--kioslave/metainfo/metainfo.cpp103
-rw-r--r--kioslave/metainfo/metainfo.h38
-rw-r--r--kioslave/metainfo/metainfo.protocol9
102 files changed, 0 insertions, 25891 deletions
diff --git a/kioslave/CMakeLists.txt b/kioslave/CMakeLists.txt
deleted file mode 100644
index 4c7bfe1c4..000000000
--- a/kioslave/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-add_subdirectory( file )
-add_subdirectory( http )
-add_subdirectory( ftp )
-add_subdirectory( gzip )
-add_subdirectory( bzip2 )
-add_subdirectory( metainfo )
-add_subdirectory( iso )
diff --git a/kioslave/Mainpage.dox b/kioslave/Mainpage.dox
deleted file mode 100644
index 44979b667..000000000
--- a/kioslave/Mainpage.dox
+++ /dev/null
@@ -1,9 +0,0 @@
-/** @mainpage KIO Slaves
-*
-* KIO Slaves are out-of-process worker applications that
-* perform protocol-specific communications.
-*
-* - <a href="../http/html/">http</a> ioslave
-* - ftp ioslave
-*
-*/
diff --git a/kioslave/Makefile.am b/kioslave/Makefile.am
deleted file mode 100644
index e6472a9c8..000000000
--- a/kioslave/Makefile.am
+++ /dev/null
@@ -1,27 +0,0 @@
-# This file is part of the KDE libraries
-# Copyright (C) 1997 Torben Weis (weis@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.
-
-if include_bzip2
-BZIP2DIR=bzip2
-endif
-
-SUBDIRS = file http ftp gzip $(BZIP2DIR) metainfo iso
-
-messages: # they get into kio.pot
-
-include $(top_srcdir)/admin/Doxyfile.am
diff --git a/kioslave/bzip2/CMakeLists.txt b/kioslave/bzip2/CMakeLists.txt
deleted file mode 100644
index a2354d6b0..000000000
--- a/kioslave/bzip2/CMakeLists.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/kio/kio
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES kbzip2filter.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-##### kbzip2filter ##############################
-
-set( target kbzip2filter )
-
-set( ${target}_SRCS
- kbzip2filter.cpp
-)
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK kio-shared ${BZIP2_LIBRARIES}
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/bzip2/Makefile.am b/kioslave/bzip2/Makefile.am
deleted file mode 100644
index 9353959ab..000000000
--- a/kioslave/bzip2/Makefile.am
+++ /dev/null
@@ -1,11 +0,0 @@
-INCLUDES = -I$(top_srcdir)/kio $(all_includes)
-METASOURCES = AUTO
-
-kde_module_LTLIBRARIES = kbzip2filter.la
-
-kbzip2filter_la_SOURCES = kbzip2filter.cpp
-kbzip2filter_la_LIBADD = $(LIB_KIO) $(LIBBZ2) $(LIB_QT) $(LIB_TDECORE)
-kbzip2filter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
-
-kde_services_DATA = kbzip2filter.desktop
-
diff --git a/kioslave/bzip2/configure.in.in b/kioslave/bzip2/configure.in.in
deleted file mode 100644
index 99392042d..000000000
--- a/kioslave/bzip2/configure.in.in
+++ /dev/null
@@ -1,11 +0,0 @@
-AC_DEFUN([KIOBZIP2_CHECK_BZIP2],
-[
-AC_REQUIRE([AC_FIND_BZIP2])
-
-AM_CONDITIONAL(include_bzip2, test -n "$BZIP2DIR")
-if test -n "$BZIP2DIR"; then
- AC_DEFINE(HAVE_BZIP2_SUPPORT, 1, [Defines if bzip2 is compiled])
-fi
-])
-
-KIOBZIP2_CHECK_BZIP2
diff --git a/kioslave/bzip2/kbzip2filter.cpp b/kioslave/bzip2/kbzip2filter.cpp
deleted file mode 100644
index ae72990d8..000000000
--- a/kioslave/bzip2/kbzip2filter.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (C) 2000 David Faure <faure@kde.org>
-
- $Id$
-
- This library 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.
-
- 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.
-*/
-
-#include <config.h>
-
-#if defined( HAVE_BZIP2_SUPPORT )
-
-// we don't need that
-#define BZ_NO_STDIO
-extern "C" {
- #include <bzlib.h>
-}
-
-#ifdef NEED_BZ2_PREFIX
- #define bzDecompressInit(x,y,z) BZ2_bzDecompressInit(x,y,z)
- #define bzDecompressEnd(x) BZ2_bzDecompressEnd(x)
- #define bzCompressEnd(x) BZ2_bzCompressEnd(x)
- #define bzDecompress(x) BZ2_bzDecompress(x)
- #define bzCompress(x,y) BZ2_bzCompress(x, y)
- #define bzCompressInit(x,y,z,a) BZ2_bzCompressInit(x, y, z, a);
-#endif
-
-#include <kdebug.h>
-#include <klibloader.h>
-
-#include "kbzip2filter.h"
-
-// For docu on this, see /usr/doc/bzip2-0.9.5d/bzip2-0.9.5d/manual_3.html
-
-class KBzip2FilterFactory : public KLibFactory
-{
-public:
- KBzip2FilterFactory() : KLibFactory() {}
- virtual ~KBzip2FilterFactory(){}
- TQObject *createObject( TQObject *, const char *, const char*, const TQStringList & )
- {
- return new KBzip2Filter;
- }
-};
-
-K_EXPORT_COMPONENT_FACTORY( kbzip2filter, KBzip2FilterFactory )
-
-// Not really useful anymore
-class KBzip2Filter::KBzip2FilterPrivate
-{
-public:
- bz_stream zStream;
-};
-
-KBzip2Filter::KBzip2Filter()
-{
- d = new KBzip2FilterPrivate;
- d->zStream.bzalloc = 0;
- d->zStream.bzfree = 0;
- d->zStream.opaque = 0;
- m_mode = 0;
-}
-
-
-KBzip2Filter::~KBzip2Filter()
-{
- delete d;
-}
-
-void KBzip2Filter::init( int mode )
-{
- d->zStream.next_in = 0;
- d->zStream.avail_in = 0;
- if ( mode == IO_ReadOnly )
- {
- (void)bzDecompressInit(&d->zStream, 0, 0);
- //kdDebug(7118) << "bzDecompressInit returned " << result << endl;
- // No idea what to do with result :)
- } else if ( mode == IO_WriteOnly ) {
- (void)bzCompressInit(&d->zStream, 5, 0, 0);
- //kdDebug(7118) << "bzDecompressInit returned " << result << endl;
- } else
- kdWarning(7118) << "Unsupported mode " << mode << ". Only IO_ReadOnly and IO_WriteOnly supported" << endl;
- m_mode = mode;
-}
-
-void KBzip2Filter::terminate()
-{
- if ( m_mode == IO_ReadOnly )
- {
- int result = bzDecompressEnd(&d->zStream);
- kdDebug(7118) << "bzDecompressEnd returned " << result << endl;
- } else if ( m_mode == IO_WriteOnly )
- {
- int result = bzCompressEnd(&d->zStream);
- kdDebug(7118) << "bzCompressEnd returned " << result << endl;
- } else
- kdWarning(7118) << "Unsupported mode " << m_mode << ". Only IO_ReadOnly and IO_WriteOnly supported" << endl;
-}
-
-
-void KBzip2Filter::reset()
-{
- kdDebug(7118) << "KBzip2Filter::reset" << endl;
- // bzip2 doesn't seem to have a reset call...
- terminate();
- init( m_mode );
-}
-
-void KBzip2Filter::setOutBuffer( char * data, uint maxlen )
-{
- d->zStream.avail_out = maxlen;
- d->zStream.next_out = data;
-}
-
-void KBzip2Filter::setInBuffer( const char *data, unsigned int size )
-{
- d->zStream.avail_in = size;
- d->zStream.next_in = const_cast<char *>(data);
-}
-
-int KBzip2Filter::inBufferAvailable() const
-{
- return d->zStream.avail_in;
-}
-
-int KBzip2Filter::outBufferAvailable() const
-{
- return d->zStream.avail_out;
-}
-
-KBzip2Filter::Result KBzip2Filter::uncompress()
-{
- //kdDebug(7118) << "Calling bzDecompress with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable() << endl;
- int result = bzDecompress(&d->zStream);
- if ( result != BZ_OK )
- {
- kdDebug(7118) << "bzDecompress returned " << result << endl;
- kdDebug(7118) << "KBzip2Filter::uncompress " << ( result == BZ_OK ? OK : ( result == BZ_STREAM_END ? END : ERROR ) ) << endl;
- }
-
- switch (result) {
- case BZ_OK:
- return OK;
- case BZ_STREAM_END:
- return END;
- default:
- return ERROR;
- }
-}
-
-KBzip2Filter::Result KBzip2Filter::compress( bool finish )
-{
- //kdDebug(7118) << "Calling bzCompress with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable() << endl;
- int result = bzCompress(&d->zStream, finish ? BZ_FINISH : BZ_RUN );
-
- switch (result) {
- case BZ_OK:
- case BZ_FLUSH_OK:
- case BZ_RUN_OK:
- case BZ_FINISH_OK:
- return OK;
- break;
- case BZ_STREAM_END:
- kdDebug(7118) << " bzCompress returned " << result << endl;
- return END;
- break;
- default:
- kdDebug(7118) << " bzCompress returned " << result << endl;
- return ERROR;
- break;
- }
-}
-
-#endif
diff --git a/kioslave/bzip2/kbzip2filter.desktop b/kioslave/bzip2/kbzip2filter.desktop
deleted file mode 100644
index 51f1c0a84..000000000
--- a/kioslave/bzip2/kbzip2filter.desktop
+++ /dev/null
@@ -1,86 +0,0 @@
-[Desktop Entry]
-Type=Service
-Name=BZip2 Filter
-Name[af]=Bzip2 Filter
-Name[ar]=Ùلتر BZip2
-Name[az]=BZip2 Filtri
-Name[be]=Фільтр BZip2
-Name[bg]=Филтър BZip2
-Name[bn]=বি-জিপ২ (BZip2) ফিলà§à¦Ÿà¦¾à¦°
-Name[br]=Sil BZip2
-Name[ca]=Filtre BZip2
-Name[cs]=Filtr BZip2
-Name[csb]=Filter BZip2
-Name[cy]=Hidl BZip2
-Name[da]=BZip2-filter
-Name[de]=BZip2-Filter
-Name[el]=ΦίλτÏο BZip2
-Name[eo]=Bzip2-filtrilo
-Name[es]=Filtro BZip2
-Name[et]=BZip2 filter
-Name[eu]=BZip2 iragazkia
-Name[fa]=پالایۀ BZip2
-Name[fi]=BZip2-suodin
-Name[fr]=Filtre Bzip2
-Name[fy]=BZip2-filter
-Name[ga]=Scagaire bzip2
-Name[gl]=Filtro BZip2
-Name[he]=מסנן BZip2
-Name[hi]=BZip2 फ़िलà¥à¤Ÿà¤°
-Name[hr]=BZip2 filtar
-Name[hu]=BZip2 szűrő
-Name[id]=Filter BZip2
-Name[is]=BZip2 sía
-Name[it]=Filtro Bzip2
-Name[ja]=BZip2 フィルタ
-Name[ka]=Bzip2 ფილტრი
-Name[kk]=BZip2 ÑүзгіÑÑ–
-Name[km]=ážáž˜áŸ’ážšáž„ BZip2
-Name[ko]=BZip2 거르개
-Name[lb]=BZip2-Filter
-Name[lt]=BZip2 filtras
-Name[lv]=BZip2 Filtrs
-Name[mk]=BZip2 филтер
-Name[mn]=BZip2-Filter
-Name[ms]=Penapis BZip2
-Name[mt]=Filtru BZip2
-Name[nb]=BZip2-filter
-Name[nds]=BZip2-Filter
-Name[ne]=BZip2 फिलà¥à¤Ÿà¤°
-Name[nl]=BZip2-filter
-Name[nn]=BZip2-filter
-Name[nso]=Sesekodi sa BZip2
-Name[pa]=BZip2 ਫਿਲਟਰ
-Name[pl]=Filtr BZip2
-Name[pt]=Filtro do Bzip2
-Name[pt_BR]=Filtro BZip2
-Name[ro]=Filtru BZip2
-Name[ru]=Фильтр bzip2
-Name[rw]=Muyunguruzi BZipu2
-Name[se]=BZip2-filter
-Name[sk]=BZip2 filter
-Name[sl]=Filter za bzip2
-Name[sq]=Filteri BZip2
-Name[sr]=BZip2 филтер
-Name[sr@Latn]=BZip2 filter
-Name[ss]=Sisefo se BZip2
-Name[sv]=Bzip2-filter
-Name[ta]=BZip2 வடிகடà¯à®Ÿà®¿
-Name[te]=బిజిపà±2 గలని
-Name[tg]=Таровиши BZip2
-Name[th]=ตัวà¸à¸£à¸­à¸‡ BZip2
-Name[tr]=BZip2 Filtresi
-Name[tt]=BZip2 Sözgeçe
-Name[uk]=Фільтр BZip2
-Name[uz]=BZip2-filter
-Name[uz@cyrillic]=BZip2-филтер
-Name[ven]=Filithara ya BZip2
-Name[vi]=Bá»™ lá»c BZip2
-Name[wa]=Passete BZip2
-Name[xh]=Isihluzi se BZip2
-Name[zh_CN]=BZip2 过滤程åº
-Name[zh_HK]=BZip2 éŽæ¿¾å™¨
-Name[zh_TW]=BZip2 éŽæ¿¾å™¨
-Name[zu]=Ihluzo le-BZip2
-X-TDE-Library=kbzip2filter
-ServiceTypes=TDECompressionFilter,application/x-bzip2,application/x-tbz
diff --git a/kioslave/bzip2/kbzip2filter.h b/kioslave/bzip2/kbzip2filter.h
deleted file mode 100644
index 2a7b13cf3..000000000
--- a/kioslave/bzip2/kbzip2filter.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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 version 2 as published by the Free Software Foundation.
-
- 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 __kbzip2filter__h
-#define __kbzip2filter__h
-
-#include <config.h>
-
-#if defined( HAVE_BZIP2_SUPPORT )
-
-#include "kfilterbase.h"
-
-class KBzip2Filter : public KFilterBase
-{
-public:
- KBzip2Filter();
- virtual ~KBzip2Filter();
-
- virtual void init( int );
- virtual int mode() const { return m_mode; }
- virtual void terminate();
- virtual void reset();
- virtual bool readHeader() { return true; } // bzip2 handles it by itself ! Cool !
- virtual bool writeHeader( const TQCString & ) { return true; }
- virtual void setOutBuffer( char * data, uint maxlen );
- virtual void setInBuffer( const char * data, uint size );
- virtual int inBufferAvailable() const;
- virtual int outBufferAvailable() const;
- virtual Result uncompress();
- virtual Result compress( bool finish );
-private:
- class KBzip2FilterPrivate;
- KBzip2FilterPrivate *d;
- int m_mode;
-};
-
-#endif
-
-#endif
diff --git a/kioslave/file/CMakeLists.txt b/kioslave/file/CMakeLists.txt
deleted file mode 100644
index 2cf415745..000000000
--- a/kioslave/file/CMakeLists.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-add_definitions(
- -D_LARGEFILE64_SOURCE
-)
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/dcop
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/kio
- ${CMAKE_SOURCE_DIR}/kio/kio
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### headers ###################################
-
-install( FILES file.h DESTINATION ${INCLUDE_INSTALL_DIR}/kio )
-
-
-##### other data ################################
-
-install( FILES file.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-##### kio_file ##################################
-
-set( target kio_file )
-
-set( ${target}_SRCS
- file.cc
-)
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK kio-shared
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
-
diff --git a/kioslave/file/Makefile.am b/kioslave/file/Makefile.am
deleted file mode 100644
index 3daf0cbcc..000000000
--- a/kioslave/file/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-## Makefile.am of tdebase/kioslave/file
-
-AM_CPPFLAGS = -D_LARGEFILE64_SOURCE
-
-INCLUDES = $(all_includes)
-
-####### Files
-
-kde_module_LTLIBRARIES = kio_file.la
-
-kio_file_la_SOURCES = file.cc
-kio_file_la_LIBADD = $(LIB_KIO) $(LIB_QT) $(LIB_TDECORE) $(ACL_LIBS)
-kio_file_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(top_builddir)/dcop/libDCOP.la
-noinst_HEADERS = file.h
-
-fileinclude_HEADERS = file.h
-fileincludedir = $(includedir)/kio
-
-METASOURCES = AUTO
-
-kdelnkdir = $(kde_servicesdir)
-kdelnk_DATA = file.protocol
diff --git a/kioslave/file/file.cc b/kioslave/file/file.cc
deleted file mode 100644
index 2deeb3535..000000000
--- a/kioslave/file/file.cc
+++ /dev/null
@@ -1,1831 +0,0 @@
-/*
- Copyright (C) 2000-2002 Stephan Kulow <coolo@kde.org>
- Copyright (C) 2000-2002 David Faure <faure@kde.org>
- Copyright (C) 2000-2002 Waldo Bastian <bastian@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 (LGPL) 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.
-*/
-
-// $Id$
-
-#include <config.h>
-
-#include <tqglobal.h> //for Q_OS_XXX
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-//sendfile has different semantics in different platforms
-#if defined HAVE_SENDFILE && defined Q_OS_LINUX
-#define USE_SENDFILE 1
-#endif
-
-#ifdef USE_SENDFILE
-#include <sys/sendfile.h>
-#endif
-
-#ifdef USE_POSIX_ACL
-#include <sys/acl.h>
-#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
-#include <acl/libacl.h>
-#else
-#include <posixacladdons.h>
-#endif
-#endif
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <grp.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <time.h>
-#include <utime.h>
-#include <unistd.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#include <tqvaluelist.h>
-#include <tqregexp.h>
-
-#include <dcopref.h>
-#include <kshred.h>
-#include <kdebug.h>
-#include <kurl.h>
-#include <kinstance.h>
-#include <ksimpleconfig.h>
-#include <ktempfile.h>
-#include <klocale.h>
-#include <tqfile.h>
-#include <tqstrlist.h>
-#include "file.h"
-#include <limits.h>
-#include <kprocess.h>
-#include <kmountpoint.h>
-#include <kstandarddirs.h>
-
-#ifdef HAVE_VOLMGT
-#include <volmgt.h>
-#include <sys/mnttab.h>
-#endif
-
-#include <kstandarddirs.h>
-#include <kio/ioslave_defaults.h>
-#include <klargefile.h>
-#include <kglobal.h>
-#include <kmimetype.h>
-
-using namespace KIO;
-
-#define MAX_IPC_SIZE (1024*32)
-
-static TQString testLogFile( const char *_filename );
-#ifdef USE_POSIX_ACL
-static TQString aclAsString( acl_t p_acl );
-static bool isExtendedACL( acl_t p_acl );
-static void appendACLAtoms( const TQCString & path, UDSEntry& entry,
- mode_t type, bool withACL );
-#endif
-
-extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); }
-
-int kdemain( int argc, char **argv )
-{
- KLocale::setMainCatalogue("tdelibs");
- KInstance instance( "kio_file" );
- ( void ) KGlobal::locale();
-
- kdDebug(7101) << "Starting " << getpid() << endl;
-
- if (argc != 4)
- {
- fprintf(stderr, "Usage: kio_file protocol domain-socket1 domain-socket2\n");
- exit(-1);
- }
-
- FileProtocol slave(argv[2], argv[3]);
- slave.dispatchLoop();
-
- kdDebug(7101) << "Done" << endl;
- return 0;
-}
-
-
-FileProtocol::FileProtocol( const TQCString &pool, const TQCString &app ) : SlaveBase( "file", pool, app )
-{
- usercache.setAutoDelete( true );
- groupcache.setAutoDelete( true );
-}
-
-
-int FileProtocol::setACL( const char *path, mode_t perm, bool directoryDefault )
-{
- int ret = 0;
-#ifdef USE_POSIX_ACL
-
- const TQString ACLString = metaData( "ACL_STRING" );
- const TQString defaultACLString = metaData( "DEFAULT_ACL_STRING" );
- // Empty strings mean leave as is
- if ( !ACLString.isEmpty() ) {
- acl_t acl = 0;
- if ( ACLString == "ACL_DELETE" ) {
- // user told us to delete the extended ACL, so let's write only
- // the minimal (UNIX permission bits) part
- acl = acl_from_mode( perm );
- }
- acl = acl_from_text( ACLString.latin1() );
- if ( acl_valid( acl ) == 0 ) { // let's be safe
- ret = acl_set_file( path, ACL_TYPE_ACCESS, acl );
- kdDebug(7101) << "Set ACL on: " << path << " to: " << aclAsString( acl ) << endl;
- }
- acl_free( acl );
- if ( ret != 0 ) return ret; // better stop trying right away
- }
-
- if ( directoryDefault && !defaultACLString.isEmpty() ) {
- if ( defaultACLString == "ACL_DELETE" ) {
- // user told us to delete the default ACL, do so
- ret += acl_delete_def_file( path );
- } else {
- acl_t acl = acl_from_text( defaultACLString.latin1() );
- if ( acl_valid( acl ) == 0 ) { // let's be safe
- ret += acl_set_file( path, ACL_TYPE_DEFAULT, acl );
- kdDebug(7101) << "Set Default ACL on: " << path << " to: " << aclAsString( acl ) << endl;
- }
- acl_free( acl );
- }
- }
-#endif
- return ret;
-}
-
-void FileProtocol::chmod( const KURL& url, int permissions )
-{
- TQCString _path( TQFile::encodeName(url.path()) );
- /* FIXME: Should be atomic */
- if ( ::chmod( _path.data(), permissions ) == -1 ||
- ( setACL( _path.data(), permissions, false ) == -1 ) ||
- /* if not a directory, cannot set default ACLs */
- ( setACL( _path.data(), permissions, true ) == -1 && errno != ENOTDIR ) ) {
-
- switch (errno) {
- case EPERM:
- case EACCES:
- error( KIO::ERR_ACCESS_DENIED, url.path() );
- break;
- case ENOTSUP:
- error( KIO::ERR_UNSUPPORTED_ACTION, url.path() );
- break;
- case ENOSPC:
- error( KIO::ERR_DISK_FULL, url.path() );
- break;
- default:
- error( KIO::ERR_CANNOT_CHMOD, url.path() );
- }
- } else
- finished();
-}
-
-void FileProtocol::mkdir( const KURL& url, int permissions )
-{
- TQCString _path( TQFile::encodeName(url.path()));
-
- kdDebug(7101) << "mkdir(): " << _path << ", permission = " << permissions << endl;
-
- KDE_struct_stat buff;
- if ( KDE_stat( _path.data(), &buff ) == -1 ) {
- if ( ::mkdir( _path.data(), 0777 /*umask will be applied*/ ) != 0 ) {
- if ( errno == EACCES ) {
- error( KIO::ERR_ACCESS_DENIED, url.path() );
- return;
- } else if ( errno == ENOSPC ) {
- error( KIO::ERR_DISK_FULL, url.path() );
- return;
- } else {
- error( KIO::ERR_COULD_NOT_MKDIR, url.path() );
- return;
- }
- } else {
- if ( permissions != -1 )
- chmod( url, permissions );
- else
- finished();
- return;
- }
- }
-
- if ( S_ISDIR( buff.st_mode ) ) {
- kdDebug(7101) << "ERR_DIR_ALREADY_EXIST" << endl;
- error( KIO::ERR_DIR_ALREADY_EXIST, url.path() );
- return;
- }
- error( KIO::ERR_FILE_ALREADY_EXIST, url.path() );
- return;
-}
-
-void FileProtocol::get( const KURL& url )
-{
- if (!url.isLocalFile()) {
- KURL redir(url);
- redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
- redirection(redir);
- finished();
- return;
- }
-
- TQCString _path( TQFile::encodeName(url.path()));
- KDE_struct_stat buff;
- if ( KDE_stat( _path.data(), &buff ) == -1 ) {
- if ( errno == EACCES )
- error( KIO::ERR_ACCESS_DENIED, url.path() );
- else
- error( KIO::ERR_DOES_NOT_EXIST, url.path() );
- return;
- }
-
- if ( S_ISDIR( buff.st_mode ) ) {
- error( KIO::ERR_IS_DIRECTORY, url.path() );
- return;
- }
- if ( !S_ISREG( buff.st_mode ) ) {
- error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
- return;
- }
-
- int fd = KDE_open( _path.data(), O_RDONLY);
- if ( fd < 0 ) {
- error( KIO::ERR_CANNOT_OPEN_FOR_READING, url.path() );
- return;
- }
-
-#ifdef HAVE_FADVISE
- posix_fadvise( fd, 0, 0, POSIX_FADV_SEQUENTIAL);
-#endif
-
- // Determine the mimetype of the file to be retrieved, and emit it.
- // This is mandatory in all slaves (for KRun/BrowserRun to work).
- KMimeType::Ptr mt = KMimeType::findByURL( url, buff.st_mode, true /* local URL */ );
- emit mimeType( mt->name() );
-
- KIO::filesize_t processed_size = 0;
-
- TQString resumeOffset = metaData("resume");
- if ( !resumeOffset.isEmpty() )
- {
- bool ok;
- KIO::fileoffset_t offset = resumeOffset.toLongLong(&ok);
- if (ok && (offset > 0) && (offset < buff.st_size))
- {
- if (KDE_lseek(fd, offset, SEEK_SET) == offset)
- {
- canResume ();
- processed_size = offset;
- kdDebug( 7101 ) << "Resume offset: " << KIO::number(offset) << endl;
- }
- }
- }
-
- totalSize( buff.st_size );
-
- char buffer[ MAX_IPC_SIZE ];
- TQByteArray array;
-
- while( 1 )
- {
- int n = ::read( fd, buffer, MAX_IPC_SIZE );
- if (n == -1)
- {
- if (errno == EINTR)
- continue;
- error( KIO::ERR_COULD_NOT_READ, url.path());
- close(fd);
- return;
- }
- if (n == 0)
- break; // Finished
-
- array.setRawData(buffer, n);
- data( array );
- array.resetRawData(buffer, n);
-
- processed_size += n;
- processedSize( processed_size );
-
- //kdDebug( 7101 ) << "Processed: " << KIO::number (processed_size) << endl;
- }
-
- data( TQByteArray() );
-
- close( fd );
-
- processedSize( buff.st_size );
- finished();
-}
-
-static int
-write_all(int fd, const char *buf, size_t len)
-{
- while (len > 0)
- {
- ssize_t written = write(fd, buf, len);
- if (written < 0)
- {
- if (errno == EINTR)
- continue;
- return -1;
- }
- buf += written;
- len -= written;
- }
- return 0;
-}
-
-static bool
-same_inode(const KDE_struct_stat &src, const KDE_struct_stat &dest)
-{
- if (src.st_ino == dest.st_ino &&
- src.st_dev == dest.st_dev)
- return true;
-
- return false;
-}
-
-void FileProtocol::put( const KURL& url, int _mode, bool _overwrite, bool _resume )
-{
- TQString dest_orig = url.path();
- TQCString _dest_orig( TQFile::encodeName(dest_orig));
-
- kdDebug(7101) << "put(): " << dest_orig << ", mode=" << _mode << endl;
-
- TQString dest_part( dest_orig );
- dest_part += TQString::fromLatin1(".part");
- TQCString _dest_part( TQFile::encodeName(dest_part));
-
- KDE_struct_stat buff_orig;
- bool bOrigExists = (KDE_lstat( _dest_orig.data(), &buff_orig ) != -1);
- bool bPartExists = false;
- bool bMarkPartial = config()->readBoolEntry("MarkPartial", true);
-
- if (bMarkPartial)
- {
- KDE_struct_stat buff_part;
- bPartExists = (KDE_stat( _dest_part.data(), &buff_part ) != -1);
-
- if (bPartExists && !_resume && !_overwrite && buff_part.st_size > 0 && S_ISREG(buff_part.st_mode))
- {
- kdDebug(7101) << "FileProtocol::put : calling canResume with "
- << KIO::number(buff_part.st_size) << endl;
-
- // Maybe we can use this partial file for resuming
- // Tell about the size we have, and the app will tell us
- // if it's ok to resume or not.
- _resume = canResume( buff_part.st_size );
-
- kdDebug(7101) << "FileProtocol::put got answer " << _resume << endl;
- }
- }
-
- if ( bOrigExists && !_overwrite && !_resume)
- {
- if (S_ISDIR(buff_orig.st_mode))
- error( KIO::ERR_DIR_ALREADY_EXIST, dest_orig );
- else
- error( KIO::ERR_FILE_ALREADY_EXIST, dest_orig );
- return;
- }
-
- int result;
- TQString dest;
- TQCString _dest;
-
- int fd = -1;
-
- // Loop until we got 0 (end of data)
- do
- {
- TQByteArray buffer;
- dataReq(); // Request for data
- result = readData( buffer );
-
- if (result >= 0)
- {
- if (dest.isEmpty())
- {
- if (bMarkPartial)
- {
- kdDebug(7101) << "Appending .part extension to " << dest_orig << endl;
- dest = dest_part;
- if ( bPartExists && !_resume )
- {
- kdDebug(7101) << "Deleting partial file " << dest_part << endl;
- remove( _dest_part.data() );
- // Catch errors when we try to open the file.
- }
- }
- else
- {
- dest = dest_orig;
- if ( bOrigExists && !_resume )
- {
- kdDebug(7101) << "Deleting destination file " << dest_orig << endl;
- remove( _dest_orig.data() );
- // Catch errors when we try to open the file.
- }
- }
-
- _dest = TQFile::encodeName(dest);
-
- if ( _resume )
- {
- fd = KDE_open( _dest.data(), O_RDWR ); // append if resuming
- KDE_lseek(fd, 0, SEEK_END); // Seek to end
- }
- else
- {
- // WABA: Make sure that we keep writing permissions ourselves,
- // otherwise we can be in for a surprise on NFS.
- mode_t initialMode;
- if (_mode != -1)
- initialMode = _mode | S_IWUSR | S_IRUSR;
- else
- initialMode = 0666;
-
- fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
- }
-
- if ( fd < 0 )
- {
- kdDebug(7101) << "####################### COULD NOT WRITE " << dest << " _mode=" << _mode << endl;
- kdDebug(7101) << "errno==" << errno << "(" << strerror(errno) << ")" << endl;
- if ( errno == EACCES )
- error( KIO::ERR_WRITE_ACCESS_DENIED, dest );
- else
- error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest );
- return;
- }
- }
-
- if (write_all( fd, buffer.data(), buffer.size()))
- {
- if ( errno == ENOSPC ) // disk full
- {
- error( KIO::ERR_DISK_FULL, dest_orig);
- result = -2; // means: remove dest file
- }
- else
- {
- kdWarning(7101) << "Couldn't write. Error:" << strerror(errno) << endl;
- error( KIO::ERR_COULD_NOT_WRITE, dest_orig);
- result = -1;
- }
- }
- }
- }
- while ( result > 0 );
-
- // An error occurred deal with it.
- if (result < 0)
- {
- kdDebug(7101) << "Error during 'put'. Aborting." << endl;
-
- if (fd != -1)
- {
- close(fd);
-
- KDE_struct_stat buff;
- if (bMarkPartial && KDE_stat( _dest.data(), &buff ) == 0)
- {
- int size = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE);
- if (buff.st_size < size)
- remove(_dest.data());
- }
- }
-
- ::exit(255);
- }
-
- if ( fd == -1 ) // we got nothing to write out, so we never opened the file
- {
- finished();
- return;
- }
-
- if ( close(fd) )
- {
- kdWarning(7101) << "Error when closing file descriptor:" << strerror(errno) << endl;
- error( KIO::ERR_COULD_NOT_WRITE, dest_orig);
- return;
- }
-
- // after full download rename the file back to original name
- if ( bMarkPartial )
- {
- // If the original URL is a symlink and we were asked to overwrite it,
- // remove the symlink first. This ensures that we do not overwrite the
- // current source if the symlink points to it.
- if( _overwrite && S_ISLNK( buff_orig.st_mode ) )
- remove( _dest_orig.data() );
-
- if ( ::rename( _dest.data(), _dest_orig.data() ) )
- {
- kdWarning(7101) << " Couldn't rename " << _dest << " to " << _dest_orig << endl;
- error( KIO::ERR_CANNOT_RENAME_PARTIAL, dest_orig );
- return;
- }
- }
-
- // set final permissions
- if ( _mode != -1 && !_resume )
- {
- if (::chmod(_dest_orig.data(), _mode) != 0)
- {
- // couldn't chmod. Eat the error if the filesystem apparently doesn't support it.
- if ( KIO::testFileSystemFlag( _dest_orig, KIO::SupportsChmod ) )
- warning( i18n( "Could not change permissions for\n%1" ).arg( dest_orig ) );
- }
- }
-
- // set modification time
- const TQString mtimeStr = metaData( "modified" );
- if ( !mtimeStr.isEmpty() ) {
- TQDateTime dt = TQT_TQDATETIME_OBJECT(TQDateTime::fromString( mtimeStr, Qt::ISODate ));
- if ( dt.isValid() ) {
- KDE_struct_stat dest_statbuf;
- if (KDE_stat( _dest_orig.data(), &dest_statbuf ) == 0) {
- struct utimbuf utbuf;
- utbuf.actime = dest_statbuf.st_atime; // access time, unchanged
- utbuf.modtime = dt.toTime_t(); // modification time
- kdDebug() << k_funcinfo << "setting modtime to " << utbuf.modtime << endl;
- utime( _dest_orig.data(), &utbuf );
- }
- }
-
- }
-
- // We have done our job => finish
- finished();
-}
-
-
-void FileProtocol::copy( const KURL &src, const KURL &dest,
- int _mode, bool _overwrite )
-{
- kdDebug(7101) << "copy(): " << src << " -> " << dest << ", mode=" << _mode << endl;
-
- TQCString _src( TQFile::encodeName(src.path()));
- TQCString _dest( TQFile::encodeName(dest.path()));
- KDE_struct_stat buff_src;
-#ifdef USE_POSIX_ACL
- acl_t acl;
-#endif
-
- if ( KDE_stat( _src.data(), &buff_src ) == -1 ) {
- if ( errno == EACCES )
- error( KIO::ERR_ACCESS_DENIED, src.path() );
- else
- error( KIO::ERR_DOES_NOT_EXIST, src.path() );
- return;
- }
-
- if ( S_ISDIR( buff_src.st_mode ) ) {
- error( KIO::ERR_IS_DIRECTORY, src.path() );
- return;
- }
- if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) {
- error( KIO::ERR_CANNOT_OPEN_FOR_READING, src.path() );
- return;
- }
-
- KDE_struct_stat buff_dest;
- bool dest_exists = ( KDE_lstat( _dest.data(), &buff_dest ) != -1 );
- if ( dest_exists )
- {
- if (S_ISDIR(buff_dest.st_mode))
- {
- error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
- return;
- }
-
- if ( same_inode( buff_dest, buff_src) )
- {
- error( KIO::ERR_IDENTICAL_FILES, dest.path() );
- return;
- }
-
- if (!_overwrite)
- {
- error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
- return;
- }
-
- // If the destination is a symlink and overwrite is TRUE,
- // remove the symlink first to prevent the scenario where
- // the symlink actually points to current source!
- if (_overwrite && S_ISLNK(buff_dest.st_mode))
- {
- kdDebug(7101) << "copy(): LINK DESTINATION" << endl;
- remove( _dest.data() );
- }
- }
-
- int src_fd = KDE_open( _src.data(), O_RDONLY);
- if ( src_fd < 0 ) {
- error( KIO::ERR_CANNOT_OPEN_FOR_READING, src.path() );
- return;
- }
-
-#ifdef HAVE_FADVISE
- posix_fadvise(src_fd,0,0,POSIX_FADV_SEQUENTIAL);
-#endif
- // WABA: Make sure that we keep writing permissions ourselves,
- // otherwise we can be in for a surprise on NFS.
- mode_t initialMode;
- if (_mode != -1)
- initialMode = _mode | S_IWUSR;
- else
- initialMode = 0666;
-
- int dest_fd = KDE_open(_dest.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
- if ( dest_fd < 0 ) {
- kdDebug(7101) << "###### COULD NOT WRITE " << dest.url() << endl;
- if ( errno == EACCES ) {
- error( KIO::ERR_WRITE_ACCESS_DENIED, dest.path() );
- } else {
- error( KIO::ERR_CANNOT_OPEN_FOR_WRITING, dest.path() );
- }
- close(src_fd);
- return;
- }
-
-#ifdef HAVE_FADVISE
- posix_fadvise(dest_fd,0,0,POSIX_FADV_SEQUENTIAL);
-#endif
-
-#ifdef USE_POSIX_ACL
- acl = acl_get_fd(src_fd);
- if ( acl && !isExtendedACL( acl ) ) {
- kdDebug(7101) << _dest.data() << " doesn't have extended ACL" << endl;
- acl_free( acl );
- acl = NULL;
- }
-#endif
- totalSize( buff_src.st_size );
-
- KIO::filesize_t processed_size = 0;
- char buffer[ MAX_IPC_SIZE ];
- int n;
-#ifdef USE_SENDFILE
- bool use_sendfile=buff_src.st_size < 0x7FFFFFFF;
-#endif
- while( 1 )
- {
-#ifdef USE_SENDFILE
- if (use_sendfile) {
- off_t sf = processed_size;
- n = ::sendfile( dest_fd, src_fd, &sf, MAX_IPC_SIZE );
- processed_size = sf;
- if ( n == -1 && errno == EINVAL ) { //not all filesystems support sendfile()
- kdDebug(7101) << "sendfile() not supported, falling back " << endl;
- use_sendfile = false;
- }
- }
- if (!use_sendfile)
-#endif
- n = ::read( src_fd, buffer, MAX_IPC_SIZE );
-
- if (n == -1)
- {
- if (errno == EINTR)
- continue;
-#ifdef USE_SENDFILE
- if ( use_sendfile ) {
- kdDebug(7101) << "sendfile() error:" << strerror(errno) << endl;
- if ( errno == ENOSPC ) // disk full
- {
- error( KIO::ERR_DISK_FULL, dest.path());
- remove( _dest.data() );
- }
- else {
- error( KIO::ERR_SLAVE_DEFINED,
- i18n("Cannot copy file from %1 to %2. (Errno: %3)")
- .arg( src.path() ).arg( dest.path() ).arg( errno ) );
- }
- } else
-#endif
- error( KIO::ERR_COULD_NOT_READ, src.path());
- close(src_fd);
- close(dest_fd);
-#ifdef USE_POSIX_ACL
- if (acl) acl_free(acl);
-#endif
- return;
- }
- if (n == 0)
- break; // Finished
-#ifdef USE_SENDFILE
- if ( !use_sendfile ) {
-#endif
- if (write_all( dest_fd, buffer, n))
- {
- close(src_fd);
- close(dest_fd);
-
- if ( errno == ENOSPC ) // disk full
- {
- error( KIO::ERR_DISK_FULL, dest.path());
- remove( _dest.data() );
- }
- else
- {
- kdWarning(7101) << "Couldn't write[2]. Error:" << strerror(errno) << endl;
- error( KIO::ERR_COULD_NOT_WRITE, dest.path());
- }
-#ifdef USE_POSIX_ACL
- if (acl) acl_free(acl);
-#endif
- return;
- }
- processed_size += n;
-#ifdef USE_SENDFILE
- }
-#endif
- processedSize( processed_size );
- }
-
- close( src_fd );
-
- if (close( dest_fd))
- {
- kdWarning(7101) << "Error when closing file descriptor[2]:" << strerror(errno) << endl;
- error( KIO::ERR_COULD_NOT_WRITE, dest.path());
-#ifdef USE_POSIX_ACL
- if (acl) acl_free(acl);
-#endif
- return;
- }
-
- // set final permissions
- if ( _mode != -1 )
- {
- if ( (::chmod(_dest.data(), _mode) != 0)
-#ifdef USE_POSIX_ACL
- || (acl && acl_set_file(_dest.data(), ACL_TYPE_ACCESS, acl) != 0)
-#endif
- )
- {
- // Eat the error if the filesystem apparently doesn't support chmod.
- if ( KIO::testFileSystemFlag( _dest, KIO::SupportsChmod ) )
- warning( i18n( "Could not change permissions for\n%1" ).arg( dest.path() ) );
- }
- }
-#ifdef USE_POSIX_ACL
- if (acl) acl_free(acl);
-#endif
-
- // copy access and modification time
- struct utimbuf ut;
- ut.actime = buff_src.st_atime;
- ut.modtime = buff_src.st_mtime;
- if ( ::utime( _dest.data(), &ut ) != 0 )
- {
- kdWarning() << TQString(TQString::fromLatin1("Couldn't preserve access and modification time for\n%1").arg( dest.path() )) << endl;
- }
-
- processedSize( buff_src.st_size );
- finished();
-}
-
-void FileProtocol::rename( const KURL &src, const KURL &dest,
- bool _overwrite )
-{
- TQCString _src( TQFile::encodeName(src.path()));
- TQCString _dest( TQFile::encodeName(dest.path()));
- KDE_struct_stat buff_src;
- if ( KDE_lstat( _src.data(), &buff_src ) == -1 ) {
- if ( errno == EACCES )
- error( KIO::ERR_ACCESS_DENIED, src.path() );
- else
- error( KIO::ERR_DOES_NOT_EXIST, src.path() );
- return;
- }
-
- KDE_struct_stat buff_dest;
- bool dest_exists = ( KDE_stat( _dest.data(), &buff_dest ) != -1 );
- if ( dest_exists )
- {
- if (S_ISDIR(buff_dest.st_mode))
- {
- error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
- return;
- }
-
- if ( same_inode( buff_dest, buff_src) )
- {
- error( KIO::ERR_IDENTICAL_FILES, dest.path() );
- return;
- }
-
- if (!_overwrite)
- {
- error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
- return;
- }
- }
-
- if ( ::rename( _src.data(), _dest.data()))
- {
- if (( errno == EACCES ) || (errno == EPERM)) {
- error( KIO::ERR_ACCESS_DENIED, dest.path() );
- }
- else if (errno == EXDEV) {
- error( KIO::ERR_UNSUPPORTED_ACTION, TQString::fromLatin1("rename"));
- }
- else if (errno == EROFS) { // The file is on a read-only filesystem
- error( KIO::ERR_CANNOT_DELETE, src.path() );
- }
- else {
- error( KIO::ERR_CANNOT_RENAME, src.path() );
- }
- return;
- }
-
- finished();
-}
-
-void FileProtocol::symlink( const TQString &target, const KURL &dest, bool overwrite )
-{
- // Assume dest is local too (wouldn't be here otherwise)
- if ( ::symlink( TQFile::encodeName( target ), TQFile::encodeName( dest.path() ) ) == -1 )
- {
- // Does the destination already exist ?
- if ( errno == EEXIST )
- {
- if ( overwrite )
- {
- // Try to delete the destination
- if ( unlink( TQFile::encodeName( dest.path() ) ) != 0 )
- {
- error( KIO::ERR_CANNOT_DELETE, dest.path() );
- return;
- }
- // Try again - this won't loop forever since unlink succeeded
- symlink( target, dest, overwrite );
- }
- else
- {
- KDE_struct_stat buff_dest;
- KDE_lstat( TQFile::encodeName( dest.path() ), &buff_dest );
- if (S_ISDIR(buff_dest.st_mode))
- error( KIO::ERR_DIR_ALREADY_EXIST, dest.path() );
- else
- error( KIO::ERR_FILE_ALREADY_EXIST, dest.path() );
- return;
- }
- }
- else
- {
- // Some error occurred while we tried to symlink
- error( KIO::ERR_CANNOT_SYMLINK, dest.path() );
- return;
- }
- }
- finished();
-}
-
-void FileProtocol::del( const KURL& url, bool isfile)
-{
- TQCString _path( TQFile::encodeName(url.path()));
- /*****
- * Delete files
- *****/
-
- if (isfile) {
- kdDebug( 7101 ) << "Deleting file "<< url.url() << endl;
-
- // TODO deletingFile( source );
-
- if ( unlink( _path.data() ) == -1 ) {
- if ((errno == EACCES) || (errno == EPERM))
- error( KIO::ERR_ACCESS_DENIED, url.path());
- else if (errno == EISDIR)
- error( KIO::ERR_IS_DIRECTORY, url.path());
- else
- error( KIO::ERR_CANNOT_DELETE, url.path() );
- return;
- }
- } else {
-
- /*****
- * Delete empty directory
- *****/
-
- kdDebug( 7101 ) << "Deleting directory " << url.url() << endl;
-
- if ( ::rmdir( _path.data() ) == -1 ) {
- if ((errno == EACCES) || (errno == EPERM))
- error( KIO::ERR_ACCESS_DENIED, url.path());
- else {
- kdDebug( 7101 ) << "could not rmdir " << perror << endl;
- error( KIO::ERR_COULD_NOT_RMDIR, url.path() );
- return;
- }
- }
- }
-
- finished();
-}
-
-
-TQString FileProtocol::getUserName( uid_t uid )
-{
- TQString *temp;
- temp = usercache.find( uid );
- if ( !temp ) {
- struct passwd *user = getpwuid( uid );
- if ( user ) {
- usercache.insert( uid, new TQString(TQString::fromLatin1(user->pw_name)) );
- return TQString::fromLatin1( user->pw_name );
- }
- else
- return TQString::number( uid );
- }
- else
- return *temp;
-}
-
-TQString FileProtocol::getGroupName( gid_t gid )
-{
- TQString *temp;
- temp = groupcache.find( gid );
- if ( !temp ) {
- struct group *grp = getgrgid( gid );
- if ( grp ) {
- groupcache.insert( gid, new TQString(TQString::fromLatin1(grp->gr_name)) );
- return TQString::fromLatin1( grp->gr_name );
- }
- else
- return TQString::number( gid );
- }
- else
- return *temp;
-}
-
-
-
-bool FileProtocol::createUDSEntry( const TQString & filename, const TQCString & path, UDSEntry & entry,
- short int details, bool withACL )
-{
- assert(entry.count() == 0); // by contract :-)
- // Note: details = 0 (only "file or directory or symlink or doesn't exist") isn't implemented
- // because there's no real performance penalty in kio_file for returning the complete
- // details. Please consider doing it in your kioslave if you're using this one as a model :)
- UDSAtom atom;
- atom.m_uds = KIO::UDS_NAME;
- atom.m_str = filename;
- entry.append( atom );
-
- mode_t type;
- mode_t access;
- KDE_struct_stat buff;
-
- if ( KDE_lstat( path.data(), &buff ) == 0 ) {
-
- if (S_ISLNK(buff.st_mode)) {
-
- char buffer2[ 1000 ];
- int n = readlink( path.data(), buffer2, 1000 );
- if ( n != -1 ) {
- buffer2[ n ] = 0;
- }
-
- atom.m_uds = KIO::UDS_LINK_DEST;
- atom.m_str = TQFile::decodeName( buffer2 );
- entry.append( atom );
-
- // A symlink -> follow it only if details>1
- if ( details > 1 && KDE_stat( path.data(), &buff ) == -1 ) {
- // It is a link pointing to nowhere
- type = S_IFMT - 1;
- access = S_IRWXU | S_IRWXG | S_IRWXO;
-
- atom.m_uds = KIO::UDS_FILE_TYPE;
- atom.m_long = type;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_ACCESS;
- atom.m_long = access;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_SIZE;
- atom.m_long = 0L;
- entry.append( atom );
-
- goto notype;
-
- }
- }
- } else {
- // kdWarning() << "lstat didn't work on " << path.data() << endl;
- return false;
- }
-
- type = buff.st_mode & S_IFMT; // extract file type
- access = buff.st_mode & 07777; // extract permissions
-
- atom.m_uds = KIO::UDS_FILE_TYPE;
- atom.m_long = type;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_ACCESS;
- atom.m_long = access;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_SIZE;
- atom.m_long = buff.st_size;
- entry.append( atom );
-
-#ifdef USE_POSIX_ACL
- /* Append an atom indicating whether the file has extended acl information
- * and if withACL is specified also one with the acl itself. If it's a directory
- * and it has a default ACL, also append that. */
- appendACLAtoms( path, entry, type, withACL );
-#endif
-
- notype:
- atom.m_uds = KIO::UDS_MODIFICATION_TIME;
- atom.m_long = buff.st_mtime;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_USER;
- atom.m_str = getUserName( buff.st_uid );
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_GROUP;
- atom.m_str = getGroupName( buff.st_gid );
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_ACCESS_TIME;
- atom.m_long = buff.st_atime;
- entry.append( atom );
-
- // Note: buff.st_ctime isn't the creation time !
- // We made that mistake for KDE 2.0, but it's in fact the
- // "file status" change time, which we don't care about.
-
- return true;
-}
-
-void FileProtocol::stat( const KURL & url )
-{
- if (!url.isLocalFile()) {
- KURL redir(url);
- redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
- redirection(redir);
- kdDebug(7101) << "redirecting to " << redir.url() << endl;
- finished();
- return;
- }
-
- /* directories may not have a slash at the end if
- * we want to stat() them; it requires that we
- * change into it .. which may not be allowed
- * stat("/is/unaccessible") -> rwx------
- * stat("/is/unaccessible/") -> EPERM H.Z.
- * This is the reason for the -1
- */
- TQCString _path( TQFile::encodeName(url.path(-1)));
-
- TQString sDetails = metaData(TQString::fromLatin1("details"));
- int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
- kdDebug(7101) << "FileProtocol::stat details=" << details << endl;
-
- UDSEntry entry;
- if ( !createUDSEntry( url.fileName(), _path, entry, details, true /*with acls*/ ) )
- {
- error( KIO::ERR_DOES_NOT_EXIST, url.path(-1) );
- return;
- }
-#if 0
-///////// debug code
- KIO::UDSEntry::ConstIterator it = entry.begin();
- for( ; it != entry.end(); it++ ) {
- switch ((*it).m_uds) {
- case KIO::UDS_FILE_TYPE:
- kdDebug(7101) << "File Type : " << (mode_t)((*it).m_long) << endl;
- break;
- case KIO::UDS_ACCESS:
- kdDebug(7101) << "Access permissions : " << (mode_t)((*it).m_long) << endl;
- break;
- case KIO::UDS_USER:
- kdDebug(7101) << "User : " << ((*it).m_str.ascii() ) << endl;
- break;
- case KIO::UDS_GROUP:
- kdDebug(7101) << "Group : " << ((*it).m_str.ascii() ) << endl;
- break;
- case KIO::UDS_NAME:
- kdDebug(7101) << "Name : " << ((*it).m_str.ascii() ) << endl;
- //m_strText = decodeFileName( (*it).m_str );
- break;
- case KIO::UDS_URL:
- kdDebug(7101) << "URL : " << ((*it).m_str.ascii() ) << endl;
- break;
- case KIO::UDS_MIME_TYPE:
- kdDebug(7101) << "MimeType : " << ((*it).m_str.ascii() ) << endl;
- break;
- case KIO::UDS_LINK_DEST:
- kdDebug(7101) << "LinkDest : " << ((*it).m_str.ascii() ) << endl;
- break;
- case KIO::UDS_EXTENDED_ACL:
- kdDebug(7101) << "Contains extended ACL " << endl;
- break;
- }
- }
- MetaData::iterator it1 = mOutgoingMetaData.begin();
- for ( ; it1 != mOutgoingMetaData.end(); it1++ ) {
- kdDebug(7101) << it1.key() << " = " << it1.data() << endl;
- }
-/////////
-#endif
- statEntry( entry );
-
- finished();
-}
-
-void FileProtocol::listDir( const KURL& url)
-{
- kdDebug(7101) << "========= LIST " << url.url() << " =========" << endl;
- if (!url.isLocalFile()) {
- KURL redir(url);
- redir.setProtocol(config()->readEntry("DefaultRemoteProtocol", "smb"));
- redirection(redir);
- kdDebug(7101) << "redirecting to " << redir.url() << endl;
- finished();
- return;
- }
-
- TQCString _path( TQFile::encodeName(url.path()));
-
- KDE_struct_stat buff;
- if ( KDE_stat( _path.data(), &buff ) == -1 ) {
- error( KIO::ERR_DOES_NOT_EXIST, url.path() );
- return;
- }
-
- if ( !S_ISDIR( buff.st_mode ) ) {
- error( KIO::ERR_IS_FILE, url.path() );
- return;
- }
-
- DIR *dp = 0L;
- KDE_struct_dirent *ep;
-
- dp = opendir( _path.data() );
- if ( dp == 0 ) {
- switch (errno)
- {
-#ifdef ENOMEDIUM
- case ENOMEDIUM:
- error( ERR_SLAVE_DEFINED,
- i18n( "No media in device for %1" ).arg( url.path() ) );
- break;
-#endif
- default:
- error( KIO::ERR_CANNOT_ENTER_DIRECTORY, url.path() );
- break;
- }
- return;
- }
-
- // Don't make this a TQStringList. The locale file name we get here
- // should be passed intact to createUDSEntry to avoid problems with
- // files where TQFile::encodeName(TQFile::decodeName(a)) != a.
- TQStrList entryNames;
-
- while ( ( ep = KDE_readdir( dp ) ) != 0L )
- entryNames.append( ep->d_name );
-
- closedir( dp );
- totalSize( entryNames.count() );
-
- /* set the current dir to the path to speed up
- in not having to pass an absolute path.
- We restore the path later to get out of the
- path - the kernel wouldn't unmount or delete
- directories we keep as active directory. And
- as the slave runs in the background, it's hard
- to see for the user what the problem would be */
-#if !defined(PATH_MAX) && defined(__GLIBC__)
- char *path_buffer;
- path_buffer = getcwd(NULL, 0);
-#else
- char path_buffer[PATH_MAX];
- (void) getcwd(path_buffer, PATH_MAX - 1);
-#endif
- if ( chdir( _path.data() ) ) {
- if (errno == EACCES)
- error(ERR_ACCESS_DENIED, _path);
- else
- error(ERR_CANNOT_ENTER_DIRECTORY, _path);
- finished();
- }
-
- UDSEntry entry;
- TQStrListIterator it(entryNames);
- for (; it.current(); ++it) {
- entry.clear();
- if ( createUDSEntry( TQFile::decodeName(*it),
- *it /* we can use the filename as relative path*/,
- entry, 2, true ) )
- listEntry( entry, false);
- //else
- // ;//Well, this should never happen... but with wrong encoding names
- }
-
- listEntry( entry, true ); // ready
-
- kdDebug(7101) << "============= COMPLETED LIST ============" << endl;
-
- chdir(path_buffer);
-#if !defined(PATH_MAX) && defined(__GLIBC__)
- free(path_buffer);
-#endif
-
- finished();
-}
-
-/*
-void FileProtocol::testDir( const TQString& path )
-{
- TQCString _path( TQFile::encodeName(path));
- KDE_struct_stat buff;
- if ( KDE_stat( _path.data(), &buff ) == -1 ) {
- error( KIO::ERR_DOES_NOT_EXIST, path );
- return;
- }
-
- if ( S_ISDIR( buff.st_mode ) )
- isDirectory();
- else
- isFile();
-
- finished();
-}
-*/
-
-void FileProtocol::special( const TQByteArray &data)
-{
- int tmp;
- TQDataStream stream(data, IO_ReadOnly);
-
- stream >> tmp;
- switch (tmp) {
- case 1:
- {
- TQString fstype, dev, point;
- TQ_INT8 iRo;
-
- stream >> iRo >> fstype >> dev >> point;
-
- bool ro = ( iRo != 0 );
-
- kdDebug(7101) << "MOUNTING fstype=" << fstype << " dev=" << dev << " point=" << point << " ro=" << ro << endl;
- bool ok = pmount( dev );
- if (ok)
- finished();
- else
- mount( ro, fstype.ascii(), dev, point );
-
- }
- break;
- case 2:
- {
- TQString point;
- stream >> point;
- bool ok = pumount( point );
- if (ok)
- finished();
- else
- unmount( point );
- }
- break;
-
- case 3:
- {
- TQString filename;
- stream >> filename;
- KShred shred( filename );
- connect( &shred, TQT_SIGNAL( processedSize( KIO::filesize_t ) ),
- this, TQT_SLOT( slotProcessedSize( KIO::filesize_t ) ) );
- connect( &shred, TQT_SIGNAL( infoMessage( const TQString & ) ),
- this, TQT_SLOT( slotInfoMessage( const TQString & ) ) );
- if (!shred.shred())
- error( KIO::ERR_CANNOT_DELETE, filename );
- else
- finished();
- break;
- }
- default:
- break;
- }
-}
-
-// Connected to KShred
-void FileProtocol::slotProcessedSize( KIO::filesize_t bytes )
-{
- kdDebug(7101) << "FileProtocol::slotProcessedSize (" << (unsigned int) bytes << ")" << endl;
- processedSize( bytes );
-}
-
-// Connected to KShred
-void FileProtocol::slotInfoMessage( const TQString & msg )
-{
- kdDebug(7101) << "FileProtocol::slotInfoMessage (" << msg << ")" << endl;
- infoMessage( msg );
-}
-
-void FileProtocol::mount( bool _ro, const char *_fstype, const TQString& _dev, const TQString& _point )
-{
- kdDebug(7101) << "FileProtocol::mount _fstype=" << _fstype << endl;
- TQCString buffer;
-
-#ifdef HAVE_VOLMGT
- /*
- * support for Solaris volume management
- */
- TQString err;
- TQCString devname = TQFile::encodeName( _dev );
-
- if( volmgt_running() ) {
-// kdDebug(7101) << "VOLMGT: vold ok." << endl;
- if( volmgt_check( devname.data() ) == 0 ) {
- kdDebug(7101) << "VOLMGT: no media in "
- << devname.data() << endl;
- err = i18n("No Media inserted or Media not recognized.");
- error( KIO::ERR_COULD_NOT_MOUNT, err );
- return;
- } else {
- kdDebug(7101) << "VOLMGT: " << devname.data()
- << ": media ok" << endl;
- finished();
- return;
- }
- } else {
- err = i18n("\"vold\" is not running.");
- kdDebug(7101) << "VOLMGT: " << err << endl;
- error( KIO::ERR_COULD_NOT_MOUNT, err );
- return;
- }
-#else
-
-
- KTempFile tmpFile;
- TQCString tmpFileC = TQFile::encodeName(tmpFile.name());
- const char *tmp = tmpFileC.data();
- TQCString dev;
- if ( _dev.startsWith( "LABEL=" ) ) { // turn LABEL=foo into -L foo (#71430)
- TQString labelName = _dev.mid( 6 );
- dev = "-L ";
- dev += TQFile::encodeName( KProcess::quote( labelName ) ); // is it correct to assume same encoding as filesystem?
- } else if ( _dev.startsWith( "UUID=" ) ) { // and UUID=bar into -U bar
- TQString uuidName = _dev.mid( 5 );
- dev = "-U ";
- dev += TQFile::encodeName( KProcess::quote( uuidName ) );
- }
- else
- dev = TQFile::encodeName( KProcess::quote(_dev) ); // get those ready to be given to a shell
-
- TQCString point = TQFile::encodeName( KProcess::quote(_point) );
- bool fstype_empty = !_fstype || !*_fstype;
- TQCString fstype = KProcess::quote(_fstype).latin1(); // good guess
- TQCString readonly = _ro ? "-r" : "";
- TQString epath = TQString::fromLatin1(getenv("PATH"));
- TQString path = TQString::fromLatin1("/sbin:/bin");
- if(!epath.isEmpty())
- path += TQString::fromLatin1(":") + epath;
- TQString mountProg = KGlobal::dirs()->findExe("mount", path);
- if (mountProg.isEmpty()){
- error( KIO::ERR_COULD_NOT_MOUNT, i18n("Could not find program \"mount\""));
- return;
- }
-
- // Two steps, in case mount doesn't like it when we pass all options
- for ( int step = 0 ; step <= 1 ; step++ )
- {
- // Mount using device only if no fstype nor mountpoint (KDE-1.x like)
- if ( !_dev.isEmpty() && _point.isEmpty() && fstype_empty )
- buffer.sprintf( "%s %s 2>%s", mountProg.latin1(), dev.data(), tmp );
- else
- // Mount using the mountpoint, if no fstype nor device (impossible in first step)
- if ( !_point.isEmpty() && _dev.isEmpty() && fstype_empty )
- buffer.sprintf( "%s %s 2>%s", mountProg.latin1(), point.data(), tmp );
- else
- // mount giving device + mountpoint but no fstype
- if ( !_point.isEmpty() && !_dev.isEmpty() && fstype_empty )
- buffer.sprintf( "%s %s %s %s 2>%s", mountProg.latin1(), readonly.data(), dev.data(), point.data(), tmp );
- else
- // mount giving device + mountpoint + fstype
-#if defined(__svr4__) && defined(__sun__) // MARCO for Solaris 8 and I
- // believe this is true for SVR4 in general
- buffer.sprintf( "%s -F %s %s %s %s 2>%s"
- mountProg.latin1()
- fstype.data()
- _ro ? "-oro" : ""
- dev.data()
- point.data()
- tmp );
-#else
- buffer.sprintf( "%s %s -t %s %s %s 2>%s", mountProg.latin1(), readonly.data(),
- fstype.data(), dev.data(), point.data(), tmp );
-#endif
-
- kdDebug(7101) << buffer << endl;
-
- int mount_ret = system( buffer.data() );
-
- TQString err = testLogFile( tmp );
- if ( err.isEmpty() && mount_ret == 0)
- {
- finished();
- return;
- }
- else
- {
- // Didn't work - or maybe we just got a warning
- TQString mp = KIO::findDeviceMountPoint( _dev );
- // Is the device mounted ?
- if ( !mp.isEmpty() && mount_ret == 0)
- {
- kdDebug(7101) << "mount got a warning: " << err << endl;
- warning( err );
- finished();
- return;
- }
- else
- {
- if ( (step == 0) && !_point.isEmpty())
- {
- kdDebug(7101) << err << endl;
- kdDebug(7101) << "Mounting with those options didn't work, trying with only mountpoint" << endl;
- fstype = "";
- fstype_empty = true;
- dev = "";
- // The reason for trying with only mountpoint (instead of
- // only device) is that some people (hi Malte!) have the
- // same device associated with two mountpoints
- // for different fstypes, like /dev/fd0 /mnt/e2floppy and
- // /dev/fd0 /mnt/dosfloppy.
- // If the user has the same mountpoint associated with two
- // different devices, well they shouldn't specify the
- // mountpoint but just the device.
- }
- else
- {
- error( KIO::ERR_COULD_NOT_MOUNT, err );
- return;
- }
- }
- }
- }
-#endif /* ! HAVE_VOLMGT */
-}
-
-
-void FileProtocol::unmount( const TQString& _point )
-{
- TQCString buffer;
-
- KTempFile tmpFile;
- TQCString tmpFileC = TQFile::encodeName(tmpFile.name());
- TQString err;
- const char *tmp = tmpFileC.data();
-
-#ifdef HAVE_VOLMGT
- /*
- * support for Solaris volume management
- */
- char *devname;
- char *ptr;
- FILE *mnttab;
- struct mnttab mnt;
-
- if( volmgt_running() ) {
- kdDebug(7101) << "VOLMGT: looking for "
- << _point.local8Bit() << endl;
-
- if( (mnttab = KDE_fopen( MNTTAB, "r" )) == NULL ) {
- err = "couldn't open mnttab";
- kdDebug(7101) << "VOLMGT: " << err << endl;
- error( KIO::ERR_COULD_NOT_UNMOUNT, err );
- return;
- }
-
- /*
- * since there's no way to derive the device name from
- * the mount point through the volmgt library (and
- * media_findname() won't work in this case), we have to
- * look ourselves...
- */
- devname = NULL;
- rewind( mnttab );
- while( getmntent( mnttab, &mnt ) == 0 ) {
- if( strcmp( _point.local8Bit(), mnt.mnt_mountp ) == 0 ){
- devname = mnt.mnt_special;
- break;
- }
- }
- fclose( mnttab );
-
- if( devname == NULL ) {
- err = "not in mnttab";
- kdDebug(7101) << "VOLMGT: "
- << TQFile::encodeName(_point).data()
- << ": " << err << endl;
- error( KIO::ERR_COULD_NOT_UNMOUNT, err );
- return;
- }
-
- /*
- * strip off the directory name (volume name)
- * the eject(1) command will handle unmounting and
- * physically eject the media (if possible)
- */
- ptr = strrchr( devname, '/' );
- *ptr = '\0';
- TQCString qdevname(TQFile::encodeName(KProcess::quote(TQFile::decodeName(TQCString(devname)))).data());
- buffer.sprintf( "/usr/bin/eject %s 2>%s", qdevname.data(), tmp );
- kdDebug(7101) << "VOLMGT: eject " << qdevname << endl;
-
- /*
- * from eject(1): exit status == 0 => need to manually eject
- * exit status == 4 => media was ejected
- */
-// if( WEXITSTATUS( system( buffer.local8Bit() )) == 4 ) {
- if( WEXITSTATUS( system( buffer.data() )) == 4 ) { // Fix for TQString -> QCString?
- /*
- * this is not an error, so skip "testLogFile()"
- * to avoid wrong/confusing error popup
- */
- unlink( tmp );
- finished();
- return;
- }
- } else {
- /*
- * eject(1) should do its job without vold(1M) running,
- * so we probably could call eject anyway, but since the
- * media is mounted now, vold must've died for some reason
- * during the user's session, so it should be restarted...
- */
- err = i18n("\"vold\" is not running.");
- kdDebug(7101) << "VOLMGT: " << err << endl;
- error( KIO::ERR_COULD_NOT_UNMOUNT, err );
- return;
- }
-#else
- TQString epath = getenv("PATH");
- TQString path = TQString::fromLatin1("/sbin:/bin");
- if (!epath.isEmpty())
- path += ":" + epath;
- TQString umountProg = KGlobal::dirs()->findExe("umount", path);
-
- if (umountProg.isEmpty()) {
- error( KIO::ERR_COULD_NOT_UNMOUNT, i18n("Could not find program \"umount\""));
- return;
- }
- buffer.sprintf( "%s %s 2>%s", umountProg.latin1(), TQFile::encodeName(KProcess::quote(_point)).data(), tmp );
- system( buffer.data() );
-#endif /* HAVE_VOLMGT */
-
- err = testLogFile( tmp );
-
- if (err.contains("fstab") || err.contains("root")) {
- TQString olderr;
- err = TQString::null;
-
- DCOPRef d("kded", "mediamanager");
- d.setDCOPClient ( dcopClient() );
- DCOPReply reply = d.call("properties", _point);
- TQString udi;
-
- if ( reply.isValid() ) {
- TQStringList list = reply;
- if (list.size())
- udi = list[0];
- }
-
- if (!udi.isEmpty())
- reply = d.call("unmount", udi);
-
- if (udi.isEmpty() || !reply.isValid())
- err = olderr;
- else if (reply.isValid())
- reply.get(err);
- }
-
- if ( err.isEmpty() )
- finished();
- else
- error( KIO::ERR_COULD_NOT_UNMOUNT, err );
-}
-
-/*************************************
- *
- * pmount handling
- *
- *************************************/
-
-bool FileProtocol::pmount(const TQString &dev)
-{
- TQString epath = getenv("PATH");
- TQString path = TQString::fromLatin1("/sbin:/bin");
- if (!epath.isEmpty())
- path += ":" + epath;
- TQString pmountProg = KGlobal::dirs()->findExe("pmount", path);
-
- if (pmountProg.isEmpty())
- return false;
-
- TQCString buffer;
- buffer.sprintf( "%s %s", TQFile::encodeName(pmountProg).data(),
- TQFile::encodeName(KProcess::quote(dev)).data() );
-
- int res = system( buffer.data() );
-
- return res==0;
-}
-
-bool FileProtocol::pumount(const TQString &point)
-{
- TQString real_point = KStandardDirs::realPath(point);
-
- KMountPoint::List mtab = KMountPoint::currentMountPoints();
-
- KMountPoint::List::const_iterator it = mtab.begin();
- KMountPoint::List::const_iterator end = mtab.end();
-
- TQString dev;
-
- for (; it!=end; ++it)
- {
- TQString tmp = (*it)->mountedFrom();
- TQString mp = (*it)->mountPoint();
- mp = KStandardDirs::realPath(mp);
-
- if (mp==real_point)
- dev = KStandardDirs::realPath(tmp);
- }
-
- if (dev.isEmpty()) return false;
- if (dev.endsWith("/")) dev.truncate(dev.length()-1);
-
- TQString epath = getenv("PATH");
- TQString path = TQString::fromLatin1("/sbin:/bin");
- if (!epath.isEmpty())
- path += ":" + epath;
- TQString pumountProg = KGlobal::dirs()->findExe("pumount", path);
-
- if (pumountProg.isEmpty())
- return false;
-
- TQCString buffer;
- buffer.sprintf( "%s %s", TQFile::encodeName(pumountProg).data(),
- TQFile::encodeName(KProcess::quote(dev)).data() );
-
- int res = system( buffer.data() );
-
- return res==0;
-}
-
-/*************************************
- *
- * Utilities
- *
- *************************************/
-
-static TQString testLogFile( const char *_filename )
-{
- char buffer[ 1024 ];
- KDE_struct_stat buff;
-
- TQString result;
-
- KDE_stat( _filename, &buff );
- int size = buff.st_size;
- if ( size == 0 ) {
- unlink( _filename );
- return result;
- }
-
- FILE * f = KDE_fopen( _filename, "rb" );
- if ( f == 0L ) {
- unlink( _filename );
- result = i18n("Could not read %1").arg(TQFile::decodeName(_filename));
- return result;
- }
-
- result = "";
- const char *p = "";
- while ( p != 0L ) {
- p = fgets( buffer, sizeof(buffer)-1, f );
- if ( p != 0L )
- result += TQString::fromLocal8Bit(buffer);
- }
-
- fclose( f );
-
- unlink( _filename );
-
- return result;
-}
-
-/*************************************
- *
- * ACL handling helpers
- *
- *************************************/
-#ifdef USE_POSIX_ACL
-
-static bool isExtendedACL( acl_t acl )
-{
- return ( acl_equiv_mode( acl, 0 ) != 0 );
-}
-
-static TQString aclAsString( acl_t acl )
-{
- char *aclString = acl_to_text( acl, 0 );
- TQString ret = TQString::fromLatin1( aclString );
- acl_free( (void*)aclString );
- return ret;
-}
-
-static void appendACLAtoms( const TQCString & path, UDSEntry& entry, mode_t type, bool withACL )
-{
- // first check for a noop
-#ifdef HAVE_NON_POSIX_ACL_EXTENSIONS
- if ( acl_extended_file( path.data() ) == 0 ) return;
-#endif
-
- acl_t acl = 0;
- acl_t defaultAcl = 0;
- UDSAtom atom;
- bool isDir = S_ISDIR( type );
- // do we have an acl for the file, and/or a default acl for the dir, if it is one?
- if ( ( acl = acl_get_file( path.data(), ACL_TYPE_ACCESS ) ) ) {
- if ( !isExtendedACL( acl ) ) {
- acl_free( acl );
- acl = 0;
- }
- }
-
- /* Sadly libacl does not provided a means of checking for extended ACL and default
- * ACL separately. Since a directory can have both, we need to check again. */
- if ( isDir )
- defaultAcl = acl_get_file( path.data(), ACL_TYPE_DEFAULT );
-
- if ( acl || defaultAcl ) {
- kdDebug(7101) << path.data() << " has extended ACL entries " << endl;
- atom.m_uds = KIO::UDS_EXTENDED_ACL;
- atom.m_long = 1;
- entry.append( atom );
- }
- if ( withACL ) {
- if ( acl ) {
- atom.m_uds = KIO::UDS_ACL_STRING;
- atom.m_str = aclAsString( acl );
- entry.append( atom );
- kdDebug(7101) << path.data() << "ACL: " << atom.m_str << endl;
- }
- if ( defaultAcl ) {
- atom.m_uds = KIO::UDS_DEFAULT_ACL_STRING;
- atom.m_str = aclAsString( defaultAcl );
- entry.append( atom );
- kdDebug(7101) << path.data() << "DEFAULT ACL: " << atom.m_str << endl;
- }
- }
- if ( acl ) acl_free( acl );
- if ( defaultAcl ) acl_free( defaultAcl );
-}
-#endif
-
-#include "file.moc"
diff --git a/kioslave/file/file.h b/kioslave/file/file.h
deleted file mode 100644
index 350703da5..000000000
--- a/kioslave/file/file.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- Copyright (C) 2000-2002 Stephan Kulow <coolo@kde.org>
- Copyright (C) 2000-2002 David Faure <faure@kde.org>
- Copyright (C) 2000-2002 Waldo Bastian <bastian@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 (LGPL) 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 __file_h__
-#define __file_h__ "$Id$"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <stdio.h>
-#include <unistd.h>
-
-#include <tqobject.h>
-#include <tqintdict.h>
-#include <tqstring.h>
-#include <tqvaluelist.h>
-
-#include <kio/global.h>
-#include <kio/slavebase.h>
-
-// Note that this header file is installed, so think twice
-// before breaking binary compatibility (read: it is forbidden :)
-
-class FileProtocol : public TQObject, public KIO::SlaveBase
-{
- Q_OBJECT
-public:
- FileProtocol( const TQCString &pool, const TQCString &app);
- virtual ~FileProtocol() { }
-
- virtual void get( const KURL& url );
- virtual void put( const KURL& url, int permissions,
- bool overwrite, bool resume );
- virtual void copy( const KURL &src, const KURL &dest,
- int permissions, bool overwrite );
- virtual void rename( const KURL &src, const KURL &dest,
- bool overwrite );
- virtual void symlink( const TQString &target, const KURL &dest,
- bool overwrite );
-
- virtual void stat( const KURL& url );
- virtual void listDir( const KURL& url );
- virtual void mkdir( const KURL& url, int permissions );
- virtual void chmod( const KURL& url, int permissions );
- virtual void del( const KURL& url, bool isfile);
-
- /**
- * Special commands supported by this slave:
- * 1 - mount
- * 2 - unmount
- * 3 - shred
- */
- virtual void special( const TQByteArray &data);
- void unmount( const TQString& point );
- void mount( bool _ro, const char *_fstype, const TQString& dev, const TQString& point );
- bool pumount( const TQString &point );
- bool pmount( const TQString &dev );
-
-protected slots:
- void slotProcessedSize( KIO::filesize_t _bytes );
- void slotInfoMessage( const TQString & msg );
-
-protected:
-
- bool createUDSEntry( const TQString & filename, const TQCString & path, KIO::UDSEntry & entry,
- short int details, bool withACL );
- int setACL( const char *path, mode_t perm, bool _directoryDefault );
-
- TQString getUserName( uid_t uid );
- TQString getGroupName( gid_t gid );
-
- TQIntDict<TQString> usercache; // maps long ==> TQString *
- TQIntDict<TQString> groupcache;
-
- class FileProtocolPrivate;
- FileProtocolPrivate *d;
-};
-
-#endif
diff --git a/kioslave/file/file.protocol b/kioslave/file/file.protocol
deleted file mode 100644
index ae3487999..000000000
--- a/kioslave/file/file.protocol
+++ /dev/null
@@ -1,15 +0,0 @@
-[Protocol]
-exec=kio_file
-protocol=file
-input=none
-output=filesystem
-listing=Name,Type,Size,Date,AccessDate,Access,Owner,Group,Link
-reading=true
-writing=true
-makedir=true
-deleting=true
-linking=true
-moving=true
-maxInstances=4
-DocPath=kioslave/file.html
-Class=:local
diff --git a/kioslave/ftp/CMakeLists.txt b/kioslave/ftp/CMakeLists.txt
deleted file mode 100644
index e0287639b..000000000
--- a/kioslave/ftp/CMakeLists.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/tdecore/network
- ${CMAKE_SOURCE_DIR}/kio
- ${CMAKE_SOURCE_DIR}/kio/kio
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES ftp.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-##### kio_ftp ###################################
-
-set( target kio_ftp )
-
-set( ${target}_SRCS
- ftp.cc
-)
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK kio-shared
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/ftp/Makefile.am b/kioslave/ftp/Makefile.am
deleted file mode 100644
index c062d6430..000000000
--- a/kioslave/ftp/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-INCLUDES= $(all_includes)
-
-####### Files
-
-kde_module_LTLIBRARIES = kio_ftp.la
-
-kio_ftp_la_SOURCES = ftp.cc
-kio_ftp_la_LIBADD = $(LIB_KIO) $(LIB_QT) $(LIB_TDECORE)
-kio_ftp_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
-
-noinst_HEADERS = ftp.h
-
-kdelnk_DATA = ftp.protocol
-kdelnkdir = $(kde_servicesdir)
-
-
diff --git a/kioslave/ftp/configure.in.in b/kioslave/ftp/configure.in.in
deleted file mode 100644
index 0c94a9b9b..000000000
--- a/kioslave/ftp/configure.in.in
+++ /dev/null
@@ -1,5 +0,0 @@
-dnl For kio_ftp
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-AC_CHECK_FUNCS( setfsent )
-AC_LANG_RESTORE
diff --git a/kioslave/ftp/ftp.cc b/kioslave/ftp/ftp.cc
deleted file mode 100644
index 5f0f993bc..000000000
--- a/kioslave/ftp/ftp.cc
+++ /dev/null
@@ -1,2675 +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.
-
- Recommended reading explaining FTP details and quirks:
- http://cr.yp.to/ftp.html (by D.J. Bernstein)
-*/
-
-
-#define KIO_FTP_PRIVATE_INCLUDE
-#include "ftp.h"
-
-#include <sys/stat.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h>
-
-#if TIME_WITH_SYS_TIME
-#include <time.h>
-#endif
-
-#include <tqdir.h>
-
-#include <kdebug.h>
-#include <klocale.h>
-#include <kinstance.h>
-#include <kmimemagic.h>
-#include <kmimetype.h>
-#include <ksockaddr.h>
-#include <tdesocketaddress.h>
-#include <kio/ioslave_defaults.h>
-#include <kio/slaveconfig.h>
-#include <kremoteencoding.h>
-#include <klargefile.h>
-
-#ifdef HAVE_STRTOLL
- #define charToLongLong(a) strtoll(a, 0, 10)
-#else
- #define charToLongLong(a) strtol(a, 0, 10)
-#endif
-
-// JPF: a remark on coding style (2004-03-06):
-// Some calls to TQString::fromLatin1() were removed from the code. In most places
-// the KDE code relies on implicit creation of QStrings. Also Qt has a lot of
-// const char* overloads, so that using TQString::fromLatin1() can be ineffectient!
-
-#define FTP_LOGIN "anonymous"
-#define FTP_PASSWD "anonymous@"
-
-//#undef kdDebug
-#define ENABLE_CAN_RESUME
-
-// JPF: somebody should find a better solution for this or move this to KIO
-// JPF: anyhow, in KDE 3.2.0 I found diffent MAX_IPC_SIZE definitions!
-namespace KIO {
- enum buffersizes
- { /**
- * largest buffer size that should be used to transfer data between
- * KIO slaves using the data() function
- */
- maximumIpcSize = 32 * 1024,
- /**
- * this is a reasonable value for an initial read() that a KIO slave
- * can do to obtain data via a slow network connection.
- */
- initialIpcSize = 2 * 1024,
- /**
- * recommended size of a data block passed to findBufferFileType()
- */
- mimimumMimeSize = 1024
- };
-
- // JPF: this helper was derived from write_all in file.cc (FileProtocol).
- static // JPF: in ftp.cc we make it static
- /**
- * This helper handles some special issues (blocking and interrupted
- * system call) when writing to a file handle.
- *
- * @return 0 on success or an error code on failure (ERR_COULD_NOT_WRITE,
- * ERR_DISK_FULL, ERR_CONNECTION_BROKEN).
- */
- int WriteToFile(int fd, const char *buf, size_t len)
- {
- while (len > 0)
- { // JPF: shouldn't there be a KDE_write?
- ssize_t written = write(fd, buf, len);
- if (written >= 0)
- { buf += written;
- len -= written;
- continue;
- }
- switch(errno)
- { case EINTR: continue;
- case EPIPE: return ERR_CONNECTION_BROKEN;
- case ENOSPC: return ERR_DISK_FULL;
- default: return ERR_COULD_NOT_WRITE;
- }
- }
- return 0;
- }
-}
-
-KIO::filesize_t Ftp::UnknownSize = (KIO::filesize_t)-1;
-
-using namespace KIO;
-
-extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); }
-
-int kdemain( int argc, char **argv )
-{
- KLocale::setMainCatalogue("tdelibs");
- KInstance instance( "kio_ftp" );
- ( void ) KGlobal::locale();
-
- kdDebug(7102) << "Starting " << getpid() << endl;
-
- if (argc != 4)
- {
- fprintf(stderr, "Usage: kio_ftp protocol domain-socket1 domain-socket2\n");
- exit(-1);
- }
-
- Ftp slave(argv[2], argv[3]);
- slave.dispatchLoop();
-
- kdDebug(7102) << "Done" << endl;
- return 0;
-}
-
-//===============================================================================
-// FtpTextReader Read Text lines from a file (or socket)
-//===============================================================================
-
-void FtpTextReader::textClear()
-{ m_iTextLine = m_iTextBuff = 0;
- m_szText[0] = 0;
- m_bTextEOF = m_bTextTruncated = false;
-}
-
-int FtpTextReader::textRead(FtpSocket *pSock)
-{
- // if we have still buffered data then move it to the left
- char* pEOL;
- if(m_iTextLine < m_iTextBuff)
- { m_iTextBuff -= m_iTextLine;
- memmove(m_szText, m_szText+m_iTextLine, m_iTextBuff);
- pEOL = (char*)memchr(m_szText, '\n', m_iTextBuff); // have a complete line?
- }
- else
- { m_iTextBuff = 0;
- pEOL = NULL;
- }
- m_bTextEOF = m_bTextTruncated = false;
-
- // read data from the control socket until a complete line is read
- int nBytes;
- while(pEOL == NULL)
- {
- if(m_iTextBuff > textReadLimit)
- { m_bTextTruncated = true;
- m_iTextBuff = textReadLimit;
- }
- nBytes = pSock->read(m_szText+m_iTextBuff, sizeof(m_szText)-m_iTextBuff);
- if(nBytes <= 0)
- {
- // This error can occur after the server closed the connection (after a timeout)
- if(nBytes < 0)
- pSock->debugMessage("textRead failed");
- m_bTextEOF = true;
- pEOL = m_szText + m_iTextBuff;
- }
- else
- {
- m_iTextBuff += nBytes;
- pEOL = (char*)memchr(m_szText, '\n', m_iTextBuff);
- }
- }
-
- nBytes = pEOL - m_szText;
- m_iTextLine = nBytes + 1;
-
- if(nBytes > textReadLimit)
- { m_bTextTruncated = true;
- nBytes = textReadLimit;
- }
- if(nBytes && m_szText[nBytes-1] == '\r')
- nBytes--;
- m_szText[nBytes] = 0;
- return nBytes;
-}
-
-//===============================================================================
-// FtpSocket Helper Class for Data or Control Connections
-//===============================================================================
-void FtpSocket::debugMessage(const char* pszMsg) const
-{
- kdDebug(7102) << m_pszName << ": " << pszMsg << endl;
-}
-
-int FtpSocket::errorMessage(int iErrorCode, const char* pszMsg) const
-{
- kdError(7102) << m_pszName << ": " << pszMsg << endl;
- return iErrorCode;
-}
-
-int FtpSocket::connectSocket(int iTimeOutSec, bool bControl)
-{
- closeSocket();
-
- int iOpt = bControl ? KExtendedSocket::inetSocket
- : KExtendedSocket::noResolve;
- setSocketFlags(iOpt | socketFlags());
- setTimeout(iTimeOutSec);
-
- int iCon = KExtendedSocket::connect();
- if(iCon < 0)
- { int iErrorCode = (status() == IO_LookupError)
- ? ERR_UNKNOWN_HOST : ERR_COULD_NOT_CONNECT;
- TQString strMsg = KExtendedSocket::strError(status(), systemError());
- strMsg.prepend("connect failed (code %1): ");
- return errorMessage(iErrorCode, TQString(strMsg.arg(iCon)).latin1());
- }
- if( !setAddressReusable(true) )
- return errorMessage(ERR_COULD_NOT_CREATE_SOCKET, "setAddressReusable failed");
-
- if(!bControl)
- { int on=1;
- if( !setSocketOption(SO_KEEPALIVE, (char *)&on, sizeof(on)) )
- errorMessage(0, "Keepalive not allowed");
-
- struct linger lng = { 1, 120 };
- if( !setSocketOption(SO_LINGER, (char *)&lng, sizeof (lng)) )
- errorMessage(0, "Linger mode was not allowed.");
- }
-
- debugMessage("connected");
- return 0;
-}
-
-void FtpSocket::closeSocket()
-{
- if(m_server != -1 || fd() != -1)
- debugMessage("disconnected");
-
- if(m_server != -1)
- {
- ::shutdown(m_server, SHUT_RDWR);
- ::close(m_server);
- m_server = -1;
- }
- if(socketStatus() > nothing)
- reset();
- textClear();
-}
-
-bool FtpSocket::setSocketOption(int opt, char*arg, socklen_t len) const
-{
- return (setsockopt(sock(), SOL_SOCKET, opt, arg, len) != -1);
-}
-
-//===============================================================================
-// Ftp
-//===============================================================================
-
-Ftp::Ftp( const TQCString &pool, const TQCString &app )
- : SlaveBase( "ftp", pool, app )
-{
- // init the socket data
- m_data = m_control = NULL;
- ftpCloseControlConnection();
-
- // init other members
- m_port = 0;
- kdDebug(7102) << "Ftp::Ftp()" << endl;
-}
-
-
-Ftp::~Ftp()
-{
- kdDebug(7102) << "Ftp::~Ftp()" << endl;
- closeConnection();
-}
-
-/**
- * This closes a data connection opened by ftpOpenDataConnection().
- */
-void Ftp::ftpCloseDataConnection()
-{
- if(m_data != NULL)
- { delete m_data;
- m_data = NULL;
- }
-}
-
-/**
- * This closes a control connection opened by ftpOpenControlConnection() and reinits the
- * related states. This method gets called from the constructor with m_control = NULL.
- */
-void Ftp::ftpCloseControlConnection()
-{
- m_extControl = 0;
- if(m_control)
- delete m_control;
- m_control = NULL;
- m_cDataMode = 0;
- m_bLoggedOn = false; // logon needs control connction
- m_bTextMode = false;
- m_bBusy = false;
-}
-
-/**
- * Returns the last response from the server (iOffset >= 0) -or- reads a new response
- * (iOffset < 0). The result is returned (with iOffset chars skipped for iOffset > 0).
- */
-const char* Ftp::ftpResponse(int iOffset)
-{
- assert(m_control != NULL); // must have control connection socket
- const char *pTxt = m_control->textLine();
-
- // read the next line ...
- if(iOffset < 0)
- {
- int iMore = 0;
- m_iRespCode = 0;
-
- // If the server sends multiline responses "nnn-text" we loop here until
- // a final "nnn text" line is reached. Only data from the final line will
- // be stored. Some servers (OpenBSD) send a single "nnn-" followed by
- // optional lines that start with a space and a final "nnn text" line.
- do {
- int nBytes = m_control->textRead();
- int iCode = atoi(pTxt);
- if(iCode > 0) m_iRespCode = iCode;
-
- // ignore lines starting with a space in multiline response
- if(iMore != 0 && pTxt[0] == 32)
- ;
- // otherwise the line should start with "nnn-" or "nnn "
- else if(nBytes < 4 || iCode < 100)
- iMore = 0;
- // we got a valid line, now check for multiline responses ...
- else if(iMore == 0 && pTxt[3] == '-')
- iMore = iCode;
- // "nnn " ends multiline mode ...
- else if(iMore != 0 && (iMore != iCode || pTxt[3] != '-'))
- iMore = 0;
-
- if(iMore != 0)
- kdDebug(7102) << " > " << pTxt << endl;
- } while(iMore != 0);
- kdDebug(7102) << "resp> " << pTxt << endl;
-
- m_iRespType = (m_iRespCode > 0) ? m_iRespCode / 100 : 0;
- }
-
- // return text with offset ...
- while(iOffset-- > 0 && pTxt[0])
- pTxt++;
- return pTxt;
-}
-
-
-void Ftp::closeConnection()
-{
- if(m_control != NULL || m_data != NULL)
- kdDebug(7102) << "Ftp::closeConnection m_bLoggedOn=" << m_bLoggedOn << " m_bBusy=" << m_bBusy << endl;
-
- if(m_bBusy) // ftpCloseCommand not called
- {
- kdWarning(7102) << "Ftp::closeConnection Abandoned data stream" << endl;
- ftpCloseDataConnection();
- }
-
- if(m_bLoggedOn) // send quit
- {
- if( !ftpSendCmd( "quit", 0 ) || (m_iRespType != 2) )
- kdWarning(7102) << "Ftp::closeConnection QUIT returned error: " << m_iRespCode << endl;
- }
-
- // close the data and control connections ...
- ftpCloseDataConnection();
- ftpCloseControlConnection();
-}
-
-void Ftp::setHost( const TQString& _host, int _port, const TQString& _user,
- const TQString& _pass )
-{
- kdDebug(7102) << "Ftp::setHost (" << getpid() << "): " << _host << endl;
-
- m_proxyURL = metaData("UseProxy");
- m_bUseProxy = (m_proxyURL.isValid() && m_proxyURL.protocol() == "ftp");
-
- if ( m_host != _host || m_port != _port ||
- m_user != _user || m_pass != _pass )
- closeConnection();
-
- m_host = _host;
- m_port = _port;
- m_user = _user;
- m_pass = _pass;
-}
-
-void Ftp::openConnection()
-{
- ftpOpenConnection(loginExplicit);
-}
-
-bool Ftp::ftpOpenConnection (LoginMode loginMode)
-{
- // check for implicit login if we are already logged on ...
- if(loginMode == loginImplicit && m_bLoggedOn)
- {
- assert(m_control != NULL); // must have control connection socket
- return true;
- }
-
- kdDebug(7102) << "ftpOpenConnection " << m_host << ":" << m_port << " "
- << m_user << " [password hidden]" << endl;
-
- infoMessage( i18n("Opening connection to host %1").arg(m_host) );
-
- if ( m_host.isEmpty() )
- {
- error( ERR_UNKNOWN_HOST, TQString::null );
- return false;
- }
-
- assert( !m_bLoggedOn );
-
- m_initialPath = TQString::null;
- m_currentPath = TQString::null;
-
- TQString host = m_bUseProxy ? m_proxyURL.host() : m_host;
- unsigned short int port = m_bUseProxy ? m_proxyURL.port() : m_port;
-
- if (!ftpOpenControlConnection(host, port) )
- return false; // error emitted by ftpOpenControlConnection
- infoMessage( i18n("Connected to host %1").arg(m_host) );
-
- if(loginMode != loginDefered)
- {
- m_bLoggedOn = ftpLogin();
- if( !m_bLoggedOn )
- return false; // error emitted by ftpLogin
- }
-
- m_bTextMode = config()->readBoolEntry("textmode", false);
- connected();
- return true;
-}
-
-
-/**
- * Called by @ref openConnection. It opens the control connection to the ftp server.
- *
- * @return true on success.
- */
-bool Ftp::ftpOpenControlConnection( const TQString &host, unsigned short int port )
-{
- if ( port == 0 ) {
- struct servent *pse;
- if ( ( pse = getservbyname( "ftp", "tcp" ) ) == NULL )
- port = 21;
- else
- port = ntohs(pse->s_port);
- }
-
- // implicitly close, then try to open a new connection ...
- closeConnection();
- int iErrorCode = ERR_OUT_OF_MEMORY;
- TQString sErrorMsg;
- m_control = new FtpSocket("CNTL");
- if(m_control != NULL)
- {
- // now connect to the server and read the login message ...
- m_control->setAddress(host, port);
- iErrorCode = m_control->connectSocket(connectTimeout(), true);
- sErrorMsg = host;
-
- // on connect success try to read the server message...
- if(iErrorCode == 0)
- {
- const char* psz = ftpResponse(-1);
- if(m_iRespType != 2)
- { // login not successful, do we have an message text?
- if(psz[0])
- sErrorMsg = i18n("%1.\n\nReason: %2").arg(host).arg(psz);
- iErrorCode = ERR_COULD_NOT_CONNECT;
- }
- }
- }
-
- // if there was a problem - report it ...
- if(iErrorCode == 0) // OK, return success
- return true;
- closeConnection(); // clean-up on error
- error(iErrorCode, sErrorMsg);
- return false;
-}
-
-/**
- * Called by @ref openConnection. It logs us in.
- * @ref m_initialPath is set to the current working directory
- * if logging on was successful.
- *
- * @return true on success.
- */
-bool Ftp::ftpLogin()
-{
- infoMessage( i18n("Sending login information") );
-
- assert( !m_bLoggedOn );
-
- TQString user = m_user;
- TQString pass = m_pass;
-
- if ( config()->readBoolEntry("EnableAutoLogin") )
- {
- TQString au = config()->readEntry("autoLoginUser");
- if ( !au.isEmpty() )
- {
- user = au;
- pass = config()->readEntry("autoLoginPass");
- }
- }
-
- // Try anonymous login if both username/password
- // information is blank.
- if (user.isEmpty() && pass.isEmpty())
- {
- user = FTP_LOGIN;
- pass = FTP_PASSWD;
- }
-
- AuthInfo info;
- info.url.setProtocol( "ftp" );
- info.url.setHost( m_host );
- info.url.setPort( m_port );
- info.url.setUser( user );
-
- TQCString tempbuf;
- int failedAuth = 0;
-
- do
- {
- // Check the cache and/or prompt user for password if 1st
- // login attempt failed OR the user supplied a login name,
- // but no password.
- if ( failedAuth > 0 || (!user.isEmpty() && pass.isEmpty()) )
- {
- TQString errorMsg;
- kdDebug(7102) << "Prompting user for login info..." << endl;
-
- // Ask user if we should retry after when login fails!
- if( failedAuth > 0 )
- {
- errorMsg = i18n("Message sent:\nLogin using username=%1 and "
- "password=[hidden]\n\nServer replied:\n%2\n\n"
- ).arg(user).arg(ftpResponse(0));
- }
-
- if ( user != FTP_LOGIN )
- info.username = user;
-
- info.prompt = i18n("You need to supply a username and a password "
- "to access this site.");
- info.commentLabel = i18n( "Site:" );
- info.comment = i18n("<b>%1</b>").arg( m_host );
- info.keepPassword = true; // Prompt the user for persistence as well.
- info.readOnly = (!m_user.isEmpty() && m_user != FTP_LOGIN);
-
- bool disablePassDlg = config()->readBoolEntry( "DisablePassDlg", false );
- if ( disablePassDlg || !openPassDlg( info, errorMsg ) )
- {
- error( ERR_USER_CANCELED, m_host );
- return false;
- }
- else
- {
- user = info.username;
- pass = info.password;
- }
- }
-
- tempbuf = "USER ";
- tempbuf += user.latin1();
- if ( m_bUseProxy )
- {
- tempbuf += '@';
- tempbuf += m_host.latin1();
- if ( m_port > 0 && m_port != DEFAULT_FTP_PORT )
- {
- tempbuf += ':';
- tempbuf += TQString::number(m_port).latin1();
- }
- }
-
- kdDebug(7102) << "Sending Login name: " << tempbuf << endl;
-
- bool loggedIn = ( ftpSendCmd(tempbuf) && (m_iRespCode == 230) );
- bool needPass = (m_iRespCode == 331);
- // Prompt user for login info if we do not
- // get back a "230" or "331".
- if ( !loggedIn && !needPass )
- {
- kdDebug(7102) << "Login failed: " << ftpResponse(0) << endl;
- ++failedAuth;
- continue; // Well we failed, prompt the user please!!
- }
-
- if( needPass )
- {
- tempbuf = "pass ";
- tempbuf += pass.latin1();
- kdDebug(7102) << "Sending Login password: " << "[protected]" << endl;
- loggedIn = ( ftpSendCmd(tempbuf) && (m_iRespCode == 230) );
- }
-
- if ( loggedIn )
- {
- // Do not cache the default login!!
- if( user != FTP_LOGIN && pass != FTP_PASSWD )
- cacheAuthentication( info );
- failedAuth = -1;
- }
-
- } while( ++failedAuth );
-
-
- kdDebug(7102) << "Login OK" << endl;
- infoMessage( i18n("Login OK") );
-
- // Okay, we're logged in. If this is IIS 4, switch dir listing style to Unix:
- // Thanks to jk@soegaard.net (Jens Kristian Søgaard) for this hint
- if( ftpSendCmd("SYST") && (m_iRespType == 2) )
- {
- if( !strncmp( ftpResponse(0), "215 Windows_NT", 14 ) ) // should do for any version
- {
- ftpSendCmd( "site dirstyle" );
- // Check if it was already in Unix style
- // Patch from Keith Refson <Keith.Refson@earth.ox.ac.uk>
- if( !strncmp( ftpResponse(0), "200 MSDOS-like directory output is on", 37 ))
- //It was in Unix style already!
- ftpSendCmd( "site dirstyle" );
- // windows won't support chmod before KDE konquers their desktop...
- m_extControl |= chmodUnknown;
- }
- }
- else
- kdWarning(7102) << "SYST failed" << endl;
-
- if ( config()->readBoolEntry ("EnableAutoLoginMacro") )
- ftpAutoLoginMacro ();
-
- // Get the current working directory
- kdDebug(7102) << "Searching for pwd" << endl;
- if( !ftpSendCmd("PWD") || (m_iRespType != 2) )
- {
- kdDebug(7102) << "Couldn't issue pwd command" << endl;
- error( ERR_COULD_NOT_LOGIN, i18n("Could not login to %1.").arg(m_host) ); // or anything better ?
- return false;
- }
-
- TQString sTmp = remoteEncoding()->decode( ftpResponse(3) );
- int iBeg = sTmp.find('"');
- int iEnd = sTmp.findRev('"');
- if(iBeg > 0 && iBeg < iEnd)
- {
- m_initialPath = sTmp.mid(iBeg+1, iEnd-iBeg-1);
- if(m_initialPath[0] != '/') m_initialPath.prepend('/');
- kdDebug(7102) << "Initial path set to: " << m_initialPath << endl;
- m_currentPath = m_initialPath;
- }
- return true;
-}
-
-void Ftp::ftpAutoLoginMacro ()
-{
- TQString macro = metaData( "autoLoginMacro" );
-
- if ( macro.isEmpty() )
- return;
-
- TQStringList list = TQStringList::split('\n', macro);
-
- for(TQStringList::Iterator it = list.begin() ; it != list.end() ; ++it )
- {
- if ( (*it).startsWith("init") )
- {
- list = TQStringList::split( '\\', macro);
- it = list.begin();
- ++it; // ignore the macro name
-
- for( ; it != list.end() ; ++it )
- {
- // TODO: Add support for arbitrary commands
- // besides simply changing directory!!
- if ( (*it).startsWith( "cwd" ) )
- ftpFolder( (*it).mid(4).stripWhiteSpace(), false );
- }
-
- break;
- }
- }
-}
-
-
-/**
- * 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 Ftp::ftpSendCmd( const TQCString& cmd, int maxretries )
-{
- assert(m_control != NULL); // must have control connection socket
-
- if ( cmd.find( '\r' ) != -1 || cmd.find( '\n' ) != -1)
- {
- kdWarning(7102) << "Invalid command received (contains CR or LF):"
- << cmd.data() << endl;
- error( ERR_UNSUPPORTED_ACTION, m_host );
- return false;
- }
-
- // Don't print out the password...
- bool isPassCmd = (cmd.left(4).lower() == "pass");
- if ( !isPassCmd )
- kdDebug(7102) << "send> " << cmd.data() << endl;
- else
- kdDebug(7102) << "send> pass [protected]" << endl;
-
- // Send the message...
- TQCString buf = cmd;
- buf += "\r\n"; // Yes, must use CR/LF - see http://cr.yp.to/ftp/request.html
- int num = m_control->write(buf.data(), buf.length());
-
- // If we were able to successfully send the command, then we will
- // attempt to read the response. Otherwise, take action to re-attempt
- // the login based on the maximum number of retires specified...
- if( num > 0 )
- ftpResponse(-1);
- else
- { m_iRespType = m_iRespCode = 0;
- m_control->textClear();
- }
-
- // If respCh is NULL or the response is 421 (Timed-out), we try to re-send
- // the command based on the value of maxretries.
- if( (m_iRespType <= 0) || (m_iRespCode == 421) )
- {
- // We have not yet logged on...
- if (!m_bLoggedOn)
- {
- // The command was sent from the ftpLogin function, i.e. we are actually
- // attempting to login in. NOTE: If we already sent the username, we
- // return false and let the user decide whether (s)he wants to start from
- // the beginning...
- if (maxretries > 0 && !isPassCmd)
- {
- closeConnection ();
- if( ftpOpenConnection(loginDefered) )
- ftpSendCmd ( cmd, maxretries - 1 );
- }
-
- return false;
- }
- else
- {
- if ( maxretries < 1 )
- return false;
- else
- {
- kdDebug(7102) << "Was not able to communicate with " << m_host << endl
- << "Attempting to re-establish connection." << endl;
-
- closeConnection(); // Close the old connection...
- openConnection(); // Attempt to re-establish a new connection...
-
- if (!m_bLoggedOn)
- {
- if (m_control != NULL) // if openConnection succeeded ...
- {
- kdDebug(7102) << "Login failure, aborting" << endl;
- error (ERR_COULD_NOT_LOGIN, m_host);
- closeConnection ();
- }
- return false;
- }
-
- kdDebug(7102) << "Logged back in, re-issuing command" << endl;
-
- // If we were able to login, resend the command...
- if (maxretries)
- maxretries--;
-
- return ftpSendCmd( cmd, maxretries );
- }
- }
- }
-
- return true;
-}
-
-/*
- * ftpOpenPASVDataConnection - set up data connection, using PASV mode
- *
- * return 1 if successful, 0 otherwise
- * doesn't set error message, since non-pasv mode will always be tried if
- * this one fails
- */
-int Ftp::ftpOpenPASVDataConnection()
-{
- assert(m_control != NULL); // must have control connection socket
- assert(m_data == NULL); // ... but no data connection
-
- // Check that we can do PASV
- const KSocketAddress *sa = m_control->peerAddress();
- if (sa != NULL && sa->family() != PF_INET)
- return ERR_INTERNAL; // no PASV for non-PF_INET connections
-
- const KInetSocketAddress *sin = static_cast<const KInetSocketAddress*>(sa);
-
- if (m_extControl & pasvUnknown)
- return ERR_INTERNAL; // already tried and got "unknown command"
-
- m_bPasv = true;
-
- /* Let's PASsiVe*/
- if( !ftpSendCmd("PASV") || (m_iRespType != 2) )
- {
- kdDebug(7102) << "PASV attempt failed" << endl;
- // unknown command?
- if( m_iRespType == 5 )
- {
- kdDebug(7102) << "disabling use of PASV" << endl;
- m_extControl |= pasvUnknown;
- }
- return ERR_INTERNAL;
- }
-
- // The usual answer is '227 Entering Passive Mode. (160,39,200,55,6,245)'
- // but anonftpd gives '227 =160,39,200,55,6,245'
- int i[6];
- const char *start = strchr(ftpResponse(3), '(');
- if ( !start )
- start = strchr(ftpResponse(3), '=');
- if ( !start ||
- ( sscanf(start, "(%d,%d,%d,%d,%d,%d)",&i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 &&
- sscanf(start, "=%d,%d,%d,%d,%d,%d", &i[0], &i[1], &i[2], &i[3], &i[4], &i[5]) != 6 ) )
- {
- kdError(7102) << "parsing IP and port numbers failed. String parsed: " << start << endl;
- return ERR_INTERNAL;
- }
-
- // Make hostname and port number ...
- int port = i[4] << 8 | i[5];
-
- // we ignore the host part on purpose for two reasons
- // a) it might be wrong anyway
- // b) it would make us being suceptible to a port scanning attack
-
- // now connect the data socket ...
- m_data = new FtpSocket("PASV");
- m_data->setAddress(sin->nodeName(), port);
-
- kdDebug(7102) << "Connecting to " << sin->nodeName() << " on port " << port << endl;
- return m_data->connectSocket(connectTimeout(), false);
-}
-
-/*
- * ftpOpenEPSVDataConnection - opens a data connection via EPSV
- */
-int Ftp::ftpOpenEPSVDataConnection()
-{
- assert(m_control != NULL); // must have control connection socket
- assert(m_data == NULL); // ... but no data connection
-
- const KSocketAddress *sa = m_control->peerAddress();
- int portnum;
- // we are sure sa is a KInetSocketAddress, because we asked for KExtendedSocket::inetSocket
- // when we connected
- const KInetSocketAddress *sin = static_cast<const KInetSocketAddress*>(sa);
-
- if (m_extControl & epsvUnknown || sa == NULL)
- return ERR_INTERNAL;
-
- m_bPasv = true;
- if( !ftpSendCmd("EPSV") || (m_iRespType != 2) )
- {
- // unknown command?
- if( m_iRespType == 5 )
- {
- kdDebug(7102) << "disabling use of EPSV" << endl;
- m_extControl |= epsvUnknown;
- }
- return ERR_INTERNAL;
- }
-
- const char *start = strchr(ftpResponse(3), '|');
- if ( !start || sscanf(start, "|||%d|", &portnum) != 1)
- return ERR_INTERNAL;
-
- m_data = new FtpSocket("EPSV");
- m_data->setAddress(sin->nodeName(), portnum);
- return m_data->connectSocket(connectTimeout(), false) != 0;
-}
-
-/*
- * ftpOpenEPRTDataConnection
- * @return 0 on success, ERR_INTERNAL if mode not acceptable -or- a fatal error code
- */
-int Ftp::ftpOpenEPRTDataConnection()
-{
- assert(m_control != NULL); // must have control connection socket
- assert(m_data == NULL); // ... but no data connection
-
- // yes, we are sure this is a KInetSocketAddress
- const KInetSocketAddress *sin = static_cast<const KInetSocketAddress*>(m_control->localAddress());
- m_bPasv = false;
- if (m_extControl & eprtUnknown || sin == NULL)
- return ERR_INTERNAL;
-
- m_data = new FtpSocket("EPRT");
- m_data->setHost(sin->nodeName());
- m_data->setPort(0); // setting port to 0 will make us bind to a random, free port
- m_data->setSocketFlags(KExtendedSocket::noResolve | KExtendedSocket::passiveSocket |
- KExtendedSocket::inetSocket);
-
- if (m_data->listen(1) < 0)
- return ERR_COULD_NOT_LISTEN;
-
- sin = static_cast<const KInetSocketAddress*>(m_data->localAddress());
- if (sin == NULL)
- return ERR_INTERNAL;
-
- // TQString command = TQString::fromLatin1("eprt |%1|%2|%3|").arg(sin->ianaFamily())
- // .arg(sin->nodeName())
- // .arg(sin->port());
- TQCString command;
- command.sprintf("eprt |%d|%s|%d|", sin->ianaFamily(),
- sin->nodeName().latin1(), sin->port());
-
- // FIXME! Encoding for hostnames?
- if( ftpSendCmd(command) && (m_iRespType == 2) )
- return 0;
-
- // unknown command?
- if( m_iRespType == 5 )
- {
- kdDebug(7102) << "disabling use of EPRT" << endl;
- m_extControl |= eprtUnknown;
- }
- return ERR_INTERNAL;
-}
-
-/*
- * ftpOpenDataConnection - set up data connection
- *
- * The routine calls several ftpOpenXxxxConnection() helpers to find
- * the best connection mode. If a helper cannot connect if returns
- * ERR_INTERNAL - so this is not really an error! All other error
- * codes are treated as fatal, e.g. they are passed back to the caller
- * who is responsible for calling error(). ftpOpenPortDataConnection
- * can be called as last try and it does never return ERR_INTERNAL.
- *
- * @return 0 if successful, err code otherwise
- */
-int Ftp::ftpOpenDataConnection()
-{
- // make sure that we are logged on and have no data connection...
- assert( m_bLoggedOn );
- ftpCloseDataConnection();
-
- int iErrCode = 0;
- int iErrCodePASV = 0; // Remember error code from PASV
-
- // First try passive (EPSV & PASV) modes
- if( !config()->readBoolEntry("DisablePassiveMode", false) )
- {
- iErrCode = ftpOpenPASVDataConnection();
- if(iErrCode == 0)
- return 0; // success
- iErrCodePASV = iErrCode;
- ftpCloseDataConnection();
-
- if( !config()->readBoolEntry("DisableEPSV", false) )
- {
- iErrCode = ftpOpenEPSVDataConnection();
- if(iErrCode == 0)
- return 0; // success
- ftpCloseDataConnection();
- }
-
- // if we sent EPSV ALL already and it was accepted, then we can't
- // use active connections any more
- if (m_extControl & epsvAllSent)
- return iErrCodePASV ? iErrCodePASV : iErrCode;
- }
-
- if( !config()->readBoolEntry("DisableEPRT", false) )
- {
- iErrCode = ftpOpenEPRTDataConnection();
- if(iErrCode == 0)
- return 0; // success
- ftpCloseDataConnection();
- }
-
- // fall back to port mode
- iErrCode = ftpOpenPortDataConnection();
- if(iErrCode == 0)
- return 0; // success
-
- ftpCloseDataConnection();
- // prefer to return the error code from PASV if any, since that's what should have worked in the first place
- return iErrCodePASV ? iErrCodePASV : iErrCode;
-}
-
-/*
- * ftpOpenPortDataConnection - set up data connection
- *
- * @return 0 if successfull, err code otherwise (but never ERR_INTERNAL
- * because this is the last connection mode that is tried)
- */
-int Ftp::ftpOpenPortDataConnection()
-{
- assert(m_control != NULL); // must have control connection socket
- assert(m_data == NULL); // ... but no data connection
-
- m_bPasv = false;
-
- // create a socket, bind it and let it listen ...
- m_data = new FtpSocket("PORT");
- m_data->setSocketFlags(KExtendedSocket::noResolve | KExtendedSocket::passiveSocket |
- KExtendedSocket::inetSocket);
-
- // yes, we are sure this is a KInetSocketAddress
- const KInetSocketAddress* pAddr = static_cast<const KInetSocketAddress*>(m_control->localAddress());
- m_data->setAddress(pAddr->nodeName(), "0");
- m_data->setAddressReusable(true);
-
- if(m_data->listen(1) < 0)
- return ERR_COULD_NOT_LISTEN;
- struct linger lng = { 0, 0 };
- if ( !m_data->setSocketOption(SO_LINGER, (char*)&lng, sizeof(lng)) )
- return ERR_COULD_NOT_CREATE_SOCKET;
-
- // send the PORT command ...
- pAddr = static_cast<const KInetSocketAddress*>(m_data->localAddress());
- struct sockaddr* psa = (struct sockaddr*)pAddr->addressV4();
- unsigned char* pData = (unsigned char*)(psa->sa_data);
- TQCString portCmd;
- portCmd.sprintf("port %d,%d,%d,%d,%d,%d",
- pData[2], pData[3], pData[4], pData[5], pData[0], pData[1]);
- if( ftpSendCmd(portCmd) && (m_iRespType == 2) )
- return 0;
- return ERR_COULD_NOT_CONNECT;
-}
-
-/*
- * ftpAcceptConnect - wait for incoming connection
- * Used by @ref ftpOpenCommand
- *
- * return false on error or timeout
- */
-int Ftp::ftpAcceptConnect()
-{
- assert(m_data != NULL);
-
- if ( m_bPasv )
- {
- m_data->setServer(-1);
- return true;
- }
-
- int sSock = m_data->fd();
- struct sockaddr addr;
- for(;;)
- {
- fd_set mask;
- FD_ZERO(&mask);
- FD_SET(sSock,&mask);
- int r = KSocks::self()->select(sSock + 1, &mask, NULL, NULL, 0L);
- if( r < 0 && errno != EINTR && errno != EAGAIN )
- continue;
- if( r > 0 )
- break;
- }
-
- ksocklen_t l = sizeof(addr);
- m_data->setServer( KSocks::self()->accept(sSock, &addr, &l) );
- return (m_data->server() != -1);
-}
-
-bool Ftp::ftpOpenCommand( const char *_command, const TQString & _path, char _mode,
- int errorcode, KIO::fileoffset_t _offset )
-{
- int errCode = 0;
- if( !ftpDataMode(_mode) )
- errCode = ERR_COULD_NOT_CONNECT;
- else
- errCode = ftpOpenDataConnection();
-
- if(errCode != 0)
- {
- error(errCode, m_host);
- return false;
- }
-
- if ( _offset > 0 ) {
- // send rest command if offset > 0, this applies to retr and stor commands
- char buf[100];
- sprintf(buf, "rest %lld", _offset);
- if ( !ftpSendCmd( buf ) )
- return false;
- if( m_iRespType != 3 )
- {
- error( ERR_CANNOT_RESUME, _path ); // should never happen
- return false;
- }
- }
-
- TQCString tmp = _command;
- TQString errormessage;
-
- if ( !_path.isEmpty() ) {
- tmp += " ";
- tmp += remoteEncoding()->encode(_path);
- }
-
- if( !ftpSendCmd( tmp ) || (m_iRespType != 1) )
- {
- if( _offset > 0 && strcmp(_command, "retr") == 0 && (m_iRespType == 4) )
- errorcode = ERR_CANNOT_RESUME;
- // The error here depends on the command
- errormessage = _path;
- }
-
- else
- {
- // Only now we know for sure that we can resume
- if ( _offset > 0 && strcmp(_command, "retr") == 0 )
- canResume();
-
- if( ftpAcceptConnect() )
- { m_bBusy = true; // cleared in ftpCloseCommand
- return true;
- }
- errorcode = ERR_COULD_NOT_ACCEPT;
- }
-
- error(errorcode, errormessage);
- return false;
-}
-
-
-bool Ftp::ftpCloseCommand()
-{
- // first close data sockets (if opened), then read response that
- // we got for whatever was used in ftpOpenCommand ( should be 226 )
- if(m_data)
- {
- delete m_data;
- m_data = NULL;
- }
- if(!m_bBusy)
- return true;
-
- kdDebug(7102) << "ftpCloseCommand: reading command result" << endl;
- m_bBusy = false;
-
- if(!ftpResponse(-1) || (m_iRespType != 2) )
- {
- kdDebug(7102) << "ftpCloseCommand: no transfer complete message" << endl;
- return false;
- }
- return true;
-}
-
-void Ftp::mkdir( const KURL & url, int permissions )
-{
- if( !ftpOpenConnection(loginImplicit) )
- return;
-
- TQString path = remoteEncoding()->encode(url);
- TQCString buf = "mkd ";
- buf += remoteEncoding()->encode(path);
-
- if( !ftpSendCmd( buf ) || (m_iRespType != 2) )
- {
- TQString currentPath( m_currentPath );
-
- // Check whether or not mkdir failed because
- // the directory already exists...
- if( ftpFolder( path, false ) )
- {
- error( ERR_DIR_ALREADY_EXIST, path );
- // Change the directory back to what it was...
- (void) ftpFolder( currentPath, false );
- return;
- }
-
- error( ERR_COULD_NOT_MKDIR, path );
- return;
- }
-
- if ( permissions != -1 )
- {
- // chmod the dir we just created, ignoring errors.
- (void) ftpChmod( path, permissions );
- }
-
- finished();
-}
-
-void Ftp::rename( const KURL& src, const KURL& dst, bool overwrite )
-{
- if( !ftpOpenConnection(loginImplicit) )
- return;
-
- // The actual functionality is in ftpRename because put needs it
- if ( ftpRename( src.path(), dst.path(), overwrite ) )
- finished();
- else
- error( ERR_CANNOT_RENAME, src.path() );
-}
-
-bool Ftp::ftpRename( const TQString & src, const TQString & dst, bool overwrite )
-{
- assert( m_bLoggedOn );
-
- // Must check if dst already exists, RNFR+RNTO overwrites by default (#127793).
- if (!overwrite) {
- if (ftpSize(dst, 'I')) {
- error(ERR_FILE_ALREADY_EXIST, dst);
- return false;
- }
- }
- if (ftpFolder(dst, false)) {
- error(ERR_DIR_ALREADY_EXIST, dst);
- return false;
- }
-
- // Must check if dst already exists, RNFR+RNTO overwrites by default (#127793).
- if (ftpFileExists(dst)) {
- error(ERR_FILE_ALREADY_EXIST, dst);
- return false;
- }
- if (ftpFolder(dst, false)) {
- error(ERR_DIR_ALREADY_EXIST, dst);
- return false;
- }
-
- int pos = src.findRev("/");
- if( !ftpFolder(src.left(pos+1), false) )
- return false;
-
- TQCString from_cmd = "RNFR ";
- from_cmd += remoteEncoding()->encode(src.mid(pos+1));
- if( !ftpSendCmd( from_cmd ) || (m_iRespType != 3) )
- return false;
-
- TQCString to_cmd = "RNTO ";
- to_cmd += remoteEncoding()->encode(dst);
- if( !ftpSendCmd( to_cmd ) || (m_iRespType != 2) )
- return false;
-
- return true;
-}
-
-void Ftp::del( const KURL& url, bool isfile )
-{
- if( !ftpOpenConnection(loginImplicit) )
- return;
-
- // When deleting a directory, we must exit from it first
- // The last command probably went into it (to stat it)
- if ( !isfile )
- ftpFolder(remoteEncoding()->directory(url), false); // ignore errors
-
- TQCString cmd = isfile ? "DELE " : "RMD ";
- cmd += remoteEncoding()->encode(url);
-
- if( !ftpSendCmd( cmd ) || (m_iRespType != 2) )
- error( ERR_CANNOT_DELETE, url.path() );
- else
- finished();
-}
-
-bool Ftp::ftpChmod( const TQString & path, int permissions )
-{
- assert( m_bLoggedOn );
-
- if(m_extControl & chmodUnknown) // previous errors?
- return false;
-
- // we need to do bit AND 777 to get permissions, in case
- // we were sent a full mode (unlikely)
- TQCString cmd;
- cmd.sprintf("SITE CHMOD %o ", permissions & 511 );
- cmd += remoteEncoding()->encode(path);
-
- ftpSendCmd(cmd);
- if(m_iRespType == 2)
- return true;
-
- if(m_iRespCode == 500)
- {
- m_extControl |= chmodUnknown;
- kdDebug(7102) << "ftpChmod: CHMOD not supported - disabling";
- }
- return false;
-}
-
-void Ftp::chmod( const KURL & url, int permissions )
-{
- if( !ftpOpenConnection(loginImplicit) )
- return;
-
- if ( !ftpChmod( url.path(), permissions ) )
- error( ERR_CANNOT_CHMOD, url.path() );
- else
- finished();
-}
-
-void Ftp::ftpCreateUDSEntry( const TQString & filename, FtpEntry& ftpEnt, UDSEntry& entry, bool isDir )
-{
- assert(entry.count() == 0); // by contract :-)
- UDSAtom atom;
- atom.m_uds = UDS_NAME;
- atom.m_str = filename;
- entry.append( atom );
-
- atom.m_uds = UDS_SIZE;
- atom.m_long = ftpEnt.size;
- entry.append( atom );
-
- atom.m_uds = UDS_MODIFICATION_TIME;
- atom.m_long = ftpEnt.date;
- entry.append( atom );
-
- atom.m_uds = UDS_ACCESS;
- atom.m_long = ftpEnt.access;
- entry.append( atom );
-
- atom.m_uds = UDS_USER;
- atom.m_str = ftpEnt.owner;
- entry.append( atom );
-
- if ( !ftpEnt.group.isEmpty() )
- {
- atom.m_uds = UDS_GROUP;
- atom.m_str = ftpEnt.group;
- entry.append( atom );
- }
-
- if ( !ftpEnt.link.isEmpty() )
- {
- atom.m_uds = UDS_LINK_DEST;
- atom.m_str = ftpEnt.link;
- entry.append( atom );
-
- KMimeType::Ptr mime = KMimeType::findByURL( KURL("ftp://host/" + filename ) );
- // Links on ftp sites are often links to dirs, and we have no way to check
- // that. Let's do like Netscape : assume dirs generally.
- // But we do this only when the mimetype can't be known from the filename.
- // --> we do better than Netscape :-)
- if ( mime->name() == KMimeType::defaultMimeType() )
- {
- kdDebug(7102) << "Setting guessed mime type to inode/directory for " << filename << endl;
- atom.m_uds = UDS_GUESSED_MIME_TYPE;
- atom.m_str = "inode/directory";
- entry.append( atom );
- isDir = true;
- }
- }
-
- atom.m_uds = UDS_FILE_TYPE;
- atom.m_long = isDir ? S_IFDIR : ftpEnt.type;
- entry.append( atom );
-
- /* atom.m_uds = UDS_ACCESS_TIME;
- atom.m_long = buff.st_atime;
- entry.append( atom );
-
- atom.m_uds = UDS_CREATION_TIME;
- atom.m_long = buff.st_ctime;
- entry.append( atom ); */
-}
-
-
-void Ftp::ftpShortStatAnswer( const TQString& filename, bool isDir )
-{
- UDSEntry entry;
- UDSAtom atom;
-
- atom.m_uds = KIO::UDS_NAME;
- atom.m_str = filename;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_FILE_TYPE;
- atom.m_long = isDir ? S_IFDIR : S_IFREG;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_ACCESS;
- atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
- entry.append( atom );
-
- // No details about size, ownership, group, etc.
-
- statEntry(entry);
- finished();
-}
-
-void Ftp::ftpStatAnswerNotFound( const TQString & path, const TQString & filename )
-{
- // Only do the 'hack' below if we want to download an existing file (i.e. when looking at the "source")
- // When e.g. uploading a file, we still need stat() to return "not found"
- // when the file doesn't exist.
- TQString statSide = metaData("statSide");
- kdDebug(7102) << "Ftp::stat statSide=" << statSide << endl;
- if ( statSide == "source" )
- {
- kdDebug(7102) << "Not found, but assuming found, because some servers don't allow listing" << endl;
- // MS Server is incapable of handling "list <blah>" in a case insensitive way
- // But "retr <blah>" works. So lie in stat(), to get going...
- //
- // There's also the case of ftp://ftp2.3ddownloads.com/90380/linuxgames/loki/patches/ut/ut-patch-436.run
- // where listing permissions are denied, but downloading is still possible.
- ftpShortStatAnswer( filename, false /*file, not dir*/ );
-
- return;
- }
-
- error( ERR_DOES_NOT_EXIST, path );
-}
-
-void Ftp::stat( const KURL &url)
-{
- kdDebug(7102) << "Ftp::stat : path='" << url.path() << "'" << endl;
- if( !ftpOpenConnection(loginImplicit) )
- return;
-
- TQString path = TQDir::cleanDirPath( url.path() );
- kdDebug(7102) << "Ftp::stat : cleaned path='" << path << "'" << endl;
-
- // We can't stat root, but we know it's a dir.
- if( path.isEmpty() || path == "/" )
- {
- UDSEntry entry;
- UDSAtom atom;
-
- atom.m_uds = KIO::UDS_NAME;
- atom.m_str = TQString::null;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_FILE_TYPE;
- atom.m_long = S_IFDIR;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_ACCESS;
- atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_USER;
- atom.m_str = "root";
- entry.append( atom );
- atom.m_uds = KIO::UDS_GROUP;
- entry.append( atom );
-
- // no size
-
- statEntry( entry );
- finished();
- return;
- }
-
- KURL tempurl( url );
- tempurl.setPath( path ); // take the clean one
- TQString listarg; // = tempurl.directory(false /*keep trailing slash*/);
- TQString parentDir;
- TQString filename = tempurl.fileName();
- Q_ASSERT(!filename.isEmpty());
- TQString search = filename;
-
- // Try cwd into it, if it works it's a dir (and then we'll list the parent directory to get more info)
- // if it doesn't work, it's a file (and then we'll use dir filename)
- bool isDir = ftpFolder(path, false);
-
- // if we're only interested in "file or directory", we should stop here
- TQString sDetails = metaData("details");
- int details = sDetails.isEmpty() ? 2 : sDetails.toInt();
- kdDebug(7102) << "Ftp::stat details=" << details << endl;
- if ( details == 0 )
- {
- if ( !isDir && !ftpSize( path, 'I' ) ) // ok, not a dir -> is it a file ?
- { // no -> it doesn't exist at all
- ftpStatAnswerNotFound( path, filename );
- return;
- }
- ftpShortStatAnswer( filename, isDir ); // successfully found a dir or a file -> done
- return;
- }
-
- if (!isDir)
- {
- // It is a file or it doesn't exist, try going to parent directory
- parentDir = tempurl.directory(false /*keep trailing slash*/);
- // With files we can do "LIST <filename>" to avoid listing the whole dir
- listarg = filename;
- }
- else
- {
- // --- New implementation:
- // Don't list the parent dir. Too slow, might not show it, etc.
- // Just return that it's a dir.
- UDSEntry entry;
- UDSAtom atom;
-
- atom.m_uds = KIO::UDS_NAME;
- atom.m_str = filename;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_FILE_TYPE;
- atom.m_long = S_IFDIR;
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_ACCESS;
- atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
- entry.append( atom );
-
- // No clue about size, ownership, group, etc.
-
- statEntry(entry);
- finished();
- return;
-
- // --- Old implementation:
-#if 0
- // It's a dir, remember that
- // Reason: it could be a symlink to a dir, in which case ftpReadDir
- // in the parent dir will have no idea about that. But we know better.
- isDir = true;
- // If the dir starts with '.', we'll need '-a' to see it in the listing.
- if ( search[0] == '.' )
- listarg = "-a";
- parentDir = "..";
-#endif
- }
-
- // Now cwd the parent dir, to prepare for listing
- if( !ftpFolder(parentDir, true) )
- return;
-
- if( !ftpOpenCommand( "list", listarg, 'I', ERR_DOES_NOT_EXIST ) )
- {
- kdError(7102) << "COULD NOT LIST" << endl;
- return;
- }
- kdDebug(7102) << "Starting of list was ok" << endl;
-
- Q_ASSERT( !search.isEmpty() && search != "/" );
-
- bool bFound = false;
- KURL linkURL;
- FtpEntry ftpEnt;
- while( ftpReadDir(ftpEnt) )
- {
- // We look for search or filename, since some servers (e.g. ftp.tuwien.ac.at)
- // return only the filename when doing "dir /full/path/to/file"
- if ( !bFound )
- {
- if ( ( search == ftpEnt.name || filename == ftpEnt.name ) ) {
- if ( !filename.isEmpty() ) {
- bFound = true;
- UDSEntry entry;
- ftpCreateUDSEntry( filename, ftpEnt, entry, isDir );
- statEntry( entry );
- }
- } else if ( isDir && ( ftpEnt.name == listarg || ftpEnt.name+'/' == listarg ) ) {
- // Damn, the dir we're trying to list is in fact a symlink
- // Follow it and try again
- if ( ftpEnt.link.isEmpty() )
- kdWarning(7102) << "Got " << listarg << " as answer, but empty link!" << endl;
- else
- {
- linkURL = url;
- kdDebug(7102) << "ftpEnt.link=" << ftpEnt.link << endl;
- if ( ftpEnt.link[0] == '/' )
- linkURL.setPath( ftpEnt.link ); // Absolute link
- else
- {
- // Relative link (stat will take care of cleaning ../.. etc.)
- linkURL.setPath( listarg ); // this is what we were listing (the link)
- linkURL.setPath( linkURL.directory() ); // go up one dir
- linkURL.addPath( ftpEnt.link ); // replace link by its destination
- kdDebug(7102) << "linkURL now " << linkURL.prettyURL() << endl;
- }
- // Re-add the filename we're looking for
- linkURL.addPath( filename );
- }
- bFound = true;
- }
- }
-
- // kdDebug(7102) << ftpEnt.name << endl;
- }
-
- ftpCloseCommand(); // closes the data connection only
-
- if ( !bFound )
- {
- ftpStatAnswerNotFound( path, filename );
- return;
- }
-
- if ( !linkURL.isEmpty() )
- {
- if ( linkURL == url || linkURL == tempurl )
- {
- error( ERR_CYCLIC_LINK, linkURL.prettyURL() );
- return;
- }
- stat( linkURL );
- return;
- }
-
- kdDebug(7102) << "stat : finished successfully" << endl;
- finished();
-}
-
-
-void Ftp::listDir( const KURL &url )
-{
- kdDebug(7102) << "Ftp::listDir " << url.prettyURL() << endl;
- if( !ftpOpenConnection(loginImplicit) )
- return;
-
- // No path specified ?
- TQString path = url.path();
- if ( path.isEmpty() )
- {
- KURL realURL;
- realURL.setProtocol( "ftp" );
- if ( m_user != FTP_LOGIN )
- realURL.setUser( m_user );
- // We set the password, so that we don't ask for it if it was given
- if ( m_pass != FTP_PASSWD )
- realURL.setPass( m_pass );
- realURL.setHost( m_host );
- realURL.setPort( m_port );
- if ( m_initialPath.isEmpty() )
- m_initialPath = "/";
- realURL.setPath( m_initialPath );
- kdDebug(7102) << "REDIRECTION to " << realURL.prettyURL() << endl;
- redirection( realURL );
- finished();
- return;
- }
-
- kdDebug(7102) << "hunting for path '" << path << "'" << endl;
-
- if (!ftpOpenDir( path ) )
- {
- if ( ftpSize( path, 'I' ) ) // is it a file ?
- {
- error( ERR_IS_FILE, path );
- return;
- }
- // not sure which to emit
- //error( ERR_DOES_NOT_EXIST, path );
- error( ERR_CANNOT_ENTER_DIRECTORY, path );
- return;
- }
-
- UDSEntry entry;
- FtpEntry ftpEnt;
- while( ftpReadDir(ftpEnt) )
- {
- //kdDebug(7102) << ftpEnt.name << endl;
- //Q_ASSERT( !ftpEnt.name.isEmpty() );
- if ( !ftpEnt.name.isEmpty() )
- {
- //if ( S_ISDIR( (mode_t)ftpEnt.type ) )
- // kdDebug(7102) << "is a dir" << endl;
- //if ( !ftpEnt.link.isEmpty() )
- // kdDebug(7102) << "is a link to " << ftpEnt.link << endl;
- entry.clear();
- ftpCreateUDSEntry( ftpEnt.name, ftpEnt, entry, false );
- listEntry( entry, false );
- }
- }
- listEntry( entry, true ); // ready
- ftpCloseCommand(); // closes the data connection only
- finished();
-}
-
-void Ftp::slave_status()
-{
- kdDebug(7102) << "Got slave_status host = " << (m_host.ascii() ? m_host.ascii() : "[None]") << " [" << (m_bLoggedOn ? "Connected" : "Not connected") << "]" << endl;
- slaveStatus( m_host, m_bLoggedOn );
-}
-
-bool Ftp::ftpOpenDir( const TQString & path )
-{
- //TQString path( _url.path(-1) );
-
- // We try to change to this directory first to see whether it really is a directory.
- // (And also to follow symlinks)
- TQString tmp = path.isEmpty() ? TQString("/") : path;
-
- // We get '550', whether it's a file or doesn't exist...
- if( !ftpFolder(tmp, false) )
- return false;
-
- // Don't use the path in the list command:
- // We changed into this directory anyway - so it's enough just to send "list".
- // We use '-a' because the application MAY be interested in dot files.
- // The only way to really know would be to have a metadata flag for this...
- // Since some windows ftp server seems not to support the -a argument, we use a fallback here.
- // In fact we have to use -la otherwise -a removes the default -l (e.g. ftp.trolltech.com)
- if( !ftpOpenCommand( "list -la", TQString::null, 'I', ERR_CANNOT_ENTER_DIRECTORY ) )
- {
- if ( !ftpOpenCommand( "list", TQString::null, 'I', ERR_CANNOT_ENTER_DIRECTORY ) )
- {
- kdWarning(7102) << "Can't open for listing" << endl;
- return false;
- }
- }
- kdDebug(7102) << "Starting of list was ok" << endl;
- return true;
-}
-
-bool Ftp::ftpReadDir(FtpEntry& de)
-{
- assert(m_data != NULL);
-
- // get a line from the data connecetion ...
- while( !m_data->textEOF() )
- {
- if(m_data->textRead() <= 0)
- continue;
- if(m_data->textTooLong())
- kdWarning(7102) << "ftpReadDir line too long - truncated" << endl;
-
- const char* buffer = m_data->textLine();
- kdDebug(7102) << "dir > " << buffer << endl;
-
- //Normally the listing looks like
- // -rw-r--r-- 1 dfaure dfaure 102 Nov 9 12:30 log
- // but on Netware servers like ftp://ci-1.ci.pwr.wroc.pl/ it looks like (#76442)
- // d [RWCEAFMS] Admin 512 Oct 13 2004 PSI
-
- // we should always get the following 5 fields ...
- const char *p_access, *p_junk, *p_owner, *p_group, *p_size;
- if( (p_access = strtok((char*)buffer," ")) == 0) continue;
- if( (p_junk = strtok(NULL," ")) == 0) continue;
- if( (p_owner = strtok(NULL," ")) == 0) continue;
- if( (p_group = strtok(NULL," ")) == 0) continue;
- if( (p_size = strtok(NULL," ")) == 0) continue;
-
- //kdDebug(7102) << "p_access=" << p_access << " p_junk=" << p_junk << " p_owner=" << p_owner << " p_group=" << p_group << " p_size=" << p_size << endl;
-
- de.access = 0;
- if ( strlen( p_access ) == 1 && p_junk[0] == '[' ) { // Netware
- de.access = S_IRWXU | S_IRWXG | S_IRWXO; // unknown -> give all permissions
- }
-
- const char *p_date_1, *p_date_2, *p_date_3, *p_name;
-
- // A special hack for "/dev". A listing may look like this:
- // crw-rw-rw- 1 root root 1, 5 Jun 29 1997 zero
- // So we just ignore the number in front of the ",". Ok, its a hack :-)
- if ( strchr( p_size, ',' ) != 0L )
- {
- //kdDebug(7102) << "Size contains a ',' -> reading size again (/dev hack)" << endl;
- if ((p_size = strtok(NULL," ")) == 0)
- continue;
- }
-
- // Check whether the size we just read was really the size
- // or a month (this happens when the server lists no group)
- // Used to be the case on sunsite.uio.no, but not anymore
- // This is needed for the Netware case, too.
- if ( !isdigit( *p_size ) )
- {
- p_date_1 = p_size;
- p_size = p_group;
- p_group = 0;
- //kdDebug(7102) << "Size didn't have a digit -> size=" << p_size << " date_1=" << p_date_1 << endl;
- }
- else
- {
- p_date_1 = strtok(NULL," ");
- //kdDebug(7102) << "Size has a digit -> ok. p_date_1=" << p_date_1 << endl;
- }
-
- if ( p_date_1 != 0 &&
- (p_date_2 = strtok(NULL," ")) != 0 &&
- (p_date_3 = strtok(NULL," ")) != 0 &&
- (p_name = strtok(NULL,"\r\n")) != 0 )
- {
- {
- TQCString tmp( p_name );
- if ( p_access[0] == 'l' )
- {
- int i = tmp.findRev( " -> " );
- if ( i != -1 ) {
- de.link = remoteEncoding()->decode(p_name + i + 4);
- tmp.truncate( i );
- }
- else
- de.link = TQString::null;
- }
- else
- de.link = TQString::null;
-
- if ( tmp[0] == '/' ) // listing on ftp://ftp.gnupg.org/ starts with '/'
- tmp.remove( 0, 1 );
-
- if (tmp.find('/') != -1)
- continue; // Don't trick us!
- // Some sites put more than one space between the date and the name
- // e.g. ftp://ftp.uni-marburg.de/mirror/
- de.name = remoteEncoding()->decode(tmp.stripWhiteSpace());
- }
-
- de.type = S_IFREG;
- switch ( p_access[0] ) {
- case 'd':
- de.type = S_IFDIR;
- break;
- case 's':
- de.type = S_IFSOCK;
- break;
- case 'b':
- de.type = S_IFBLK;
- break;
- case 'c':
- de.type = S_IFCHR;
- break;
- case 'l':
- de.type = S_IFREG;
- // we don't set S_IFLNK here. de.link says it.
- break;
- default:
- break;
- }
-
- if ( p_access[1] == 'r' )
- de.access |= S_IRUSR;
- if ( p_access[2] == 'w' )
- de.access |= S_IWUSR;
- if ( p_access[3] == 'x' || p_access[3] == 's' )
- de.access |= S_IXUSR;
- if ( p_access[4] == 'r' )
- de.access |= S_IRGRP;
- if ( p_access[5] == 'w' )
- de.access |= S_IWGRP;
- if ( p_access[6] == 'x' || p_access[6] == 's' )
- de.access |= S_IXGRP;
- if ( p_access[7] == 'r' )
- de.access |= S_IROTH;
- if ( p_access[8] == 'w' )
- de.access |= S_IWOTH;
- if ( p_access[9] == 'x' || p_access[9] == 't' )
- de.access |= S_IXOTH;
- if ( p_access[3] == 's' || p_access[3] == 'S' )
- de.access |= S_ISUID;
- if ( p_access[6] == 's' || p_access[6] == 'S' )
- de.access |= S_ISGID;
- if ( p_access[9] == 't' || p_access[9] == 'T' )
- de.access |= S_ISVTX;
-
- de.owner = remoteEncoding()->decode(p_owner);
- de.group = remoteEncoding()->decode(p_group);
- de.size = charToLongLong(p_size);
-
- // Parsing the date is somewhat tricky
- // Examples : "Oct 6 22:49", "May 13 1999"
-
- // First get current time - we need the current month and year
- time_t currentTime = time( 0L );
- struct tm * tmptr = gmtime( &currentTime );
- int currentMonth = tmptr->tm_mon;
- //kdDebug(7102) << "Current time :" << asctime( tmptr ) << endl;
- // Reset time fields
- tmptr->tm_isdst = -1; // We do not know anything about day saving time (of any random day of the year)
- tmptr->tm_sec = 0;
- tmptr->tm_min = 0;
- tmptr->tm_hour = 0;
- // Get day number (always second field)
- tmptr->tm_mday = atoi( p_date_2 );
- // Get month from first field
- // NOTE : no, we don't want to use KLocale here
- // It seems all FTP servers use the English way
- //kdDebug(7102) << "Looking for month " << p_date_1 << endl;
- static const char * s_months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
- for ( int c = 0 ; c < 12 ; c ++ )
- if ( !strcmp( p_date_1, s_months[c]) )
- {
- //kdDebug(7102) << "Found month " << c << " for " << p_date_1 << endl;
- tmptr->tm_mon = c;
- break;
- }
-
- // Parse third field
- if ( strlen( p_date_3 ) == 4 ) // 4 digits, looks like a year
- tmptr->tm_year = atoi( p_date_3 ) - 1900;
- else
- {
- // otherwise, the year is implicit
- // according to man ls, this happens when it is between than 6 months
- // old and 1 hour in the future.
- // So the year is : current year if tm_mon <= currentMonth+1
- // otherwise current year minus one
- // (The +1 is a security for the "+1 hour" at the end of the month issue)
- if ( tmptr->tm_mon > currentMonth + 1 )
- tmptr->tm_year--;
-
- // and p_date_3 contains probably a time
- char * semicolon;
- if ( ( semicolon = const_cast<char*>(strchr( p_date_3, ':' )) ) )
- {
- *semicolon = '\0';
- tmptr->tm_min = atoi( semicolon + 1 );
- tmptr->tm_hour = atoi( p_date_3 );
- }
- else
- kdWarning(7102) << "Can't parse third field " << p_date_3 << endl;
- }
-
- //kdDebug(7102) << asctime( tmptr ) << endl;
- de.date = mktime( tmptr );
- return true;
- }
- } // line invalid, loop to get another line
- return false;
-}
-
-//===============================================================================
-// public: get download file from server
-// helper: ftpGet called from get() and copy()
-//===============================================================================
-void Ftp::get( const KURL & url )
-{
- kdDebug(7102) << "Ftp::get " << url.url() << endl;
- int iError = 0;
- ftpGet(iError, -1, url, 0); // iError gets status
- if(iError) // can have only server side errs
- error(iError, url.path());
- ftpCloseCommand(); // must close command!
-}
-
-Ftp::StatusCode Ftp::ftpGet(int& iError, int iCopyFile, const KURL& url, KIO::fileoffset_t llOffset)
-{
- // Calls error() by itself!
- if( !ftpOpenConnection(loginImplicit) )
- return statusServerError;
-
- // Try to find the size of the file (and check that it exists at
- // the same time). If we get back a 550, "File does not exist"
- // or "not a plain file", check if it is a directory. If it is a
- // directory, return an error; otherwise simply try to retrieve
- // the request...
- if ( !ftpSize( url.path(), '?' ) && (m_iRespCode == 550) &&
- ftpFolder(url.path(), false) )
- {
- // Ok it's a dir in fact
- kdDebug(7102) << "ftpGet: it is a directory in fact" << endl;
- iError = ERR_IS_DIRECTORY;
- return statusServerError;
- }
-
- TQString resumeOffset = metaData("resume");
- if ( !resumeOffset.isEmpty() )
- {
- llOffset = resumeOffset.toLongLong();
- kdDebug(7102) << "ftpGet: got offset from metadata : " << llOffset << endl;
- }
-
- if( !ftpOpenCommand("retr", url.path(), '?', ERR_CANNOT_OPEN_FOR_READING, llOffset) )
- {
- kdWarning(7102) << "ftpGet: Can't open for reading" << endl;
- return statusServerError;
- }
-
- // Read the size from the response string
- if(m_size == UnknownSize)
- {
- const char* psz = strrchr( ftpResponse(4), '(' );
- if(psz) m_size = charToLongLong(psz+1);
- if (!m_size) m_size = UnknownSize;
- }
-
- KIO::filesize_t bytesLeft = 0;
- if ( m_size != UnknownSize )
- bytesLeft = m_size - llOffset;
-
- kdDebug(7102) << "ftpGet: starting with offset=" << llOffset << endl;
- KIO::fileoffset_t processed_size = llOffset;
-
- TQByteArray array;
- bool mimetypeEmitted = false;
- char buffer[maximumIpcSize];
- // start whith small data chunks in case of a slow data source (modem)
- // - unfortunately this has a negative impact on performance for large
- // - files - so we will increase the block size after a while ...
- int iBlockSize = initialIpcSize;
- int iBufferCur = 0;
-
- while(m_size == UnknownSize || bytesLeft > 0)
- { // let the buffer size grow if the file is larger 64kByte ...
- if(processed_size-llOffset > 1024 * 64)
- iBlockSize = maximumIpcSize;
-
- // read the data and detect EOF or error ...
- if(iBlockSize+iBufferCur > (int)sizeof(buffer))
- iBlockSize = sizeof(buffer) - iBufferCur;
- int n = m_data->read( buffer+iBufferCur, iBlockSize );
- if(n <= 0)
- { // this is how we detect EOF in case of unknown size
- if( m_size == UnknownSize && n == 0 )
- break;
- // unexpected eof. Happens when the daemon gets killed.
- iError = ERR_COULD_NOT_READ;
- return statusServerError;
- }
- processed_size += n;
-
- // collect very small data chunks in buffer before processing ...
- if(m_size != UnknownSize)
- {
- bytesLeft -= n;
- iBufferCur += n;
- if(iBufferCur < mimimumMimeSize && bytesLeft > 0)
- {
- processedSize( processed_size );
- continue;
- }
- n = iBufferCur;
- iBufferCur = 0;
- }
-
- // get the mime type and set the total size ...
- if(!mimetypeEmitted)
- {
- mimetypeEmitted = true;
-
- // We need a KMimeType::findByNameAndContent(data,filename)
- // For now we do: find by extension, and if not found (or extension not reliable)
- // then find by content.
- bool accurate = false;
- KMimeType::Ptr mime = KMimeType::findByURL( url, 0, false, true, &accurate );
- if ( !mime || mime->name() == KMimeType::defaultMimeType()
- || !accurate )
- {
- array.setRawData(buffer, n);
- KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType(array, url.fileName());
- array.resetRawData(buffer, n);
- if ( result->mimeType() != KMimeType::defaultMimeType() )
- mime = KMimeType::mimeType( result->mimeType() );
- }
-
- kdDebug(7102) << "ftpGet: Emitting mimetype " << mime->name() << endl;
- mimeType( mime->name() );
- if( m_size != UnknownSize ) // Emit total size AFTER mimetype
- totalSize( m_size );
- }
-
- // write output file or pass to data pump ...
- if(iCopyFile == -1)
- {
- array.setRawData(buffer, n);
- data( array );
- array.resetRawData(buffer, n);
- }
- else if( (iError = WriteToFile(iCopyFile, buffer, n)) != 0)
- return statusClientError; // client side error
- processedSize( processed_size );
- }
-
- kdDebug(7102) << "ftpGet: done" << endl;
- if(iCopyFile == -1) // must signal EOF to data pump ...
- data(array); // array is empty and must be empty!
-
- processedSize( m_size == UnknownSize ? processed_size : m_size );
- kdDebug(7102) << "ftpGet: emitting finished()" << endl;
- finished();
- return statusSuccess;
-}
-
-/*
-void Ftp::mimetype( const KURL& url )
-{
- if( !ftpOpenConnection(loginImplicit) )
- return;
-
- if ( !ftpOpenCommand( "retr", url.path(), 'I', ERR_CANNOT_OPEN_FOR_READING, 0 ) ) {
- kdWarning(7102) << "Can't open for reading" << endl;
- return;
- }
- char buffer[ 2048 ];
- TQByteArray array;
- // Get one chunk of data only and send it, KIO::Job will determine the
- // mimetype from it using KMimeMagic
- int n = m_data->read( buffer, 2048 );
- array.setRawData(buffer, n);
- data( array );
- array.resetRawData(buffer, n);
-
- kdDebug(7102) << "aborting" << endl;
- ftpAbortTransfer();
-
- kdDebug(7102) << "finished" << endl;
- finished();
- kdDebug(7102) << "after finished" << endl;
-}
-
-void Ftp::ftpAbortTransfer()
-{
- // RFC 959, page 34-35
- // IAC (interpret as command) = 255 ; IP (interrupt process) = 254
- // DM = 242 (data mark)
- char msg[4];
- // 1. User system inserts the Telnet "Interrupt Process" (IP) signal
- // in the Telnet stream.
- msg[0] = (char) 255; //IAC
- msg[1] = (char) 254; //IP
- (void) send(sControl, msg, 2, 0);
- // 2. User system sends the Telnet "Sync" signal.
- msg[0] = (char) 255; //IAC
- msg[1] = (char) 242; //DM
- if (send(sControl, msg, 2, MSG_OOB) != 2)
- ; // error...
-
- // Send ABOR
- kdDebug(7102) << "send ABOR" << endl;
- TQCString buf = "ABOR\r\n";
- if ( KSocks::self()->write( sControl, buf.data(), buf.length() ) <= 0 ) {
- error( ERR_COULD_NOT_WRITE, TQString::null );
- return;
- }
-
- //
- kdDebug(7102) << "read resp" << endl;
- if ( readresp() != '2' )
- {
- error( ERR_COULD_NOT_READ, TQString::null );
- return;
- }
-
- kdDebug(7102) << "close sockets" << endl;
- closeSockets();
-}
-*/
-
-//===============================================================================
-// public: put upload file to server
-// helper: ftpPut called from put() and copy()
-//===============================================================================
-void Ftp::put(const KURL& url, int permissions, bool overwrite, bool resume)
-{
- kdDebug(7102) << "Ftp::put " << url.url() << endl;
- int iError = 0; // iError gets status
- ftpPut(iError, -1, url, permissions, overwrite, resume);
- if(iError) // can have only server side errs
- error(iError, url.path());
- ftpCloseCommand(); // must close command!
-}
-
-Ftp::StatusCode Ftp::ftpPut(int& iError, int iCopyFile, const KURL& dest_url,
- int permissions, bool overwrite, bool resume)
-{
- if( !ftpOpenConnection(loginImplicit) )
- return statusServerError;
-
- // Don't use mark partial over anonymous FTP.
- // My incoming dir allows put but not rename...
- bool bMarkPartial;
- if (m_user.isEmpty () || m_user == FTP_LOGIN)
- bMarkPartial = false;
- else
- bMarkPartial = config()->readBoolEntry("MarkPartial", true);
-
- TQString dest_orig = dest_url.path();
- TQString dest_part( dest_orig );
- dest_part += ".part";
-
- if ( ftpSize( dest_orig, 'I' ) )
- {
- if ( m_size == 0 )
- { // delete files with zero size
- TQCString cmd = "DELE ";
- cmd += remoteEncoding()->encode(dest_orig);
- if( !ftpSendCmd( cmd ) || (m_iRespType != 2) )
- {
- iError = ERR_CANNOT_DELETE_PARTIAL;
- return statusServerError;
- }
- }
- else if ( !overwrite && !resume )
- {
- iError = ERR_FILE_ALREADY_EXIST;
- return statusServerError;
- }
- else if ( bMarkPartial )
- { // when using mark partial, append .part extension
- if ( !ftpRename( dest_orig, dest_part, true ) )
- {
- iError = ERR_CANNOT_RENAME_PARTIAL;
- return statusServerError;
- }
- }
- // Don't chmod an existing file
- permissions = -1;
- }
- else if ( bMarkPartial && ftpSize( dest_part, 'I' ) )
- { // file with extension .part exists
- if ( m_size == 0 )
- { // delete files with zero size
- TQCString cmd = "DELE ";
- cmd += remoteEncoding()->encode(dest_part);
- if ( !ftpSendCmd( cmd ) || (m_iRespType != 2) )
- {
- iError = ERR_CANNOT_DELETE_PARTIAL;
- return statusServerError;
- }
- }
- else if ( !overwrite && !resume )
- {
- resume = canResume (m_size);
- if (!resume)
- {
- iError = ERR_FILE_ALREADY_EXIST;
- return statusServerError;
- }
- }
- }
- else
- m_size = 0;
-
- TQString dest;
-
- // if we are using marking of partial downloads -> add .part extension
- if ( bMarkPartial ) {
- kdDebug(7102) << "Adding .part extension to " << dest_orig << endl;
- dest = dest_part;
- } else
- dest = dest_orig;
-
- KIO::fileoffset_t offset = 0;
-
- // set the mode according to offset
- if( resume && m_size > 0 )
- {
- offset = m_size;
- if(iCopyFile != -1)
- {
- if( KDE_lseek(iCopyFile, offset, SEEK_SET) < 0 )
- {
- iError = ERR_CANNOT_RESUME;
- return statusClientError;
- }
- }
- }
-
- if (! ftpOpenCommand( "stor", dest, '?', ERR_COULD_NOT_WRITE, offset ) )
- return statusServerError;
-
- kdDebug(7102) << "ftpPut: starting with offset=" << offset << endl;
- KIO::fileoffset_t processed_size = offset;
-
- TQByteArray buffer;
- int result;
- int iBlockSize = initialIpcSize;
- // Loop until we got 'dataEnd'
- do
- {
- if(iCopyFile == -1)
- {
- dataReq(); // Request for data
- result = readData( buffer );
- }
- else
- { // let the buffer size grow if the file is larger 64kByte ...
- if(processed_size-offset > 1024 * 64)
- iBlockSize = maximumIpcSize;
- buffer.resize(iBlockSize);
- result = ::read(iCopyFile, buffer.data(), buffer.size());
- if(result < 0)
- iError = ERR_COULD_NOT_WRITE;
- else
- buffer.resize(result);
- }
-
- if (result > 0)
- {
- m_data->write( buffer.data(), buffer.size() );
- processed_size += result;
- processedSize (processed_size);
- }
- }
- while ( result > 0 );
-
- if (result != 0) // error
- {
- ftpCloseCommand(); // don't care about errors
- kdDebug(7102) << "Error during 'put'. Aborting." << endl;
- if (bMarkPartial)
- {
- // Remove if smaller than minimum size
- if ( ftpSize( dest, 'I' ) &&
- ( processed_size < (unsigned long) config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE) ) )
- {
- TQCString cmd = "DELE ";
- cmd += remoteEncoding()->encode(dest);
- (void) ftpSendCmd( cmd );
- }
- }
- return statusServerError;
- }
-
- if ( !ftpCloseCommand() )
- {
- iError = ERR_COULD_NOT_WRITE;
- return statusServerError;
- }
-
- // after full download rename the file back to original name
- if ( bMarkPartial )
- {
- kdDebug(7102) << "renaming dest (" << dest << ") back to dest_orig (" << dest_orig << ")" << endl;
- if ( !ftpRename( dest, dest_orig, true ) )
- {
- iError = ERR_CANNOT_RENAME_PARTIAL;
- return statusServerError;
- }
- }
-
- // set final permissions
- if ( permissions != -1 )
- {
- if ( m_user == FTP_LOGIN )
- kdDebug(7102) << "Trying to chmod over anonymous FTP ???" << endl;
- // chmod the file we just put
- if ( ! ftpChmod( dest_orig, permissions ) )
- {
- // To be tested
- //if ( m_user != FTP_LOGIN )
- // warning( i18n( "Could not change permissions for\n%1" ).arg( dest_orig ) );
- }
- }
-
- // We have done our job => finish
- finished();
- return statusSuccess;
-}
-
-
-/** Use the SIZE command to get the file size.
- Warning : the size depends on the transfer mode, hence the second arg. */
-bool Ftp::ftpSize( const TQString & path, char mode )
-{
- m_size = UnknownSize;
- if( !ftpDataMode(mode) )
- return false;
-
- TQCString buf;
- buf = "SIZE ";
- buf += remoteEncoding()->encode(path);
- if( !ftpSendCmd( buf ) || (m_iRespType != 2) )
- return false;
-
- // skip leading "213 " (response code)
- const char* psz = ftpResponse(4);
- if(!psz)
- return false;
- m_size = charToLongLong(psz);
- if (!m_size) m_size = UnknownSize;
- return true;
-}
-
-bool Ftp::ftpFileExists(const TQString& path)
-{
- TQCString buf;
- buf = "SIZE ";
- buf += remoteEncoding()->encode(path);
- if( !ftpSendCmd( buf ) || (m_iRespType != 2) )
- return false;
-
- // skip leading "213 " (response code)
- const char* psz = ftpResponse(4);
- return psz != 0;
-}
-
-// Today the differences between ASCII and BINARY are limited to
-// CR or CR/LF line terminators. Many servers ignore ASCII (like
-// win2003 -or- vsftp with default config). In the early days of
-// computing, when even text-files had structure, this stuff was
-// more important.
-// Theoretically "list" could return different results in ASCII
-// and BINARY mode. But again, most servers ignore ASCII here.
-bool Ftp::ftpDataMode(char cMode)
-{
- if(cMode == '?') cMode = m_bTextMode ? 'A' : 'I';
- else if(cMode == 'a') cMode = 'A';
- else if(cMode != 'A') cMode = 'I';
-
- kdDebug(7102) << "ftpDataMode: want '" << cMode << "' has '" << m_cDataMode << "'" << endl;
- if(m_cDataMode == cMode)
- return true;
-
- TQCString buf;
- buf.sprintf("TYPE %c", cMode);
- if( !ftpSendCmd(buf) || (m_iRespType != 2) )
- return false;
- m_cDataMode = cMode;
- return true;
-}
-
-
-bool Ftp::ftpFolder(const TQString& path, bool bReportError)
-{
- TQString newPath = path;
- int iLen = newPath.length();
- if(iLen > 1 && newPath[iLen-1] == '/') newPath.truncate(iLen-1);
-
- //kdDebug(7102) << "ftpFolder: want '" << newPath << "' has '" << m_currentPath << "'" << endl;
- if(m_currentPath == newPath)
- return true;
-
- TQCString tmp = "cwd ";
- tmp += remoteEncoding()->encode(newPath);
- if( !ftpSendCmd(tmp) )
- return false; // connection failure
- if(m_iRespType != 2)
- {
- if(bReportError)
- error(ERR_CANNOT_ENTER_DIRECTORY, path);
- return false; // not a folder
- }
- m_currentPath = newPath;
- return true;
-}
-
-
-//===============================================================================
-// public: copy don't use kio data pump if one side is a local file
-// helper: ftpCopyPut called from copy() on upload
-// helper: ftpCopyGet called from copy() on download
-//===============================================================================
-void Ftp::copy( const KURL &src, const KURL &dest, int permissions, bool overwrite )
-{
- int iError = 0;
- int iCopyFile = -1;
- StatusCode cs = statusSuccess;
- bool bSrcLocal = src.isLocalFile();
- bool bDestLocal = dest.isLocalFile();
- TQString sCopyFile;
-
- if(bSrcLocal && !bDestLocal) // File -> Ftp
- {
- sCopyFile = src.path();
- kdDebug(7102) << "Ftp::copy local file '" << sCopyFile << "' -> ftp '" << dest.path() << "'" << endl;
- cs = ftpCopyPut(iError, iCopyFile, sCopyFile, dest, permissions, overwrite);
- if( cs == statusServerError) sCopyFile = dest.url();
- }
- else if(!bSrcLocal && bDestLocal) // Ftp -> File
- {
- sCopyFile = dest.path();
- kdDebug(7102) << "Ftp::copy ftp '" << src.path() << "' -> local file '" << sCopyFile << "'" << endl;
- cs = ftpCopyGet(iError, iCopyFile, sCopyFile, src, permissions, overwrite);
- if( cs == statusServerError ) sCopyFile = src.url();
- }
- else {
- error( ERR_UNSUPPORTED_ACTION, TQString::null );
- return;
- }
-
- // perform clean-ups and report error (if any)
- if(iCopyFile != -1)
- ::close(iCopyFile);
- if(iError)
- error(iError, sCopyFile);
- ftpCloseCommand(); // must close command!
-}
-
-
-Ftp::StatusCode Ftp::ftpCopyPut(int& iError, int& iCopyFile, TQString sCopyFile,
- const KURL& url, int permissions, bool overwrite)
-{
- // check if source is ok ...
- KDE_struct_stat buff;
- TQCString sSrc( TQFile::encodeName(sCopyFile) );
- bool bSrcExists = (KDE_stat( sSrc.data(), &buff ) != -1);
- if(bSrcExists)
- { if(S_ISDIR(buff.st_mode))
- {
- iError = ERR_IS_DIRECTORY;
- return statusClientError;
- }
- }
- else
- {
- iError = ERR_DOES_NOT_EXIST;
- return statusClientError;
- }
-
- iCopyFile = KDE_open( sSrc.data(), O_RDONLY );
- if(iCopyFile == -1)
- {
- iError = ERR_CANNOT_OPEN_FOR_READING;
- return statusClientError;
- }
-
- // delegate the real work (iError gets status) ...
- totalSize(buff.st_size);
-#ifdef ENABLE_CAN_RESUME
- return ftpPut(iError, iCopyFile, url, permissions, overwrite, false);
-#else
- return ftpPut(iError, iCopyFile, url, permissions, overwrite, true);
-#endif
-}
-
-
-Ftp::StatusCode Ftp::ftpCopyGet(int& iError, int& iCopyFile, const TQString sCopyFile,
- const KURL& url, int permissions, bool overwrite)
-{
- // check if destination is ok ...
- KDE_struct_stat buff;
- TQCString sDest( TQFile::encodeName(sCopyFile) );
- bool bDestExists = (KDE_stat( sDest.data(), &buff ) != -1);
- if(bDestExists)
- { if(S_ISDIR(buff.st_mode))
- {
- iError = ERR_IS_DIRECTORY;
- return statusClientError;
- }
- if(!overwrite)
- {
- iError = ERR_FILE_ALREADY_EXIST;
- return statusClientError;
- }
- }
-
- // do we have a ".part" file?
- TQCString sPart = TQFile::encodeName(sCopyFile + ".part");
- bool bResume = false;
- bool bPartExists = (KDE_stat( sPart.data(), &buff ) != -1);
- const bool bMarkPartial = config()->readBoolEntry("MarkPartial", true);
-
- if(!bMarkPartial)
- {
- sPart = TQFile::encodeName(sCopyFile);
- }
- else if(bPartExists && buff.st_size > 0)
- { // must not be a folder! please fix a similar bug in kio_file!!
- if(S_ISDIR(buff.st_mode))
- {
- iError = ERR_DIR_ALREADY_EXIST;
- return statusClientError; // client side error
- }
- //doesn't work for copy? -> design flaw?
-#ifdef ENABLE_CAN_RESUME
- bResume = canResume( buff.st_size );
-#else
- bResume = true;
-#endif
- }
-
- if(bPartExists && !bResume) // get rid of an unwanted ".part" file
- remove(sPart.data());
-
- // JPF: in kio_file overwrite disables ".part" operations. I do not believe
- // JPF: that this is a good behaviour!
- if(bDestExists) // must delete for overwrite
- remove(sDest.data());
-
- // WABA: Make sure that we keep writing permissions ourselves,
- // otherwise we can be in for a surprise on NFS.
- mode_t initialMode;
- if (permissions != -1)
- initialMode = permissions | S_IWUSR;
- else
- initialMode = 0666;
-
- // open the output file ...
- KIO::fileoffset_t hCopyOffset = 0;
- if(bResume)
- {
- iCopyFile = KDE_open( sPart.data(), O_RDWR ); // append if resuming
- hCopyOffset = KDE_lseek(iCopyFile, 0, SEEK_END);
- if(hCopyOffset < 0)
- {
- iError = ERR_CANNOT_RESUME;
- return statusClientError; // client side error
- }
- kdDebug(7102) << "copy: resuming at " << hCopyOffset << endl;
- }
- else
- iCopyFile = KDE_open(sPart.data(), O_CREAT | O_TRUNC | O_WRONLY, initialMode);
-
- if(iCopyFile == -1)
- {
- kdDebug(7102) << "copy: ### COULD NOT WRITE " << sCopyFile << endl;
- iError = (errno == EACCES) ? ERR_WRITE_ACCESS_DENIED
- : ERR_CANNOT_OPEN_FOR_WRITING;
- return statusClientError;
- }
-
- // delegate the real work (iError gets status) ...
- StatusCode iRes = ftpGet(iError, iCopyFile, url, hCopyOffset);
- if( ::close(iCopyFile) && iRes == statusSuccess )
- {
- iError = ERR_COULD_NOT_WRITE;
- iRes = statusClientError;
- }
-
- // handle renaming or deletion of a partial file ...
- if(bMarkPartial)
- {
- if(iRes == statusSuccess)
- { // rename ".part" on success
- if ( ::rename( sPart.data(), sDest.data() ) )
- {
- kdDebug(7102) << "copy: cannot rename " << sPart << " to " << sDest << endl;
- iError = ERR_CANNOT_RENAME_PARTIAL;
- iRes = statusClientError;
- }
- }
- else if(KDE_stat( sPart.data(), &buff ) == 0)
- { // should a very small ".part" be deleted?
- int size = config()->readNumEntry("MinimumKeepSize", DEFAULT_MINIMUM_KEEP_SIZE);
- if (buff.st_size < size)
- remove(sPart.data());
- }
- }
- return iRes;
-}
diff --git a/kioslave/ftp/ftp.h b/kioslave/ftp/ftp.h
deleted file mode 100644
index 44f0bdc71..000000000
--- a/kioslave/ftp/ftp.h
+++ /dev/null
@@ -1,603 +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.
-*/
-
-// $Id$
-
-#ifndef __ftp_h__
-#define __ftp_h__
-
-#include <config.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <tqcstring.h>
-#include <tqstring.h>
-
-#include <kurl.h>
-#include <kio/slavebase.h>
-#include <kextsock.h>
-#include <ksocks.h>
-
-struct FtpEntry
-{
- TQString name;
- TQString owner;
- TQString group;
- TQString link;
-
- KIO::filesize_t size;
- mode_t type;
- mode_t access;
- time_t date;
-};
-
-//===============================================================================
-// FtpTextReader A helper class to read text lines from a socket
-//===============================================================================
-
-#ifdef KIO_FTP_PRIVATE_INCLUDE
-class FtpSocket;
-
-class FtpTextReader
-{
-public:
- FtpTextReader() { textClear(); }
-
-/**
- * Resets the status of the object, also called from xtor
- */
- void textClear();
-
-/**
- * Read a line from the socket into m_szText. Only the first RESP_READ_LIMIT
- * characters are copied. If the server response is longer all extra data up to
- * the new-line gets discarded. An ending CR gets stripped. The number of chars
- * in the buffer is returned. Use textToLong() to check for truncation!
- */
- int textRead(FtpSocket *pSock);
-
-/**
- * An accessor to the data read by textRead()
- */
- const char* textLine() const { return m_szText; }
-
-/**
- * Returns true if the last textRead() resulted in a truncated line
- */
- bool textTooLong() const { return m_bTextTruncated; }
-
-/**
- * Returns true if the last textRead() got an EOF or an error
- */
- bool textEOF() const { return m_bTextEOF; }
-
- enum {
-
- /**
- * This is the physical size of m_szText. Only up to textReadLimit
- * characters are used to store a server reply. If the server reply
- * is longer, the stored line gets truncated - see textTooLong()!
- */
- textReadBuffer = 2048,
-
-/**
- * Max number of chars returned from textLine(). If the server
- * sends more all chars until the next new-line are discarded.
- */
- textReadLimit = 1024
- };
-
-private:
- /**
- * textRead() sets this true on trucation (e.g. line too long)
- */
- bool m_bTextTruncated;
-
- /**
- * textRead() sets this true if the read returns 0 bytes or error
- */
- bool m_bTextEOF;
-
- /**
- * textRead() fills this buffer with data
- */
- char m_szText[textReadBuffer];
-
- /**
- * the number of bytes in the current response line
- */
- int m_iTextLine;
-
- /**
- * the number of bytes in the response buffer (includes m_iRespLine)
- */
- int m_iTextBuff;
-};
-#endif // KIO_FTP_PRIVATE_INCLUDE
-
-//===============================================================================
-// FtpSocket Helper Class for Data or Control Connections
-//===============================================================================
-#ifdef KIO_FTP_PRIVATE_INCLUDE
-class FtpSocket : public FtpTextReader, public KExtendedSocket
-{
-private:
- // hide the default xtor
- FtpSocket() {}
-public:
-/**
- * The one and only public xtor. The string data passed to the
- * xtor must remain valid during the object's lifetime - it is
- * used in debug messages to identify the socket instance.
- */
- FtpSocket(const char* pszName)
- {
- m_pszName = pszName;
- m_server = -1;
- }
-
- ~FtpSocket() { closeSocket(); }
-
-/**
- * Resets the status of the object, also called from xtor
- */
- void closeSocket();
-
-/**
- * We may have a server connection socket if not in passive mode. This
- * routine returns the server socket set by setServer. The sock()
- * function will return the server socket - if it is set.
- */
- int server() const { return m_server; }
-
-/**
- * Set the server socket if arg >= 0, otherwise clear it.
- */
- void setServer(int i) { m_server = (i >= 0) ? i : -1; }
-
-/**
- * returns the effective socket that user used for read/write. See server()
- */
- int sock() const { return (m_server != -1) ? m_server : fd(); }
-
-/**
- * output an debug message via kdDebug
- */
- void debugMessage(const char* pszMsg) const;
-
-/**
- * output an error message via kdError, returns iErrorCode
- */
- int errorMessage(int iErrorCode, const char* pszMsg) const;
-
-/**
- * connect socket and set some options (reuse, keepalive, linger)
- */
- int connectSocket(int iTimeOutSec, bool bControl);
-
-/**
- * utility to simplify calls to ::setsockopt(). Uses sock().
- */
- bool setSocketOption(int opt, char*arg, socklen_t len) const;
-
-/**
- * utility to read data from the effective socket, see sock()
- */
- long read(void* pData, long iMaxlen)
- {
- return KSocks::self()->read(sock(), pData, iMaxlen);
- }
-
-/**
- * utility to write data to the effective socket, see sock()
- */
- long write(void* pData, long iMaxlen)
- {
- return KSocks::self()->write(sock(), pData, iMaxlen);
- }
-
-/**
- * Use the inherited FtpTextReader to read a line from the socket
- */
- int textRead()
- {
- return FtpTextReader::textRead(this);
- }
-
-private:
- const char* m_pszName; // set by the xtor, used for debug output
- int m_server; // socket override, see setSock()
-};
-#else
- class FtpSocket;
-#endif // KIO_FTP_PRIVATE_INCLUDE
-
-//===============================================================================
-// Ftp
-//===============================================================================
-class Ftp : public KIO::SlaveBase
-{
- // Ftp() {}
-
-public:
- Ftp( const TQCString &pool, const TQCString &app );
- virtual ~Ftp();
-
- virtual void setHost( const TQString& host, int port, const TQString& user, const TQString& pass );
-
- /**
- * Connects to a ftp server and logs us in
- * m_bLoggedOn is set to true if logging on was successful.
- * It is set to false if the connection becomes closed.
- *
- */
- virtual void openConnection();
-
- /**
- * Closes the connection
- */
- virtual void closeConnection();
-
- 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 & dest, bool overwrite );
- 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, bool overwrite, bool resume);
- //virtual void mimetype( const KURL& url );
-
- virtual void slave_status();
-
- /**
- * Handles the case that one side of the job is a local file
- */
- virtual void copy( const KURL &src, const KURL &dest, int permissions, bool overwrite );
-
-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);
-
- /**
- * Executes any auto login macro's as specified in a .netrc file.
- */
- void ftpAutoLoginMacro ();
-
- /**
- * Called by openConnection. It logs us in.
- * m_initialPath is set to the current working directory
- * if logging on was successful.
- *
- * @return true on success.
- */
- bool ftpLogin();
-
- /**
- * 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 TQCString& 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 TQString & path, char mode );
-
- /**
- * Set the current working directory, but only if not yet current
- */
- bool ftpFileExists(const TQString& path);
-
- /**
- * Set the current working directory, but only if not yet current
- */
- bool ftpFolder(const TQString& 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 TQString & 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 ftpOpenEPRTDataConnection();
- /**
- * Helper for ftpOpenDataConnection
- */
- int ftpOpenPortDataConnection();
-
- /**
- * ftpAcceptConnect - wait for incoming connection
- *
- * return -2 on error or timeout
- * otherwise returns socket descriptor
- */
- int ftpAcceptConnect();
-
- bool ftpChmod( const TQString & path, int permissions );
-
- // used by listDir
- bool ftpOpenDir( const TQString & path );
- /**
- * Called to parse directory listings, call this until it returns false
- */
- bool ftpReadDir(FtpEntry& ftpEnt);
-
- /**
- * Helper to fill an UDSEntry
- */
- void ftpCreateUDSEntry( const TQString & filename, FtpEntry& ftpEnt, KIO::UDSEntry& entry, bool isDir );
-
- void ftpShortStatAnswer( const TQString& filename, bool isDir );
-
- void ftpStatAnswerNotFound( const TQString & path, const TQString & filename );
-
- /**
- * This is the internal implementation of rename() - set put().
- *
- * @return true on success.
- */
- bool ftpRename( const TQString & src, const TQString & dst, bool overwrite );
-
- /**
- * Called by openConnection. It opens the control connection to the ftp server.
- *
- * @return true on success.
- */
- bool ftpOpenControlConnection( const TQString & host, unsigned short 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, bool overwrite, bool resume);
-
- /**
- * 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, TQString sCopyFile, const KURL& url, int permissions, bool overwrite);
-
- /**
- * 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, TQString sCopyFile, const KURL& url, int permissions, bool overwrite);
-
-private: // data members
-
- TQString m_host;
- unsigned short int m_port;
- TQString m_user;
- TQString m_pass;
- /**
- * Where we end up after connecting
- */
- TQString m_initialPath;
- KURL m_proxyURL;
-
- /**
- * the current working directory - see ftpFolder
- */
- TQString 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 closeConnection().
- *
- * When the user cancels a get or put command the Ftp dtor will be called,
- * which in turn calls closeConnection(). 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;
- bool m_bUseProxy;
-
- 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
- */
- FtpSocket *m_control;
-
- /**
- * data connection socket
- */
- FtpSocket *m_data;
-};
-
-#endif
diff --git a/kioslave/ftp/ftp.protocol b/kioslave/ftp/ftp.protocol
deleted file mode 100644
index 3af1e33ec..000000000
--- a/kioslave/ftp/ftp.protocol
+++ /dev/null
@@ -1,18 +0,0 @@
-[Protocol]
-exec=kio_ftp
-protocol=ftp
-input=none
-output=filesystem
-copyToFile=true
-copyFromFile=true
-listing=Name,Type,Size,Date,Access,Owner,Group,Link,
-reading=true
-writing=true
-makedir=true
-deleting=true
-moving=true
-ProxiedBy=http
-Icon=ftp
-maxInstances=2
-DocPath=kioslave/ftp.html
-Class=:internet
diff --git a/kioslave/gzip/CMakeLists.txt b/kioslave/gzip/CMakeLists.txt
deleted file mode 100644
index e71908c31..000000000
--- a/kioslave/gzip/CMakeLists.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/kio/kio
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES kgzipfilter.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-##### kgzipfilter ###############################
-
-set( target kgzipfilter )
-
-set( ${target}_SRCS
- kgzipfilter.cpp
-)
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK kio-shared
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/gzip/Makefile.am b/kioslave/gzip/Makefile.am
deleted file mode 100644
index 3da565fb7..000000000
--- a/kioslave/gzip/Makefile.am
+++ /dev/null
@@ -1,12 +0,0 @@
-INCLUDES = -I$(top_srcdir)/kio $(all_includes)
-AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor
-METASOURCES = AUTO
-
-kde_module_LTLIBRARIES = kgzipfilter.la
-
-kgzipfilter_la_SOURCES = kgzipfilter.cpp
-kgzipfilter_la_LIBADD = $(LIB_KIO) $(LIBZ) $(LIB_QT) $(LIB_TDECORE)
-kgzipfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
-
-kde_services_DATA = kgzipfilter.desktop
-
diff --git a/kioslave/gzip/kgzipfilter.cpp b/kioslave/gzip/kgzipfilter.cpp
deleted file mode 100644
index 375f9f9bc..000000000
--- a/kioslave/gzip/kgzipfilter.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/* 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 version 2 as published by the Free Software Foundation.
-
- 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.
-*/
-
-#include "kgzipfilter.h"
-#include <time.h>
-#include <zlib.h>
-#include <kdebug.h>
-#include <klibloader.h>
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
-#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define RESERVED 0xE0 /* bits 5..7: reserved */
-
-
-// #define DEBUG_GZIP
-
-class KGzipFilterFactory : public KLibFactory
-{
-public:
- KGzipFilterFactory() : KLibFactory() {}
- ~KGzipFilterFactory(){}
- TQObject *createObject( TQObject *parent, const char *name, const char*className, const TQStringList & args )
- {
- Q_UNUSED(parent);
- Q_UNUSED(name);
- Q_UNUSED(className);
- Q_UNUSED(args);
- return new KGzipFilter;
- }
-};
-
-K_EXPORT_COMPONENT_FACTORY( kgzipfilter, KGzipFilterFactory )
-
-// Not really necessary anymore, now that this is a dynamically-loaded lib.
-class KGzipFilter::KGzipFilterPrivate
-{
-public:
- z_stream zStream;
- bool bCompressed;
-};
-
-KGzipFilter::KGzipFilter()
-{
- d = new KGzipFilterPrivate;
- d->zStream.zalloc = (alloc_func)0;
- d->zStream.zfree = (free_func)0;
- d->zStream.opaque = (voidpf)0;
-}
-
-
-KGzipFilter::~KGzipFilter()
-{
- delete d;
-}
-
-void KGzipFilter::init( int mode )
-{
- d->zStream.next_in = Z_NULL;
- d->zStream.avail_in = 0;
- if ( mode == IO_ReadOnly )
- {
- int result = inflateInit2(&d->zStream, -MAX_WBITS); // windowBits is passed < 0 to suppress zlib header
- if ( result != Z_OK )
- kdDebug(7005) << "inflateInit returned " << result << endl;
- // No idea what to do with result :)
- } else if ( mode == IO_WriteOnly )
- {
- int result = deflateInit2(&d->zStream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); // same here
- if ( result != Z_OK )
- kdDebug(7005) << "deflateInit returned " << result << endl;
- } else {
- kdWarning(7005) << "KGzipFilter: Unsupported mode " << mode << ". Only IO_ReadOnly and IO_WriteOnly supported" << endl;
- }
- m_mode = mode;
- d->bCompressed = true;
- m_headerWritten = false;
-}
-
-void KGzipFilter::terminate()
-{
- if ( m_mode == IO_ReadOnly )
- {
- int result = inflateEnd(&d->zStream);
- if ( result != Z_OK )
- kdDebug(7005) << "inflateEnd returned " << result << endl;
- } else if ( m_mode == IO_WriteOnly )
- {
- int result = deflateEnd(&d->zStream);
- if ( result != Z_OK )
- kdDebug(7005) << "deflateEnd returned " << result << endl;
- }
-}
-
-
-void KGzipFilter::reset()
-{
- if ( m_mode == IO_ReadOnly )
- {
- int result = inflateReset(&d->zStream);
- if ( result != Z_OK )
- kdDebug(7005) << "inflateReset returned " << result << endl;
- } else if ( m_mode == IO_WriteOnly ) {
- int result = deflateReset(&d->zStream);
- if ( result != Z_OK )
- kdDebug(7005) << "deflateReset returned " << result << endl;
- m_headerWritten = false;
- }
-}
-
-bool KGzipFilter::readHeader()
-{
-#ifdef DEBUG_GZIP
- kdDebug(7005) << "KGzipFilter::readHeader avail=" << d->zStream.avail_in << endl;
-#endif
- // Assume not compressed until we successfully decode the header
- d->bCompressed = false;
- // Assume the first block of data contains the whole header.
- // The right way is to build this as a big state machine which
- // is a pain in the ass.
- // With 8K-blocks, we don't risk much anyway.
- Bytef *p = d->zStream.next_in;
- int i = d->zStream.avail_in;
- if ((i -= 10) < 0) return false; // Need at least 10 bytes
-#ifdef DEBUG_GZIP
- kdDebug(7005) << "KGzipFilter::readHeader first byte is " << TQString::number(*p,16) << endl;
-#endif
- if (*p++ != 0x1f) return false; // GZip magic
-#ifdef DEBUG_GZIP
- kdDebug(7005) << "KGzipFilter::readHeader second byte is " << TQString::number(*p,16) << endl;
-#endif
- if (*p++ != 0x8b) return false;
- int method = *p++;
- int flags = *p++;
- if ((method != Z_DEFLATED) || (flags & RESERVED) != 0) return false;
- p += 6;
- if ((flags & EXTRA_FIELD) != 0) // skip extra field
- {
- if ((i -= 2) < 0) return false; // Need at least 2 bytes
- int len = *p++;
- len += (*p++) << 8;
- if ((i -= len) < 0) return false; // Need at least len bytes
- p += len;
- }
- if ((flags & ORIG_NAME) != 0) // skip original file name
- {
-#ifdef DEBUG_GZIP
- kdDebug(7005) << "ORIG_NAME=" << p << endl;
-#endif
- while( (i > 0) && (*p))
- {
- i--; p++;
- }
- if (--i <= 0) return false;
- p++;
- }
- if ((flags & COMMENT) != 0) // skip comment
- {
- while( (i > 0) && (*p))
- {
- i--; p++;
- }
- if (--i <= 0) return false;
- p++;
- }
- if ((flags & HEAD_CRC) != 0) // skip the header crc
- {
- if ((i-=2) < 0) return false;
- p += 2;
- }
-
- d->zStream.avail_in = i;
- d->zStream.next_in = p;
- d->bCompressed = true;
-#ifdef DEBUG_GZIP
- kdDebug(7005) << "header OK" << endl;
-#endif
- return true;
-}
-
-/* Output a 16 bit value, lsb first */
-#define put_short(w) \
- *p++ = (uchar) ((w) & 0xff); \
- *p++ = (uchar) ((ushort)(w) >> 8);
-
-/* Output a 32 bit value to the bit stream, lsb first */
-#define put_long(n) \
- put_short((n) & 0xffff); \
- put_short(((ulong)(n)) >> 16);
-
-bool KGzipFilter::writeHeader( const TQCString & fileName )
-{
- Bytef *p = d->zStream.next_out;
- int i = d->zStream.avail_out;
- *p++ = 0x1f;
- *p++ = 0x8b;
- *p++ = Z_DEFLATED;
- *p++ = ORIG_NAME;
- put_long( time( 0L ) ); // Modification time (in unix format)
- *p++ = 0; // Extra flags (2=max compress, 4=fastest compress)
- *p++ = 3; // Unix
-
- uint len = fileName.length();
- for ( uint j = 0 ; j < len ; ++j )
- *p++ = fileName[j];
- *p++ = 0;
- int headerSize = p - d->zStream.next_out;
- i -= headerSize;
- Q_ASSERT(i>0);
- m_crc = crc32(0L, Z_NULL, 0);
- d->zStream.next_out = p;
- d->zStream.avail_out = i;
- m_headerWritten = true;
- return true;
-}
-
-void KGzipFilter::writeFooter()
-{
- Q_ASSERT( m_headerWritten );
- if (!m_headerWritten) kdDebug() << kdBacktrace();
- Bytef *p = d->zStream.next_out;
- int i = d->zStream.avail_out;
- //kdDebug(7005) << "KGzipFilter::writeFooter writing CRC= " << TQString::number( m_crc, 16 ) << endl;
- put_long( m_crc );
- //kdDebug(7005) << "KGzipFilter::writing writing totalin= " << d->zStream.total_in << endl;
- put_long( d->zStream.total_in );
- i -= p - d->zStream.next_out;
- d->zStream.next_out = p;
- d->zStream.avail_out = i;
-}
-
-void KGzipFilter::setOutBuffer( char * data, uint maxlen )
-{
- d->zStream.avail_out = maxlen;
- d->zStream.next_out = (Bytef *) data;
-}
-void KGzipFilter::setInBuffer( const char * data, uint size )
-{
-#ifdef DEBUG_GZIP
- kdDebug(7005) << "KGzipFilter::setInBuffer avail_in=" << size << endl;
-#endif
- d->zStream.avail_in = size;
- d->zStream.next_in = (Bytef*) data;
-}
-int KGzipFilter::inBufferAvailable() const
-{
- return d->zStream.avail_in;
-}
-int KGzipFilter::outBufferAvailable() const
-{
- return d->zStream.avail_out;
-}
-
-KGzipFilter::Result KGzipFilter::uncompress_noop()
-{
- // I'm not sure we really need support for that (uncompressed streams),
- // but why not, it can't hurt to have it. One case I can think of is someone
- // naming a tar file "blah.tar.gz" :-)
- if ( d->zStream.avail_in > 0 )
- {
- int n = (d->zStream.avail_in < d->zStream.avail_out) ? d->zStream.avail_in : d->zStream.avail_out;
- memcpy( d->zStream.next_out, d->zStream.next_in, n );
- d->zStream.avail_out -= n;
- d->zStream.next_in += n;
- d->zStream.avail_in -= n;
- return OK;
- } else
- return END;
-}
-
-KGzipFilter::Result KGzipFilter::uncompress()
-{
- Q_ASSERT ( m_mode == IO_ReadOnly );
- if ( d->bCompressed )
- {
-#ifdef DEBUG_GZIP
- kdDebug(7005) << "Calling inflate with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable() << endl;
- kdDebug(7005) << " next_in=" << d->zStream.next_in << endl;
-#endif
- int result = inflate(&d->zStream, Z_SYNC_FLUSH);
-#ifdef DEBUG_GZIP
- kdDebug(7005) << " -> inflate returned " << result << endl;
- kdDebug(7005) << "Now avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable() << endl;
- kdDebug(7005) << " next_in=" << d->zStream.next_in << endl;
-#else
- if ( result != Z_OK && result != Z_STREAM_END )
- kdDebug(7005) << "Warning: inflate() returned " << result << endl;
-#endif
- return ( result == Z_OK ? OK : ( result == Z_STREAM_END ? END : ERROR ) );
- } else
- return uncompress_noop();
-}
-
-KGzipFilter::Result KGzipFilter::compress( bool finish )
-{
- Q_ASSERT ( d->bCompressed );
- Q_ASSERT ( m_mode == IO_WriteOnly );
-
- Bytef* p = d->zStream.next_in;
- ulong len = d->zStream.avail_in;
-#ifdef DEBUG_GZIP
- kdDebug(7005) << " calling deflate with avail_in=" << inBufferAvailable() << " avail_out=" << outBufferAvailable() << endl;
-#endif
- int result = deflate(&d->zStream, finish ? Z_FINISH : Z_NO_FLUSH);
- if ( result != Z_OK && result != Z_STREAM_END )
- kdDebug(7005) << " deflate returned " << result << endl;
- if ( m_headerWritten )
- {
- //kdDebug(7005) << "Computing CRC for the next " << len - d->zStream.avail_in << " bytes" << endl;
- m_crc = crc32(m_crc, p, len - d->zStream.avail_in);
- }
- if ( result == Z_STREAM_END && m_headerWritten )
- {
- //kdDebug(7005) << "KGzipFilter::compress finished, write footer" << endl;
- writeFooter();
- }
- return ( result == Z_OK ? OK : ( result == Z_STREAM_END ? END : ERROR ) );
-}
diff --git a/kioslave/gzip/kgzipfilter.desktop b/kioslave/gzip/kgzipfilter.desktop
deleted file mode 100644
index a3b6c027b..000000000
--- a/kioslave/gzip/kgzipfilter.desktop
+++ /dev/null
@@ -1,86 +0,0 @@
-[Desktop Entry]
-Type=Service
-Name=GZip Filter
-Name[af]=Gzip Filter
-Name[ar]=Ùلتر GZip
-Name[az]=GZip Filtri
-Name[be]=Фільтр GZip
-Name[bg]=Филтър GZip
-Name[bn]=জি-জিপ (Gzip) ফিলà§à¦Ÿà¦¾à¦°
-Name[br]=Sil GZip
-Name[ca]=Filtre GZip
-Name[cs]=Filtr GZip2
-Name[csb]=Filter GZipa
-Name[cy]=Hidl GZip
-Name[da]=GZip-filter
-Name[de]=GZip-Filter
-Name[el]=ΦίλτÏο GZip
-Name[eo]=GZip-filtrilo
-Name[es]=Filtro GZip
-Name[et]=GZip filter
-Name[eu]=GZip iragazkia
-Name[fa]=پالایۀ GZip
-Name[fi]=GZip-suodin
-Name[fr]=Filtre Gzip
-Name[fy]=GZip-filter
-Name[ga]=Scagaire gzip
-Name[gl]=Filtro GZip
-Name[he]=מסנן GZip
-Name[hi]=GZip फ़िलà¥à¤Ÿà¤°
-Name[hr]=GZip filtar
-Name[hu]=GZip szűrő
-Name[id]=Filter Gzip
-Name[is]=GZip sía
-Name[it]=Filtro Gzip
-Name[ja]=GZip フィルタ
-Name[ka]=GZip ფილტრი
-Name[kk]=GZip ÑүзгіÑÑ–
-Name[km]=ážáž˜áŸ’ážšáž„ GZip
-Name[ko]=GZip 거르개
-Name[lb]=GZip-Filter
-Name[lt]=GZip filtras
-Name[lv]=GZip Filtrs
-Name[mk]=GZip филтер
-Name[mn]=GZip-Filter
-Name[ms]=Penapis GZip
-Name[mt]=Filtru GZip
-Name[nb]=GZip-filter
-Name[nds]=GZip-Filter
-Name[ne]=GZip फिलà¥à¤Ÿà¤°
-Name[nl]=GZip-filter
-Name[nn]=GZip-filter
-Name[nso]=Sesekodi sa GZip
-Name[pa]=GZip ਫਿਲਟਰ
-Name[pl]=Filtr GZipa
-Name[pt]=Filtro GZip
-Name[pt_BR]=Filtro GZip
-Name[ro]=Filtru GZip
-Name[ru]=Фильтр gzip
-Name[rw]=Muyunguruzi GZipu
-Name[se]=GZip-filter
-Name[sk]=GZip filter
-Name[sl]=Filter za gzip
-Name[sq]=Filteri GZip
-Name[sr]=GZip филтер
-Name[sr@Latn]=GZip filter
-Name[ss]=Sisefo se GZip
-Name[sv]=Gzip-filter
-Name[ta]=GZip வடிகடà¯à®Ÿà®¿
-Name[te]=జిజిపౠగలని
-Name[tg]=Таровиши GZip
-Name[th]=ตัวà¸à¸£à¸­à¸‡ GZip
-Name[tr]=GZip Filtresi
-Name[tt]=GZip Sözgeçe
-Name[uk]=Фільтр GZip
-Name[uz]=GZip-filter
-Name[uz@cyrillic]=GZip-филтер
-Name[ven]=Filithara ya GZip
-Name[vi]=Bá»™ lá»c GZip
-Name[wa]=Passete GZip
-Name[xh]=Isihluzi se GZip
-Name[zh_CN]=GZip 过滤程åº
-Name[zh_HK]=GZip éŽæ¿¾å™¨
-Name[zh_TW]=GZip éŽæ¿¾å™¨
-Name[zu]=Ihluzo le-GZip
-X-TDE-Library=kgzipfilter
-ServiceTypes=TDECompressionFilter,application/x-gzip,application/x-tgz
diff --git a/kioslave/gzip/kgzipfilter.h b/kioslave/gzip/kgzipfilter.h
deleted file mode 100644
index 73b5173f3..000000000
--- a/kioslave/gzip/kgzipfilter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* 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 version 2 as published by the Free Software Foundation.
-
- 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 __kgzipfilter__h
-#define __kgzipfilter__h
-
-#include "kfilterbase.h"
-
-class KGzipFilter : public KFilterBase
-{
-public:
- KGzipFilter();
- virtual ~KGzipFilter();
-
- virtual void init( int mode );
- virtual int mode() const { return m_mode; }
- virtual void terminate();
- virtual void reset();
- virtual bool readHeader();
- virtual bool writeHeader( const TQCString & fileName );
- void writeFooter();
- virtual void setOutBuffer( char * data, uint maxlen );
- virtual void setInBuffer( const char * data, uint size );
- virtual int inBufferAvailable() const;
- virtual int outBufferAvailable() const;
- virtual Result uncompress();
- virtual Result compress( bool finish );
-private:
- Result uncompress_noop();
- int m_mode;
- ulong m_crc;
- bool m_headerWritten;
- class KGzipFilterPrivate;
- KGzipFilterPrivate *d;
-};
-
-#endif
diff --git a/kioslave/http/CMakeLists.txt b/kioslave/http/CMakeLists.txt
deleted file mode 100644
index 51bcfe092..000000000
--- a/kioslave/http/CMakeLists.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-add_subdirectory( kcookiejar )
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/dcop
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/tdecore/network
- ${CMAKE_SOURCE_DIR}/interfaces
- ${CMAKE_SOURCE_DIR}/kio
- ${CMAKE_SOURCE_DIR}/kio/kio
- ${CMAKE_SOURCE_DIR}/kio/httpfilter
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES
- http_cache_cleaner.desktop http.protocol https.protocol
- webdav.protocol webdavs.protocol
- DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-##### kio_http_cache_cleaner ####################
-
-set( target kio_http_cache_cleaner )
-
-set( ${target}_SRCS
- http_cache_cleaner.cpp
-)
-
-tde_add_tdeinit_executable( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK kio-shared
-)
-
-
-##### kio_http ##################################
-
-# FIXME GSSAPI support is not handled yet
-
-set( target kio_http )
-
-set( ${target}_SRCS
- http.cc
-)
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK httpfilter-static kntlm-shared kio-shared
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/http/Makefile.am b/kioslave/http/Makefile.am
deleted file mode 100644
index f8e099140..000000000
--- a/kioslave/http/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-# $Id$
-# Makefile.am of tdebase/kioslave/http
-
-SUBDIRS = kcookiejar
-
-INCLUDES= -I$(top_srcdir)/interfaces -I$(top_srcdir)/kio/httpfilter -I$(top_srcdir)/tdecore/network $(all_includes) $(GSSAPI_INCS)
-AM_LDFLAGS = $(all_libraries) $(GSSAPI_RPATH)
-
-####### Files
-
-bin_PROGRAMS=
-lib_LTLIBRARIES=
-tdeinit_LTLIBRARIES = kio_http_cache_cleaner.la
-kde_module_LTLIBRARIES = kio_http.la
-
-kio_http_la_SOURCES = http.cc
-kio_http_la_METASOURCES = AUTO
-kio_http_la_LIBADD = $(LIB_KIO) $(top_builddir)/kio/httpfilter/libhttpfilter.la $(LIB_QT) $(LIB_TDECORE) $(LIBZ) $(top_builddir)/dcop/libDCOP.la $(top_builddir)/kio/misc/kntlm/libkntlm.la
-kio_http_la_LDFLAGS = $(all_libraries) $(GSSAPI_RPATH) -module $(KDE_PLUGIN) $(GSSAPI_LIBS)
-
-kio_http_cache_cleaner_la_SOURCES = http_cache_cleaner.cpp
-kio_http_cache_cleaner_la_LIBADD = $(LIB_KIO) $(LIB_QT) $(LIB_TDECORE) $(top_builddir)/dcop/libDCOP.la
-kio_http_cache_cleaner_la_LDFLAGS = -module -avoid-version
-
-noinst_HEADERS = http.h
-
-kdelnkdir = $(kde_servicesdir)
-kdelnk_DATA = http_cache_cleaner.desktop http.protocol https.protocol \
- webdav.protocol webdavs.protocol
-
-include $(top_srcdir)/admin/Doxyfile.am
diff --git a/kioslave/http/README.http_cache_cleaner b/kioslave/http/README.http_cache_cleaner
deleted file mode 100644
index 7714bfba6..000000000
--- a/kioslave/http/README.http_cache_cleaner
+++ /dev/null
@@ -1,20 +0,0 @@
-khttpcache README
-=================
-
-khttpcache checks the HTTP Cache of a user
-and throws out expired entries.
-
-TODO:
-
-* Skip entries which end in .new and are younger than
-30 minutes / delte entries which end in .new and are
-older than 30 minutes.
-
-* Let kio_http fill in expire dates other than 0.
-
-DONE:
-
-* Start khttpcache from kio_http if the file "cleaned"
-is older than 30(?) minutes.
-
-* Accept command line parameteres
diff --git a/kioslave/http/README.webdav b/kioslave/http/README.webdav
deleted file mode 100644
index c7ee900bb..000000000
--- a/kioslave/http/README.webdav
+++ /dev/null
@@ -1,184 +0,0 @@
-This document describes how to add support for extended webdav features (locking,
-properties etc.) to your webdav-aware application.
-Author: Hamish Rodda, rodda@kde.org
-Version: 0.3
-
-Compatable with (tested on):
-Apache + mod_dav version 1 and 2
-Zope
-Silverstream webdav server
-
-Applications supporting extended webdav features
- (include name and contact email, in case the interface has to change):
-[none currently]
-
-Much of the info here is elaborated by rfc #2518; the rest can be understood by reading
-davPropStat() in http.cc, specifically the setMetaData() calls.
-
-Extended information is transferred via kio's metadata system...
-
-=== MISCELLANEOUS ===
-Display Names (names suitable for presentation to the user) are passed as the metadata
-element davDisplayName.
-
-Source template locations (href, usually an absolute URL w/o host info)
-are passed as element davSource.
-
-Content languages are passed as element davContentLanguage.
-
-Extra webdav headers are passed as metadata element davHeader
-
-For doing a webdav SEARCH, use listDir() and set the metadata element
-davSearchQuery to the search query. The root element of this query should be like
-<d:basicsearch> or <d:sql>.
-
-For doing a generic webdav action, call a special request, with
-the following data:
-int, value 7 (WEBDAV generic)
-KURL url
-int method - the HTTP/WEBDAV method to call
-Send the xml request and receive the xml response in the usual way.
-
-=== CREATING A LOCK ===
-To create a lock, call a special request, with the following data:
-
-int, value 5 (LOCK request)
-KURL url - the location of the resource to lock
-QString scope - the scope of the lock, currently "exclusive" or "shared"
-QString type - the type of the lock, currently only "write"
-QString owner (optional) - owner contact details (url)
-
-Additionally, the lock timeout requested from the server may be altered from the default
-of Infinity by setting the metadata "davTimeout" to the number of seconds, or 0 for
-infinity.
-
-=== REMOVING A LOCK ===
-To remove a lock, call a special request, with the following data:
-
-int, value 5 (LOCK request)
-KURL url - the location of the resource to unlock
-
-metadata required:
-davLockToken - the lock token to remove
-
-and, of course, any other lock information as below required for the operation
-to suceed.
-
-=== SETTING LOCK INFORMATION ===
-To provide lock data so that urls can be accessed, you need to pass the following metadata:
-davLockCount: (uint) the number of locks you are providing
-davLockToken%1: (string) the token
-(optional) davLockURL%1: (string) the absolute URL specified by the lock token
-(optional) davLockNot%1: (value ignored) the presence of this meta key negates the lock
- (ie. requires the lock to not be set)
-
-Example data:
-=============
-davLockCount: 2
-davLockToken1: opaquelocktoken:f81de2ad-7f3d-a1b2-4f3c-00a0c91a9d76A
-davLockNot1: (value ignored)
-davLockToken2: opaquelocktoken:f81de2ad-7f3d-a1b2-4f3c-00a0c91a9d76B
-davLockURL2: http://www.foo.bar/container2/
-
-
-=== RECEIVING LOCK INFORMATION ===
-For each file, stat/listdir always returns two pieces of information:
-
-davSupportedLockCount: (uint) the number of lock types discovered for this resource.
-davLockCount: (uint) the number of locks discovered on this resource.
-
-for each count, additional information is returned:
-
-===================
-Information about the locks on a resource:
-
-davLockCount: %1 (the number of locks to be described, as below)
-*** Required items ***
-davLockScope%1 - The scope of this lock. May be exclusive, shared, or a custom type.
-davLockType%1 - The type of the lock.
-davLockDepth%1 - The depth to which this lock applies
- (0=only this resource, 1=this collection, infinity=applies recursively)
-
-*** Optional items ***
-davLockOwner%1 - The owner of this lock.
-davLockTimeout%1 - The timeout parameter. Possibilities: see section 9.8, rfc #2518
-davLockToken%1 - The token which iden
-
-===================
-Information about the lock types supported by the resource
-
-davSupportedLockCount: %1 (the number of locks types to be described, as below)
-
-davSupportedLockScope%1 - The scope of the lock (exclusive, shared, other custom type)
-davSupportedLockType%1 - The type of the lock (webdav 1.0 supports only the "write" type)
-===================
-
-Example Metadata which would be supplied if the response was the example XML below:
-
-davSupportedLockCount: 2
-davLockCount: 2
-davLockScope1: exclusive
-davLockType1: write
-davLockDepth1: 0
-davLockOwner1: Jane Smith
-davLockTimeout1: infinite
-davLockToken1: opaquelocktoken:f81de2ad-7f3d-a1b2-4f3c-00a0c91a9d76A
-davLockScope2: shared
-davLockType2: write
-davLockDepth2: 1
-davLockOwner2: John Doe
-davLockToken2: opaquelocktoken:f81de2ad-7f3d-a1b2-4f3c-00a0c91a9d76B
-davSupportedLockScope1: exclusive
-davSupportedLockType1: write
-davSupportedLockScope2: shared
-davSupportedLockType2: write
-
-
-(example XML:)
-
- <?xml version="1.0" encoding="utf-8" ?>
- <D:multistatus xmlns:D='DAV:'>
- <D:response>
- <D:href>http://www.foo.bar/container/</D:href>
- <D:propstat>
- <D:prop>
- <D:lockdiscovery>
- <D:activelock>
- <D:locktype><D:write/></D:locktype>
- <D:lockscope><D:exclusive/></D:lockscope>
- <D:depth>0</D:depth>
- <D:owner>Jane Smith</D:owner>
- <D:timeout>Infinite</D:timeout>
- <D:locktoken>
- <D:href>
- opaquelocktoken:f81de2ad-7f3d-a1b2-4f3c-00a0c91a9d76A
- </D:href>
- </D:locktoken>
- </D:activelock>
- <D:activelock>
- <D:locktype><D:write/></D:locktype>
- <D:lockscope><D:shared/></D:lockscope>
- <D:depth>1</D:depth>
- <D:owner>John Doe</D:owner>
- <D:locktoken>
- <D:href>
- opaquelocktoken:f81de2ad-7f3d-a1b2-4f3c-00a0c91a9d76B
- </D:href>
- </D:locktoken>
- </D:activelock>
- </D:lockdiscovery>
- <D:supportedlock>
- <D:lockentry>
- <D:lockscope><D:exclusive/></D:lockscope>
- <D:locktype><D:write/></D:locktype>
- </D:lockentry>
- <D:lockentry>
- <D:lockscope><D:shared/></D:lockscope>
- <D:locktype><D:write/></D:locktype>
- </D:lockentry>
- </D:supportedlock>
- </D:prop>
- <D:status>HTTP/1.1 200 OK</D:status>
- </D:propstat>
- </D:response>
- </D:multistatus>
diff --git a/kioslave/http/THOUGHTS b/kioslave/http/THOUGHTS
deleted file mode 100644
index 9715b5c2f..000000000
--- a/kioslave/http/THOUGHTS
+++ /dev/null
@@ -1,28 +0,0 @@
-Here's a few ideas for those with blistered hands and nothing better to
-do:
-
-SSL certificate verification:
-We do establish SSL connections, but we never actually verify a
-certificate!
-
-HTTP/1.1 Persistant Connections:
-The header often specifies the timeout value used for connections.
-Close the connection ourselves when the timeout has expired. That way
-we don't loose time sending stuff to an already closed connection.
-
-Rating(s) support. http://www.w3.org/PICS
-This might involve an external program to parse the labels, and something
-to configure access.
-
-WebDAV support. MSIE5 calls it web folders support, and a similar
-approach would probably be a good idea. Perhaps with an exists()
-function.. one could tell if an http url was part of a WebDAV collection..
-and this could be used for some kind of integration with kfile... to
-provide seamless integration. Uhm, also, this might entail an external
-program (xml parser and such).
-
-"Friendly" error messages. How often have you seen a useless 404 message?
-Again something I first notied in MSIE5, and that would be some sort of
-translation of what an error really means. Yes this would have to be
-i18n'd and easily turned off. But this could also be extended to all the
-slaves (ftp, pop3, etc, etc).
diff --git a/kioslave/http/TODO b/kioslave/http/TODO
deleted file mode 100644
index 12a929525..000000000
--- a/kioslave/http/TODO
+++ /dev/null
@@ -1,45 +0,0 @@
-The following is a list of items that are currently missing or partially implemented
-in kio_http:
-
-- HTTP/1.1 Persistant Connections:
-The header often specifies the timeout value used for connections.
-Close the connection ourselves when the timeout has expired. That way
-we don't loose time sending stuff to an already closed connection.
-
-- HTTP/1.1 Pipelining support
-This more of an optimization of the http io-slave that is intended to make it
-faster while using as few resources as possible. Work on this is currently
-being done to add this support for KDE 3.x version.
-
-- WebDAV support:
-The majority of the work for this is done, see README.webdav. GUI integration
-into konqueror as a konqueror part would be nice, to add GUI support for
-features such as locking.
-
-- Rating(s) support. http://www.w3.org/PICS:
-This might involve an external program to parse the labels, and something to
-configure access accordingly. There is only some basic things that need to be
-added to kio_http to support this. The majority of the work has to be done at the
-application level. A khtml plugin in tdeaddons to do this might be a nice idea.
-
-- P3P support:
-This can also be implemented as a plugin to konqueror and does
-not need any speical support in HTTP except perhaps sending a
-flag that indicates that the web page provides some P3P information.
-This is something that can be added as a plugin to tdeaddons.
-
-
-Things that do not require programming
-============================
-
-- "Friendly" error message html page.
-We currently support the sending of error messages, but this is only done if the server
-sends back nicely formatted error messages. We do not have fall back HTML pages that
-describe these error messages in a non-technical manner! This of course also means that
-we will certainly need to have these files translated.
-
-
-Maintainers
-Waldo Bastian <bastian@kde.org>
-Dawit Alemayehu <adawit@kde.org>
-WebDAV support: Hamish Rodda <rodda@kde.org>
diff --git a/kioslave/http/configure.in.bot b/kioslave/http/configure.in.bot
deleted file mode 100644
index 56d051424..000000000
--- a/kioslave/http/configure.in.bot
+++ /dev/null
@@ -1,10 +0,0 @@
-dnl put here things which have to be done as very last part of configure
-
-if test "x$with_gssapi" = xNOTFOUND; then
- echo ""
- echo "You're missing GSSAPI/Kerberos."
- echo "KDE can use GSSAPI/Kerberos to authenticate on certain secure websites."
- echo "GSSAPI/Kerberos authentication is typically used on intranets."
- echo ""
- all_tests=bad
-fi
diff --git a/kioslave/http/configure.in.in b/kioslave/http/configure.in.in
deleted file mode 100644
index a7d1ca7cf..000000000
--- a/kioslave/http/configure.in.in
+++ /dev/null
@@ -1,110 +0,0 @@
-AC_MSG_CHECKING(whether to enable GSSAPI support)
-AC_ARG_WITH(gssapi,
-[ --with-gssapi=PATH Set path for GSSAPI files [default=check]],
-[ case "$withval" in
- yes)
- with_gssapi=CHECK
- ;;
- esac ],
-[ with_gssapi=CHECK ]
-)dnl
-
-if test "x$with_gssapi" = "xCHECK" ; then
- with_gssapi=NOTFOUND
- KDE_FIND_PATH(krb5-config, KRB5_CONFIG, [${prefix}/bin ${exec_prefix}/bin /usr/bin /usr/local/bin /opt/local/bin /usr/lib/mit/bin], [
- AC_MSG_WARN([Could not find krb5-config])
- ])
-
- if test -n "$KRB5_CONFIG"; then
- kde_save_cflags="$CFLAGS"
- unset CFLAGS
- GSSAPI_INCS="`$KRB5_CONFIG --cflags gssapi`"
- GSSAPI_LIBS="`$KRB5_CONFIG --libs gssapi`"
- CFLAGS="$kde_save_cflags"
- if test "$USE_RPATH" = yes; then
- for args in $GSSAPI_LIBS; do
- case $args in
- -L/usr/lib) ;;
- -L*)
- GSSAPI_RPATH="$GSSAPI_RPATH $args"
- ;;
- esac
- done
- GSSAPI_RPATH=`echo $GSSAPI_RPATH | sed -e "s/-L/-R/g"`
- fi
- gssapi_incdir="$GSSAPI_INCS"
- gssapi_libdir="$GSSAPI_LIBS"
- with_gssapi=FOUND
- if $KRB5_CONFIG --vendor | grep "Massachusetts" > /dev/null; then
- gssapi_flavor=MIT
- else
- gssapi_flavor=HEIMDAL
- fi
- else
- search_incs="$kde_includes /usr/include /usr/local/include"
- AC_FIND_FILE(gssapi.h, $search_incs, gssapi_incdir)
- if test -r $gssapi_incdir/gssapi.h ; then
- test "x$gssapi_incdir" != "x/usr/include" && GSSAPI_INCS="-I$gssapi_incdir"
- with_gssapi=FOUND
- fi
- if test $with_gssapi = FOUND ; then
- with_gssapi=NOTFOUND
- for ext in la so sl a dylib ; do
- AC_FIND_FILE(libgssapi.$ext, $kde_libraries /usr/lib /usr/local/lib,
- gssapi_libdir)
- if test -r $gssapi_libdir/libgssapi.$ext ; then
- if test "x$gssapi_libdir" != "x/usr/lib" ; then
- GSSAPI_LIBS="-L$gssapi_libdir "
- test "$USE_RPATH" = yes && GSSAPI_RPATH="-R $gssapi_libdir"
- fi
- GSSAPI_LIBS="${GSSAPI_LIBS} -lgssapi -lkrb5 -lasn1 -lcrypto -lroken -lcrypt ${LIBRESOLV}"
- with_gssapi=FOUND
- gssapi_flavor=HEIMDAL
- break
- fi
- done
- fi
- fi
-fi
-
-case "$with_gssapi" in
-no) AC_MSG_RESULT(no) ;;
-framework)
- GSSAPI_LIBS="-Xlinker -framework -Xlinker Kerberos"
- AC_DEFINE_UNQUOTED(HAVE_LIBGSSAPI, 1, [Define if you have GSSAPI libraries])
- GSSAPI_SUBDIR="gssapi"
- AC_MSG_RESULT(Apple framework)
- ;;
-NOTFOUND) AC_MSG_RESULT(searched but not found) ;;
-*)
- if test "x$with_gssapi" = "xFOUND" ; then
- msg="incs=$gssapi_incdir libs=$gssapi_libdir"
- else
- msg="$with_gssapi"
- GSSAPI_ROOT="$with_gssapi"
- if test "x$GSSAPI_ROOT" != "x/usr" ; then
- GSSAPI_INCS="-I${GSSAPI_ROOT}/include"
- GSSAPI_LIBS="-L${GSSAPI_ROOT}/lib "
- if test "$USE_RPATH" = "yes" ; then
- GSSAPI_RPATH="-R ${GSSAPI_ROOT}/lib"
- fi
- fi
- if test -f ${GSSAPI_ROOT}/include/gssapi/gssapi.h ; then
- gssapi_flavor=MIT
- GSSAPI_LIBS="${GSSAPI_LIBS}-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err ${LIBRESOLV}"
- else
- gssapi_flavor=HEIMDAL
- GSSAPI_LIBS="${GSSAPI_LIBS}-lgssapi -lkrb5 -lasn1 -lcrypto -lroken -lcrypt ${LIBRESOLV}"
- fi
- fi
- if test "x$gssapi_flavor" = "xMIT" ; then
- AC_DEFINE_UNQUOTED(GSSAPI_MIT, 1, [Define if you have the MIT Kerberos libraries])
- fi
- AC_DEFINE_UNQUOTED(HAVE_LIBGSSAPI, 1, [Define if you have GSSAPI libraries])
- AC_MSG_RESULT($msg)
- ;;
-esac
-
-AC_SUBST(GSSAPI_INCS)
-AC_SUBST(GSSAPI_LIBS)
-AC_SUBST(GSSAPI_RPATH)
diff --git a/kioslave/http/http.cc b/kioslave/http/http.cc
deleted file mode 100644
index 16b785d03..000000000
--- a/kioslave/http/http.cc
+++ /dev/null
@@ -1,6108 +0,0 @@
-/*
- Copyright (C) 2000-2003 Waldo Bastian <bastian@kde.org>
- Copyright (C) 2000-2002 George Staikos <staikos@kde.org>
- Copyright (C) 2000-2002 Dawit Alemayehu <adawit@kde.org>
- Copyright (C) 2001,2002 Hamish Rodda <rodda@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 (LGPL) 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.
-*/
-
-#include <config.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <utime.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <netinet/in.h> // Required for AIX
-#include <netinet/tcp.h>
-#include <unistd.h> // must be explicitly included for MacOSX
-
-/*
-#include <netdb.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-*/
-
-#include <tqdom.h>
-#include <tqfile.h>
-#include <tqregexp.h>
-#include <tqdatetime.h>
-#include <tqstringlist.h>
-#include <tqurl.h>
-
-#include <kurl.h>
-#include <kidna.h>
-#include <ksocks.h>
-#include <kdebug.h>
-#include <klocale.h>
-#include <kconfig.h>
-#include <kextsock.h>
-#include <kservice.h>
-#include <krfcdate.h>
-#include <kmdcodec.h>
-#include <kinstance.h>
-#include <kresolver.h>
-#include <kmimemagic.h>
-#include <dcopclient.h>
-#include <kdatastream.h>
-#include <kapplication.h>
-#include <kstandarddirs.h>
-#include <kstringhandler.h>
-#include <kremoteencoding.h>
-
-#include "kio/ioslave_defaults.h"
-#include "kio/http_slave_defaults.h"
-
-#include "httpfilter.h"
-#include "http.h"
-
-#ifdef HAVE_LIBGSSAPI
-#ifdef GSSAPI_MIT
-#include <gssapi/gssapi.h>
-#else
-#include <gssapi.h>
-#endif /* GSSAPI_MIT */
-
-// Catch uncompatible crap (BR86019)
-#if defined(GSS_RFC_COMPLIANT_OIDS) && (GSS_RFC_COMPLIANT_OIDS == 0)
-#include <gssapi/gssapi_generic.h>
-#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
-#endif
-
-#endif /* HAVE_LIBGSSAPI */
-
-#include <misc/kntlm/kntlm.h>
-
-using namespace KIO;
-
-extern "C" {
- KDE_EXPORT int kdemain(int argc, char **argv);
-}
-
-int kdemain( int argc, char **argv )
-{
- KLocale::setMainCatalogue("tdelibs");
- KInstance instance( "kio_http" );
- ( void ) KGlobal::locale();
-
- if (argc != 4)
- {
- fprintf(stderr, "Usage: kio_http protocol domain-socket1 domain-socket2\n");
- exit(-1);
- }
-
- HTTPProtocol slave(argv[1], argv[2], argv[3]);
- slave.dispatchLoop();
- return 0;
-}
-
-/*********************************** Generic utility functions ********************/
-
-static char * trimLead (char *orig_string)
-{
- while (*orig_string == ' ')
- orig_string++;
- return orig_string;
-}
-
-static bool isCrossDomainRequest( const TQString& fqdn, const TQString& originURL )
-{
- if (originURL == "true") // Backwards compatibility
- return true;
-
- KURL url ( originURL );
-
- // Document Origin domain
- TQString a = url.host();
-
- // Current request domain
- TQString b = fqdn;
-
- if (a == b)
- return false;
-
- TQStringList l1 = TQStringList::split('.', a);
- TQStringList l2 = TQStringList::split('.', b);
-
- while(l1.count() > l2.count())
- l1.pop_front();
-
- while(l2.count() > l1.count())
- l2.pop_front();
-
- while(l2.count() >= 2)
- {
- if (l1 == l2)
- return false;
-
- l1.pop_front();
- l2.pop_front();
- }
-
- return true;
-}
-
-/*
- Eliminates any custom header that could potentically alter the request
-*/
-static TQString sanitizeCustomHTTPHeader(const TQString& _header)
-{
- TQString sanitizedHeaders;
- TQStringList headers = TQStringList::split(TQRegExp("[\r\n]"), _header);
-
- for(TQStringList::Iterator it = headers.begin(); it != headers.end(); ++it)
- {
- TQString header = (*it).lower();
- // Do not allow Request line to be specified and ignore
- // the other HTTP headers.
- if (header.find(':') == -1 ||
- header.startsWith("host") ||
- header.startsWith("via"))
- continue;
-
- sanitizedHeaders += (*it);
- sanitizedHeaders += "\r\n";
- }
-
- return sanitizedHeaders.stripWhiteSpace();
-}
-
-
-#define NO_SIZE ((KIO::filesize_t) -1)
-
-#ifdef HAVE_STRTOLL
-#define STRTOLL strtoll
-#else
-#define STRTOLL strtol
-#endif
-
-
-/************************************** HTTPProtocol **********************************************/
-
-HTTPProtocol::HTTPProtocol( const TQCString &protocol, const TQCString &pool,
- const TQCString &app )
- :TCPSlaveBase( 0, protocol , pool, app,
- (protocol == "https" || protocol == "webdavs") )
-{
- m_requestQueue.setAutoDelete(true);
-
- m_bBusy = false;
- m_bFirstRequest = false;
- m_bProxyAuthValid = false;
-
- m_iSize = NO_SIZE;
- m_lineBufUnget = 0;
-
- m_protocol = protocol;
-
- m_maxCacheAge = DEFAULT_MAX_CACHE_AGE;
- m_maxCacheSize = DEFAULT_MAX_CACHE_SIZE / 2;
- m_remoteConnTimeout = DEFAULT_CONNECT_TIMEOUT;
- m_remoteRespTimeout = DEFAULT_RESPONSE_TIMEOUT;
- m_proxyConnTimeout = DEFAULT_PROXY_CONNECT_TIMEOUT;
-
- m_pid = getpid();
-
- setMultipleAuthCaching( true );
- reparseConfiguration();
-}
-
-HTTPProtocol::~HTTPProtocol()
-{
- httpClose(false);
-}
-
-void HTTPProtocol::reparseConfiguration()
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::reparseConfiguration" << endl;
-
- m_strProxyRealm = TQString::null;
- m_strProxyAuthorization = TQString::null;
- ProxyAuthentication = AUTH_None;
- m_bUseProxy = false;
-
- if (m_protocol == "https" || m_protocol == "webdavs")
- m_iDefaultPort = DEFAULT_HTTPS_PORT;
- else if (m_protocol == "ftp")
- m_iDefaultPort = DEFAULT_FTP_PORT;
- else
- m_iDefaultPort = DEFAULT_HTTP_PORT;
-}
-
-void HTTPProtocol::resetConnectionSettings()
-{
- m_bEOF = false;
- m_bError = false;
- m_lineCount = 0;
- m_iWWWAuthCount = 0;
- m_lineCountUnget = 0;
- m_iProxyAuthCount = 0;
-
-}
-
-void HTTPProtocol::resetResponseSettings()
-{
- m_bRedirect = false;
- m_redirectLocation = KURL();
- m_bChunked = false;
- m_iSize = NO_SIZE;
-
- m_responseHeader.clear();
- m_qContentEncodings.clear();
- m_qTransferEncodings.clear();
- m_sContentMD5 = TQString::null;
- m_strMimeType = TQString::null;
-
- setMetaData("request-id", m_request.id);
-}
-
-void HTTPProtocol::resetSessionSettings()
-{
- // Do not reset the URL on redirection if the proxy
- // URL, username or password has not changed!
- KURL proxy ( config()->readEntry("UseProxy") );
-
- if ( m_strProxyRealm.isEmpty() || !proxy.isValid() ||
- m_proxyURL.host() != proxy.host() ||
- (!proxy.user().isNull() && proxy.user() != m_proxyURL.user()) ||
- (!proxy.pass().isNull() && proxy.pass() != m_proxyURL.pass()) )
- {
- m_bProxyAuthValid = false;
- m_proxyURL = proxy;
- m_bUseProxy = m_proxyURL.isValid();
-
- kdDebug(7113) << "(" << m_pid << ") Using proxy: " << m_bUseProxy <<
- " URL: " << m_proxyURL.url() <<
- " Realm: " << m_strProxyRealm << endl;
- }
-
- m_bPersistentProxyConnection = config()->readBoolEntry("PersistentProxyConnection", false);
- kdDebug(7113) << "(" << m_pid << ") Enable Persistent Proxy Connection: "
- << m_bPersistentProxyConnection << endl;
-
- m_request.bUseCookiejar = config()->readBoolEntry("Cookies");
- m_request.bUseCache = config()->readBoolEntry("UseCache", true);
- m_request.bErrorPage = config()->readBoolEntry("errorPage", true);
- m_request.bNoAuth = config()->readBoolEntry("no-auth");
- m_strCacheDir = config()->readPathEntry("CacheDir");
- m_maxCacheAge = config()->readNumEntry("MaxCacheAge", DEFAULT_MAX_CACHE_AGE);
- m_request.window = config()->readEntry("window-id");
-
- kdDebug(7113) << "(" << m_pid << ") Window Id = " << m_request.window << endl;
- kdDebug(7113) << "(" << m_pid << ") ssl_was_in_use = "
- << metaData ("ssl_was_in_use") << endl;
-
- m_request.referrer = TQString::null;
- if ( config()->readBoolEntry("SendReferrer", true) &&
- (m_protocol == "https" || m_protocol == "webdavs" ||
- metaData ("ssl_was_in_use") != "TRUE" ) )
- {
- KURL referrerURL ( metaData("referrer") );
- if (referrerURL.isValid())
- {
- // Sanitize
- TQString protocol = referrerURL.protocol();
- if (protocol.startsWith("webdav"))
- {
- protocol.replace(0, 6, "http");
- referrerURL.setProtocol(protocol);
- }
-
- if (protocol.startsWith("http"))
- {
- referrerURL.setRef(TQString::null);
- referrerURL.setUser(TQString::null);
- referrerURL.setPass(TQString::null);
- m_request.referrer = referrerURL.url();
- }
- }
- }
-
- if ( config()->readBoolEntry("SendLanguageSettings", true) )
- {
- m_request.charsets = config()->readEntry( "Charsets", "iso-8859-1" );
-
- if ( !m_request.charsets.isEmpty() )
- m_request.charsets += DEFAULT_PARTIAL_CHARSET_HEADER;
-
- m_request.languages = config()->readEntry( "Languages", DEFAULT_LANGUAGE_HEADER );
- }
- else
- {
- m_request.charsets = TQString::null;
- m_request.languages = TQString::null;
- }
-
- // Adjust the offset value based on the "resume" meta-data.
- TQString resumeOffset = metaData("resume");
- if ( !resumeOffset.isEmpty() )
- m_request.offset = resumeOffset.toInt(); // TODO: Convert to 64 bit
- else
- m_request.offset = 0;
-
- m_request.disablePassDlg = config()->readBoolEntry("DisablePassDlg", false);
- m_request.allowCompressedPage = config()->readBoolEntry("AllowCompressedPage", true);
- m_request.id = metaData("request-id");
-
- // Store user agent for this host.
- if ( config()->readBoolEntry("SendUserAgent", true) )
- m_request.userAgent = metaData("UserAgent");
- else
- m_request.userAgent = TQString::null;
-
- // Deal with cache cleaning.
- // TODO: Find a smarter way to deal with cleaning the
- // cache ?
- if ( m_request.bUseCache )
- cleanCache();
-
- // Deal with HTTP tunneling
- if ( m_bIsSSL && m_bUseProxy && m_proxyURL.protocol() != "https" &&
- m_proxyURL.protocol() != "webdavs")
- {
- m_bNeedTunnel = true;
- setRealHost( m_request.hostname );
- kdDebug(7113) << "(" << m_pid << ") SSL tunnel: Setting real hostname to: "
- << m_request.hostname << endl;
- }
- else
- {
- m_bNeedTunnel = false;
- setRealHost( TQString::null);
- }
-
- m_responseCode = 0;
- m_prevResponseCode = 0;
-
- m_strRealm = TQString::null;
- m_strAuthorization = TQString::null;
- Authentication = AUTH_None;
-
- // Obtain the proxy and remote server timeout values
- m_proxyConnTimeout = proxyConnectTimeout();
- m_remoteConnTimeout = connectTimeout();
- m_remoteRespTimeout = responseTimeout();
-
- // Set the SSL meta-data here...
- setSSLMetaData();
-
- // Bounce back the actual referrer sent
- setMetaData("referrer", m_request.referrer);
-
- // Follow HTTP/1.1 spec and enable keep-alive by default
- // unless the remote side tells us otherwise or we determine
- // the persistent link has been terminated by the remote end.
- m_bKeepAlive = true;
- m_keepAliveTimeout = 0;
- m_bUnauthorized = false;
-
- // A single request can require multiple exchanges with the remote
- // server due to authentication challenges or SSL tunneling.
- // m_bFirstRequest is a flag that indicates whether we are
- // still processing the first request. This is important because we
- // should not force a close of a keep-alive connection in the middle
- // of the first request.
- // m_bFirstRequest is set to "true" whenever a new connection is
- // made in httpOpenConnection()
- m_bFirstRequest = false;
-}
-
-void HTTPProtocol::setHost( const TQString& host, int port,
- const TQString& user, const TQString& pass )
-{
- // Reset the webdav-capable flags for this host
- if ( m_request.hostname != host )
- m_davHostOk = m_davHostUnsupported = false;
-
- // is it an IPv6 address?
- if (host.find(':') == -1)
- {
- m_request.hostname = host;
- m_request.encoded_hostname = KIDNA::toAscii(host);
- }
- else
- {
- m_request.hostname = host;
- int pos = host.find('%');
- if (pos == -1)
- m_request.encoded_hostname = '[' + host + ']';
- else
- // don't send the scope-id in IPv6 addresses to the server
- m_request.encoded_hostname = '[' + host.left(pos) + ']';
- }
- m_request.port = (port == 0) ? m_iDefaultPort : port;
- m_request.user = user;
- m_request.passwd = pass;
-
- m_bIsTunneled = false;
-
- kdDebug(7113) << "(" << m_pid << ") Hostname is now: " << m_request.hostname <<
- " (" << m_request.encoded_hostname << ")" <<endl;
-}
-
-bool HTTPProtocol::checkRequestURL( const KURL& u )
-{
- kdDebug (7113) << "(" << m_pid << ") HTTPProtocol::checkRequestURL: " << u.url() << endl;
-
- m_request.url = u;
-
- if (m_request.hostname.isEmpty())
- {
- error( KIO::ERR_UNKNOWN_HOST, i18n("No host specified."));
- return false;
- }
-
- if (u.path().isEmpty())
- {
- KURL newUrl(u);
- newUrl.setPath("/");
- redirection(newUrl);
- finished();
- return false;
- }
-
- if ( m_protocol != u.protocol().latin1() )
- {
- short unsigned int oldDefaultPort = m_iDefaultPort;
- m_protocol = u.protocol().latin1();
- reparseConfiguration();
- if ( m_iDefaultPort != oldDefaultPort &&
- m_request.port == oldDefaultPort )
- m_request.port = m_iDefaultPort;
- }
-
- resetSessionSettings();
- return true;
-}
-
-void HTTPProtocol::retrieveContent( bool dataInternal /* = false */ )
-{
- kdDebug (7113) << "(" << m_pid << ") HTTPProtocol::retrieveContent " << endl;
- if ( !retrieveHeader( false ) )
- {
- if ( m_bError )
- return;
- }
- else
- {
- if ( !readBody( dataInternal ) && m_bError )
- return;
- }
-
- httpClose(m_bKeepAlive);
-
- // if data is required internally, don't finish,
- // it is processed before we finish()
- if ( !dataInternal )
- {
- if ((m_responseCode == 204) &&
- ((m_request.method == HTTP_GET) || (m_request.method == HTTP_POST)))
- error(ERR_NO_CONTENT, "");
- else
- finished();
- }
-}
-
-bool HTTPProtocol::retrieveHeader( bool close_connection )
-{
- kdDebug (7113) << "(" << m_pid << ") HTTPProtocol::retrieveHeader " << endl;
- while ( 1 )
- {
- if (!httpOpen())
- return false;
-
- resetResponseSettings();
- if (!readHeader())
- {
- if ( m_bError )
- return false;
-
- if (m_bIsTunneled)
- {
- kdDebug(7113) << "(" << m_pid << ") Re-establishing SSL tunnel..." << endl;
- httpCloseConnection();
- }
- }
- else
- {
- // Do not save authorization if the current response code is
- // 4xx (client error) or 5xx (server error).
- kdDebug(7113) << "(" << m_pid << ") Previous Response: "
- << m_prevResponseCode << endl;
- kdDebug(7113) << "(" << m_pid << ") Current Response: "
- << m_responseCode << endl;
-
- if (isSSLTunnelEnabled() && m_bIsSSL && !m_bUnauthorized && !m_bError)
- {
- // If there is no error, disable tunneling
- if ( m_responseCode < 400 )
- {
- kdDebug(7113) << "(" << m_pid << ") Unset tunneling flag!" << endl;
- setEnableSSLTunnel( false );
- m_bIsTunneled = true;
- // Reset the CONNECT response code...
- m_responseCode = m_prevResponseCode;
- continue;
- }
- else
- {
- if ( !m_request.bErrorPage )
- {
- kdDebug(7113) << "(" << m_pid << ") Sending an error message!" << endl;
- error( ERR_UNKNOWN_PROXY_HOST, m_proxyURL.host() );
- return false;
- }
-
- kdDebug(7113) << "(" << m_pid << ") Sending an error page!" << endl;
- }
- }
-
- if (m_responseCode < 400 && (m_prevResponseCode == 401 ||
- m_prevResponseCode == 407))
- saveAuthorization();
- break;
- }
- }
-
- // Clear of the temporary POST buffer if it is not empty...
- if (!m_bufPOST.isEmpty())
- {
- m_bufPOST.resize(0);
- kdDebug(7113) << "(" << m_pid << ") HTTP::retreiveHeader: Cleared POST "
- "buffer..." << endl;
- }
-
- if ( close_connection )
- {
- httpClose(m_bKeepAlive);
- finished();
- }
-
- return true;
-}
-
-void HTTPProtocol::stat(const KURL& url)
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::stat " << url.prettyURL()
- << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- if ( m_protocol != "webdav" && m_protocol != "webdavs" )
- {
- TQString statSide = metaData(TQString::fromLatin1("statSide"));
- if ( statSide != "source" )
- {
- // When uploading we assume the file doesn't exit
- error( ERR_DOES_NOT_EXIST, url.prettyURL() );
- return;
- }
-
- // When downloading we assume it exists
- UDSEntry entry;
- UDSAtom atom;
- atom.m_uds = KIO::UDS_NAME;
- atom.m_str = url.fileName();
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_FILE_TYPE;
- atom.m_long = S_IFREG; // a file
- entry.append( atom );
-
- atom.m_uds = KIO::UDS_ACCESS;
- atom.m_long = S_IRUSR | S_IRGRP | S_IROTH; // readable by everybody
- entry.append( atom );
-
- statEntry( entry );
- finished();
- return;
- }
-
- davStatList( url );
-}
-
-void HTTPProtocol::listDir( const KURL& url )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::listDir " << url.url()
- << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- if (!url.protocol().startsWith("webdav")) {
- error(ERR_UNSUPPORTED_ACTION, url.prettyURL());
- return;
- }
-
- davStatList( url, false );
-}
-
-void HTTPProtocol::davSetRequest( const TQCString& requestXML )
-{
- // insert the document into the POST buffer, kill trailing zero byte
- m_bufPOST = requestXML;
-
- if (m_bufPOST.size())
- m_bufPOST.truncate( m_bufPOST.size() - 1 );
-}
-
-void HTTPProtocol::davStatList( const KURL& url, bool stat )
-{
- UDSEntry entry;
- UDSAtom atom;
-
- // check to make sure this host supports WebDAV
- if ( !davHostOk() )
- return;
-
- // Maybe it's a disguised SEARCH...
- TQString query = metaData("davSearchQuery");
- if ( !query.isEmpty() )
- {
- TQCString request = "<?xml version=\"1.0\"?>\r\n";
- request.append( "<D:searchrequest xmlns:D=\"DAV:\">\r\n" );
- request.append( query.utf8() );
- request.append( "</D:searchrequest>\r\n" );
-
- davSetRequest( request );
- } else {
- // We are only after certain features...
- TQCString request;
- request = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
- "<D:propfind xmlns:D=\"DAV:\">";
-
- // insert additional XML request from the davRequestResponse metadata
- if ( hasMetaData( "davRequestResponse" ) )
- request += metaData( "davRequestResponse" ).utf8();
- else {
- // No special request, ask for default properties
- request += "<D:prop>"
- "<D:creationdate/>"
- "<D:getcontentlength/>"
- "<D:displayname/>"
- "<D:source/>"
- "<D:getcontentlanguage/>"
- "<D:getcontenttype/>"
- "<D:executable/>"
- "<D:getlastmodified/>"
- "<D:getetag/>"
- "<D:supportedlock/>"
- "<D:lockdiscovery/>"
- "<D:resourcetype/>"
- "</D:prop>";
- }
- request += "</D:propfind>";
-
- davSetRequest( request );
- }
-
- // WebDAV Stat or List...
- m_request.method = query.isEmpty() ? DAV_PROPFIND : DAV_SEARCH;
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
- m_request.davData.depth = stat ? 0 : 1;
- if (!stat)
- m_request.url.adjustPath(+1);
-
- retrieveContent( true );
-
- // Has a redirection already been called? If so, we're done.
- if (m_bRedirect) {
- finished();
- return;
- }
-
- TQDomDocument multiResponse;
- multiResponse.setContent( m_bufWebDavData, true );
-
- bool hasResponse = false;
-
- for ( TQDomNode n = multiResponse.documentElement().firstChild();
- !n.isNull(); n = n.nextSibling())
- {
- TQDomElement thisResponse = n.toElement();
- if (thisResponse.isNull())
- continue;
-
- hasResponse = true;
-
- TQDomElement href = thisResponse.namedItem( "href" ).toElement();
- if ( !href.isNull() )
- {
- entry.clear();
-
- TQString urlStr = href.text();
-#if 0
- int encoding = remoteEncoding()->encodingMib();
- if ((encoding == 106) && (!KStringHandler::isUtf8(KURL::decode_string(urlStr, 4).latin1())))
- encoding = 4; // Use latin1 if the file is not actually utf-8
-#else
- TQUrl::decode(urlStr);
- int encoding = 106;
-#endif
-
- KURL thisURL ( urlStr, encoding );
-
- atom.m_uds = KIO::UDS_NAME;
-
- if ( thisURL.isValid() ) {
- // don't list the base dir of a listDir()
- if ( !stat && thisURL.path(+1).length() == url.path(+1).length() )
- continue;
-
- atom.m_str = thisURL.fileName();
- } else {
- // This is a relative URL.
- atom.m_str = href.text();
- }
-
- entry.append( atom );
-
- TQDomNodeList propstats = thisResponse.elementsByTagName( "propstat" );
-
- davParsePropstats( propstats, entry );
-
- if ( stat )
- {
- // return an item
- statEntry( entry );
- finished();
- return;
- }
- else
- {
- listEntry( entry, false );
- }
- }
- else
- {
- kdDebug(7113) << "Error: no URL contained in response to PROPFIND on "
- << url.prettyURL() << endl;
- }
- }
-
- if ( stat || !hasResponse )
- {
- error( ERR_DOES_NOT_EXIST, url.prettyURL() );
- }
- else
- {
- listEntry( entry, true );
- finished();
- }
-}
-
-void HTTPProtocol::davGeneric( const KURL& url, KIO::HTTP_METHOD method )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davGeneric " << url.url()
- << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- // check to make sure this host supports WebDAV
- if ( !davHostOk() )
- return;
-
- // WebDAV method
- m_request.method = method;
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveContent( false );
-}
-
-int HTTPProtocol::codeFromResponse( const TQString& response )
-{
- int firstSpace = response.find( ' ' );
- int secondSpace = response.find( ' ', firstSpace + 1 );
- return response.mid( firstSpace + 1, secondSpace - firstSpace - 1 ).toInt();
-}
-
-void HTTPProtocol::davParsePropstats( const TQDomNodeList& propstats, UDSEntry& entry )
-{
- TQString mimeType;
- UDSAtom atom;
- bool foundExecutable = false;
- bool isDirectory = false;
- uint lockCount = 0;
- uint supportedLockCount = 0;
-
- for ( uint i = 0; i < propstats.count(); i++)
- {
- TQDomElement propstat = propstats.item(i).toElement();
-
- TQDomElement status = propstat.namedItem( "status" ).toElement();
- if ( status.isNull() )
- {
- // error, no status code in this propstat
- kdDebug(7113) << "Error, no status code in this propstat" << endl;
- return;
- }
-
- int code = codeFromResponse( status.text() );
-
- if ( code != 200 )
- {
- kdDebug(7113) << "Warning: status code " << code << " (this may mean that some properties are unavailable" << endl;
- continue;
- }
-
- TQDomElement prop = propstat.namedItem( "prop" ).toElement();
- if ( prop.isNull() )
- {
- kdDebug(7113) << "Error: no prop segment in this propstat." << endl;
- return;
- }
-
- if ( hasMetaData( "davRequestResponse" ) )
- {
- atom.m_uds = KIO::UDS_XML_PROPERTIES;
- TQDomDocument doc;
- doc.appendChild(prop);
- atom.m_str = doc.toString();
- entry.append( atom );
- }
-
- for ( TQDomNode n = prop.firstChild(); !n.isNull(); n = n.nextSibling() )
- {
- TQDomElement property = n.toElement();
- if (property.isNull())
- continue;
-
- if ( property.namespaceURI() != "DAV:" )
- {
- // break out - we're only interested in properties from the DAV namespace
- continue;
- }
-
- if ( property.tagName() == "creationdate" )
- {
- // Resource creation date. Should be is ISO 8601 format.
- atom.m_uds = KIO::UDS_CREATION_TIME;
- atom.m_long = parseDateTime( property.text(), property.attribute("dt") );
- entry.append( atom );
- }
- else if ( property.tagName() == "getcontentlength" )
- {
- // Content length (file size)
- atom.m_uds = KIO::UDS_SIZE;
- atom.m_long = property.text().toULong();
- entry.append( atom );
- }
- else if ( property.tagName() == "displayname" )
- {
- // Name suitable for presentation to the user
- setMetaData( "davDisplayName", property.text() );
- }
- else if ( property.tagName() == "source" )
- {
- // Source template location
- TQDomElement source = property.namedItem( "link" ).toElement()
- .namedItem( "dst" ).toElement();
- if ( !source.isNull() )
- setMetaData( "davSource", source.text() );
- }
- else if ( property.tagName() == "getcontentlanguage" )
- {
- // equiv. to Content-Language header on a GET
- setMetaData( "davContentLanguage", property.text() );
- }
- else if ( property.tagName() == "getcontenttype" )
- {
- // Content type (mime type)
- // This may require adjustments for other server-side webdav implementations
- // (tested with Apache + mod_dav 1.0.3)
- if ( property.text() == "httpd/unix-directory" )
- {
- isDirectory = true;
- }
- else
- {
- mimeType = property.text();
- }
- }
- else if ( property.tagName() == "executable" )
- {
- // File executable status
- if ( property.text() == "T" )
- foundExecutable = true;
-
- }
- else if ( property.tagName() == "getlastmodified" )
- {
- // Last modification date
- atom.m_uds = KIO::UDS_MODIFICATION_TIME;
- atom.m_long = parseDateTime( property.text(), property.attribute("dt") );
- entry.append( atom );
-
- }
- else if ( property.tagName() == "getetag" )
- {
- // Entity tag
- setMetaData( "davEntityTag", property.text() );
- }
- else if ( property.tagName() == "supportedlock" )
- {
- // Supported locking specifications
- for ( TQDomNode n2 = property.firstChild(); !n2.isNull(); n2 = n2.nextSibling() )
- {
- TQDomElement lockEntry = n2.toElement();
- if ( lockEntry.tagName() == "lockentry" )
- {
- TQDomElement lockScope = lockEntry.namedItem( "lockscope" ).toElement();
- TQDomElement lockType = lockEntry.namedItem( "locktype" ).toElement();
- if ( !lockScope.isNull() && !lockType.isNull() )
- {
- // Lock type was properly specified
- supportedLockCount++;
- TQString scope = lockScope.firstChild().toElement().tagName();
- TQString type = lockType.firstChild().toElement().tagName();
-
- setMetaData( TQString("davSupportedLockScope%1").arg(supportedLockCount), scope );
- setMetaData( TQString("davSupportedLockType%1").arg(supportedLockCount), type );
- }
- }
- }
- }
- else if ( property.tagName() == "lockdiscovery" )
- {
- // Lists the available locks
- davParseActiveLocks( property.elementsByTagName( "activelock" ), lockCount );
- }
- else if ( property.tagName() == "resourcetype" )
- {
- // Resource type. "Specifies the nature of the resource."
- if ( !property.namedItem( "collection" ).toElement().isNull() )
- {
- // This is a collection (directory)
- isDirectory = true;
- }
- }
- else
- {
- kdDebug(7113) << "Found unknown webdav property: " << property.tagName() << endl;
- }
- }
- }
-
- setMetaData( "davLockCount", TQString("%1").arg(lockCount) );
- setMetaData( "davSupportedLockCount", TQString("%1").arg(supportedLockCount) );
-
- atom.m_uds = KIO::UDS_FILE_TYPE;
- atom.m_long = isDirectory ? S_IFDIR : S_IFREG;
- entry.append( atom );
-
- if ( foundExecutable || isDirectory )
- {
- // File was executable, or is a directory.
- atom.m_uds = KIO::UDS_ACCESS;
- atom.m_long = 0700;
- entry.append(atom);
- }
- else
- {
- atom.m_uds = KIO::UDS_ACCESS;
- atom.m_long = 0600;
- entry.append(atom);
- }
-
- if ( !isDirectory && !mimeType.isEmpty() )
- {
- atom.m_uds = KIO::UDS_MIME_TYPE;
- atom.m_str = mimeType;
- entry.append( atom );
- }
-}
-
-void HTTPProtocol::davParseActiveLocks( const TQDomNodeList& activeLocks,
- uint& lockCount )
-{
- for ( uint i = 0; i < activeLocks.count(); i++ )
- {
- TQDomElement activeLock = activeLocks.item(i).toElement();
-
- lockCount++;
- // required
- TQDomElement lockScope = activeLock.namedItem( "lockscope" ).toElement();
- TQDomElement lockType = activeLock.namedItem( "locktype" ).toElement();
- TQDomElement lockDepth = activeLock.namedItem( "depth" ).toElement();
- // optional
- TQDomElement lockOwner = activeLock.namedItem( "owner" ).toElement();
- TQDomElement lockTimeout = activeLock.namedItem( "timeout" ).toElement();
- TQDomElement lockToken = activeLock.namedItem( "locktoken" ).toElement();
-
- if ( !lockScope.isNull() && !lockType.isNull() && !lockDepth.isNull() )
- {
- // lock was properly specified
- lockCount++;
- TQString scope = lockScope.firstChild().toElement().tagName();
- TQString type = lockType.firstChild().toElement().tagName();
- TQString depth = lockDepth.text();
-
- setMetaData( TQString("davLockScope%1").arg( lockCount ), scope );
- setMetaData( TQString("davLockType%1").arg( lockCount ), type );
- setMetaData( TQString("davLockDepth%1").arg( lockCount ), depth );
-
- if ( !lockOwner.isNull() )
- setMetaData( TQString("davLockOwner%1").arg( lockCount ), lockOwner.text() );
-
- if ( !lockTimeout.isNull() )
- setMetaData( TQString("davLockTimeout%1").arg( lockCount ), lockTimeout.text() );
-
- if ( !lockToken.isNull() )
- {
- TQDomElement tokenVal = lockScope.namedItem( "href" ).toElement();
- if ( !tokenVal.isNull() )
- setMetaData( TQString("davLockToken%1").arg( lockCount ), tokenVal.text() );
- }
- }
- }
-}
-
-long HTTPProtocol::parseDateTime( const TQString& input, const TQString& type )
-{
- if ( type == "dateTime.tz" )
- {
- return KRFCDate::parseDateISO8601( input );
- }
- else if ( type == "dateTime.rfc1123" )
- {
- return KRFCDate::parseDate( input );
- }
-
- // format not advertised... try to parse anyway
- time_t time = KRFCDate::parseDate( input );
- if ( time != 0 )
- return time;
-
- return KRFCDate::parseDateISO8601( input );
-}
-
-TQString HTTPProtocol::davProcessLocks()
-{
- if ( hasMetaData( "davLockCount" ) )
- {
- TQString response("If:");
- int numLocks;
- numLocks = metaData( "davLockCount" ).toInt();
- bool bracketsOpen = false;
- for ( int i = 0; i < numLocks; i++ )
- {
- if ( hasMetaData( TQString("davLockToken%1").arg(i) ) )
- {
- if ( hasMetaData( TQString("davLockURL%1").arg(i) ) )
- {
- if ( bracketsOpen )
- {
- response += ")";
- bracketsOpen = false;
- }
- response += " <" + metaData( TQString("davLockURL%1").arg(i) ) + ">";
- }
-
- if ( !bracketsOpen )
- {
- response += " (";
- bracketsOpen = true;
- }
- else
- {
- response += " ";
- }
-
- if ( hasMetaData( TQString("davLockNot%1").arg(i) ) )
- response += "Not ";
-
- response += "<" + metaData( TQString("davLockToken%1").arg(i) ) + ">";
- }
- }
-
- if ( bracketsOpen )
- response += ")";
-
- response += "\r\n";
- return response;
- }
-
- return TQString::null;
-}
-
-bool HTTPProtocol::davHostOk()
-{
- // FIXME needs to be reworked. Switched off for now.
- return true;
-
- // cached?
- if ( m_davHostOk )
- {
- kdDebug(7113) << "(" << m_pid << ") " << k_funcinfo << " true" << endl;
- return true;
- }
- else if ( m_davHostUnsupported )
- {
- kdDebug(7113) << "(" << m_pid << ") " << k_funcinfo << " false" << endl;
- davError( -2 );
- return false;
- }
-
- m_request.method = HTTP_OPTIONS;
-
- // query the server's capabilities generally, not for a specific URL
- m_request.path = "*";
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- // clear davVersions variable, which holds the response to the DAV: header
- m_davCapabilities.clear();
-
- retrieveHeader(false);
-
- if (m_davCapabilities.count())
- {
- for (uint i = 0; i < m_davCapabilities.count(); i++)
- {
- bool ok;
- uint verNo = m_davCapabilities[i].toUInt(&ok);
- if (ok && verNo > 0 && verNo < 3)
- {
- m_davHostOk = true;
- kdDebug(7113) << "Server supports DAV version " << verNo << "." << endl;
- }
- }
-
- if ( m_davHostOk )
- return true;
- }
-
- m_davHostUnsupported = true;
- davError( -2 );
- return false;
-}
-
-// This function is for closing retrieveHeader( false ); requests
-// Required because there may or may not be further info expected
-void HTTPProtocol::davFinished()
-{
- // TODO: Check with the DAV extension developers
- httpClose(m_bKeepAlive);
- finished();
-}
-
-void HTTPProtocol::mkdir( const KURL& url, int )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::mkdir " << url.url()
- << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- m_request.method = DAV_MKCOL;
- m_request.path = url.path();
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveHeader( false );
-
- if ( m_responseCode == 201 )
- davFinished();
- else
- davError();
-}
-
-void HTTPProtocol::get( const KURL& url )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::get " << url.url()
- << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- m_request.method = HTTP_GET;
- m_request.path = url.path();
- m_request.query = url.query();
-
- TQString tmp = metaData("cache");
- if (!tmp.isEmpty())
- m_request.cache = parseCacheControl(tmp);
- else
- m_request.cache = DEFAULT_CACHE_CONTROL;
-
- m_request.passwd = url.pass();
- m_request.user = url.user();
- m_request.doProxy = m_bUseProxy;
-
- retrieveContent();
-}
-
-void HTTPProtocol::put( const KURL &url, int, bool overwrite, bool)
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put " << url.prettyURL()
- << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- // Webdav hosts are capable of observing overwrite == false
- if (!overwrite && m_protocol.left(6) == "webdav") {
- // check to make sure this host supports WebDAV
- if ( !davHostOk() )
- return;
-
- TQCString request;
- request = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
- "<D:propfind xmlns:D=\"DAV:\"><D:prop>"
- "<D:creationdate/>"
- "<D:getcontentlength/>"
- "<D:displayname/>"
- "<D:resourcetype/>"
- "</D:prop></D:propfind>";
-
- davSetRequest( request );
-
- // WebDAV Stat or List...
- m_request.method = DAV_PROPFIND;
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
- m_request.davData.depth = 0;
-
- retrieveContent(true);
-
- if (m_responseCode == 207) {
- error(ERR_FILE_ALREADY_EXIST, TQString::null);
- return;
- }
-
- m_bError = false;
- }
-
- m_request.method = HTTP_PUT;
- m_request.path = url.path();
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveHeader( false );
-
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put error = " << m_bError << endl;
- if (m_bError)
- return;
-
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::put responseCode = " << m_responseCode << endl;
-
- httpClose(false); // Always close connection.
-
- if ( (m_responseCode >= 200) && (m_responseCode < 300) )
- finished();
- else
- httpError();
-}
-
-void HTTPProtocol::copy( const KURL& src, const KURL& dest, int, bool overwrite )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::copy " << src.prettyURL()
- << " -> " << dest.prettyURL() << endl;
-
- if ( !checkRequestURL( dest ) || !checkRequestURL( src ) )
- return;
-
- // destination has to be "http(s)://..."
- KURL newDest = dest;
- if (newDest.protocol() == "webdavs")
- newDest.setProtocol("https");
- else
- newDest.setProtocol("http");
-
- m_request.method = DAV_COPY;
- m_request.path = src.path();
- m_request.davData.desturl = newDest.url();
- m_request.davData.overwrite = overwrite;
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveHeader( false );
-
- // The server returns a HTTP/1.1 201 Created or 204 No Content on successful completion
- if ( m_responseCode == 201 || m_responseCode == 204 )
- davFinished();
- else
- davError();
-}
-
-void HTTPProtocol::rename( const KURL& src, const KURL& dest, bool overwrite )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::rename " << src.prettyURL()
- << " -> " << dest.prettyURL() << endl;
-
- if ( !checkRequestURL( dest ) || !checkRequestURL( src ) )
- return;
-
- // destination has to be "http://..."
- KURL newDest = dest;
- if (newDest.protocol() == "webdavs")
- newDest.setProtocol("https");
- else
- newDest.setProtocol("http");
-
- m_request.method = DAV_MOVE;
- m_request.path = src.path();
- m_request.davData.desturl = newDest.url();
- m_request.davData.overwrite = overwrite;
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveHeader( false );
-
- if ( m_responseCode == 301 )
- {
- // Work around strict Apache-2 WebDAV implementation which refuses to cooperate
- // with webdav://host/directory, instead requiring webdav://host/directory/
- // (strangely enough it accepts Destination: without a trailing slash)
-
- if (m_redirectLocation.protocol() == "https")
- m_redirectLocation.setProtocol("webdavs");
- else
- m_redirectLocation.setProtocol("webdav");
-
- if ( !checkRequestURL( m_redirectLocation ) )
- return;
-
- m_request.method = DAV_MOVE;
- m_request.path = m_redirectLocation.path();
- m_request.davData.desturl = newDest.url();
- m_request.davData.overwrite = overwrite;
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveHeader( false );
- }
-
- if ( m_responseCode == 201 )
- davFinished();
- else
- davError();
-}
-
-void HTTPProtocol::del( const KURL& url, bool )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::del " << url.prettyURL()
- << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- m_request.method = HTTP_DELETE;
- m_request.path = url.path();
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveHeader( false );
-
- // The server returns a HTTP/1.1 200 Ok or HTTP/1.1 204 No Content
- // on successful completion
- if ( m_responseCode == 200 || m_responseCode == 204 )
- davFinished();
- else
- davError();
-}
-
-void HTTPProtocol::post( const KURL& url )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::post "
- << url.prettyURL() << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- m_request.method = HTTP_POST;
- m_request.path = url.path();
- m_request.query = url.query();
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveContent();
-}
-
-void HTTPProtocol::davLock( const KURL& url, const TQString& scope,
- const TQString& type, const TQString& owner )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davLock "
- << url.prettyURL() << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- m_request.method = DAV_LOCK;
- m_request.path = url.path();
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- /* Create appropriate lock XML request. */
- TQDomDocument lockReq;
-
- TQDomElement lockInfo = lockReq.createElementNS( "DAV:", "lockinfo" );
- lockReq.appendChild( lockInfo );
-
- TQDomElement lockScope = lockReq.createElement( "lockscope" );
- lockInfo.appendChild( lockScope );
-
- lockScope.appendChild( lockReq.createElement( scope ) );
-
- TQDomElement lockType = lockReq.createElement( "locktype" );
- lockInfo.appendChild( lockType );
-
- lockType.appendChild( lockReq.createElement( type ) );
-
- if ( !owner.isNull() ) {
- TQDomElement ownerElement = lockReq.createElement( "owner" );
- lockReq.appendChild( ownerElement );
-
- TQDomElement ownerHref = lockReq.createElement( "href" );
- ownerElement.appendChild( ownerHref );
-
- ownerHref.appendChild( lockReq.createTextNode( owner ) );
- }
-
- // insert the document into the POST buffer
- m_bufPOST = lockReq.toCString();
-
- retrieveContent( true );
-
- if ( m_responseCode == 200 ) {
- // success
- TQDomDocument multiResponse;
- multiResponse.setContent( m_bufWebDavData, true );
-
- TQDomElement prop = multiResponse.documentElement().namedItem( "prop" ).toElement();
-
- TQDomElement lockdiscovery = prop.namedItem( "lockdiscovery" ).toElement();
-
- uint lockCount = 0;
- davParseActiveLocks( lockdiscovery.elementsByTagName( "activelock" ), lockCount );
-
- setMetaData( "davLockCount", TQString("%1").arg( lockCount ) );
-
- finished();
-
- } else
- davError();
-}
-
-void HTTPProtocol::davUnlock( const KURL& url )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::davUnlock "
- << url.prettyURL() << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- m_request.method = DAV_UNLOCK;
- m_request.path = url.path();
- m_request.query = TQString::null;
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- retrieveContent( true );
-
- if ( m_responseCode == 200 )
- finished();
- else
- davError();
-}
-
-TQString HTTPProtocol::davError( int code /* = -1 */, TQString url )
-{
- bool callError = false;
- if ( code == -1 ) {
- code = m_responseCode;
- callError = true;
- }
- if ( code == -2 ) {
- callError = true;
- }
-
- if ( !url.isNull() )
- url = m_request.url.url();
-
- TQString action, errorString;
- KIO::Error kError;
-
- // for 412 Precondition Failed
- TQString ow = i18n( "Otherwise, the request would have succeeded." );
-
- switch ( m_request.method ) {
- case DAV_PROPFIND:
- action = i18n( "retrieve property values" );
- break;
- case DAV_PROPPATCH:
- action = i18n( "set property values" );
- break;
- case DAV_MKCOL:
- action = i18n( "create the requested folder" );
- break;
- case DAV_COPY:
- action = i18n( "copy the specified file or folder" );
- break;
- case DAV_MOVE:
- action = i18n( "move the specified file or folder" );
- break;
- case DAV_SEARCH:
- action = i18n( "search in the specified folder" );
- break;
- case DAV_LOCK:
- action = i18n( "lock the specified file or folder" );
- break;
- case DAV_UNLOCK:
- action = i18n( "unlock the specified file or folder" );
- break;
- case HTTP_DELETE:
- action = i18n( "delete the specified file or folder" );
- break;
- case HTTP_OPTIONS:
- action = i18n( "query the server's capabilities" );
- break;
- case HTTP_GET:
- action = i18n( "retrieve the contents of the specified file or folder" );
- break;
- case HTTP_PUT:
- case HTTP_POST:
- case HTTP_HEAD:
- default:
- // this should not happen, this function is for webdav errors only
- Q_ASSERT(0);
- }
-
- // default error message if the following code fails
- kError = ERR_INTERNAL;
- errorString = i18n("An unexpected error (%1) occurred while attempting to %2.")
- .arg( code ).arg( action );
-
- switch ( code )
- {
- case -2:
- // internal error: OPTIONS request did not specify DAV compliance
- kError = ERR_UNSUPPORTED_PROTOCOL;
- errorString = i18n("The server does not support the WebDAV protocol.");
- break;
- case 207:
- // 207 Multi-status
- {
- // our error info is in the returned XML document.
- // retrieve the XML document
-
- // there was an error retrieving the XML document.
- // ironic, eh?
- if ( !readBody( true ) && m_bError )
- return TQString::null;
-
- TQStringList errors;
- TQDomDocument multiResponse;
-
- multiResponse.setContent( m_bufWebDavData, true );
-
- TQDomElement multistatus = multiResponse.documentElement().namedItem( "multistatus" ).toElement();
-
- TQDomNodeList responses = multistatus.elementsByTagName( "response" );
-
- for (uint i = 0; i < responses.count(); i++)
- {
- int errCode;
- TQString errUrl;
-
- TQDomElement response = responses.item(i).toElement();
- TQDomElement code = response.namedItem( "status" ).toElement();
-
- if ( !code.isNull() )
- {
- errCode = codeFromResponse( code.text() );
- TQDomElement href = response.namedItem( "href" ).toElement();
- if ( !href.isNull() )
- errUrl = href.text();
- errors << davError( errCode, errUrl );
- }
- }
-
- //kError = ERR_SLAVE_DEFINED;
- errorString = i18n("An error occurred while attempting to %1, %2. A "
- "summary of the reasons is below.<ul>").arg( action ).arg( url );
-
- for ( TQStringList::Iterator it = errors.begin(); it != errors.end(); ++it )
- errorString += "<li>" + *it + "</li>";
-
- errorString += "</ul>";
- }
- case 403:
- case 500: // hack: Apache mod_dav returns this instead of 403 (!)
- // 403 Forbidden
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("Access was denied while attempting to %1.").arg( action );
- break;
- case 405:
- // 405 Method Not Allowed
- if ( m_request.method == DAV_MKCOL )
- {
- kError = ERR_DIR_ALREADY_EXIST;
- errorString = i18n("The specified folder already exists.");
- }
- break;
- case 409:
- // 409 Conflict
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("A resource cannot be created at the destination "
- "until one or more intermediate collections (folders) "
- "have been created.");
- break;
- case 412:
- // 412 Precondition failed
- if ( m_request.method == DAV_COPY || m_request.method == DAV_MOVE )
- {
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("The server was unable to maintain the liveness of "
- "the properties listed in the propertybehavior XML "
- "element or you attempted to overwrite a file while "
- "requesting that files are not overwritten. %1")
- .arg( ow );
-
- }
- else if ( m_request.method == DAV_LOCK )
- {
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("The requested lock could not be granted. %1").arg( ow );
- }
- break;
- case 415:
- // 415 Unsupported Media Type
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("The server does not support the request type of the body.");
- break;
- case 423:
- // 423 Locked
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("Unable to %1 because the resource is locked.").arg( action );
- break;
- case 425:
- // 424 Failed Dependency
- errorString = i18n("This action was prevented by another error.");
- break;
- case 502:
- // 502 Bad Gateway
- if ( m_request.method == DAV_COPY || m_request.method == DAV_MOVE )
- {
- kError = ERR_WRITE_ACCESS_DENIED;
- errorString = i18n("Unable to %1 because the destination server refuses "
- "to accept the file or folder.").arg( action );
- }
- break;
- case 507:
- // 507 Insufficient Storage
- kError = ERR_DISK_FULL;
- errorString = i18n("The destination resource does not have sufficient space "
- "to record the state of the resource after the execution "
- "of this method.");
- break;
- }
-
- // if ( kError != ERR_SLAVE_DEFINED )
- //errorString += " (" + url + ")";
-
- if ( callError )
- error( ERR_SLAVE_DEFINED, errorString );
-
- return errorString;
-}
-
-void HTTPProtocol::httpError()
-{
- TQString action, errorString;
- KIO::Error kError;
-
- switch ( m_request.method ) {
- case HTTP_PUT:
- action = i18n( "upload %1" ).arg(m_request.url.prettyURL());
- break;
- default:
- // this should not happen, this function is for http errors only
- Q_ASSERT(0);
- }
-
- // default error message if the following code fails
- kError = ERR_INTERNAL;
- errorString = i18n("An unexpected error (%1) occurred while attempting to %2.")
- .arg( m_responseCode ).arg( action );
-
- switch ( m_responseCode )
- {
- case 403:
- case 405:
- case 500: // hack: Apache mod_dav returns this instead of 403 (!)
- // 403 Forbidden
- // 405 Method Not Allowed
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("Access was denied while attempting to %1.").arg( action );
- break;
- case 409:
- // 409 Conflict
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("A resource cannot be created at the destination "
- "until one or more intermediate collections (folders) "
- "have been created.");
- break;
- case 423:
- // 423 Locked
- kError = ERR_ACCESS_DENIED;
- errorString = i18n("Unable to %1 because the resource is locked.").arg( action );
- break;
- case 502:
- // 502 Bad Gateway
- kError = ERR_WRITE_ACCESS_DENIED;
- errorString = i18n("Unable to %1 because the destination server refuses "
- "to accept the file or folder.").arg( action );
- break;
- case 507:
- // 507 Insufficient Storage
- kError = ERR_DISK_FULL;
- errorString = i18n("The destination resource does not have sufficient space "
- "to record the state of the resource after the execution "
- "of this method.");
- break;
- }
-
- // if ( kError != ERR_SLAVE_DEFINED )
- //errorString += " (" + url + ")";
-
- error( ERR_SLAVE_DEFINED, errorString );
-}
-
-bool HTTPProtocol::isOffline(const KURL &url)
-{
- const int NetWorkStatusUnknown = 1;
- const int NetWorkStatusOnline = 8;
- TQCString replyType;
- TQByteArray params;
- TQByteArray reply;
-
- TQDataStream stream(params, IO_WriteOnly);
-
- if ( url.host() == TQString::fromLatin1("localhost") || url.host() == TQString::fromLatin1("127.0.0.1") || url.host() == TQString::fromLatin1("::") ) {
- return false;
- }
- if ( dcopClient()->call( "kded", "networkstatus", "status()",
- params, replyType, reply ) && (replyType == "int") )
- {
- int result;
- TQDataStream stream2( reply, IO_ReadOnly );
- stream2 >> result;
- kdDebug(7113) << "(" << m_pid << ") networkstatus status = " << result << endl;
- return (result != NetWorkStatusUnknown) && (result != NetWorkStatusOnline);
- }
- kdDebug(7113) << "(" << m_pid << ") networkstatus <unreachable>" << endl;
- return false; // On error, assume we are online
-}
-
-void HTTPProtocol::multiGet(const TQByteArray &data)
-{
- TQDataStream stream(data, IO_ReadOnly);
- TQ_UINT32 n;
- stream >> n;
-
- kdDebug(7113) << "(" << m_pid << ") HTTPProtcool::multiGet n = " << n << endl;
-
- HTTPRequest saveRequest;
- if (m_bBusy)
- saveRequest = m_request;
-
-// m_requestQueue.clear();
- for(unsigned i = 0; i < n; i++)
- {
- KURL url;
- stream >> url >> mIncomingMetaData;
-
- if ( !checkRequestURL( url ) )
- continue;
-
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::multi_get " << url.url() << endl;
-
- m_request.method = HTTP_GET;
- m_request.path = url.path();
- m_request.query = url.query();
- TQString tmp = metaData("cache");
- if (!tmp.isEmpty())
- m_request.cache = parseCacheControl(tmp);
- else
- m_request.cache = DEFAULT_CACHE_CONTROL;
-
- m_request.passwd = url.pass();
- m_request.user = url.user();
- m_request.doProxy = m_bUseProxy;
-
- HTTPRequest *newRequest = new HTTPRequest(m_request);
- m_requestQueue.append(newRequest);
- }
-
- if (m_bBusy)
- m_request = saveRequest;
-
- if (!m_bBusy)
- {
- m_bBusy = true;
- while(!m_requestQueue.isEmpty())
- {
- HTTPRequest *request = m_requestQueue.take(0);
- m_request = *request;
- delete request;
- retrieveContent();
- }
- m_bBusy = false;
- }
-}
-
-ssize_t HTTPProtocol::write (const void *_buf, size_t nbytes)
-{
- int bytes_sent = 0;
- const char* buf = static_cast<const char*>(_buf);
- while ( nbytes > 0 )
- {
- int n = TCPSlaveBase::write(buf, nbytes);
-
- if ( n <= 0 )
- {
- // remote side closed connection ?
- if ( n == 0 )
- break;
- // a valid exception(s) occurred, let's retry...
- if (n < 0 && ((errno == EINTR) || (errno == EAGAIN)))
- continue;
- // some other error occurred ?
- return -1;
- }
-
- nbytes -= n;
- buf += n;
- bytes_sent += n;
- }
-
- return bytes_sent;
-}
-
-void HTTPProtocol::setRewindMarker()
-{
- m_rewindCount = 0;
-}
-
-void HTTPProtocol::rewind()
-{
- m_linePtrUnget = m_rewindBuf,
- m_lineCountUnget = m_rewindCount;
- m_rewindCount = 0;
-}
-
-
-char *HTTPProtocol::gets (char *s, int size)
-{
- int len=0;
- char *buf=s;
- char mybuf[2]={0,0};
-
- while (len < size)
- {
- read(mybuf, 1);
- if (m_bEOF)
- break;
-
- if (m_rewindCount < sizeof(m_rewindBuf))
- m_rewindBuf[m_rewindCount++] = *mybuf;
-
- if (*mybuf == '\r') // Ignore!
- continue;
-
- if ((*mybuf == '\n') || !*mybuf)
- break;
-
- *buf++ = *mybuf;
- len++;
- }
-
- *buf=0;
- return s;
-}
-
-ssize_t HTTPProtocol::read (void *b, size_t nbytes)
-{
- ssize_t ret = 0;
-
- if (m_lineCountUnget > 0)
- {
- ret = ( nbytes < m_lineCountUnget ? nbytes : m_lineCountUnget );
- m_lineCountUnget -= ret;
- memcpy(b, m_linePtrUnget, ret);
- m_linePtrUnget += ret;
-
- return ret;
- }
-
- if (m_lineCount > 0)
- {
- ret = ( nbytes < m_lineCount ? nbytes : m_lineCount );
- m_lineCount -= ret;
- memcpy(b, m_linePtr, ret);
- m_linePtr += ret;
- return ret;
- }
-
- if (nbytes == 1)
- {
- ret = read(m_lineBuf, 1024); // Read into buffer
- m_linePtr = m_lineBuf;
- if (ret <= 0)
- {
- m_lineCount = 0;
- return ret;
- }
- m_lineCount = ret;
- return read(b, 1); // Read from buffer
- }
-
- do
- {
- ret = TCPSlaveBase::read( b, nbytes);
- if (ret == 0)
- m_bEOF = true;
-
- } while ((ret == -1) && (errno == EAGAIN || errno == EINTR));
-
- return ret;
-}
-
-void HTTPProtocol::httpCheckConnection()
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpCheckConnection: " <<
- " Socket status: " << m_iSock <<
- " Keep Alive: " << m_bKeepAlive <<
- " First: " << m_bFirstRequest << endl;
-
- if ( !m_bFirstRequest && (m_iSock != -1) )
- {
- bool closeDown = false;
- if ( !isConnectionValid())
- {
- kdDebug(7113) << "(" << m_pid << ") Connection lost!" << endl;
- closeDown = true;
- }
- else if ( m_request.method != HTTP_GET )
- {
- closeDown = true;
- }
- else if ( !m_state.doProxy && !m_request.doProxy )
- {
- if (m_state.hostname != m_request.hostname ||
- m_state.port != m_request.port ||
- m_state.user != m_request.user ||
- m_state.passwd != m_request.passwd)
- closeDown = true;
- }
- else
- {
- // Keep the connection to the proxy.
- if ( !(m_request.doProxy && m_state.doProxy) )
- closeDown = true;
- }
-
- if (closeDown)
- httpCloseConnection();
- }
-
- // Let's update our current state
- m_state.hostname = m_request.hostname;
- m_state.encoded_hostname = m_request.encoded_hostname;
- m_state.port = m_request.port;
- m_state.user = m_request.user;
- m_state.passwd = m_request.passwd;
- m_state.doProxy = m_request.doProxy;
-}
-
-bool HTTPProtocol::httpOpenConnection()
-{
- int errCode;
- TQString errMsg;
-
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpenConnection" << endl;
-
- setBlockConnection( true );
- // kio_http uses its own proxying:
- KSocks::self()->disableSocks();
-
- if ( m_state.doProxy )
- {
- TQString proxy_host = m_proxyURL.host();
- int proxy_port = m_proxyURL.port();
-
- kdDebug(7113) << "(" << m_pid << ") Connecting to proxy server: "
- << proxy_host << ", port: " << proxy_port << endl;
-
- infoMessage( i18n("Connecting to %1...").arg(m_state.hostname) );
-
- setConnectTimeout( m_proxyConnTimeout );
-
- if ( !connectToHost(proxy_host, proxy_port, false) )
- {
- if (userAborted()) {
- error(ERR_NO_CONTENT, "");
- return false;
- }
-
- switch ( connectResult() )
- {
- case IO_LookupError:
- errMsg = proxy_host;
- errCode = ERR_UNKNOWN_PROXY_HOST;
- break;
- case IO_TimeOutError:
- errMsg = i18n("Proxy %1 at port %2").arg(proxy_host).arg(proxy_port);
- errCode = ERR_SERVER_TIMEOUT;
- break;
- default:
- errMsg = i18n("Proxy %1 at port %2").arg(proxy_host).arg(proxy_port);
- errCode = ERR_COULD_NOT_CONNECT;
- }
- error( errCode, errMsg );
- return false;
- }
- }
- else
- {
- // Apparently we don't want a proxy. let's just connect directly
- setConnectTimeout(m_remoteConnTimeout);
-
- if ( !connectToHost(m_state.hostname, m_state.port, false ) )
- {
- if (userAborted()) {
- error(ERR_NO_CONTENT, "");
- return false;
- }
-
- switch ( connectResult() )
- {
- case IO_LookupError:
- errMsg = m_state.hostname;
- errCode = ERR_UNKNOWN_HOST;
- break;
- case IO_TimeOutError:
- errMsg = i18n("Connection was to %1 at port %2").arg(m_state.hostname).arg(m_state.port);
- errCode = ERR_SERVER_TIMEOUT;
- break;
- default:
- errCode = ERR_COULD_NOT_CONNECT;
- if (m_state.port != m_iDefaultPort)
- errMsg = i18n("%1 (port %2)").arg(m_state.hostname).arg(m_state.port);
- else
- errMsg = m_state.hostname;
- }
- error( errCode, errMsg );
- return false;
- }
- }
-
- // Set our special socket option!!
- int on = 1;
- (void) setsockopt( m_iSock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on) );
-
- m_bFirstRequest = true;
-
- connected();
- return true;
-}
-
-
-/**
- * This function is responsible for opening up the connection to the remote
- * HTTP server and sending the header. If this requires special
- * authentication or other such fun stuff, then it will handle it. This
- * function will NOT receive anything from the server, however. This is in
- * contrast to previous incarnations of 'httpOpen'.
- *
- * The reason for the change is due to one small fact: some requests require
- * data to be sent in addition to the header (POST requests) and there is no
- * way for this function to get that data. This function is called in the
- * slotPut() or slotGet() functions which, in turn, are called (indirectly) as
- * a result of a KIOJob::put() or KIOJob::get(). It is those latter functions
- * which are responsible for starting up this ioslave in the first place.
- * This means that 'httpOpen' is called (essentially) as soon as the ioslave
- * is created -- BEFORE any data gets to this slave.
- *
- * The basic process now is this:
- *
- * 1) Open up the socket and port
- * 2) Format our request/header
- * 3) Send the header to the remote server
- */
-bool HTTPProtocol::httpOpen()
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen" << endl;
-
- // Cannot have an https request without the m_bIsSSL being set! This can
- // only happen if TCPSlaveBase::InitializeSSL() function failed in which it
- // means the current installation does not support SSL...
- if ( (m_protocol == "https" || m_protocol == "webdavs") && !m_bIsSSL )
- {
- error( ERR_UNSUPPORTED_PROTOCOL, m_protocol );
- return false;
- }
-
- m_request.fcache = 0;
- m_request.bCachedRead = false;
- m_request.bCachedWrite = false;
- m_request.bMustRevalidate = false;
- m_request.expireDate = 0;
- m_request.creationDate = 0;
-
- if (m_request.bUseCache)
- {
- m_request.fcache = checkCacheEntry( );
-
- bool bCacheOnly = (m_request.cache == KIO::CC_CacheOnly);
- bool bOffline = isOffline(m_request.doProxy ? m_proxyURL : m_request.url);
- if (bOffline && (m_request.cache != KIO::CC_Reload))
- m_request.cache = KIO::CC_CacheOnly;
-
- if (m_request.cache == CC_Reload && m_request.fcache)
- {
- if (m_request.fcache)
- fclose(m_request.fcache);
- m_request.fcache = 0;
- }
- if ((m_request.cache == KIO::CC_CacheOnly) || (m_request.cache == KIO::CC_Cache))
- m_request.bMustRevalidate = false;
-
- m_request.bCachedWrite = true;
-
- if (m_request.fcache && !m_request.bMustRevalidate)
- {
- // Cache entry is OK.
- m_request.bCachedRead = true; // Cache hit.
- return true;
- }
- else if (!m_request.fcache)
- {
- m_request.bMustRevalidate = false; // Cache miss
- }
- else
- {
- // Conditional cache hit. (Validate)
- }
-
- if (bCacheOnly && bOffline)
- {
- error( ERR_OFFLINE_MODE, m_request.url.url() );
- return false;
- }
- if (bCacheOnly)
- {
- error( ERR_DOES_NOT_EXIST, m_request.url.url() );
- return false;
- }
- if (bOffline)
- {
- error( ERR_OFFLINE_MODE, m_request.url.url() );
- return false;
- }
- }
-
- TQString header;
- TQString davHeader;
-
- bool moreData = false;
- bool davData = false;
-
- // Clear out per-connection settings...
- resetConnectionSettings ();
-
- // Check the validity of the current connection, if one exists.
- httpCheckConnection();
-
- if ( !m_bIsTunneled && m_bNeedTunnel )
- {
- setEnableSSLTunnel( true );
- // We send a HTTP 1.0 header since some proxies refuse HTTP 1.1 and we don't
- // need any HTTP 1.1 capabilities for CONNECT - Waba
- header = TQString("CONNECT %1:%2 HTTP/1.0"
- "\r\n").arg( m_request.encoded_hostname).arg(m_request.port);
-
- // Identify who you are to the proxy server!
- if (!m_request.userAgent.isEmpty())
- header += "User-Agent: " + m_request.userAgent + "\r\n";
-
- /* Add hostname information */
- header += "Host: " + m_state.encoded_hostname;
-
- if (m_state.port != m_iDefaultPort)
- header += TQString(":%1").arg(m_state.port);
- header += "\r\n";
-
- header += proxyAuthenticationHeader();
- }
- else
- {
- // Determine if this is a POST or GET method
- switch (m_request.method)
- {
- case HTTP_GET:
- header = "GET ";
- break;
- case HTTP_PUT:
- header = "PUT ";
- moreData = true;
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case HTTP_POST:
- header = "POST ";
- moreData = true;
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case HTTP_HEAD:
- header = "HEAD ";
- break;
- case HTTP_DELETE:
- header = "DELETE ";
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case HTTP_OPTIONS:
- header = "OPTIONS ";
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case DAV_PROPFIND:
- header = "PROPFIND ";
- davData = true;
- davHeader = "Depth: ";
- if ( hasMetaData( "davDepth" ) )
- {
- kdDebug(7113) << "Reading DAV depth from metadata: " << metaData( "davDepth" ) << endl;
- davHeader += metaData( "davDepth" );
- }
- else
- {
- if ( m_request.davData.depth == 2 )
- davHeader += "infinity";
- else
- davHeader += TQString("%1").arg( m_request.davData.depth );
- }
- davHeader += "\r\n";
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case DAV_PROPPATCH:
- header = "PROPPATCH ";
- davData = true;
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case DAV_MKCOL:
- header = "MKCOL ";
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case DAV_COPY:
- case DAV_MOVE:
- header = ( m_request.method == DAV_COPY ) ? "COPY " : "MOVE ";
- davHeader = "Destination: " + m_request.davData.desturl;
- // infinity depth means copy recursively
- // (optional for copy -> but is the desired action)
- davHeader += "\r\nDepth: infinity\r\nOverwrite: ";
- davHeader += m_request.davData.overwrite ? "T" : "F";
- davHeader += "\r\n";
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case DAV_LOCK:
- header = "LOCK ";
- davHeader = "Timeout: ";
- {
- uint timeout = 0;
- if ( hasMetaData( "davTimeout" ) )
- timeout = metaData( "davTimeout" ).toUInt();
- if ( timeout == 0 )
- davHeader += "Infinite";
- else
- davHeader += TQString("Seconds-%1").arg(timeout);
- }
- davHeader += "\r\n";
- m_request.bCachedWrite = false; // Do not put any result in the cache
- davData = true;
- break;
- case DAV_UNLOCK:
- header = "UNLOCK ";
- davHeader = "Lock-token: " + metaData("davLockToken") + "\r\n";
- m_request.bCachedWrite = false; // Do not put any result in the cache
- break;
- case DAV_SEARCH:
- header = "SEARCH ";
- davData = true;
- m_request.bCachedWrite = false;
- break;
- case DAV_SUBSCRIBE:
- header = "SUBSCRIBE ";
- m_request.bCachedWrite = false;
- break;
- case DAV_UNSUBSCRIBE:
- header = "UNSUBSCRIBE ";
- m_request.bCachedWrite = false;
- break;
- case DAV_POLL:
- header = "POLL ";
- m_request.bCachedWrite = false;
- break;
- default:
- error (ERR_UNSUPPORTED_ACTION, TQString::null);
- return false;
- }
- // DAV_POLL; DAV_NOTIFY
-
- // format the URI
- if (m_state.doProxy && !m_bIsTunneled)
- {
- KURL u;
-
- if (m_protocol == "webdav")
- u.setProtocol( "http" );
- else if (m_protocol == "webdavs" )
- u.setProtocol( "https" );
- else
- u.setProtocol( m_protocol );
-
- // For all protocols other than the once handled by this io-slave
- // append the username. This fixes a long standing bug of ftp io-slave
- // logging in anonymously in proxied connections even when the username
- // is explicitly specified.
- if (m_protocol != "http" && m_protocol != "https" &&
- !m_state.user.isEmpty())
- u.setUser (m_state.user);
-
- u.setHost( m_state.hostname );
- if (m_state.port != m_iDefaultPort)
- u.setPort( m_state.port );
- u.setEncodedPathAndQuery( m_request.url.encodedPathAndQuery(0,true) );
- header += u.url();
- }
- else
- {
- header += m_request.url.encodedPathAndQuery(0, true);
- }
-
- header += " HTTP/1.1\r\n"; /* start header */
-
- if (!m_request.userAgent.isEmpty())
- {
- header += "User-Agent: ";
- header += m_request.userAgent;
- header += "\r\n";
- }
-
- if (!m_request.referrer.isEmpty())
- {
- header += "Referer: "; //Don't try to correct spelling!
- header += m_request.referrer;
- header += "\r\n";
- }
-
- if ( m_request.offset > 0 )
- {
- header += TQString("Range: bytes=%1-\r\n").arg(KIO::number(m_request.offset));
- kdDebug(7103) << "kio_http : Range = " << KIO::number(m_request.offset) << endl;
- }
-
- if ( m_request.cache == CC_Reload )
- {
- /* No caching for reload */
- header += "Pragma: no-cache\r\n"; /* for HTTP/1.0 caches */
- header += "Cache-control: no-cache\r\n"; /* for HTTP >=1.1 caches */
- }
-
- if (m_request.bMustRevalidate)
- {
- /* conditional get */
- if (!m_request.etag.isEmpty())
- header += "If-None-Match: "+m_request.etag+"\r\n";
- if (!m_request.lastModified.isEmpty())
- header += "If-Modified-Since: "+m_request.lastModified+"\r\n";
- }
-
- header += "Accept: ";
- TQString acceptHeader = metaData("accept");
- if (!acceptHeader.isEmpty())
- header += acceptHeader;
- else
- header += DEFAULT_ACCEPT_HEADER;
- header += "\r\n";
-
-#ifdef DO_GZIP
- if (m_request.allowCompressedPage)
- header += "Accept-Encoding: x-gzip, x-deflate, gzip, deflate\r\n";
-#endif
-
- if (!m_request.charsets.isEmpty())
- header += "Accept-Charset: " + m_request.charsets + "\r\n";
-
- if (!m_request.languages.isEmpty())
- header += "Accept-Language: " + m_request.languages + "\r\n";
-
-
- /* support for virtual hosts and required by HTTP 1.1 */
- header += "Host: " + m_state.encoded_hostname;
-
- if (m_state.port != m_iDefaultPort)
- header += TQString(":%1").arg(m_state.port);
- header += "\r\n";
-
- TQString cookieStr;
- TQString cookieMode = metaData("cookies").lower();
- if (cookieMode == "none")
- {
- m_request.cookieMode = HTTPRequest::CookiesNone;
- }
- else if (cookieMode == "manual")
- {
- m_request.cookieMode = HTTPRequest::CookiesManual;
- cookieStr = metaData("setcookies");
- }
- else
- {
- m_request.cookieMode = HTTPRequest::CookiesAuto;
- if (m_request.bUseCookiejar)
- cookieStr = findCookies( m_request.url.url());
- }
-
- if (!cookieStr.isEmpty())
- header += cookieStr + "\r\n";
-
- TQString customHeader = metaData( "customHTTPHeader" );
- if (!customHeader.isEmpty())
- {
- header += sanitizeCustomHTTPHeader(customHeader);
- header += "\r\n";
- }
-
- if (m_request.method == HTTP_POST)
- {
- header += metaData("content-type");
- header += "\r\n";
- }
-
- // Only check for a cached copy if the previous
- // response was NOT a 401 or 407.
- // no caching for Negotiate auth.
- if ( !m_request.bNoAuth && m_responseCode != 401 && m_responseCode != 407 && Authentication != AUTH_Negotiate )
- {
- kdDebug(7113) << "(" << m_pid << ") Calling checkCachedAuthentication " << endl;
- AuthInfo info;
- info.url = m_request.url;
- info.verifyPath = true;
- if ( !m_request.user.isEmpty() )
- info.username = m_request.user;
- if ( checkCachedAuthentication( info ) && !info.digestInfo.isEmpty() )
- {
- Authentication = info.digestInfo.startsWith("Basic") ? AUTH_Basic : info.digestInfo.startsWith("NTLM") ? AUTH_NTLM : info.digestInfo.startsWith("Negotiate") ? AUTH_Negotiate : AUTH_Digest ;
- m_state.user = info.username;
- m_state.passwd = info.password;
- m_strRealm = info.realmValue;
- if ( Authentication != AUTH_NTLM && Authentication != AUTH_Negotiate ) // don't use the cached challenge
- m_strAuthorization = info.digestInfo;
- }
- }
- else
- {
- kdDebug(7113) << "(" << m_pid << ") Not calling checkCachedAuthentication " << endl;
- }
-
- switch ( Authentication )
- {
- case AUTH_Basic:
- header += createBasicAuth();
- break;
- case AUTH_Digest:
- header += createDigestAuth();
- break;
-#ifdef HAVE_LIBGSSAPI
- case AUTH_Negotiate:
- header += createNegotiateAuth();
- break;
-#endif
- case AUTH_NTLM:
- header += createNTLMAuth();
- break;
- case AUTH_None:
- default:
- break;
- }
-
- /********* Only for debugging purpose *********/
- if ( Authentication != AUTH_None )
- {
- kdDebug(7113) << "(" << m_pid << ") Using Authentication: " << endl;
- kdDebug(7113) << "(" << m_pid << ") HOST= " << m_state.hostname << endl;
- kdDebug(7113) << "(" << m_pid << ") PORT= " << m_state.port << endl;
- kdDebug(7113) << "(" << m_pid << ") USER= " << m_state.user << endl;
- kdDebug(7113) << "(" << m_pid << ") PASSWORD= [protected]" << endl;
- kdDebug(7113) << "(" << m_pid << ") REALM= " << m_strRealm << endl;
- kdDebug(7113) << "(" << m_pid << ") EXTRA= " << m_strAuthorization << endl;
- }
-
- // Do we need to authorize to the proxy server ?
- if ( m_state.doProxy && !m_bIsTunneled )
- header += proxyAuthenticationHeader();
-
- // Support old HTTP/1.0 style keep-alive header for compatability
- // purposes as well as performance improvements while giving end
- // users the ability to disable this feature proxy servers that
- // don't not support such feature, e.g. junkbuster proxy server.
- if (!m_bUseProxy || m_bPersistentProxyConnection || m_bIsTunneled)
- header += "Connection: Keep-Alive\r\n";
- else
- header += "Connection: close\r\n";
-
- if ( m_protocol == "webdav" || m_protocol == "webdavs" )
- {
- header += davProcessLocks();
-
- // add extra webdav headers, if supplied
- TQString davExtraHeader = metaData("davHeader");
- if ( !davExtraHeader.isEmpty() )
- davHeader += davExtraHeader;
-
- // Set content type of webdav data
- if (davData)
- davHeader += "Content-Type: text/xml; charset=utf-8\r\n";
-
- // add extra header elements for WebDAV
- if ( !davHeader.isNull() )
- header += davHeader;
- }
- }
-
- kdDebug(7103) << "(" << m_pid << ") ============ Sending Header:" << endl;
-
- TQStringList headerOutput = TQStringList::split("\r\n", header);
- TQStringList::Iterator it = headerOutput.begin();
-
- for (; it != headerOutput.end(); it++)
- kdDebug(7103) << "(" << m_pid << ") " << (*it) << endl;
-
- if ( !moreData && !davData)
- header += "\r\n"; /* end header */
-
- // Now that we have our formatted header, let's send it!
- // Create a new connection to the remote machine if we do
- // not already have one...
- if ( m_iSock == -1)
- {
- if (!httpOpenConnection())
- return false;
- }
-
- // Send the data to the remote machine...
- bool sendOk = (write(header.latin1(), header.length()) == (ssize_t) header.length());
- if (!sendOk)
- {
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen: "
- "Connection broken! (" << m_state.hostname << ")" << endl;
-
- // With a Keep-Alive connection this can happen.
- // Just reestablish the connection.
- if (m_bKeepAlive)
- {
- httpCloseConnection();
- return true; // Try again
- }
-
- if (!sendOk)
- {
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpOpen: sendOk==false."
- " Connnection broken !" << endl;
- error( ERR_CONNECTION_BROKEN, m_state.hostname );
- return false;
- }
- }
-
- bool res = true;
-
- if ( moreData || davData )
- res = sendBody();
-
- infoMessage(i18n("%1 contacted. Waiting for reply...").arg(m_request.hostname));
-
- return res;
-}
-
-void HTTPProtocol::forwardHttpResponseHeader()
-{
- // Send the response header if it was requested
- if ( config()->readBoolEntry("PropagateHttpHeader", false) )
- {
- setMetaData("HTTP-Headers", m_responseHeader.join("\n"));
- sendMetaData();
- }
- m_responseHeader.clear();
-}
-
-/**
- * This function will read in the return header from the server. It will
- * not read in the body of the return message. It will also not transmit
- * the header to our client as the client doesn't need to know the gory
- * details of HTTP headers.
- */
-bool HTTPProtocol::readHeader()
-{
-try_again:
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader" << endl;
-
- // Check
- if (m_request.bCachedRead)
- {
- m_responseHeader << "HTTP-CACHE";
- // Read header from cache...
- char buffer[4097];
- if (!fgets(buffer, 4096, m_request.fcache) )
- {
- // Error, delete cache entry
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: "
- << "Could not access cache to obtain mimetype!" << endl;
- error( ERR_CONNECTION_BROKEN, m_state.hostname );
- return false;
- }
-
- m_strMimeType = TQString(TQString::fromUtf8( buffer)).stripWhiteSpace();
-
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: cached "
- << "data mimetype: " << m_strMimeType << endl;
-
- if (!fgets(buffer, 4096, m_request.fcache) )
- {
- // Error, delete cache entry
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: "
- << "Could not access cached data! " << endl;
- error( ERR_CONNECTION_BROKEN, m_state.hostname );
- return false;
- }
-
- m_request.strCharset = TQString(TQString::fromUtf8( buffer)).stripWhiteSpace().lower();
- setMetaData("charset", m_request.strCharset);
- if (!m_request.lastModified.isEmpty())
- setMetaData("modified", m_request.lastModified);
- TQString tmp;
- tmp.setNum(m_request.expireDate);
- setMetaData("expire-date", tmp);
- tmp.setNum(m_request.creationDate);
- setMetaData("cache-creation-date", tmp);
- mimeType(m_strMimeType);
- forwardHttpResponseHeader();
- return true;
- }
-
- TQCString locationStr; // In case we get a redirect.
- TQCString cookieStr; // In case we get a cookie.
-
- TQString dispositionType; // In case we get a Content-Disposition type
- TQString dispositionFilename; // In case we get a Content-Disposition filename
-
- TQString mediaValue;
- TQString mediaAttribute;
-
- TQStringList upgradeOffers;
-
- bool upgradeRequired = false; // Server demands that we upgrade to something
- // This is also true if we ask to upgrade and
- // the server accepts, since we are now
- // committed to doing so
- bool canUpgrade = false; // The server offered an upgrade
-
-
- m_request.etag = TQString::null;
- m_request.lastModified = TQString::null;
- m_request.strCharset = TQString::null;
-
- time_t dateHeader = 0;
- time_t expireDate = 0; // 0 = no info, 1 = already expired, > 1 = actual date
- int currentAge = 0;
- int maxAge = -1; // -1 = no max age, 0 already expired, > 0 = actual time
- int maxHeaderSize = 64*1024; // 64Kb to catch DOS-attacks
-
- // read in 8192 bytes at a time (HTTP cookies can be quite large.)
- int len = 0;
- char buffer[8193];
- bool cont = false;
- bool cacheValidated = false; // Revalidation was successful
- bool mayCache = true;
- bool hasCacheDirective = false;
- bool bCanResume = false;
-
- if (m_iSock == -1)
- {
- kdDebug(7113) << "HTTPProtocol::readHeader: No connection." << endl;
- return false; // Restablish connection and try again
- }
-
- if (!waitForResponse(m_remoteRespTimeout))
- {
- // No response error
- error( ERR_SERVER_TIMEOUT , m_state.hostname );
- return false;
- }
-
- setRewindMarker();
-
- gets(buffer, sizeof(buffer)-1);
-
- if (m_bEOF || *buffer == '\0')
- {
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readHeader: "
- << "EOF while waiting for header start." << endl;
- if (m_bKeepAlive) // Try to reestablish connection.
- {
- httpCloseConnection();
- return false; // Reestablish connection and try again.
- }
-
- if (m_request.method == HTTP_HEAD)
- {
- // HACK
- // Some web-servers fail to respond properly to a HEAD request.
- // We compensate for their failure to properly implement the HTTP standard
- // by assuming that they will be sending html.
- kdDebug(7113) << "(" << m_pid << ") HTTPPreadHeader: HEAD -> returned "
- << "mimetype: " << DEFAULT_MIME_TYPE << endl;
- mimeType(TQString::fromLatin1(DEFAULT_MIME_TYPE));
- return true;
- }
-
- kdDebug(7113) << "HTTPProtocol::readHeader: Connection broken !" << endl;
- error( ERR_CONNECTION_BROKEN, m_state.hostname );
- return false;
- }
-
- kdDebug(7103) << "(" << m_pid << ") ============ Received Response:"<< endl;
-
- bool noHeader = true;
- HTTP_REV httpRev = HTTP_None;
- int headerSize = 0;
-
- do
- {
- // strip off \r and \n if we have them
- len = strlen(buffer);
-
- while(len && (buffer[len-1] == '\n' || buffer[len-1] == '\r'))
- buffer[--len] = 0;
-
- // if there was only a newline then continue
- if (!len)
- {
- kdDebug(7103) << "(" << m_pid << ") --empty--" << endl;
- continue;
- }
-
- headerSize += len;
-
- // We have a response header. This flag is a work around for
- // servers that append a "\r\n" before the beginning of the HEADER
- // response!!! It only catches x number of \r\n being placed at the
- // top of the reponse...
- noHeader = false;
-
- kdDebug(7103) << "(" << m_pid << ") \"" << buffer << "\"" << endl;
-
- // Save broken servers from damnation!!
- char* buf = buffer;
- while( *buf == ' ' )
- buf++;
-
-
- if (buf[0] == '<')
- {
- // We get XML / HTTP without a proper header
- // put string back
- kdDebug(7103) << "kio_http: No valid HTTP header found! Document starts with XML/HTML tag" << endl;
-
- // Document starts with a tag, assume html instead of text/plain
- m_strMimeType = "text/html";
-
- rewind();
- break;
- }
-
- // Store the the headers so they can be passed to the
- // calling application later
- m_responseHeader << TQString::fromLatin1(buf);
-
- if ((strncasecmp(buf, "HTTP/", 5) == 0) ||
- (strncasecmp(buf, "ICY ", 4) == 0)) // Shoutcast support
- {
- if (strncasecmp(buf, "ICY ", 4) == 0)
- {
- // Shoutcast support
- httpRev = SHOUTCAST;
- m_bKeepAlive = false;
- }
- else if (strncmp((buf + 5), "1.0",3) == 0)
- {
- httpRev = HTTP_10;
- // For 1.0 servers, the server itself has to explicitly
- // tell us whether it supports persistent connection or
- // not. By default, we assume it does not, but we do
- // send the old style header "Connection: Keep-Alive" to
- // inform it that we support persistence.
- m_bKeepAlive = false;
- }
- else if (strncmp((buf + 5), "1.1",3) == 0)
- {
- httpRev = HTTP_11;
- }
- else
- {
- httpRev = HTTP_Unknown;
- }
-
- if (m_responseCode)
- m_prevResponseCode = m_responseCode;
-
- const char* rptr = buf;
- while ( *rptr && *rptr > ' ' )
- ++rptr;
- m_responseCode = atoi(rptr);
-
- // server side errors
- if (m_responseCode >= 500 && m_responseCode <= 599)
- {
- if (m_request.method == HTTP_HEAD)
- {
- ; // Ignore error
- }
- else
- {
- if (m_request.bErrorPage)
- errorPage();
- else
- {
- error(ERR_INTERNAL_SERVER, m_request.url.url());
- return false;
- }
- }
- m_request.bCachedWrite = false; // Don't put in cache
- mayCache = false;
- }
- // Unauthorized access
- else if (m_responseCode == 401 || m_responseCode == 407)
- {
- // Double authorization requests, i.e. a proxy auth
- // request followed immediately by a regular auth request.
- if ( m_prevResponseCode != m_responseCode &&
- (m_prevResponseCode == 401 || m_prevResponseCode == 407) )
- saveAuthorization();
-
- m_bUnauthorized = true;
- m_request.bCachedWrite = false; // Don't put in cache
- mayCache = false;
- }
- //
- else if (m_responseCode == 416) // Range not supported
- {
- m_request.offset = 0;
- httpCloseConnection();
- return false; // Try again.
- }
- // Upgrade Required
- else if (m_responseCode == 426)
- {
- upgradeRequired = true;
- }
- // Any other client errors
- else if (m_responseCode >= 400 && m_responseCode <= 499)
- {
- // Tell that we will only get an error page here.
- if (m_request.bErrorPage)
- errorPage();
- else
- {
- error(ERR_DOES_NOT_EXIST, m_request.url.url());
- return false;
- }
- m_request.bCachedWrite = false; // Don't put in cache
- mayCache = false;
- }
- else if (m_responseCode == 307)
- {
- // 307 Temporary Redirect
- m_request.bCachedWrite = false; // Don't put in cache
- mayCache = false;
- }
- else if (m_responseCode == 304)
- {
- // 304 Not Modified
- // The value in our cache is still valid.
- cacheValidated = true;
- }
- else if (m_responseCode >= 301 && m_responseCode<= 303)
- {
- // 301 Moved permanently
- if (m_responseCode == 301)
- setMetaData("permanent-redirect", "true");
-
- // 302 Found (temporary location)
- // 303 See Other
- if (m_request.method != HTTP_HEAD && m_request.method != HTTP_GET)
- {
-#if 0
- // Reset the POST buffer to avoid a double submit
- // on redirection
- if (m_request.method == HTTP_POST)
- m_bufPOST.resize(0);
-#endif
-
- // NOTE: This is wrong according to RFC 2616. However,
- // because most other existing user agent implementations
- // treat a 301/302 response as a 303 response and preform
- // a GET action regardless of what the previous method was,
- // many servers have simply adapted to this way of doing
- // things!! Thus, we are forced to do the same thing or we
- // won't be able to retrieve these pages correctly!! See RFC
- // 2616 sections 10.3.[2/3/4/8]
- m_request.method = HTTP_GET; // Force a GET
- }
- m_request.bCachedWrite = false; // Don't put in cache
- mayCache = false;
- }
- else if ( m_responseCode == 207 ) // Multi-status (for WebDav)
- {
-
- }
- else if ( m_responseCode == 204 ) // No content
- {
- // error(ERR_NO_CONTENT, i18n("Data have been successfully sent."));
- // Short circuit and do nothing!
-
- // The original handling here was wrong, this is not an error: eg. in the
- // example of a 204 No Content response to a PUT completing.
- // m_bError = true;
- // return false;
- }
- else if ( m_responseCode == 206 )
- {
- if ( m_request.offset )
- bCanResume = true;
- }
- else if (m_responseCode == 102) // Processing (for WebDAV)
- {
- /***
- * This status code is given when the server expects the
- * command to take significant time to complete. So, inform
- * the user.
- */
- infoMessage( i18n( "Server processing request, please wait..." ) );
- cont = true;
- }
- else if (m_responseCode == 100)
- {
- // We got 'Continue' - ignore it
- cont = true;
- }
- }
-
- // are we allowd to resume? this will tell us
- else if (strncasecmp(buf, "Accept-Ranges:", 14) == 0) {
- if (strncasecmp(trimLead(buf + 14), "none", 4) == 0)
- bCanResume = false;
- }
- // Keep Alive
- else if (strncasecmp(buf, "Keep-Alive:", 11) == 0) {
- TQStringList options = TQStringList::split(',',
- TQString::fromLatin1(trimLead(buf+11)));
- for(TQStringList::ConstIterator it = options.begin();
- it != options.end();
- it++)
- {
- TQString option = (*it).stripWhiteSpace().lower();
- if (option.startsWith("timeout="))
- {
- m_keepAliveTimeout = option.mid(8).toInt();
- }
- }
- }
-
- // Cache control
- else if (strncasecmp(buf, "Cache-Control:", 14) == 0) {
- TQStringList cacheControls = TQStringList::split(',',
- TQString::fromLatin1(trimLead(buf+14)));
- for(TQStringList::ConstIterator it = cacheControls.begin();
- it != cacheControls.end();
- it++)
- {
- TQString cacheControl = (*it).stripWhiteSpace();
- if (strncasecmp(cacheControl.latin1(), "no-cache", 8) == 0)
- {
- m_request.bCachedWrite = false; // Don't put in cache
- mayCache = false;
- }
- else if (strncasecmp(cacheControl.latin1(), "no-store", 8) == 0)
- {
- m_request.bCachedWrite = false; // Don't put in cache
- mayCache = false;
- }
- else if (strncasecmp(cacheControl.latin1(), "max-age=", 8) == 0)
- {
- TQString age = cacheControl.mid(8).stripWhiteSpace();
- if (!age.isNull())
- maxAge = STRTOLL(age.latin1(), 0, 10);
- }
- }
- hasCacheDirective = true;
- }
-
- // get the size of our data
- else if (strncasecmp(buf, "Content-length:", 15) == 0) {
- char* len = trimLead(buf + 15);
- if (len)
- m_iSize = STRTOLL(len, 0, 10);
- }
-
- else if (strncasecmp(buf, "Content-location:", 17) == 0) {
- setMetaData ("content-location",
- TQString::fromLatin1(trimLead(buf+17)).stripWhiteSpace());
- }
-
- // what type of data do we have?
- else if (strncasecmp(buf, "Content-type:", 13) == 0) {
- char *start = trimLead(buf + 13);
- char *pos = start;
-
- // Increment until we encounter ";" or the end of the buffer
- while ( *pos && *pos != ';' ) pos++;
-
- // Assign the mime-type.
- m_strMimeType = TQString::fromLatin1(start, pos-start).stripWhiteSpace().lower();
- kdDebug(7113) << "(" << m_pid << ") Content-type: " << m_strMimeType << endl;
-
- // If we still have text, then it means we have a mime-type with a
- // parameter (eg: charset=iso-8851) ; so let's get that...
- while (*pos)
- {
- start = ++pos;
- while ( *pos && *pos != '=' ) pos++;
-
- char *end = pos;
- while ( *end && *end != ';' ) end++;
-
- if (*pos)
- {
- mediaAttribute = TQString::fromLatin1(start, pos-start).stripWhiteSpace().lower();
- mediaValue = TQString::fromLatin1(pos+1, end-pos-1).stripWhiteSpace();
- pos = end;
- if (mediaValue.length() &&
- (mediaValue[0] == '"') &&
- (mediaValue[mediaValue.length()-1] == '"'))
- mediaValue = mediaValue.mid(1, mediaValue.length()-2);
-
- kdDebug (7113) << "(" << m_pid << ") Media-Parameter Attribute: "
- << mediaAttribute << endl;
- kdDebug (7113) << "(" << m_pid << ") Media-Parameter Value: "
- << mediaValue << endl;
-
- if ( mediaAttribute == "charset")
- {
- mediaValue = mediaValue.lower();
- m_request.strCharset = mediaValue;
- }
- else
- {
- setMetaData("media-"+mediaAttribute, mediaValue);
- }
- }
- }
- }
-
- // Date
- else if (strncasecmp(buf, "Date:", 5) == 0) {
- dateHeader = KRFCDate::parseDate(trimLead(buf+5));
- }
-
- // Cache management
- else if (strncasecmp(buf, "ETag:", 5) == 0) {
- m_request.etag = trimLead(buf+5);
- }
-
- // Cache management
- else if (strncasecmp(buf, "Expires:", 8) == 0) {
- expireDate = KRFCDate::parseDate(trimLead(buf+8));
- if (!expireDate)
- expireDate = 1; // Already expired
- }
-
- // Cache management
- else if (strncasecmp(buf, "Last-Modified:", 14) == 0) {
- m_request.lastModified = (TQString::fromLatin1(trimLead(buf+14))).stripWhiteSpace();
- }
-
- // whoops.. we received a warning
- else if (strncasecmp(buf, "Warning:", 8) == 0) {
- //Don't use warning() here, no need to bother the user.
- //Those warnings are mostly about caches.
- infoMessage(trimLead(buf + 8));
- }
-
- // Cache management (HTTP 1.0)
- else if (strncasecmp(buf, "Pragma:", 7) == 0) {
- TQCString pragma = TQCString(trimLead(buf+7)).stripWhiteSpace().lower();
- if (pragma == "no-cache")
- {
- m_request.bCachedWrite = false; // Don't put in cache
- mayCache = false;
- hasCacheDirective = true;
- }
- }
-
- // The deprecated Refresh Response
- else if (strncasecmp(buf,"Refresh:", 8) == 0) {
- mayCache = false; // Do not cache page as it defeats purpose of Refresh tag!
- setMetaData( "http-refresh", TQString::fromLatin1(trimLead(buf+8)).stripWhiteSpace() );
- }
-
- // In fact we should do redirection only if we got redirection code
- else if (strncasecmp(buf, "Location:", 9) == 0) {
- // Redirect only for 3xx status code, will ya! Thanks, pal!
- if ( m_responseCode > 299 && m_responseCode < 400 )
- locationStr = TQCString(trimLead(buf+9)).stripWhiteSpace();
- }
-
- // Check for cookies
- else if (strncasecmp(buf, "Set-Cookie", 10) == 0) {
- cookieStr += buf;
- cookieStr += '\n';
- }
-
- // check for direct authentication
- else if (strncasecmp(buf, "WWW-Authenticate:", 17) == 0) {
- configAuth(trimLead(buf + 17), false);
- }
-
- // check for proxy-based authentication
- else if (strncasecmp(buf, "Proxy-Authenticate:", 19) == 0) {
- configAuth(trimLead(buf + 19), true);
- }
-
- else if (strncasecmp(buf, "Upgrade:", 8) == 0) {
- // Now we have to check to see what is offered for the upgrade
- TQString offered = &(buf[8]);
- upgradeOffers = TQStringList::split(TQRegExp("[ \n,\r\t]"), offered);
- }
-
- // content?
- else if (strncasecmp(buf, "Content-Encoding:", 17) == 0) {
- // This is so wrong !! No wonder kio_http is stripping the
- // gzip encoding from downloaded files. This solves multiple
- // bug reports and caitoo's problem with downloads when such a
- // header is encountered...
-
- // A quote from RFC 2616:
- // " When present, its (Content-Encoding) value indicates what additional
- // content have been applied to the entity body, and thus what decoding
- // mechanism must be applied to obtain the media-type referenced by the
- // Content-Type header field. Content-Encoding is primarily used to allow
- // a document to be compressed without loosing the identity of its underlying
- // media type. Simply put if it is specified, this is the actual mime-type
- // we should use when we pull the resource !!!
- addEncoding(trimLead(buf + 17), m_qContentEncodings);
- }
- // Refer to RFC 2616 sec 15.5/19.5.1 and RFC 2183
- else if(strncasecmp(buf, "Content-Disposition:", 20) == 0) {
- char* dispositionBuf = trimLead(buf + 20);
- while ( *dispositionBuf )
- {
- if ( strncasecmp( dispositionBuf, "filename", 8 ) == 0 )
- {
- dispositionBuf += 8;
-
- while ( *dispositionBuf == ' ' || *dispositionBuf == '=' )
- dispositionBuf++;
-
- char* bufStart = dispositionBuf;
-
- while ( *dispositionBuf && *dispositionBuf != ';' )
- dispositionBuf++;
-
- if ( dispositionBuf > bufStart )
- {
- // Skip any leading quotes...
- while ( *bufStart == '"' )
- bufStart++;
-
- // Skip any trailing quotes as well as white spaces...
- while ( *(dispositionBuf-1) == ' ' || *(dispositionBuf-1) == '"')
- dispositionBuf--;
-
- if ( dispositionBuf > bufStart )
- dispositionFilename = TQString::fromLatin1( bufStart, dispositionBuf-bufStart );
-
- break;
- }
- }
- else
- {
- char *bufStart = dispositionBuf;
-
- while ( *dispositionBuf && *dispositionBuf != ';' )
- dispositionBuf++;
-
- if ( dispositionBuf > bufStart )
- dispositionType = TQString::fromLatin1( bufStart, dispositionBuf-bufStart ).stripWhiteSpace();
-
- while ( *dispositionBuf == ';' || *dispositionBuf == ' ' )
- dispositionBuf++;
- }
- }
-
- // Content-Dispostion is not allowed to dictate directory
- // path, thus we extract the filename only.
- if ( !dispositionFilename.isEmpty() )
- {
- int pos = dispositionFilename.findRev( '/' );
-
- if( pos > -1 )
- dispositionFilename = dispositionFilename.mid(pos+1);
-
- kdDebug(7113) << "(" << m_pid << ") Content-Disposition: filename="
- << dispositionFilename<< endl;
- }
- }
- else if(strncasecmp(buf, "Content-Language:", 17) == 0) {
- TQString language = TQString::fromLatin1(trimLead(buf+17)).stripWhiteSpace();
- if (!language.isEmpty())
- setMetaData("content-language", language);
- }
- else if (strncasecmp(buf, "Proxy-Connection:", 17) == 0)
- {
- if (strncasecmp(trimLead(buf + 17), "Close", 5) == 0)
- m_bKeepAlive = false;
- else if (strncasecmp(trimLead(buf + 17), "Keep-Alive", 10)==0)
- m_bKeepAlive = true;
- }
- else if (strncasecmp(buf, "Link:", 5) == 0) {
- // We only support Link: <url>; rel="type" so far
- TQStringList link = TQStringList::split(";", TQString(buf)
- .replace(TQRegExp("^Link:[ ]*"),
- ""));
- if (link.count() == 2) {
- TQString rel = link[1].stripWhiteSpace();
- if (rel.startsWith("rel=\"")) {
- rel = rel.mid(5, rel.length() - 6);
- if (rel.lower() == "pageservices") {
- TQString url = TQString(link[0].replace(TQRegExp("[<>]"),"")).stripWhiteSpace();
- setMetaData("PageServices", url);
- }
- }
- }
- }
- else if (strncasecmp(buf, "P3P:", 4) == 0) {
- TQString p3pstr = buf;
- p3pstr = p3pstr.mid(4).simplifyWhiteSpace();
- TQStringList policyrefs, compact;
- TQStringList policyfields = TQStringList::split(TQRegExp(",[ ]*"), p3pstr);
- for (TQStringList::Iterator it = policyfields.begin();
- it != policyfields.end();
- ++it) {
- TQStringList policy = TQStringList::split("=", *it);
-
- if (policy.count() == 2) {
- if (policy[0].lower() == "policyref") {
- policyrefs << TQString(policy[1].replace(TQRegExp("[\"\']"), ""))
- .stripWhiteSpace();
- } else if (policy[0].lower() == "cp") {
- // We convert to cp\ncp\ncp\n[...]\ncp to be consistent with
- // other metadata sent in strings. This could be a bit more
- // efficient but I'm going for correctness right now.
- TQStringList cps = TQStringList::split(" ",
- TQString(policy[1].replace(TQRegExp("[\"\']"), ""))
- .simplifyWhiteSpace());
-
- for (TQStringList::Iterator j = cps.begin(); j != cps.end(); ++j)
- compact << *j;
- }
- }
- }
-
- if (!policyrefs.isEmpty())
- setMetaData("PrivacyPolicy", policyrefs.join("\n"));
-
- if (!compact.isEmpty())
- setMetaData("PrivacyCompactPolicy", compact.join("\n"));
- }
- // let them tell us if we should stay alive or not
- else if (strncasecmp(buf, "Connection:", 11) == 0)
- {
- if (strncasecmp(trimLead(buf + 11), "Close", 5) == 0)
- m_bKeepAlive = false;
- else if (strncasecmp(trimLead(buf + 11), "Keep-Alive", 10)==0)
- m_bKeepAlive = true;
- else if (strncasecmp(trimLead(buf + 11), "Upgrade", 7)==0)
- {
- if (m_responseCode == 101) {
- // Ok, an upgrade was accepted, now we must do it
- upgradeRequired = true;
- } else if (upgradeRequired) { // 426
- // Nothing to do since we did it above already
- } else {
- // Just an offer to upgrade - no need to take it
- canUpgrade = true;
- }
- }
- }
- // continue only if we know that we're HTTP/1.1
- else if ( httpRev == HTTP_11) {
- // what kind of encoding do we have? transfer?
- if (strncasecmp(buf, "Transfer-Encoding:", 18) == 0) {
- // If multiple encodings have been applied to an entity, the
- // transfer-codings MUST be listed in the order in which they
- // were applied.
- addEncoding(trimLead(buf + 18), m_qTransferEncodings);
- }
-
- // md5 signature
- else if (strncasecmp(buf, "Content-MD5:", 12) == 0) {
- m_sContentMD5 = TQString::fromLatin1(trimLead(buf + 12));
- }
-
- // *** Responses to the HTTP OPTIONS method follow
- // WebDAV capabilities
- else if (strncasecmp(buf, "DAV:", 4) == 0) {
- if (m_davCapabilities.isEmpty()) {
- m_davCapabilities << TQString::fromLatin1(trimLead(buf + 4));
- }
- else {
- m_davCapabilities << TQString::fromLatin1(trimLead(buf + 4));
- }
- }
- // *** Responses to the HTTP OPTIONS method finished
- }
- else if ((httpRev == HTTP_None) && (strlen(buf) != 0))
- {
- // Remote server does not seem to speak HTTP at all
- // Put the crap back into the buffer and hope for the best
- rewind();
- if (m_responseCode)
- m_prevResponseCode = m_responseCode;
-
- m_responseCode = 200; // Fake it
- httpRev = HTTP_Unknown;
- m_bKeepAlive = false;
- break;
- }
- setRewindMarker();
-
- // Clear out our buffer for further use.
- memset(buffer, 0, sizeof(buffer));
-
- } while (!m_bEOF && (len || noHeader) && (headerSize < maxHeaderSize) && (gets(buffer, sizeof(buffer)-1)));
-
- // Now process the HTTP/1.1 upgrade
- TQStringList::Iterator opt = upgradeOffers.begin();
- for( ; opt != upgradeOffers.end(); ++opt) {
- if (*opt == "TLS/1.0") {
- if(upgradeRequired) {
- if (!startTLS() && !usingTLS()) {
- error(ERR_UPGRADE_REQUIRED, *opt);
- return false;
- }
- }
- } else if (*opt == "HTTP/1.1") {
- httpRev = HTTP_11;
- } else {
- // unknown
- if (upgradeRequired) {
- error(ERR_UPGRADE_REQUIRED, *opt);
- return false;
- }
- }
- }
-
- setMetaData("charset", m_request.strCharset);
-
- // If we do not support the requested authentication method...
- if ( (m_responseCode == 401 && Authentication == AUTH_None) ||
- (m_responseCode == 407 && ProxyAuthentication == AUTH_None) )
- {
- m_bUnauthorized = false;
- if (m_request.bErrorPage)
- errorPage();
- else
- {
- error( ERR_UNSUPPORTED_ACTION, "Unknown Authorization method!" );
- return false;
- }
- }
-
- // Fixup expire date for clock drift.
- if (expireDate && (expireDate <= dateHeader))
- expireDate = 1; // Already expired.
-
- // Convert max-age into expireDate (overriding previous set expireDate)
- if (maxAge == 0)
- expireDate = 1; // Already expired.
- else if (maxAge > 0)
- {
- if (currentAge)
- maxAge -= currentAge;
- if (maxAge <=0)
- maxAge = 0;
- expireDate = time(0) + maxAge;
- }
-
- if (!expireDate)
- {
- time_t lastModifiedDate = 0;
- if (!m_request.lastModified.isEmpty())
- lastModifiedDate = KRFCDate::parseDate(m_request.lastModified);
-
- if (lastModifiedDate)
- {
- long diff = static_cast<long>(difftime(dateHeader, lastModifiedDate));
- if (diff < 0)
- expireDate = time(0) + 1;
- else
- expireDate = time(0) + (diff / 10);
- }
- else
- {
- expireDate = time(0) + DEFAULT_CACHE_EXPIRE;
- }
- }
-
- // DONE receiving the header!
- if (!cookieStr.isEmpty())
- {
- if ((m_request.cookieMode == HTTPRequest::CookiesAuto) && m_request.bUseCookiejar)
- {
- // Give cookies to the cookiejar.
- TQString domain = config()->readEntry("cross-domain");
- if (!domain.isEmpty() && isCrossDomainRequest(m_request.url.host(), domain))
- cookieStr = "Cross-Domain\n" + cookieStr;
- addCookies( m_request.url.url(), cookieStr );
- }
- else if (m_request.cookieMode == HTTPRequest::CookiesManual)
- {
- // Pass cookie to application
- setMetaData("setcookies", cookieStr);
- }
- }
-
- if (m_request.bMustRevalidate)
- {
- m_request.bMustRevalidate = false; // Reset just in case.
- if (cacheValidated)
- {
- // Yippie, we can use the cached version.
- // Update the cache with new "Expire" headers.
- fclose(m_request.fcache);
- m_request.fcache = 0;
- updateExpireDate( expireDate, true );
- m_request.fcache = checkCacheEntry( ); // Re-read cache entry
-
- if (m_request.fcache)
- {
- m_request.bCachedRead = true;
- goto try_again; // Read header again, but now from cache.
- }
- else
- {
- // Where did our cache entry go???
- }
- }
- else
- {
- // Validation failed. Close cache.
- fclose(m_request.fcache);
- m_request.fcache = 0;
- }
- }
-
- // We need to reread the header if we got a '100 Continue' or '102 Processing'
- if ( cont )
- {
- goto try_again;
- }
-
- // Do not do a keep-alive connection if the size of the
- // response is not known and the response is not Chunked.
- if (!m_bChunked && (m_iSize == NO_SIZE))
- m_bKeepAlive = false;
-
- if ( m_responseCode == 204 )
- {
- return true;
- }
-
- // We need to try to login again if we failed earlier
- if ( m_bUnauthorized )
- {
- if ( (m_responseCode == 401) ||
- (m_bUseProxy && (m_responseCode == 407))
- )
- {
- if ( getAuthorization() )
- {
- // for NTLM Authentication we have to keep the connection open!
- if ( Authentication == AUTH_NTLM && m_strAuthorization.length() > 4 )
- {
- m_bKeepAlive = true;
- readBody( true );
- }
- else if (ProxyAuthentication == AUTH_NTLM && m_strProxyAuthorization.length() > 4)
- {
- readBody( true );
- }
- else
- httpCloseConnection();
- return false; // Try again.
- }
-
- if (m_bError)
- return false; // Error out
-
- // Show error page...
- }
- m_bUnauthorized = false;
- }
-
- // We need to do a redirect
- if (!locationStr.isEmpty())
- {
- KURL u(m_request.url, locationStr);
- if(!u.isValid())
- {
- error(ERR_MALFORMED_URL, u.url());
- return false;
- }
- if ((u.protocol() != "http") && (u.protocol() != "https") &&
- (u.protocol() != "ftp") && (u.protocol() != "webdav") &&
- (u.protocol() != "webdavs"))
- {
- redirection(u);
- error(ERR_ACCESS_DENIED, u.url());
- return false;
- }
-
- // preserve #ref: (bug 124654)
- // if we were at http://host/resource1#ref, we sent a GET for "/resource1"
- // if we got redirected to http://host/resource2, then we have to re-add
- // the fragment:
- if (m_request.url.hasRef() && !u.hasRef() &&
- (m_request.url.host() == u.host()) &&
- (m_request.url.protocol() == u.protocol()))
- u.setRef(m_request.url.ref());
-
- m_bRedirect = true;
- m_redirectLocation = u;
-
- if (!m_request.id.isEmpty())
- {
- sendMetaData();
- }
-
- kdDebug(7113) << "(" << m_pid << ") request.url: " << m_request.url.url()
- << endl << "LocationStr: " << locationStr.data() << endl;
-
- kdDebug(7113) << "(" << m_pid << ") Requesting redirection to: " << u.url()
- << endl;
-
- // If we're redirected to a http:// url, remember that we're doing webdav...
- if (m_protocol == "webdav" || m_protocol == "webdavs")
- u.setProtocol(m_protocol);
-
- redirection(u);
- m_request.bCachedWrite = false; // Turn off caching on re-direction (DA)
- mayCache = false;
- }
-
- // Inform the job that we can indeed resume...
- if ( bCanResume && m_request.offset )
- canResume();
- else
- m_request.offset = 0;
-
- // We don't cache certain text objects
- if (m_strMimeType.startsWith("text/") &&
- (m_strMimeType != "text/css") &&
- (m_strMimeType != "text/x-javascript") &&
- !hasCacheDirective)
- {
- // Do not cache secure pages or pages
- // originating from password protected sites
- // unless the webserver explicitly allows it.
- if ( m_bIsSSL || (Authentication != AUTH_None) )
- {
- m_request.bCachedWrite = false;
- mayCache = false;
- }
- }
-
- // WABA: Correct for tgz files with a gzip-encoding.
- // They really shouldn't put gzip in the Content-Encoding field!
- // Web-servers really shouldn't do this: They let Content-Size refer
- // to the size of the tgz file, not to the size of the tar file,
- // while the Content-Type refers to "tar" instead of "tgz".
- if (m_qContentEncodings.last() == "gzip")
- {
- if (m_strMimeType == "application/x-tar")
- {
- m_qContentEncodings.remove(m_qContentEncodings.fromLast());
- m_strMimeType = TQString::fromLatin1("application/x-tgz");
- }
- else if (m_strMimeType == "application/postscript")
- {
- // LEONB: Adding another exception for psgz files.
- // Could we use the mimelnk files instead of hardcoding all this?
- m_qContentEncodings.remove(m_qContentEncodings.fromLast());
- m_strMimeType = TQString::fromLatin1("application/x-gzpostscript");
- }
- else if ( m_request.allowCompressedPage &&
- m_strMimeType != "application/x-tgz" &&
- m_strMimeType != "application/x-targz" &&
- m_strMimeType != "application/x-gzip" &&
- m_request.url.path().right(6) == ".ps.gz" )
- {
- m_qContentEncodings.remove(m_qContentEncodings.fromLast());
- m_strMimeType = TQString::fromLatin1("application/x-gzpostscript");
- }
- else if ( (m_request.allowCompressedPage &&
- m_strMimeType == "text/html")
- ||
- (m_request.allowCompressedPage &&
- m_strMimeType != "application/x-tgz" &&
- m_strMimeType != "application/x-targz" &&
- m_strMimeType != "application/x-gzip" &&
- m_request.url.path().right(3) != ".gz")
- )
- {
- // Unzip!
- }
- else
- {
- m_qContentEncodings.remove(m_qContentEncodings.fromLast());
- m_strMimeType = TQString::fromLatin1("application/x-gzip");
- }
- }
-
- // We can't handle "bzip2" encoding (yet). So if we get something with
- // bzip2 encoding, we change the mimetype to "application/x-bzip2".
- // Note for future changes: some web-servers send both "bzip2" as
- // encoding and "application/x-bzip2" as mimetype. That is wrong.
- // currently that doesn't bother us, because we remove the encoding
- // and set the mimetype to x-bzip2 anyway.
- if (m_qContentEncodings.last() == "bzip2")
- {
- m_qContentEncodings.remove(m_qContentEncodings.fromLast());
- m_strMimeType = TQString::fromLatin1("application/x-bzip2");
- }
-
- // Convert some common mimetypes to standard KDE mimetypes
- if (m_strMimeType == "application/x-targz")
- m_strMimeType = TQString::fromLatin1("application/x-tgz");
- else if (m_strMimeType == "application/zip")
- m_strMimeType = TQString::fromLatin1("application/x-zip");
- else if (m_strMimeType == "image/x-png")
- m_strMimeType = TQString::fromLatin1("image/png");
- else if (m_strMimeType == "image/bmp")
- m_strMimeType = TQString::fromLatin1("image/x-bmp");
- else if (m_strMimeType == "audio/mpeg" || m_strMimeType == "audio/x-mpeg" || m_strMimeType == "audio/mp3")
- m_strMimeType = TQString::fromLatin1("audio/x-mp3");
- else if (m_strMimeType == "audio/microsoft-wave")
- m_strMimeType = TQString::fromLatin1("audio/x-wav");
- else if (m_strMimeType == "audio/midi")
- m_strMimeType = TQString::fromLatin1("audio/x-midi");
- else if (m_strMimeType == "image/x-xpixmap")
- m_strMimeType = TQString::fromLatin1("image/x-xpm");
- else if (m_strMimeType == "application/rtf")
- m_strMimeType = TQString::fromLatin1("text/rtf");
-
- // Crypto ones....
- else if (m_strMimeType == "application/pkix-cert" ||
- m_strMimeType == "application/binary-certificate")
- {
- m_strMimeType = TQString::fromLatin1("application/x-x509-ca-cert");
- }
-
- // Prefer application/x-tgz or x-gzpostscript over application/x-gzip.
- else if (m_strMimeType == "application/x-gzip")
- {
- if ((m_request.url.path().right(7) == ".tar.gz") ||
- (m_request.url.path().right(4) == ".tar"))
- m_strMimeType = TQString::fromLatin1("application/x-tgz");
- if ((m_request.url.path().right(6) == ".ps.gz"))
- m_strMimeType = TQString::fromLatin1("application/x-gzpostscript");
- }
-
- // Some webservers say "text/plain" when they mean "application/x-bzip2"
- else if ((m_strMimeType == "text/plain") || (m_strMimeType == "application/octet-stream"))
- {
- TQString ext = m_request.url.path().right(4).upper();
- if (ext == ".BZ2")
- m_strMimeType = TQString::fromLatin1("application/x-bzip2");
- else if (ext == ".PEM")
- m_strMimeType = TQString::fromLatin1("application/x-x509-ca-cert");
- else if (ext == ".SWF")
- m_strMimeType = TQString::fromLatin1("application/x-shockwave-flash");
- else if (ext == ".PLS")
- m_strMimeType = TQString::fromLatin1("audio/x-scpls");
- else if (ext == ".WMV")
- m_strMimeType = TQString::fromLatin1("video/x-ms-wmv");
- }
-
-#if 0
- // Even if we can't rely on content-length, it seems that we should
- // never get more data than content-length. Maybe less, if the
- // content-length refers to the unzipped data.
- if (!m_qContentEncodings.isEmpty())
- {
- // If we still have content encoding we can't rely on the Content-Length.
- m_iSize = NO_SIZE;
- }
-#endif
-
- if( !dispositionType.isEmpty() )
- {
- kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition type to: "
- << dispositionType << endl;
- setMetaData("content-disposition-type", dispositionType);
- }
- if( !dispositionFilename.isEmpty() )
- {
- kdDebug(7113) << "(" << m_pid << ") Setting Content-Disposition filename to: "
- << dispositionFilename << endl;
- // ### KDE4: setting content-disposition to filename for pre 3.5.2 compatability
- setMetaData("content-disposition", dispositionFilename);
- setMetaData("content-disposition-filename", dispositionFilename);
- }
-
- if (!m_request.lastModified.isEmpty())
- setMetaData("modified", m_request.lastModified);
-
- if (!mayCache)
- {
- setMetaData("no-cache", "true");
- setMetaData("expire-date", "1"); // Expired
- }
- else
- {
- TQString tmp;
- tmp.setNum(expireDate);
- setMetaData("expire-date", tmp);
- tmp.setNum(time(0)); // Cache entry will be created shortly.
- setMetaData("cache-creation-date", tmp);
- }
-
- // Let the app know about the mime-type iff this is not
- // a redirection and the mime-type string is not empty.
- if (locationStr.isEmpty() && (!m_strMimeType.isEmpty() ||
- m_request.method == HTTP_HEAD))
- {
- kdDebug(7113) << "(" << m_pid << ") Emitting mimetype " << m_strMimeType << endl;
- mimeType( m_strMimeType );
- }
-
- // Do not move send response header before any redirection as it seems
- // to screw up some sites. See BR# 150904.
- forwardHttpResponseHeader();
-
- if (m_request.method == HTTP_HEAD)
- return true;
-
- // Do we want to cache this request?
- if (m_request.bUseCache)
- {
- ::unlink( TQFile::encodeName(m_request.cef));
- if ( m_request.bCachedWrite && !m_strMimeType.isEmpty() )
- {
- // Check...
- createCacheEntry(m_strMimeType, expireDate); // Create a cache entry
- if (!m_request.fcache)
- {
- m_request.bCachedWrite = false; // Error creating cache entry.
- kdDebug(7113) << "(" << m_pid << ") Error creating cache entry for " << m_request.url.url()<<"!\n";
- }
- m_request.expireDate = expireDate;
- m_maxCacheSize = config()->readNumEntry("MaxCacheSize", DEFAULT_MAX_CACHE_SIZE) / 2;
- }
- }
-
- if (m_request.bCachedWrite && !m_strMimeType.isEmpty())
- kdDebug(7113) << "(" << m_pid << ") Cache, adding \"" << m_request.url.url() << "\"" << endl;
- else if (m_request.bCachedWrite && m_strMimeType.isEmpty())
- kdDebug(7113) << "(" << m_pid << ") Cache, pending \"" << m_request.url.url() << "\"" << endl;
- else
- kdDebug(7113) << "(" << m_pid << ") Cache, not adding \"" << m_request.url.url() << "\"" << endl;
- return true;
-}
-
-
-void HTTPProtocol::addEncoding(TQString encoding, TQStringList &encs)
-{
- encoding = encoding.stripWhiteSpace().lower();
- // Identity is the same as no encoding
- if (encoding == "identity") {
- return;
- } else if (encoding == "8bit") {
- // Strange encoding returned by http://linac.ikp.physik.tu-darmstadt.de
- return;
- } else if (encoding == "chunked") {
- m_bChunked = true;
- // Anyone know of a better way to handle unknown sizes possibly/ideally with unsigned ints?
- //if ( m_cmd != CMD_COPY )
- m_iSize = NO_SIZE;
- } else if ((encoding == "x-gzip") || (encoding == "gzip")) {
- encs.append(TQString::fromLatin1("gzip"));
- } else if ((encoding == "x-bzip2") || (encoding == "bzip2")) {
- encs.append(TQString::fromLatin1("bzip2")); // Not yet supported!
- } else if ((encoding == "x-deflate") || (encoding == "deflate")) {
- encs.append(TQString::fromLatin1("deflate"));
- } else {
- kdDebug(7113) << "(" << m_pid << ") Unknown encoding encountered. "
- << "Please write code. Encoding = \"" << encoding
- << "\"" << endl;
- }
-}
-
-bool HTTPProtocol::sendBody()
-{
- int result=-1;
- int length=0;
-
- infoMessage( i18n( "Requesting data to send" ) );
-
- // m_bufPOST will NOT be empty iff authentication was required before posting
- // the data OR a re-connect is requested from ::readHeader because the
- // connection was lost for some reason.
- if ( !m_bufPOST.isNull() )
- {
- kdDebug(7113) << "(" << m_pid << ") POST'ing saved data..." << endl;
-
- result = 0;
- length = m_bufPOST.size();
- }
- else
- {
- kdDebug(7113) << "(" << m_pid << ") POST'ing live data..." << endl;
-
- TQByteArray buffer;
- int old_size;
-
- m_bufPOST.resize(0);
- do
- {
- dataReq(); // Request for data
- result = readData( buffer );
- if ( result > 0 )
- {
- length += result;
- old_size = m_bufPOST.size();
- m_bufPOST.resize( old_size+result );
- memcpy( m_bufPOST.data()+ old_size, buffer.data(), buffer.size() );
- buffer.resize(0);
- }
- } while ( result > 0 );
- }
-
- if ( result < 0 )
- {
- error( ERR_ABORTED, m_request.hostname );
- return false;
- }
-
- infoMessage( i18n( "Sending data to %1" ).arg( m_request.hostname ) );
-
- TQString size = TQString ("Content-Length: %1\r\n\r\n").arg(length);
- kdDebug( 7113 ) << "(" << m_pid << ")" << size << endl;
-
- // Send the content length...
- bool sendOk = (write(size.latin1(), size.length()) == (ssize_t) size.length());
- if (!sendOk)
- {
- kdDebug( 7113 ) << "(" << m_pid << ") Connection broken when sending "
- << "content length: (" << m_state.hostname << ")" << endl;
- error( ERR_CONNECTION_BROKEN, m_state.hostname );
- return false;
- }
-
- // Send the data...
- // kdDebug( 7113 ) << "(" << m_pid << ") POST DATA: " << TQCString(m_bufPOST) << endl;
- sendOk = (write(m_bufPOST.data(), m_bufPOST.size()) == (ssize_t) m_bufPOST.size());
- if (!sendOk)
- {
- kdDebug(7113) << "(" << m_pid << ") Connection broken when sending message body: ("
- << m_state.hostname << ")" << endl;
- error( ERR_CONNECTION_BROKEN, m_state.hostname );
- return false;
- }
-
- return true;
-}
-
-void HTTPProtocol::httpClose( bool keepAlive )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpClose" << endl;
-
- if (m_request.fcache)
- {
- fclose(m_request.fcache);
- m_request.fcache = 0;
- if (m_request.bCachedWrite)
- {
- TQString filename = m_request.cef + ".new";
- ::unlink( TQFile::encodeName(filename) );
- }
- }
-
- // Only allow persistent connections for GET requests.
- // NOTE: we might even want to narrow this down to non-form
- // based submit requests which will require a meta-data from
- // khtml.
- if (keepAlive && (!m_bUseProxy ||
- m_bPersistentProxyConnection || m_bIsTunneled))
- {
- if (!m_keepAliveTimeout)
- m_keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
- else if (m_keepAliveTimeout > 2*DEFAULT_KEEP_ALIVE_TIMEOUT)
- m_keepAliveTimeout = 2*DEFAULT_KEEP_ALIVE_TIMEOUT;
-
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpClose: keep alive (" << m_keepAliveTimeout << ")" << endl;
- TQByteArray data;
- TQDataStream stream( data, IO_WriteOnly );
- stream << int(99); // special: Close connection
- setTimeoutSpecialCommand(m_keepAliveTimeout, data);
- return;
- }
-
- httpCloseConnection();
-}
-
-void HTTPProtocol::closeConnection()
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::closeConnection" << endl;
- httpCloseConnection ();
-}
-
-void HTTPProtocol::httpCloseConnection ()
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::httpCloseConnection" << endl;
- m_bIsTunneled = false;
- m_bKeepAlive = false;
- closeDescriptor();
- setTimeoutSpecialCommand(-1); // Cancel any connection timeout
-}
-
-void HTTPProtocol::slave_status()
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::slave_status" << endl;
-
- if ( m_iSock != -1 && !isConnectionValid() )
- httpCloseConnection();
-
- slaveStatus( m_state.hostname, (m_iSock != -1) );
-}
-
-void HTTPProtocol::mimetype( const KURL& url )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::mimetype: "
- << url.prettyURL() << endl;
-
- if ( !checkRequestURL( url ) )
- return;
-
- m_request.method = HTTP_HEAD;
- m_request.path = url.path();
- m_request.query = url.query();
- m_request.cache = CC_Cache;
- m_request.doProxy = m_bUseProxy;
-
- retrieveHeader();
-
- kdDebug(7113) << "(" << m_pid << ") http: mimetype = " << m_strMimeType
- << endl;
-}
-
-void HTTPProtocol::special( const TQByteArray &data )
-{
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::special" << endl;
-
- int tmp;
- TQDataStream stream(data, IO_ReadOnly);
-
- stream >> tmp;
- switch (tmp) {
- case 1: // HTTP POST
- {
- KURL url;
- stream >> url;
- post( url );
- break;
- }
- case 2: // cache_update
- {
- KURL url;
- bool no_cache;
- time_t expireDate;
- stream >> url >> no_cache >> expireDate;
- cacheUpdate( url, no_cache, expireDate );
- break;
- }
- case 5: // WebDAV lock
- {
- KURL url;
- TQString scope, type, owner;
- stream >> url >> scope >> type >> owner;
- davLock( url, scope, type, owner );
- break;
- }
- case 6: // WebDAV unlock
- {
- KURL url;
- stream >> url;
- davUnlock( url );
- break;
- }
- case 7: // Generic WebDAV
- {
- KURL url;
- int method;
- stream >> url >> method;
- davGeneric( url, (KIO::HTTP_METHOD) method );
- break;
- }
- case 99: // Close Connection
- {
- httpCloseConnection();
- break;
- }
- default:
- // Some command we don't understand.
- // Just ignore it, it may come from some future version of KDE.
- break;
- }
-}
-
-/**
- * Read a chunk from the data stream.
- */
-int HTTPProtocol::readChunked()
-{
- if ((m_iBytesLeft == 0) || (m_iBytesLeft == NO_SIZE))
- {
- setRewindMarker();
-
- m_bufReceive.resize(4096);
-
- if (!gets(m_bufReceive.data(), m_bufReceive.size()-1))
- {
- kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk header" << endl;
- return -1;
- }
- // We could have got the CRLF of the previous chunk.
- // If so, try again.
- if (m_bufReceive[0] == '\0')
- {
- if (!gets(m_bufReceive.data(), m_bufReceive.size()-1))
- {
- kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk header" << endl;
- return -1;
- }
- }
-
- // m_bEOF is set to true when read called from gets returns 0. For chunked reading 0
- // means end of chunked transfer and not error. See RFC 2615 section 3.6.1
- #if 0
- if (m_bEOF)
- {
- kdDebug(7113) << "(" << m_pid << ") EOF on Chunk header" << endl;
- return -1;
- }
- #endif
-
- long long trunkSize = STRTOLL(m_bufReceive.data(), 0, 16);
- if (trunkSize < 0)
- {
- kdDebug(7113) << "(" << m_pid << ") Negative chunk size" << endl;
- return -1;
- }
- m_iBytesLeft = trunkSize;
-
- // kdDebug(7113) << "(" << m_pid << ") Chunk size = " << m_iBytesLeft << " bytes" << endl;
-
- if (m_iBytesLeft == 0)
- {
- // Last chunk.
- // Skip trailers.
- do {
- // Skip trailer of last chunk.
- if (!gets(m_bufReceive.data(), m_bufReceive.size()-1))
- {
- kdDebug(7113) << "(" << m_pid << ") gets() failure on Chunk trailer" << endl;
- return -1;
- }
- // kdDebug(7113) << "(" << m_pid << ") Chunk trailer = \"" << m_bufReceive.data() << "\"" << endl;
- }
- while (strlen(m_bufReceive.data()) != 0);
-
- return 0;
- }
- }
-
- int bytesReceived = readLimited();
- if (!m_iBytesLeft)
- m_iBytesLeft = NO_SIZE; // Don't stop, continue with next chunk
-
- // kdDebug(7113) << "(" << m_pid << ") readChunked: BytesReceived=" << bytesReceived << endl;
- return bytesReceived;
-}
-
-int HTTPProtocol::readLimited()
-{
- if (!m_iBytesLeft)
- return 0;
-
- m_bufReceive.resize(4096);
-
- int bytesReceived;
- int bytesToReceive;
-
- if (m_iBytesLeft > m_bufReceive.size())
- bytesToReceive = m_bufReceive.size();
- else
- bytesToReceive = m_iBytesLeft;
-
- bytesReceived = read(m_bufReceive.data(), bytesToReceive);
-
- if (bytesReceived <= 0)
- return -1; // Error: connection lost
-
- m_iBytesLeft -= bytesReceived;
- return bytesReceived;
-}
-
-int HTTPProtocol::readUnlimited()
-{
- if (m_bKeepAlive)
- {
- kdDebug(7113) << "(" << m_pid << ") Unbounded datastream on a Keep "
- << "alive connection!" << endl;
- m_bKeepAlive = false;
- }
-
- m_bufReceive.resize(4096);
-
- int result = read(m_bufReceive.data(), m_bufReceive.size());
- if (result > 0)
- return result;
-
- m_bEOF = true;
- m_iBytesLeft = 0;
- return 0;
-}
-
-void HTTPProtocol::slotData(const TQByteArray &_d)
-{
- if (!_d.size())
- {
- m_bEOD = true;
- return;
- }
-
- if (m_iContentLeft != NO_SIZE)
- {
- if (m_iContentLeft >= _d.size())
- m_iContentLeft -= _d.size();
- else
- m_iContentLeft = NO_SIZE;
- }
-
- TQByteArray d = _d;
- if ( !m_dataInternal )
- {
- // If a broken server does not send the mime-type,
- // we try to id it from the content before dealing
- // with the content itself.
- if ( m_strMimeType.isEmpty() && !m_bRedirect &&
- !( m_responseCode >= 300 && m_responseCode <=399) )
- {
- kdDebug(7113) << "(" << m_pid << ") Determining mime-type from content..." << endl;
- int old_size = m_mimeTypeBuffer.size();
- m_mimeTypeBuffer.resize( old_size + d.size() );
- memcpy( m_mimeTypeBuffer.data() + old_size, d.data(), d.size() );
- if ( (m_iBytesLeft != NO_SIZE) && (m_iBytesLeft > 0)
- && (m_mimeTypeBuffer.size() < 1024) )
- {
- m_cpMimeBuffer = true;
- return; // Do not send up the data since we do not yet know its mimetype!
- }
-
- kdDebug(7113) << "(" << m_pid << ") Mimetype buffer size: " << m_mimeTypeBuffer.size()
- << endl;
-
- KMimeMagicResult *result;
- result = KMimeMagic::self()->findBufferFileType( m_mimeTypeBuffer,
- m_request.url.fileName() );
- if( result )
- {
- m_strMimeType = result->mimeType();
- kdDebug(7113) << "(" << m_pid << ") Mimetype from content: "
- << m_strMimeType << endl;
- }
-
- if ( m_strMimeType.isEmpty() )
- {
- m_strMimeType = TQString::fromLatin1( DEFAULT_MIME_TYPE );
- kdDebug(7113) << "(" << m_pid << ") Using default mimetype: "
- << m_strMimeType << endl;
- }
-
- if ( m_request.bCachedWrite )
- {
- createCacheEntry( m_strMimeType, m_request.expireDate );
- if (!m_request.fcache)
- m_request.bCachedWrite = false;
- }
-
- if ( m_cpMimeBuffer )
- {
- // Do not make any assumption about the state of the TQByteArray we received.
- // Fix the crash described by BR# 130104.
- d.detach();
- d.resize(0);
- d.resize(m_mimeTypeBuffer.size());
- memcpy( d.data(), m_mimeTypeBuffer.data(),
- d.size() );
- }
- mimeType(m_strMimeType);
- m_mimeTypeBuffer.resize(0);
- }
-
- data( d );
- if (m_request.bCachedWrite && m_request.fcache)
- writeCacheEntry(d.data(), d.size());
- }
- else
- {
- uint old_size = m_bufWebDavData.size();
- m_bufWebDavData.resize (old_size + d.size());
- memcpy (m_bufWebDavData.data() + old_size, d.data(), d.size());
- }
-}
-
-/**
- * This function is our "receive" function. It is responsible for
- * downloading the message (not the header) from the HTTP server. It
- * is called either as a response to a client's KIOJob::dataEnd()
- * (meaning that the client is done sending data) or by 'httpOpen()'
- * (if we are in the process of a PUT/POST request). It can also be
- * called by a webDAV function, to receive stat/list/property/etc.
- * data; in this case the data is stored in m_bufWebDavData.
- */
-bool HTTPProtocol::readBody( bool dataInternal /* = false */ )
-{
- if (m_responseCode == 204)
- return true;
-
- m_bEOD = false;
- // Note that when dataInternal is true, we are going to:
- // 1) save the body data to a member variable, m_bufWebDavData
- // 2) _not_ advertise the data, speed, size, etc., through the
- // corresponding functions.
- // This is used for returning data to WebDAV.
- m_dataInternal = dataInternal;
- if ( dataInternal )
- m_bufWebDavData.resize (0);
-
- // Check if we need to decode the data.
- // If we are in copy mode, then use only transfer decoding.
- bool useMD5 = !m_sContentMD5.isEmpty();
-
- // Deal with the size of the file.
- KIO::filesize_t sz = m_request.offset;
- if ( sz )
- m_iSize += sz;
-
- // Update the application with total size except when
- // it is compressed, or when the data is to be handled
- // internally (webDAV). If compressed we have to wait
- // until we uncompress to find out the actual data size
- if ( !dataInternal ) {
- if ( (m_iSize > 0) && (m_iSize != NO_SIZE)) {
- totalSize(m_iSize);
- infoMessage( i18n( "Retrieving %1 from %2...").arg(KIO::convertSize(m_iSize))
- .arg( m_request.hostname ) );
- }
- else
- {
- totalSize ( 0 );
- }
- }
- else
- infoMessage( i18n( "Retrieving from %1..." ).arg( m_request.hostname ) );
-
- if (m_request.bCachedRead)
- {
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readBody: read data from cache!" << endl;
- m_request.bCachedWrite = false;
-
- char buffer[ MAX_IPC_SIZE ];
-
- m_iContentLeft = NO_SIZE;
-
- // Jippie! It's already in the cache :-)
- while (!feof(m_request.fcache) && !ferror(m_request.fcache))
- {
- int nbytes = fread( buffer, 1, MAX_IPC_SIZE, m_request.fcache);
-
- if (nbytes > 0)
- {
- m_bufReceive.setRawData( buffer, nbytes);
- slotData( m_bufReceive );
- m_bufReceive.resetRawData( buffer, nbytes );
- sz += nbytes;
- }
- }
-
- m_bufReceive.resize( 0 );
-
- if ( !dataInternal )
- {
- processedSize( sz );
- data( TQByteArray() );
- }
-
- return true;
- }
-
-
- if (m_iSize != NO_SIZE)
- m_iBytesLeft = m_iSize - sz;
- else
- m_iBytesLeft = NO_SIZE;
-
- m_iContentLeft = m_iBytesLeft;
-
- if (m_bChunked)
- m_iBytesLeft = NO_SIZE;
-
- kdDebug(7113) << "(" << m_pid << ") HTTPProtocol::readBody: retrieve data. "
- << KIO::number(m_iBytesLeft) << " left." << endl;
-
- // Main incoming loop... Gather everything while we can...
- m_cpMimeBuffer = false;
- m_mimeTypeBuffer.resize(0);
- struct timeval last_tv;
- gettimeofday( &last_tv, 0L );
-
- HTTPFilterChain chain;
-
- TQObject::connect(&chain, TQT_SIGNAL(output(const TQByteArray &)),
- this, TQT_SLOT(slotData(const TQByteArray &)));
- TQObject::connect(&chain, TQT_SIGNAL(error(int, const TQString &)),
- this, TQT_SLOT(error(int, const TQString &)));
-
- // decode all of the transfer encodings
- while (!m_qTransferEncodings.isEmpty())
- {
- TQString enc = m_qTransferEncodings.last();
- m_qTransferEncodings.remove(m_qTransferEncodings.fromLast());
- if ( enc == "gzip" )
- chain.addFilter(new HTTPFilterGZip);
- else if ( enc == "deflate" )
- chain.addFilter(new HTTPFilterDeflate);
- }
-
- // From HTTP 1.1 Draft 6:
- // The MD5 digest is computed based on the content of the entity-body,
- // including any content-coding that has been applied, but not including
- // any transfer-encoding applied to the message-body. If the message is
- // received with a transfer-encoding, that encoding MUST be removed
- // prior to checking the Content-MD5 value against the received entity.
- HTTPFilterMD5 *md5Filter = 0;
- if ( useMD5 )
- {
- md5Filter = new HTTPFilterMD5;
- chain.addFilter(md5Filter);
- }
-
- // now decode all of the content encodings
- // -- Why ?? We are not
- // -- a proxy server, be a client side implementation!! The applications
- // -- are capable of determinig how to extract the encoded implementation.
- // WB: That's a misunderstanding. We are free to remove the encoding.
- // WB: Some braindead www-servers however, give .tgz files an encoding
- // WB: of "gzip" (or even "x-gzip") and a content-type of "applications/tar"
- // WB: They shouldn't do that. We can work around that though...
- while (!m_qContentEncodings.isEmpty())
- {
- TQString enc = m_qContentEncodings.last();
- m_qContentEncodings.remove(m_qContentEncodings.fromLast());
- if ( enc == "gzip" )
- chain.addFilter(new HTTPFilterGZip);
- else if ( enc == "deflate" )
- chain.addFilter(new HTTPFilterDeflate);
- }
-
- while (!m_bEOF)
- {
- int bytesReceived;
-
- if (m_bChunked)
- bytesReceived = readChunked();
- else if (m_iSize != NO_SIZE)
- bytesReceived = readLimited();
- else
- bytesReceived = readUnlimited();
-
- // make sure that this wasn't an error, first
- // kdDebug(7113) << "(" << (int) m_pid << ") readBody: bytesReceived: "
- // << (int) bytesReceived << " m_iSize: " << (int) m_iSize << " Chunked: "
- // << (int) m_bChunked << " BytesLeft: "<< (int) m_iBytesLeft << endl;
- if (bytesReceived == -1)
- {
- if (m_iContentLeft == 0)
- {
- // gzip'ed data sometimes reports a too long content-length.
- // (The length of the unzipped data)
- m_iBytesLeft = 0;
- break;
- }
- // Oh well... log an error and bug out
- kdDebug(7113) << "(" << m_pid << ") readBody: bytesReceived==-1 sz=" << (int)sz
- << " Connnection broken !" << endl;
- error(ERR_CONNECTION_BROKEN, m_state.hostname);
- return false;
- }
-
- // I guess that nbytes == 0 isn't an error.. but we certainly
- // won't work with it!
- if (bytesReceived > 0)
- {
- // Important: truncate the buffer to the actual size received!
- // Otherwise garbage will be passed to the app
- m_bufReceive.truncate( bytesReceived );
-
- chain.slotInput(m_bufReceive);
-
- if (m_bError)
- return false;
-
- sz += bytesReceived;
- if (!dataInternal)
- processedSize( sz );
- }
- m_bufReceive.resize(0); // res
-
- if (m_iBytesLeft && m_bEOD && !m_bChunked)
- {
- // gzip'ed data sometimes reports a too long content-length.
- // (The length of the unzipped data)
- m_iBytesLeft = 0;
- }
-
- if (m_iBytesLeft == 0)
- {
- kdDebug(7113) << "("<<m_pid<<") EOD received! Left = "<< KIO::number(m_iBytesLeft) << endl;
- break;
- }
- }
- chain.slotInput(TQByteArray()); // Flush chain.
-
- if ( useMD5 )
- {
- TQString calculatedMD5 = md5Filter->md5();
-
- if ( m_sContentMD5 == calculatedMD5 )
- kdDebug(7113) << "(" << m_pid << ") MD5 checksum MATCHED!!" << endl;
- else
- kdDebug(7113) << "(" << m_pid << ") MD5 checksum MISMATCH! Expected: "
- << calculatedMD5 << ", Got: " << m_sContentMD5 << endl;
- }
-
- // Close cache entry
- if (m_iBytesLeft == 0)
- {
- if (m_request.bCachedWrite && m_request.fcache)
- closeCacheEntry();
- else if (m_request.bCachedWrite)
- kdDebug(7113) << "(" << m_pid << ") no cache file!\n";
- }
- else
- {
- kdDebug(7113) << "(" << m_pid << ") still "<< KIO::number(m_iBytesLeft)
- << " bytes left! can't close cache entry!\n";
- }
-
- if (sz <= 1)
- {
- /* kdDebug(7113) << "(" << m_pid << ") readBody: sz = " << KIO::number(sz)
- << ", responseCode =" << m_responseCode << endl; */
- if (m_responseCode >= 500 && m_responseCode <= 599)
- error(ERR_INTERNAL_SERVER, m_state.hostname);
- else if (m_responseCode >= 400 && m_responseCode <= 499)
- error(ERR_DOES_NOT_EXIST, m_state.hostname);
- }
-
- if (!dataInternal)
- data( TQByteArray() );
-
- return true;
-}
-
-
-void HTTPProtocol::error( int _err, const TQString &_text )
-{
- httpClose(false);
-
- if (!m_request.id.isEmpty())
- {
- forwardHttpResponseHeader();
- sendMetaData();
- }
-
- // Clear of the temporary POST buffer if it is not empty...
- if (!m_bufPOST.isEmpty())
- {
- m_bufPOST.resize(0);
- kdDebug(7113) << "(" << m_pid << ") HTTP::retreiveHeader: Cleared POST "
- "buffer..." << endl;
- }
-
- SlaveBase::error( _err, _text );
- m_bError = true;
-}
-
-
-void HTTPProtocol::addCookies( const TQString &url, const TQCString &cookieHeader )
-{
- long windowId = m_request.window.toLong();
- TQByteArray params;
- TQDataStream stream(params, IO_WriteOnly);
- stream << url << cookieHeader << windowId;
-
- kdDebug(7113) << "(" << m_pid << ") " << cookieHeader << endl;
- kdDebug(7113) << "(" << m_pid << ") " << "Window ID: "
- << windowId << ", for host = " << url << endl;
-
- if ( !dcopClient()->send( "kded", "kcookiejar", "addCookies(TQString,TQCString,long int)", params ) )
- {
- kdWarning(7113) << "(" << m_pid << ") Can't communicate with kded_kcookiejar!" << endl;
- }
-}
-
-TQString HTTPProtocol::findCookies( const TQString &url)
-{
- TQCString replyType;
- TQByteArray params;
- TQByteArray reply;
- TQString result;
-
- long windowId = m_request.window.toLong();
- result = TQString::null;
- TQDataStream stream(params, IO_WriteOnly);
- stream << url << windowId;
-
- if ( !dcopClient()->call( "kded", "kcookiejar", "findCookies(TQString,long int)",
- params, replyType, reply ) )
- {
- kdWarning(7113) << "(" << m_pid << ") Can't communicate with kded_kcookiejar!" << endl;
- return result;
- }
- if ( replyType == "TQString" )
- {
- TQDataStream stream2( reply, IO_ReadOnly );
- stream2 >> result;
- }
- else
- {
- kdError(7113) << "(" << m_pid << ") DCOP function findCookies(...) returns "
- << replyType << ", expected TQString" << endl;
- }
- return result;
-}
-
-/******************************* CACHING CODE ****************************/
-
-
-void HTTPProtocol::cacheUpdate( const KURL& url, bool no_cache, time_t expireDate)
-{
- if ( !checkRequestURL( url ) )
- return;
-
- m_request.path = url.path();
- m_request.query = url.query();
- m_request.cache = CC_Reload;
- m_request.doProxy = m_bUseProxy;
-
- if (no_cache)
- {
- m_request.fcache = checkCacheEntry( );
- if (m_request.fcache)
- {
- fclose(m_request.fcache);
- m_request.fcache = 0;
- ::unlink( TQFile::encodeName(m_request.cef) );
- }
- }
- else
- {
- updateExpireDate( expireDate );
- }
- finished();
-}
-
-// !START SYNC!
-// The following code should be kept in sync
-// with the code in http_cache_cleaner.cpp
-
-FILE* HTTPProtocol::checkCacheEntry( bool readWrite)
-{
- const TQChar separator = '_';
-
- TQString CEF = m_request.path;
-
- int p = CEF.find('/');
-
- while(p != -1)
- {
- CEF[p] = separator;
- p = CEF.find('/', p);
- }
-
- TQString host = m_request.hostname.lower();
- CEF = host + CEF + '_';
-
- TQString dir = m_strCacheDir;
- if (dir[dir.length()-1] != '/')
- dir += "/";
-
- int l = host.length();
- for(int i = 0; i < l; i++)
- {
- if (host[i].isLetter() && (host[i] != 'w'))
- {
- dir += host[i];
- break;
- }
- }
- if (dir[dir.length()-1] == '/')
- dir += "0";
-
- unsigned long hash = 0x00000000;
- TQCString u = m_request.url.url().latin1();
- for(int i = u.length(); i--;)
- {
- hash = (hash * 12211 + static_cast<const char>(u.at(i))) % 2147483563;
- }
-
- TQString hashString;
- hashString.sprintf("%08lx", hash);
-
- CEF = CEF + hashString;
-
- CEF = dir + "/" + CEF;
-
- m_request.cef = CEF;
-
- const char *mode = (readWrite ? "r+" : "r");
-
- FILE *fs = fopen( TQFile::encodeName(CEF), mode); // Open for reading and writing
- if (!fs)
- return 0;
-
- char buffer[401];
- bool ok = true;
-
- // CacheRevision
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok && (strcmp(buffer, CACHE_REVISION) != 0))
- ok = false;
-
- time_t date;
- time_t currentDate = time(0);
-
- // URL
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
- int l = strlen(buffer);
- if (l>0)
- buffer[l-1] = 0; // Strip newline
- if (m_request.url.url() != buffer)
- {
- ok = false; // Hash collision
- }
- }
-
- // Creation Date
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
- date = (time_t) strtoul(buffer, 0, 10);
- m_request.creationDate = date;
- if (m_maxCacheAge && (difftime(currentDate, date) > m_maxCacheAge))
- {
- m_request.bMustRevalidate = true;
- m_request.expireDate = currentDate;
- }
- }
-
- // Expiration Date
- m_request.cacheExpireDateOffset = ftell(fs);
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
- if (m_request.cache == CC_Verify)
- {
- date = (time_t) strtoul(buffer, 0, 10);
- // After the expire date we need to revalidate.
- if (!date || difftime(currentDate, date) >= 0)
- m_request.bMustRevalidate = true;
- m_request.expireDate = date;
- }
- else if (m_request.cache == CC_Refresh)
- {
- m_request.bMustRevalidate = true;
- m_request.expireDate = currentDate;
- }
- }
-
- // ETag
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
- m_request.etag = TQString(buffer).stripWhiteSpace();
- }
-
- // Last-Modified
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
- m_request.lastModified = TQString(buffer).stripWhiteSpace();
- }
-
- if (ok)
- return fs;
-
- fclose(fs);
- unlink( TQFile::encodeName(CEF));
- return 0;
-}
-
-void HTTPProtocol::updateExpireDate(time_t expireDate, bool updateCreationDate)
-{
- bool ok = true;
-
- FILE *fs = checkCacheEntry(true);
- if (fs)
- {
- TQString date;
- char buffer[401];
- time_t creationDate;
-
- fseek(fs, 0, SEEK_SET);
- if (ok && !fgets(buffer, 400, fs))
- ok = false;
- if (ok && !fgets(buffer, 400, fs))
- ok = false;
- long cacheCreationDateOffset = ftell(fs);
- if (ok && !fgets(buffer, 400, fs))
- ok = false;
- creationDate = strtoul(buffer, 0, 10);
- if (!creationDate)
- ok = false;
-
- if (updateCreationDate)
- {
- if (!ok || fseek(fs, cacheCreationDateOffset, SEEK_SET))
- return;
- TQString date;
- date.setNum( time(0) );
- date = date.leftJustify(16);
- fputs(date.latin1(), fs); // Creation date
- fputc('\n', fs);
- }
-
- if (expireDate>(30*365*24*60*60))
- {
- // expire date is a really a big number, it can't be
- // a relative date.
- date.setNum( expireDate );
- }
- else
- {
- // expireDate before 2000. those values must be
- // interpreted as relative expiration dates from
- // <META http-equiv="Expires"> tags.
- // so we have to scan the creation time and add
- // it to the expiryDate
- date.setNum( creationDate + expireDate );
- }
- date = date.leftJustify(16);
- if (!ok || fseek(fs, m_request.cacheExpireDateOffset, SEEK_SET))
- return;
- fputs(date.latin1(), fs); // Expire date
- fseek(fs, 0, SEEK_END);
- fclose(fs);
- }
-}
-
-void HTTPProtocol::createCacheEntry( const TQString &mimetype, time_t expireDate)
-{
- TQString dir = m_request.cef;
- int p = dir.findRev('/');
- if (p == -1) return; // Error.
- dir.truncate(p);
-
- // Create file
- (void) ::mkdir( TQFile::encodeName(dir), 0700 );
-
- TQString filename = m_request.cef + ".new"; // Create a new cache entryexpireDate
-
-// kdDebug( 7103 ) << "creating new cache entry: " << filename << endl;
-
- m_request.fcache = fopen( TQFile::encodeName(filename), "w");
- if (!m_request.fcache)
- {
- kdWarning(7113) << "(" << m_pid << ")createCacheEntry: opening " << filename << " failed." << endl;
- return; // Error.
- }
-
- fputs(CACHE_REVISION, m_request.fcache); // Revision
-
- fputs(m_request.url.url().latin1(), m_request.fcache); // Url
- fputc('\n', m_request.fcache);
-
- TQString date;
- m_request.creationDate = time(0);
- date.setNum( m_request.creationDate );
- date = date.leftJustify(16);
- fputs(date.latin1(), m_request.fcache); // Creation date
- fputc('\n', m_request.fcache);
-
- date.setNum( expireDate );
- date = date.leftJustify(16);
- fputs(date.latin1(), m_request.fcache); // Expire date
- fputc('\n', m_request.fcache);
-
- if (!m_request.etag.isEmpty())
- fputs(m_request.etag.latin1(), m_request.fcache); //ETag
- fputc('\n', m_request.fcache);
-
- if (!m_request.lastModified.isEmpty())
- fputs(m_request.lastModified.latin1(), m_request.fcache); // Last modified
- fputc('\n', m_request.fcache);
-
- fputs(mimetype.latin1(), m_request.fcache); // Mimetype
- fputc('\n', m_request.fcache);
-
- if (!m_request.strCharset.isEmpty())
- fputs(m_request.strCharset.latin1(), m_request.fcache); // Charset
- fputc('\n', m_request.fcache);
-
- return;
-}
-// The above code should be kept in sync
-// with the code in http_cache_cleaner.cpp
-// !END SYNC!
-
-void HTTPProtocol::writeCacheEntry( const char *buffer, int nbytes)
-{
- if (fwrite( buffer, nbytes, 1, m_request.fcache) != 1)
- {
- kdWarning(7113) << "(" << m_pid << ") writeCacheEntry: writing " << nbytes << " bytes failed." << endl;
- fclose(m_request.fcache);
- m_request.fcache = 0;
- TQString filename = m_request.cef + ".new";
- ::unlink( TQFile::encodeName(filename) );
- return;
- }
- long file_pos = ftell( m_request.fcache ) / 1024;
- if ( file_pos > m_maxCacheSize )
- {
- kdDebug(7113) << "writeCacheEntry: File size reaches " << file_pos
- << "Kb, exceeds cache limits. (" << m_maxCacheSize << "Kb)" << endl;
- fclose(m_request.fcache);
- m_request.fcache = 0;
- TQString filename = m_request.cef + ".new";
- ::unlink( TQFile::encodeName(filename) );
- return;
- }
-}
-
-void HTTPProtocol::closeCacheEntry()
-{
- TQString filename = m_request.cef + ".new";
- int result = fclose( m_request.fcache);
- m_request.fcache = 0;
- if (result == 0)
- {
- if (::rename( TQFile::encodeName(filename), TQFile::encodeName(m_request.cef)) == 0)
- return; // Success
-
- kdWarning(7113) << "(" << m_pid << ") closeCacheEntry: error renaming "
- << "cache entry. (" << filename << " -> " << m_request.cef
- << ")" << endl;
- }
-
- kdWarning(7113) << "(" << m_pid << ") closeCacheEntry: error closing cache "
- << "entry. (" << filename<< ")" << endl;
-}
-
-void HTTPProtocol::cleanCache()
-{
- const time_t maxAge = DEFAULT_CLEAN_CACHE_INTERVAL; // 30 Minutes.
- bool doClean = false;
- TQString cleanFile = m_strCacheDir;
- if (cleanFile[cleanFile.length()-1] != '/')
- cleanFile += "/";
- cleanFile += "cleaned";
-
- struct stat stat_buf;
-
- int result = ::stat(TQFile::encodeName(cleanFile), &stat_buf);
- if (result == -1)
- {
- int fd = creat( TQFile::encodeName(cleanFile), 0600);
- if (fd != -1)
- {
- doClean = true;
- ::close(fd);
- }
- }
- else
- {
- time_t age = (time_t) difftime( time(0), stat_buf.st_mtime );
- if (age > maxAge) //
- doClean = true;
- }
- if (doClean)
- {
- // Touch file.
- utime(TQFile::encodeName(cleanFile), 0);
- KApplication::startServiceByDesktopPath("http_cache_cleaner.desktop");
- }
-}
-
-
-
-//************************** AUTHENTICATION CODE ********************/
-
-
-void HTTPProtocol::configAuth( char *p, bool isForProxy )
-{
- HTTP_AUTH f = AUTH_None;
- const char *strAuth = p;
-
- if ( strncasecmp( p, "Basic", 5 ) == 0 )
- {
- f = AUTH_Basic;
- p += 5;
- strAuth = "Basic"; // Correct for upper-case variations.
- }
- else if ( strncasecmp (p, "Digest", 6) == 0 )
- {
- f = AUTH_Digest;
- memcpy((void *)p, "Digest", 6); // Correct for upper-case variations.
- p += 6;
- }
- else if (strncasecmp( p, "MBS_PWD_COOKIE", 14 ) == 0)
- {
- // Found on http://www.webscription.net/baen/default.asp
- f = AUTH_Basic;
- p += 14;
- strAuth = "Basic";
- }
-#ifdef HAVE_LIBGSSAPI
- else if ( strncasecmp( p, "Negotiate", 9 ) == 0 )
- {
- // if we get two 401 in a row let's assume for now that
- // Negotiate isn't working and ignore it
- if ( !isForProxy && !(m_responseCode == 401 && m_prevResponseCode == 401) )
- {
- f = AUTH_Negotiate;
- memcpy((void *)p, "Negotiate", 9); // Correct for upper-case variations.
- p += 9;
- };
- }
-#endif
- else if ( strncasecmp( p, "NTLM", 4 ) == 0 )
- {
- f = AUTH_NTLM;
- memcpy((void *)p, "NTLM", 4); // Correct for upper-case variations.
- p += 4;
- m_strRealm = "NTLM"; // set a dummy realm
- }
- else
- {
- kdWarning(7113) << "(" << m_pid << ") Unsupported or invalid authorization "
- << "type requested" << endl;
- if (isForProxy)
- kdWarning(7113) << "(" << m_pid << ") Proxy URL: " << m_proxyURL << endl;
- else
- kdWarning(7113) << "(" << m_pid << ") URL: " << m_request.url << endl;
- kdWarning(7113) << "(" << m_pid << ") Request Authorization: " << p << endl;
- }
-
- /*
- This check ensures the following:
- 1.) Rejection of any unknown/unsupported authentication schemes
- 2.) Usage of the strongest possible authentication schemes if
- and when multiple Proxy-Authenticate or WWW-Authenticate
- header field is sent.
- */
- if (isForProxy)
- {
- if ((f == AUTH_None) ||
- ((m_iProxyAuthCount > 0) && (f < ProxyAuthentication)))
- {
- // Since I purposefully made the Proxy-Authentication settings
- // persistent to reduce the number of round-trips to tdesud we
- // have to take special care when an unknown/unsupported auth-
- // scheme is received. This check accomplishes just that...
- if ( m_iProxyAuthCount == 0)
- ProxyAuthentication = f;
- kdDebug(7113) << "(" << m_pid << ") Rejected proxy auth method: " << f << endl;
- return;
- }
- m_iProxyAuthCount++;
- kdDebug(7113) << "(" << m_pid << ") Accepted proxy auth method: " << f << endl;
- }
- else
- {
- if ((f == AUTH_None) ||
- ((m_iWWWAuthCount > 0) && (f < Authentication)))
- {
- kdDebug(7113) << "(" << m_pid << ") Rejected auth method: " << f << endl;
- return;
- }
- m_iWWWAuthCount++;
- kdDebug(7113) << "(" << m_pid << ") Accepted auth method: " << f << endl;
- }
-
-
- while (*p)
- {
- int i = 0;
- while( (*p == ' ') || (*p == ',') || (*p == '\t') ) { p++; }
- if ( strncasecmp( p, "realm=", 6 ) == 0 )
- {
- //for sites like lib.homelinux.org
- TQTextCodec* oldCodec=TQTextCodec::codecForCStrings();
- if (KGlobal::locale()->language().contains("ru"))
- TQTextCodec::setCodecForCStrings(TQTextCodec::codecForName("CP1251"));
-
- p += 6;
- if (*p == '"') p++;
- while( p[i] && p[i] != '"' ) i++;
- if( isForProxy )
- m_strProxyRealm = TQString::fromAscii( p, i );
- else
- m_strRealm = TQString::fromAscii( p, i );
-
- TQTextCodec::setCodecForCStrings(oldCodec);
-
- if (!p[i]) break;
- }
- p+=(i+1);
- }
-
- if( isForProxy )
- {
- ProxyAuthentication = f;
- m_strProxyAuthorization = TQString::fromLatin1( strAuth );
- }
- else
- {
- Authentication = f;
- m_strAuthorization = TQString::fromLatin1( strAuth );
- }
-}
-
-
-bool HTTPProtocol::retryPrompt()
-{
- TQString prompt;
- switch ( m_responseCode )
- {
- case 401:
- prompt = i18n("Authentication Failed.");
- break;
- case 407:
- prompt = i18n("Proxy Authentication Failed.");
- break;
- default:
- break;
- }
- prompt += i18n(" Do you want to retry?");
- return (messageBox(QuestionYesNo, prompt, i18n("Authentication")) == 3);
-}
-
-void HTTPProtocol::promptInfo( AuthInfo& info )
-{
- if ( m_responseCode == 401 )
- {
- info.url = m_request.url;
- if ( !m_state.user.isEmpty() )
- info.username = m_state.user;
- info.readOnly = !m_request.url.user().isEmpty();
- info.prompt = i18n( "You need to supply a username and a "
- "password to access this site." );
- info.keepPassword = true; // Prompt the user for persistence as well.
- if ( !m_strRealm.isEmpty() )
- {
- info.realmValue = m_strRealm;
- info.verifyPath = false;
- info.digestInfo = m_strAuthorization;
- info.commentLabel = i18n( "Site:" );
- info.comment = i18n("<b>%1</b> at <b>%2</b>").arg( m_strRealm ).arg( m_request.hostname );
- }
- }
- else if ( m_responseCode == 407 )
- {
- info.url = m_proxyURL;
- info.username = m_proxyURL.user();
- info.prompt = i18n( "You need to supply a username and a password for "
- "the proxy server listed below before you are allowed "
- "to access any sites." );
- info.keepPassword = true;
- if ( !m_strProxyRealm.isEmpty() )
- {
- info.realmValue = m_strProxyRealm;
- info.verifyPath = false;
- info.digestInfo = m_strProxyAuthorization;
- info.commentLabel = i18n( "Proxy:" );
- info.comment = i18n("<b>%1</b> at <b>%2</b>").arg( m_strProxyRealm ).arg( m_proxyURL.host() );
- }
- }
-}
-
-bool HTTPProtocol::getAuthorization()
-{
- AuthInfo info;
- bool result = false;
-
- kdDebug (7113) << "(" << m_pid << ") HTTPProtocol::getAuthorization: "
- << "Current Response: " << m_responseCode << ", "
- << "Previous Response: " << m_prevResponseCode << ", "
- << "Authentication: " << Authentication << ", "
- << "ProxyAuthentication: " << ProxyAuthentication << endl;
-
- if (m_request.bNoAuth)
- {
- if (m_request.bErrorPage)
- errorPage();
- else
- error( ERR_COULD_NOT_LOGIN, i18n("Authentication needed for %1 but authentication is disabled.").arg(m_request.hostname));
- return false;
- }
-
- bool repeatFailure = (m_prevResponseCode == m_responseCode);
-
- TQString errorMsg;
-
- if (repeatFailure)
- {
- bool prompt = true;
- if ( Authentication == AUTH_Digest || ProxyAuthentication == AUTH_Digest )
- {
- bool isStaleNonce = false;
- TQString auth = ( m_responseCode == 401 ) ? m_strAuthorization : m_strProxyAuthorization;
- int pos = auth.find("stale", 0, false);
- if ( pos != -1 )
- {
- pos += 5;
- int len = auth.length();
- while( pos < len && (auth[pos] == ' ' || auth[pos] == '=') ) pos++;
- if ( pos < len && auth.find("true", pos, false) != -1 )
- {
- isStaleNonce = true;
- kdDebug(7113) << "(" << m_pid << ") Stale nonce value. "
- << "Will retry using same info..." << endl;
- }
- }
- if ( isStaleNonce )
- {
- prompt = false;
- result = true;
- if ( m_responseCode == 401 )
- {
- info.username = m_request.user;
- info.password = m_request.passwd;
- info.realmValue = m_strRealm;
- info.digestInfo = m_strAuthorization;
- }
- else if ( m_responseCode == 407 )
- {
- info.username = m_proxyURL.user();
- info.password = m_proxyURL.pass();
- info.realmValue = m_strProxyRealm;
- info.digestInfo = m_strProxyAuthorization;
- }
- }
- }
-
- if ( Authentication == AUTH_NTLM || ProxyAuthentication == AUTH_NTLM )
- {
- TQString auth = ( m_responseCode == 401 ) ? m_strAuthorization : m_strProxyAuthorization;
- kdDebug(7113) << "auth: " << auth << endl;
- if ( auth.length() > 4 )
- {
- prompt = false;
- result = true;
- kdDebug(7113) << "(" << m_pid << ") NTLM auth second phase, "
- << "sending response..." << endl;
- if ( m_responseCode == 401 )
- {
- info.username = m_request.user;
- info.password = m_request.passwd;
- info.realmValue = m_strRealm;
- info.digestInfo = m_strAuthorization;
- }
- else if ( m_responseCode == 407 )
- {
- info.username = m_proxyURL.user();
- info.password = m_proxyURL.pass();
- info.realmValue = m_strProxyRealm;
- info.digestInfo = m_strProxyAuthorization;
- }
- }
- }
-
- if ( prompt )
- {
- switch ( m_responseCode )
- {
- case 401:
- errorMsg = i18n("Authentication Failed.");
- break;
- case 407:
- errorMsg = i18n("Proxy Authentication Failed.");
- break;
- default:
- break;
- }
- }
- }
- else
- {
- // At this point we know more details, so use it to find
- // out if we have a cached version and avoid a re-prompt!
- // We also do not use verify path unlike the pre-emptive
- // requests because we already know the realm value...
-
- if (m_bProxyAuthValid)
- {
- // Reset cached proxy auth
- m_bProxyAuthValid = false;
- KURL proxy ( config()->readEntry("UseProxy") );
- m_proxyURL.setUser(proxy.user());
- m_proxyURL.setPass(proxy.pass());
- }
-
- info.verifyPath = false;
- if ( m_responseCode == 407 )
- {
- info.url = m_proxyURL;
- info.username = m_proxyURL.user();
- info.password = m_proxyURL.pass();
- info.realmValue = m_strProxyRealm;
- info.digestInfo = m_strProxyAuthorization;
- }
- else
- {
- info.url = m_request.url;
- info.username = m_request.user;
- info.password = m_request.passwd;
- info.realmValue = m_strRealm;
- info.digestInfo = m_strAuthorization;
- }
-
- // If either username or password is not supplied
- // with the request, check the password cache.
- if ( info.username.isNull() ||
- info.password.isNull() )
- result = checkCachedAuthentication( info );
-
- if ( Authentication == AUTH_Digest )
- {
- TQString auth;
-
- if (m_responseCode == 401)
- auth = m_strAuthorization;
- else
- auth = m_strProxyAuthorization;
-
- int pos = auth.find("stale", 0, false);
- if ( pos != -1 )
- {
- pos += 5;
- int len = auth.length();
- while( pos < len && (auth[pos] == ' ' || auth[pos] == '=') ) pos++;
- if ( pos < len && auth.find("true", pos, false) != -1 )
- {
- info.digestInfo = (m_responseCode == 401) ? m_strAuthorization : m_strProxyAuthorization;
- kdDebug(7113) << "(" << m_pid << ") Just a stale nonce value! "
- << "Retrying using the new nonce sent..." << endl;
- }
- }
- }
- }
-
- if (!result )
- {
- // Do not prompt if the username & password
- // is already supplied and the login attempt
- // did not fail before.
- if ( !repeatFailure &&
- !info.username.isNull() &&
- !info.password.isNull() )
- result = true;
- else
- {
- if (Authentication == AUTH_Negotiate)
- {
- if (!repeatFailure)
- result = true;
- }
- else if ( m_request.disablePassDlg == false )
- {
- kdDebug( 7113 ) << "(" << m_pid << ") Prompting the user for authorization..." << endl;
- promptInfo( info );
- result = openPassDlg( info, errorMsg );
- }
- }
- }
-
- if ( result )
- {
- switch (m_responseCode)
- {
- case 401: // Request-Authentication
- m_request.user = info.username;
- m_request.passwd = info.password;
- m_strRealm = info.realmValue;
- m_strAuthorization = info.digestInfo;
- break;
- case 407: // Proxy-Authentication
- m_proxyURL.setUser( info.username );
- m_proxyURL.setPass( info.password );
- m_strProxyRealm = info.realmValue;
- m_strProxyAuthorization = info.digestInfo;
- break;
- default:
- break;
- }
- return true;
- }
-
- if (m_request.bErrorPage)
- errorPage();
- else
- error( ERR_USER_CANCELED, TQString::null );
- return false;
-}
-
-void HTTPProtocol::saveAuthorization()
-{
- AuthInfo info;
- if ( m_prevResponseCode == 407 )
- {
- if (!m_bUseProxy)
- return;
- m_bProxyAuthValid = true;
- info.url = m_proxyURL;
- info.username = m_proxyURL.user();
- info.password = m_proxyURL.pass();
- info.realmValue = m_strProxyRealm;
- info.digestInfo = m_strProxyAuthorization;
- cacheAuthentication( info );
- }
- else
- {
- info.url = m_request.url;
- info.username = m_request.user;
- info.password = m_request.passwd;
- info.realmValue = m_strRealm;
- info.digestInfo = m_strAuthorization;
- cacheAuthentication( info );
- }
-}
-
-#ifdef HAVE_LIBGSSAPI
-TQCString HTTPProtocol::gssError( int major_status, int minor_status )
-{
- OM_uint32 new_status;
- OM_uint32 msg_ctx = 0;
- gss_buffer_desc major_string;
- gss_buffer_desc minor_string;
- OM_uint32 ret;
- TQCString errorstr;
-
- errorstr = "";
-
- do {
- ret = gss_display_status(&new_status, major_status, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &major_string);
- errorstr += (const char *)major_string.value;
- errorstr += " ";
- ret = gss_display_status(&new_status, minor_status, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &minor_string);
- errorstr += (const char *)minor_string.value;
- errorstr += " ";
- } while (!GSS_ERROR(ret) && msg_ctx != 0);
-
- return errorstr;
-}
-
-TQString HTTPProtocol::createNegotiateAuth()
-{
- TQString auth;
- TQCString servicename;
- TQByteArray input;
- OM_uint32 major_status, minor_status;
- OM_uint32 req_flags = 0;
- gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
- gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
- gss_name_t server;
- gss_ctx_id_t ctx;
- gss_OID mech_oid;
- static gss_OID_desc krb5_oid_desc = {9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
- static gss_OID_desc spnego_oid_desc = {6, (void *) "\x2b\x06\x01\x05\x05\x02"};
- int found = 0;
- unsigned int i;
- gss_OID_set mech_set;
- gss_OID tmp_oid;
-
- ctx = GSS_C_NO_CONTEXT;
- mech_oid = &krb5_oid_desc;
-
- // see whether we can use the SPNEGO mechanism
- major_status = gss_indicate_mechs(&minor_status, &mech_set);
- if (GSS_ERROR(major_status)) {
- kdDebug(7113) << "(" << m_pid << ") gss_indicate_mechs failed: " << gssError(major_status, minor_status) << endl;
- } else {
- for (i=0; i<mech_set->count && !found; i++) {
- tmp_oid = &mech_set->elements[i];
- if (tmp_oid->length == spnego_oid_desc.length &&
- !memcmp(tmp_oid->elements, spnego_oid_desc.elements, tmp_oid->length)) {
- kdDebug(7113) << "(" << m_pid << ") createNegotiateAuth: found SPNEGO mech" << endl;
- found = 1;
- mech_oid = &spnego_oid_desc;
- break;
- }
- }
- gss_release_oid_set(&minor_status, &mech_set);
- }
-
- // the service name is "HTTP/f.q.d.n"
- servicename = "HTTP@";
- servicename += m_state.hostname.ascii();
-
- input_token.value = (void *)servicename.data();
- input_token.length = servicename.length() + 1;
-
- major_status = gss_import_name(&minor_status, &input_token,
- GSS_C_NT_HOSTBASED_SERVICE, &server);
-
- input_token.value = NULL;
- input_token.length = 0;
-
- if (GSS_ERROR(major_status)) {
- kdDebug(7113) << "(" << m_pid << ") gss_import_name failed: " << gssError(major_status, minor_status) << endl;
- // reset the auth string so that subsequent methods aren't confused
- m_strAuthorization = TQString::null;
- return TQString::null;
- }
-
- major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
- &ctx, server, mech_oid,
- req_flags, GSS_C_INDEFINITE,
- GSS_C_NO_CHANNEL_BINDINGS,
- GSS_C_NO_BUFFER, NULL, &output_token,
- NULL, NULL);
-
-
- if (GSS_ERROR(major_status) || (output_token.length == 0)) {
- kdDebug(7113) << "(" << m_pid << ") gss_init_sec_context failed: " << gssError(major_status, minor_status) << endl;
- gss_release_name(&minor_status, &server);
- if (ctx != GSS_C_NO_CONTEXT) {
- gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER);
- ctx = GSS_C_NO_CONTEXT;
- }
- // reset the auth string so that subsequent methods aren't confused
- m_strAuthorization = TQString::null;
- return TQString::null;
- }
-
- input.duplicate((const char *)output_token.value, output_token.length);
- auth = "Authorization: Negotiate ";
- auth += KCodecs::base64Encode( input );
- auth += "\r\n";
-
- // free everything
- gss_release_name(&minor_status, &server);
- if (ctx != GSS_C_NO_CONTEXT) {
- gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER);
- ctx = GSS_C_NO_CONTEXT;
- }
- gss_release_buffer(&minor_status, &output_token);
-
- return auth;
-}
-#else
-
-// Dummy
-TQCString HTTPProtocol::gssError( int, int )
-{
- return "";
-}
-
-// Dummy
-TQString HTTPProtocol::createNegotiateAuth()
-{
- return TQString::null;
-}
-#endif
-
-TQString HTTPProtocol::createNTLMAuth( bool isForProxy )
-{
- uint len;
- TQString auth, user, domain, passwd;
- TQCString strauth;
- TQByteArray buf;
-
- if ( isForProxy )
- {
- auth = "Proxy-Connection: Keep-Alive\r\n";
- auth += "Proxy-Authorization: NTLM ";
- user = m_proxyURL.user();
- passwd = m_proxyURL.pass();
- strauth = m_strProxyAuthorization.latin1();
- len = m_strProxyAuthorization.length();
- }
- else
- {
- auth = "Authorization: NTLM ";
- user = m_state.user;
- passwd = m_state.passwd;
- strauth = m_strAuthorization.latin1();
- len = m_strAuthorization.length();
- }
- if ( user.contains('\\') ) {
- domain = user.section( '\\', 0, 0);
- user = user.section( '\\', 1 );
- }
-
- kdDebug(7113) << "(" << m_pid << ") NTLM length: " << len << endl;
- if ( user.isEmpty() || passwd.isEmpty() || len < 4 )
- return TQString::null;
-
- if ( len > 4 )
- {
- // create a response
- TQByteArray challenge;
- KCodecs::base64Decode( strauth.right( len - 5 ), challenge );
- KNTLM::getAuth( buf, challenge, user, passwd, domain,
- KNetwork::KResolver::localHostName(), false, false );
- }
- else
- {
- KNTLM::getNegotiate( buf );
- }
-
- // remove the challenge to prevent reuse
- if ( isForProxy )
- m_strProxyAuthorization = "NTLM";
- else
- m_strAuthorization = "NTLM";
-
- auth += KCodecs::base64Encode( buf );
- auth += "\r\n";
-
- return auth;
-}
-
-TQString HTTPProtocol::createBasicAuth( bool isForProxy )
-{
- TQString auth;
- TQCString user, passwd;
- if ( isForProxy )
- {
- auth = "Proxy-Authorization: Basic ";
- user = m_proxyURL.user().latin1();
- passwd = m_proxyURL.pass().latin1();
- }
- else
- {
- auth = "Authorization: Basic ";
- user = m_state.user.latin1();
- passwd = m_state.passwd.latin1();
- }
-
- if ( user.isEmpty() )
- user = "";
- if ( passwd.isEmpty() )
- passwd = "";
-
- user += ':';
- user += passwd;
- auth += KCodecs::base64Encode( user );
- auth += "\r\n";
-
- return auth;
-}
-
-void HTTPProtocol::calculateResponse( DigestAuthInfo& info, TQCString& Response )
-{
- KMD5 md;
- TQCString HA1;
- TQCString HA2;
-
- // Calculate H(A1)
- TQCString authStr = info.username;
- authStr += ':';
- authStr += info.realm;
- authStr += ':';
- authStr += info.password;
- md.update( authStr );
-
- if ( info.algorithm.lower() == "md5-sess" )
- {
- authStr = md.hexDigest();
- authStr += ':';
- authStr += info.nonce;
- authStr += ':';
- authStr += info.cnonce;
- md.reset();
- md.update( authStr );
- }
- HA1 = md.hexDigest();
-
- kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A1 => " << HA1 << endl;
-
- // Calcualte H(A2)
- authStr = info.method;
- authStr += ':';
- authStr += m_request.url.encodedPathAndQuery(0, true).latin1();
- if ( info.qop == "auth-int" )
- {
- authStr += ':';
- authStr += info.entityBody;
- }
- md.reset();
- md.update( authStr );
- HA2 = md.hexDigest();
-
- kdDebug(7113) << "(" << m_pid << ") calculateResponse(): A2 => "
- << HA2 << endl;
-
- // Calcualte the response.
- authStr = HA1;
- authStr += ':';
- authStr += info.nonce;
- authStr += ':';
- if ( !info.qop.isEmpty() )
- {
- authStr += info.nc;
- authStr += ':';
- authStr += info.cnonce;
- authStr += ':';
- authStr += info.qop;
- authStr += ':';
- }
- authStr += HA2;
- md.reset();
- md.update( authStr );
- Response = md.hexDigest();
-
- kdDebug(7113) << "(" << m_pid << ") calculateResponse(): Response => "
- << Response << endl;
-}
-
-TQString HTTPProtocol::createDigestAuth ( bool isForProxy )
-{
- const char *p;
-
- TQString auth;
- TQCString opaque;
- TQCString Response;
-
- DigestAuthInfo info;
-
- opaque = "";
- if ( isForProxy )
- {
- auth = "Proxy-Authorization: Digest ";
- info.username = m_proxyURL.user().latin1();
- info.password = m_proxyURL.pass().latin1();
- p = m_strProxyAuthorization.latin1();
- }
- else
- {
- auth = "Authorization: Digest ";
- info.username = m_state.user.latin1();
- info.password = m_state.passwd.latin1();
- p = m_strAuthorization.latin1();
- }
- if (!p || !*p)
- return TQString::null;
-
- p += 6; // Skip "Digest"
-
- if ( info.username.isEmpty() || info.password.isEmpty() || !p )
- return TQString::null;
-
- // info.entityBody = p; // FIXME: send digest of data for POST action ??
- info.realm = "";
- info.algorithm = "MD5";
- info.nonce = "";
- info.qop = "";
-
- // cnonce is recommended to contain about 64 bits of entropy
- info.cnonce = KApplication::randomString(16).latin1();
-
- // HACK: Should be fixed according to RFC 2617 section 3.2.2
- info.nc = "00000001";
-
- // Set the method used...
- switch ( m_request.method )
- {
- case HTTP_GET:
- info.method = "GET";
- break;
- case HTTP_PUT:
- info.method = "PUT";
- break;
- case HTTP_POST:
- info.method = "POST";
- break;
- case HTTP_HEAD:
- info.method = "HEAD";
- break;
- case HTTP_DELETE:
- info.method = "DELETE";
- break;
- case DAV_PROPFIND:
- info.method = "PROPFIND";
- break;
- case DAV_PROPPATCH:
- info.method = "PROPPATCH";
- break;
- case DAV_MKCOL:
- info.method = "MKCOL";
- break;
- case DAV_COPY:
- info.method = "COPY";
- break;
- case DAV_MOVE:
- info.method = "MOVE";
- break;
- case DAV_LOCK:
- info.method = "LOCK";
- break;
- case DAV_UNLOCK:
- info.method = "UNLOCK";
- break;
- case DAV_SEARCH:
- info.method = "SEARCH";
- break;
- case DAV_SUBSCRIBE:
- info.method = "SUBSCRIBE";
- break;
- case DAV_UNSUBSCRIBE:
- info.method = "UNSUBSCRIBE";
- break;
- case DAV_POLL:
- info.method = "POLL";
- break;
- default:
- error( ERR_UNSUPPORTED_ACTION, i18n("Unsupported method: authentication will fail. Please submit a bug report."));
- break;
- }
-
- // Parse the Digest response....
- while (*p)
- {
- int i = 0;
- while ( (*p == ' ') || (*p == ',') || (*p == '\t')) { p++; }
- if (strncasecmp(p, "realm=", 6 )==0)
- {
- p+=6;
- while ( *p == '"' ) p++; // Go past any number of " mark(s) first
- while ( p[i] != '"' ) i++; // Read everything until the last " mark
- info.realm = TQCString( p, i+1 );
- }
- else if (strncasecmp(p, "algorith=", 9)==0)
- {
- p+=9;
- while ( *p == '"' ) p++; // Go past any number of " mark(s) first
- while ( ( p[i] != '"' ) && ( p[i] != ',' ) && ( p[i] != '\0' ) ) i++;
- info.algorithm = TQCString(p, i+1);
- }
- else if (strncasecmp(p, "algorithm=", 10)==0)
- {
- p+=10;
- while ( *p == '"' ) p++; // Go past any " mark(s) first
- while ( ( p[i] != '"' ) && ( p[i] != ',' ) && ( p[i] != '\0' ) ) i++;
- info.algorithm = TQCString(p,i+1);
- }
- else if (strncasecmp(p, "domain=", 7)==0)
- {
- p+=7;
- while ( *p == '"' ) p++; // Go past any " mark(s) first
- while ( p[i] != '"' ) i++; // Read everything until the last " mark
- int pos;
- int idx = 0;
- TQCString uri = TQCString(p,i+1);
- do
- {
- pos = uri.find( ' ', idx );
- if ( pos != -1 )
- {
- KURL u (m_request.url, uri.mid(idx, pos-idx));
- if (u.isValid ())
- info.digestURI.append( u.url().latin1() );
- }
- else
- {
- KURL u (m_request.url, uri.mid(idx, uri.length()-idx));
- if (u.isValid ())
- info.digestURI.append( u.url().latin1() );
- }
- idx = pos+1;
- } while ( pos != -1 );
- }
- else if (strncasecmp(p, "nonce=", 6)==0)
- {
- p+=6;
- while ( *p == '"' ) p++; // Go past any " mark(s) first
- while ( p[i] != '"' ) i++; // Read everything until the last " mark
- info.nonce = TQCString(p,i+1);
- }
- else if (strncasecmp(p, "opaque=", 7)==0)
- {
- p+=7;
- while ( *p == '"' ) p++; // Go past any " mark(s) first
- while ( p[i] != '"' ) i++; // Read everything until the last " mark
- opaque = TQCString(p,i+1);
- }
- else if (strncasecmp(p, "qop=", 4)==0)
- {
- p+=4;
- while ( *p == '"' ) p++; // Go past any " mark(s) first
- while ( p[i] != '"' ) i++; // Read everything until the last " mark
- info.qop = TQCString(p,i+1);
- }
- p+=(i+1);
- }
-
- if (info.realm.isEmpty() || info.nonce.isEmpty())
- return TQString::null;
-
- // If the "domain" attribute was not specified and the current response code
- // is authentication needed, add the current request url to the list over which
- // this credential can be automatically applied.
- if (info.digestURI.isEmpty() && (m_responseCode == 401 || m_responseCode == 407))
- info.digestURI.append (m_request.url.url().latin1());
- else
- {
- // Verify whether or not we should send a cached credential to the
- // server based on the stored "domain" attribute...
- bool send = true;
-
- // Determine the path of the request url...
- TQString requestPath = m_request.url.directory(false, false);
- if (requestPath.isEmpty())
- requestPath = "/";
-
- int count = info.digestURI.count();
-
- for (int i = 0; i < count; i++ )
- {
- KURL u ( info.digestURI.at(i) );
-
- send &= (m_request.url.protocol().lower() == u.protocol().lower());
- send &= (m_request.hostname.lower() == u.host().lower());
-
- if (m_request.port > 0 && u.port() > 0)
- send &= (m_request.port == u.port());
-
- TQString digestPath = u.directory (false, false);
- if (digestPath.isEmpty())
- digestPath = "/";
-
- send &= (requestPath.startsWith(digestPath));
-
- if (send)
- break;
- }
-
- kdDebug(7113) << "(" << m_pid << ") createDigestAuth(): passed digest "
- "authentication credential test: " << send << endl;
-
- if (!send)
- return TQString::null;
- }
-
- kdDebug(7113) << "(" << m_pid << ") RESULT OF PARSING:" << endl;
- kdDebug(7113) << "(" << m_pid << ") algorithm: " << info.algorithm << endl;
- kdDebug(7113) << "(" << m_pid << ") realm: " << info.realm << endl;
- kdDebug(7113) << "(" << m_pid << ") nonce: " << info.nonce << endl;
- kdDebug(7113) << "(" << m_pid << ") opaque: " << opaque << endl;
- kdDebug(7113) << "(" << m_pid << ") qop: " << info.qop << endl;
-
- // Calculate the response...
- calculateResponse( info, Response );
-
- auth += "username=\"";
- auth += info.username;
-
- auth += "\", realm=\"";
- auth += info.realm;
- auth += "\"";
-
- auth += ", nonce=\"";
- auth += info.nonce;
-
- auth += "\", uri=\"";
- auth += m_request.url.encodedPathAndQuery(0, true);
-
- auth += "\", algorithm=\"";
- auth += info.algorithm;
- auth +="\"";
-
- if ( !info.qop.isEmpty() )
- {
- auth += ", qop=\"";
- auth += info.qop;
- auth += "\", cnonce=\"";
- auth += info.cnonce;
- auth += "\", nc=";
- auth += info.nc;
- }
-
- auth += ", response=\"";
- auth += Response;
- if ( !opaque.isEmpty() )
- {
- auth += "\", opaque=\"";
- auth += opaque;
- }
- auth += "\"\r\n";
-
- return auth;
-}
-
-TQString HTTPProtocol::proxyAuthenticationHeader()
-{
- TQString header;
-
- // We keep proxy authentication locally until they are changed.
- // Thus, no need to check with the password manager for every
- // connection.
- if ( m_strProxyRealm.isEmpty() )
- {
- AuthInfo info;
- info.url = m_proxyURL;
- info.username = m_proxyURL.user();
- info.password = m_proxyURL.pass();
- info.verifyPath = true;
-
- // If the proxy URL already contains username
- // and password simply attempt to retrieve it
- // without prompting the user...
- if ( !info.username.isNull() && !info.password.isNull() )
- {
- if( m_strProxyAuthorization.isEmpty() )
- ProxyAuthentication = AUTH_None;
- else if( m_strProxyAuthorization.startsWith("Basic") )
- ProxyAuthentication = AUTH_Basic;
- else if( m_strProxyAuthorization.startsWith("NTLM") )
- ProxyAuthentication = AUTH_NTLM;
- else
- ProxyAuthentication = AUTH_Digest;
- }
- else
- {
- if ( checkCachedAuthentication(info) && !info.digestInfo.isEmpty() )
- {
- m_proxyURL.setUser( info.username );
- m_proxyURL.setPass( info.password );
- m_strProxyRealm = info.realmValue;
- m_strProxyAuthorization = info.digestInfo;
- if( m_strProxyAuthorization.startsWith("Basic") )
- ProxyAuthentication = AUTH_Basic;
- else if( m_strProxyAuthorization.startsWith("NTLM") )
- ProxyAuthentication = AUTH_NTLM;
- else
- ProxyAuthentication = AUTH_Digest;
- }
- else
- {
- ProxyAuthentication = AUTH_None;
- }
- }
- }
-
- /********* Only for debugging purpose... *********/
- if ( ProxyAuthentication != AUTH_None )
- {
- kdDebug(7113) << "(" << m_pid << ") Using Proxy Authentication: " << endl;
- kdDebug(7113) << "(" << m_pid << ") HOST= " << m_proxyURL.host() << endl;
- kdDebug(7113) << "(" << m_pid << ") PORT= " << m_proxyURL.port() << endl;
- kdDebug(7113) << "(" << m_pid << ") USER= " << m_proxyURL.user() << endl;
- kdDebug(7113) << "(" << m_pid << ") PASSWORD= [protected]" << endl;
- kdDebug(7113) << "(" << m_pid << ") REALM= " << m_strProxyRealm << endl;
- kdDebug(7113) << "(" << m_pid << ") EXTRA= " << m_strProxyAuthorization << endl;
- }
-
- switch ( ProxyAuthentication )
- {
- case AUTH_Basic:
- header += createBasicAuth( true );
- break;
- case AUTH_Digest:
- header += createDigestAuth( true );
- break;
- case AUTH_NTLM:
- if ( m_bFirstRequest ) header += createNTLMAuth( true );
- break;
- case AUTH_None:
- default:
- break;
- }
-
- return header;
-}
-
-#include "http.moc"
diff --git a/kioslave/http/http.h b/kioslave/http/http.h
deleted file mode 100644
index 2985eb938..000000000
--- a/kioslave/http/http.h
+++ /dev/null
@@ -1,577 +0,0 @@
-/*
- Copyright (C) 2000,2001 Dawit Alemayehu <adawit@kde.org>
- Copyright (C) 2000,2001 Waldo Bastian <bastian@kde.org>
- Copyright (C) 2000,2001 George Staikos <staikos@kde.org>
- Copyright (C) 2001,2002 Hamish Rodda <rodda@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 HTTP_H_
-#define HTTP_H_
-
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <stdio.h>
-#include <time.h>
-
-#include <tqptrlist.h>
-#include <tqstrlist.h>
-#include <tqstringlist.h>
-
-#include <kurl.h>
-#include "kio/tcpslavebase.h"
-#include "kio/http.h"
-
-class DCOPClient;
-class TQDomElement;
-class TQDomNodeList;
-
-namespace KIO {
- class AuthInfo;
-}
-
-class HTTPProtocol : public TQObject, public KIO::TCPSlaveBase
-{
- Q_OBJECT
-public:
- HTTPProtocol( const TQCString &protocol, const TQCString &pool,
- const TQCString &app );
- virtual ~HTTPProtocol();
-
- /** HTTP version **/
- enum HTTP_REV {HTTP_None, HTTP_Unknown, HTTP_10, HTTP_11, SHOUTCAST};
-
- /** Authorization method used **/
- enum HTTP_AUTH {AUTH_None, AUTH_Basic, AUTH_NTLM, AUTH_Digest, AUTH_Negotiate};
-
- /** HTTP / DAV method **/
- // Removed to interfaces/kio/http.h
- //enum HTTP_METHOD {HTTP_GET, HTTP_PUT, HTTP_POST, HTTP_HEAD, HTTP_DELETE,
- // HTTP_OPTIONS, DAV_PROPFIND, DAV_PROPPATCH, DAV_MKCOL,
- // DAV_COPY, DAV_MOVE, DAV_LOCK, DAV_UNLOCK, DAV_SEARCH };
-
- /** State of the current Connection **/
- struct HTTPState
- {
- HTTPState ()
- {
- port = 0;
- doProxy = false;
- }
-
- TQString hostname;
- TQString encoded_hostname;
- short unsigned int port;
- TQString user;
- TQString passwd;
- bool doProxy;
- };
-
- /** DAV-specific request elements for the current connection **/
- struct DAVRequest
- {
- DAVRequest ()
- {
- overwrite = false;
- depth = 0;
- }
-
- TQString desturl;
- bool overwrite;
- int depth;
- };
-
- /** The request for the current connection **/
- struct HTTPRequest
- {
- HTTPRequest ()
- {
- port = 0;
- method = KIO::HTTP_UNKNOWN;
- offset = 0;
- doProxy = false;
- allowCompressedPage = false;
- disablePassDlg = false;
- bNoAuth = false;
- bUseCache = false;
- bCachedRead = false;
- bCachedWrite = false;
- fcache = 0;
- bMustRevalidate = false;
- cacheExpireDateOffset = 0;
- bErrorPage = false;
- bUseCookiejar = false;
- expireDate = 0;
- creationDate = 0;
- }
-
- TQString hostname;
- TQString encoded_hostname;
- short unsigned int port;
- TQString user;
- TQString passwd;
- TQString path;
- TQString query;
- KIO::HTTP_METHOD method;
- KIO::CacheControl cache;
- KIO::filesize_t offset;
- bool doProxy;
- KURL url;
- TQString window; // Window Id this request is related to.
- TQString referrer;
- TQString charsets;
- TQString languages;
- bool allowCompressedPage;
- bool disablePassDlg;
- TQString userAgent;
- TQString id;
- DAVRequest davData;
-
- bool bNoAuth; // Do not authenticate
-
- // Cache related
- TQString cef; // Cache Entry File belonging to this URL.
- bool bUseCache; // Whether the cache is active
- bool bCachedRead; // Whether the file is to be read from m_fcache.
- bool bCachedWrite; // Whether the file is to be written to m_fcache.
- FILE* fcache; // File stream of a cache entry
- TQString etag; // ETag header.
- TQString lastModified; // Last modified.
- bool bMustRevalidate; // Cache entry is expired.
- long cacheExpireDateOffset; // Position in the cache entry where the
- // 16 byte expire date is stored.
- time_t expireDate; // Date when the cache entry will expire
- time_t creationDate; // Date when the cache entry was created
- TQString strCharset; // Charset
-
- // Indicates whether an error-page or error-msg should is preferred.
- bool bErrorPage;
-
- // Cookie flags
- bool bUseCookiejar;
- enum { CookiesAuto, CookiesManual, CookiesNone } cookieMode;
- };
-
- struct DigestAuthInfo
- {
- TQCString nc;
- TQCString qop;
- TQCString realm;
- TQCString nonce;
- TQCString method;
- TQCString cnonce;
- TQCString username;
- TQCString password;
- TQStrList digestURI;
- TQCString algorithm;
- TQCString entityBody;
- };
-
-//---------------------- Re-implemented methods ----------------
- virtual void setHost(const TQString& host, int port, const TQString& user,
- const TQString& pass);
-
- virtual void slave_status();
-
- virtual void get( const KURL& url );
- virtual void put( const KURL& url, int permissions, bool overwrite,
- bool resume );
-
-//----------------- Re-implemented methods for WebDAV -----------
- virtual void listDir( const KURL& url );
- virtual void mkdir( const KURL& url, int permissions );
-
- virtual void rename( const KURL& src, const KURL& dest, bool overwrite );
- virtual void copy( const KURL& src, const KURL& dest, int permissions, bool overwrite );
- virtual void del( const KURL& url, bool isfile );
-
- // ask the host whether it supports WebDAV & cache this info
- bool davHostOk();
-
- // send generic DAV request
- void davGeneric( const KURL& url, KIO::HTTP_METHOD method );
-
- // Send requests to lock and unlock resources
- void davLock( const KURL& url, const TQString& scope,
- const TQString& type, const TQString& owner );
- void davUnlock( const KURL& url );
-
- // Calls httpClose() and finished()
- void davFinished();
-
- // Handle error conditions
- TQString davError( int code = -1, TQString url = TQString::null );
-//---------------------------- End WebDAV -----------------------
-
- /**
- * Special commands supported by this slave :
- * 1 - HTTP POST
- * 2 - Cache has been updated
- * 3 - SSL Certificate Cache has been updated
- * 4 - HTTP multi get
- * 5 - DAV LOCK (see
- * 6 - DAV UNLOCK README.webdav)
- */
- virtual void special( const TQByteArray &data );
-
- virtual void mimetype( const KURL& url);
-
- virtual void stat( const KURL& url );
-
- virtual void reparseConfiguration();
-
- virtual void closeConnection(); // Forced close of connection
-
- void post( const KURL& url );
- void multiGet(const TQByteArray &data);
- bool checkRequestURL( const KURL& );
- void cacheUpdate( const KURL &url, bool nocache, time_t expireDate);
-
- void httpError(); // Generate error message based on response code
-
- bool isOffline(const KURL &url); // Check network status
-
-protected slots:
- void slotData(const TQByteArray &);
- void error( int _errid, const TQString &_text );
-
-protected:
- int readChunked(); // Read a chunk
- int readLimited(); // Read maximum m_iSize bytes.
- int readUnlimited(); // Read as much as possible.
-
- /**
- * A "smart" wrapper around write that will use SSL_write or
- * write(2) depending on whether you've got an SSL connection or not.
- * The only shortcomming is that it uses the "global" file handles and
- * soforth. So you can't really use this on individual files/sockets.
- */
- ssize_t write(const void *buf, size_t nbytes);
-
- /**
- * Another "smart" wrapper, this time around read that will
- * use SSL_read or read(2) depending on whether you've got an
- * SSL connection or not.
- */
- ssize_t read (void *b, size_t nbytes);
-
- char *gets (char *str, int size);
-
- void setRewindMarker();
- void rewind();
-
- /**
- * Add an encoding on to the appropriate stack this
- * is nececesary because transfer encodings and
- * content encodings must be handled separately.
- */
- void addEncoding(TQString, TQStringList &);
-
- void configAuth( char *, bool );
-
- bool httpOpen(); // Open transfer
- void httpClose(bool keepAlive); // Close transfer
-
- bool httpOpenConnection(); // Open connection
- void httpCloseConnection(); // Close connection
- void httpCheckConnection(); // Check whether to keep connection.
-
- void forwardHttpResponseHeader();
-
- bool readHeader();
-
- bool sendBody();
-
- // where dataInternal == true, the content is to be made available
- // to an internal function.
- bool readBody( bool dataInternal = false );
-
- /**
- * Performs a WebDAV stat or list
- */
- void davSetRequest( const TQCString& requestXML );
- void davStatList( const KURL& url, bool stat = true );
- void davParsePropstats( const TQDomNodeList& propstats, KIO::UDSEntry& entry );
- void davParseActiveLocks( const TQDomNodeList& activeLocks,
- uint& lockCount );
-
- /**
- * Parses a date & time string
- */
- long parseDateTime( const TQString& input, const TQString& type );
-
- /**
- * Returns the error code from a "HTTP/1.1 code Code Name" string
- */
- int codeFromResponse( const TQString& response );
-
- /**
- * Extracts locks from metadata
- * Returns the appropriate If: header
- */
- TQString davProcessLocks();
-
- /**
- * Send a cookie to the cookiejar
- */
- void addCookies( const TQString &url, const TQCString &cookieHeader);
-
- /**
- * Look for cookies in the cookiejar
- */
- TQString findCookies( const TQString &url);
-
- /**
- * Do a cache lookup for the current url. (m_state.url)
- *
- * @param readWrite If true, file is opened read/write.
- * If false, file is opened read-only.
- *
- * @return a file stream open for reading and at the start of
- * the header section when the Cache entry exists and is valid.
- * 0 if no cache entry could be found, or if the entry is not
- * valid (any more).
- */
- FILE *checkCacheEntry(bool readWrite = false);
-
- /**
- * Create a cache entry for the current url. (m_state.url)
- *
- * Set the contents type of the cache entry to 'mimetype'.
- */
- void createCacheEntry(const TQString &mimetype, time_t expireDate);
-
- /**
- * Write data to cache.
- *
- * Write 'nbytes' from 'buffer' to the Cache Entry File
- */
- void writeCacheEntry( const char *buffer, int nbytes);
-
- /**
- * Close cache entry
- */
- void closeCacheEntry();
-
- /**
- * Update expire time of current cache entry.
- */
- void updateExpireDate(time_t expireDate, bool updateCreationDate=false);
-
- /**
- * Quick check whether the cache needs cleaning.
- */
- void cleanCache();
-
- /**
- * Performs a GET HTTP request.
- */
- // where dataInternal == true, the content is to be made available
- // to an internal function.
- void retrieveContent( bool dataInternal = false );
-
- /**
- * Performs a HEAD HTTP request.
- */
- bool retrieveHeader(bool close_connection = true);
-
- /**
- * Resets any per session settings.
- */
- void resetSessionSettings();
-
- /**
- * Resets settings related to parsing a response.
- */
- void resetResponseSettings();
-
- /**
- * Resets any per connection settings. These are different from
- * per-session settings in that they must be invalidates every time
- * a request is made, e.g. a retry to re-send the header to the
- * server, as compared to only when a new request arrives.
- */
- void resetConnectionSettings();
-
- /**
- * Returns any pre-cached proxy authentication info
- * info in HTTP header format.
- */
- TQString proxyAuthenticationHeader();
-
- /**
- * Retrieves authorization info from cache or user.
- */
- bool getAuthorization();
-
- /**
- * Saves valid authorization info in the cache daemon.
- */
- void saveAuthorization();
-
- /**
- * Creates the entity-header for Basic authentication.
- */
- TQString createBasicAuth( bool isForProxy = false );
-
- /**
- * Creates the entity-header for Digest authentication.
- */
- TQString createDigestAuth( bool isForProxy = false );
-
- /**
- * Creates the entity-header for NTLM authentication.
- */
- TQString createNTLMAuth( bool isForProxy = false );
-
- /**
- * Creates the entity-header for Negotiate authentication.
- */
- TQString createNegotiateAuth();
-
- /**
- * create GSS error string
- */
- TQCString gssError( int major_status, int minor_status );
-
- /**
- * Calcualtes the message digest response based on RFC 2617.
- */
- void calculateResponse( DigestAuthInfo &info, TQCString &Response );
-
- /**
- * Prompts the user for authorization retry.
- */
- bool retryPrompt();
-
- /**
- * Creates authorization prompt info.
- */
- void promptInfo( KIO::AuthInfo& info );
-
-protected:
- HTTPState m_state;
- HTTPRequest m_request;
- TQPtrList<HTTPRequest> m_requestQueue;
-
- bool m_bBusy; // Busy handling request queue.
- bool m_bEOF;
- bool m_bEOD;
-
-//--- Settings related to a single response only
- TQStringList m_responseHeader; // All headers
- KURL m_redirectLocation;
- bool m_bRedirect; // Indicates current request is a redirection
-
- // Processing related
- bool m_bChunked; // Chunked tranfer encoding
- KIO::filesize_t m_iSize; // Expected size of message
- KIO::filesize_t m_iBytesLeft; // # of bytes left to receive in this message.
- KIO::filesize_t m_iContentLeft; // # of content bytes left
- TQByteArray m_bufReceive; // Receive buffer
- bool m_dataInternal; // Data is for internal consumption
- char m_lineBuf[1024];
- char m_rewindBuf[8192];
- size_t m_rewindCount;
- char *m_linePtr;
- size_t m_lineCount;
- char *m_lineBufUnget;
- char *m_linePtrUnget;
- size_t m_lineCountUnget;
-
- // Mimetype determination
- bool m_cpMimeBuffer;
- TQByteArray m_mimeTypeBuffer;
-
- // Language/Encoding related
- TQStringList m_qTransferEncodings;
- TQStringList m_qContentEncodings;
- TQString m_sContentMD5;
- TQString m_strMimeType;
-
-
-//--- WebDAV
- // Data structure to hold data which will be passed to an internal func.
- TQByteArray m_bufWebDavData;
- TQStringList m_davCapabilities;
-
- bool m_davHostOk;
- bool m_davHostUnsupported;
-//----------
-
- // Holds the POST data so it won't get lost on if we
- // happend to get a 401/407 response when submitting,
- // a form.
- TQByteArray m_bufPOST;
-
- // Cache related
- int m_maxCacheAge; // Maximum age of a cache entry.
- long m_maxCacheSize; // Maximum cache size in Kb.
- TQString m_strCacheDir; // Location of the cache.
-
-
-
-//--- Proxy related members
- bool m_bUseProxy;
- bool m_bNeedTunnel; // Whether we need to make a SSL tunnel
- bool m_bIsTunneled; // Whether we have an active SSL tunnel
- bool m_bProxyAuthValid;
- int m_iProxyPort;
- KURL m_proxyURL;
- TQString m_strProxyRealm;
-
- // Operation mode
- TQCString m_protocol;
-
- // Authentication
- TQString m_strRealm;
- TQString m_strAuthorization;
- TQString m_strProxyAuthorization;
- HTTP_AUTH Authentication;
- HTTP_AUTH ProxyAuthentication;
- bool m_bUnauthorized;
- short unsigned int m_iProxyAuthCount;
- short unsigned int m_iWWWAuthCount;
-
- // First request on a connection
- bool m_bFirstRequest;
-
- // Persistent connections
- bool m_bKeepAlive;
- int m_keepAliveTimeout; // Timeout in seconds.
-
- // Persistent proxy connections
- bool m_bPersistentProxyConnection;
-
-
- // Indicates whether there was some connection error.
- bool m_bError;
-
- // Previous and current response codes
- unsigned int m_responseCode;
- unsigned int m_prevResponseCode;
-
- // Values that determine the remote connection timeouts.
- int m_proxyConnTimeout;
- int m_remoteConnTimeout;
- int m_remoteRespTimeout;
-
- int m_pid;
-};
-#endif
diff --git a/kioslave/http/http.protocol b/kioslave/http/http.protocol
deleted file mode 100644
index ea7b57869..000000000
--- a/kioslave/http/http.protocol
+++ /dev/null
@@ -1,12 +0,0 @@
-[Protocol]
-exec=kio_http
-protocol=http
-input=none
-output=filesystem
-reading=true
-defaultMimetype=application/octet-stream
-determineMimetypeFromExtension=false
-Icon=www
-maxInstances=3
-DocPath=kioslave/http.html
-Class=:internet
diff --git a/kioslave/http/http_cache_cleaner.cpp b/kioslave/http/http_cache_cleaner.cpp
deleted file mode 100644
index fcf58b683..000000000
--- a/kioslave/http/http_cache_cleaner.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
-This file is part of KDE
-
- Copyright (C) 1999-2000 Waldo Bastian (bastian@kde.org)
-
-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, 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.
-*/
-//----------------------------------------------------------------------------
-//
-// KDE Http Cache cleanup tool
-// $Id$
-
-#include <time.h>
-#include <stdlib.h>
-
-#include <tqdir.h>
-#include <tqstring.h>
-#include <tqptrlist.h>
-
-#include <kinstance.h>
-#include <klocale.h>
-#include <kcmdlineargs.h>
-#include <kglobal.h>
-#include <kstandarddirs.h>
-#include <dcopclient.h>
-#include <kprotocolmanager.h>
-
-#include <unistd.h>
-
-#include <kdebug.h>
-
-time_t currentDate;
-int m_maxCacheAge;
-int m_maxCacheSize;
-
-static const char appName[] = "kio_http_cache_cleaner";
-
-static const char description[] = I18N_NOOP("TDE HTTP cache maintenance tool");
-
-static const char version[] = "1.0.0";
-
-static const KCmdLineOptions options[] =
-{
- {"clear-all", I18N_NOOP("Empty the cache"), 0},
- KCmdLineLastOption
-};
-
-struct FileInfo {
- TQString name;
- int size; // Size in Kb.
- int age;
-};
-
-template class TQPtrList<FileInfo>;
-
-class FileInfoList : public TQPtrList<FileInfo>
-{
-public:
- FileInfoList() : TQPtrList<FileInfo>() { }
- int compareItems(TQPtrCollection::Item item1, TQPtrCollection::Item item2)
- { return ((FileInfo *)item1)->age - ((FileInfo *)item2)->age; }
-};
-
-// !START OF SYNC!
-// Keep the following in sync with the cache code in http.cc
-#define CACHE_REVISION "7\n"
-
-FileInfo *readEntry( const TQString &filename)
-{
- TQCString CEF = TQFile::encodeName(filename);
- FILE *fs = fopen( CEF.data(), "r");
- if (!fs)
- return 0;
-
- char buffer[401];
- bool ok = true;
-
- // CacheRevision
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok && (strcmp(buffer, CACHE_REVISION) != 0))
- ok = false;
-
- // Full URL
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
-
- time_t creationDate;
- int age =0;
-
- // Creation Date
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
- creationDate = (time_t) strtoul(buffer, 0, 10);
- age = (int) difftime(currentDate, creationDate);
- if ( m_maxCacheAge && ( age > m_maxCacheAge))
- {
- ok = false; // Expired
- }
- }
-
- // Expiration Date
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
-//WABA: It seems I slightly misunderstood the meaning of "Expire:" header.
-#if 0
- time_t expireDate;
- expireDate = (time_t) strtoul(buffer, 0, 10);
- if (expireDate && (expireDate < currentDate))
- ok = false; // Expired
-#endif
- }
-
- // ETag
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
- // Ignore ETag
- }
-
- // Last-Modified
- if (ok && (!fgets(buffer, 400, fs)))
- ok = false;
- if (ok)
- {
- // Ignore Last-Modified
- }
-
-
- fclose(fs);
- if (ok)
- {
- FileInfo *info = new FileInfo;
- info->age = age;
- return info;
- }
-
- unlink( CEF.data());
- return 0;
-}
-// Keep the above in sync with the cache code in http.cc
-// !END OF SYNC!
-
-void scanDirectory(FileInfoList &fileEntries, const TQString &name, const TQString &strDir)
-{
- TQDir dir(strDir);
- if (!dir.exists()) return;
-
- TQFileInfoList *newEntries = (TQFileInfoList *) dir.entryInfoList();
-
- if (!newEntries) return; // Directory not accessible ??
-
- for(TQFileInfo *qFileInfo = newEntries->first();
- qFileInfo;
- qFileInfo = newEntries->next())
- {
- if (qFileInfo->isFile())
- {
- FileInfo *fileInfo = readEntry( strDir + "/" + qFileInfo->fileName());
- if (fileInfo)
- {
- fileInfo->name = name + "/" + qFileInfo->fileName();
- fileInfo->size = (qFileInfo->size() + 1023) / 1024;
- fileEntries.append(fileInfo);
- }
- }
- }
-}
-
-extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
-{
- KLocale::setMainCatalogue("tdelibs");
- KCmdLineArgs::init( argc, argv, appName,
- I18N_NOOP("TDE HTTP cache maintenance tool"),
- description, version, true);
-
- KCmdLineArgs::addCmdLineOptions( options );
-
- KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
-
- bool deleteAll = args->isSet("clear-all");
-
- KInstance ins( appName );
-
- if (!deleteAll)
- {
- DCOPClient *dcop = new DCOPClient();
- TQCString name = dcop->registerAs(appName, false);
- if (!name.isEmpty() && (name != appName))
- {
- fprintf(stderr, "%s: Already running! (%s)\n", appName, name.data());
- return 0;
- }
- }
-
- currentDate = time(0);
- m_maxCacheAge = KProtocolManager::maxCacheAge();
- m_maxCacheSize = KProtocolManager::maxCacheSize();
-
- if (deleteAll)
- m_maxCacheSize = -1;
-
- TQString strCacheDir = KGlobal::dirs()->saveLocation("cache", "http");
-
- TQDir cacheDir( strCacheDir );
- if (!cacheDir.exists())
- {
- fprintf(stderr, "%s: '%s' does not exist.\n", appName, strCacheDir.ascii());
- return 0;
- }
-
- TQStringList dirs = cacheDir.entryList( );
-
- FileInfoList cachedEntries;
-
- for(TQStringList::Iterator it = dirs.begin();
- it != dirs.end();
- it++)
- {
- if ((*it)[0] != '.')
- {
- scanDirectory( cachedEntries, *it, strCacheDir + "/" + *it);
- }
- }
-
- cachedEntries.sort();
-
- int maxCachedSize = m_maxCacheSize / 2;
-
- for(FileInfo *fileInfo = cachedEntries.first();
- fileInfo;
- fileInfo = cachedEntries.next())
- {
- if (fileInfo->size > maxCachedSize)
- {
- TQCString filename = TQFile::encodeName( strCacheDir + "/" + fileInfo->name);
- unlink(filename.data());
-// kdDebug () << appName << ": Object too big, deleting '" << filename.data() << "' (" << result<< ")" << endl;
- }
- }
-
- int totalSize = 0;
-
- for(FileInfo *fileInfo = cachedEntries.first();
- fileInfo;
- fileInfo = cachedEntries.next())
- {
- if ((totalSize + fileInfo->size) > m_maxCacheSize)
- {
- TQCString filename = TQFile::encodeName( strCacheDir + "/" + fileInfo->name);
- unlink(filename.data());
-// kdDebug () << appName << ": Cache too big, deleting '" << filename.data() << "' (" << fileInfo->size << ")" << endl;
- }
- else
- {
- totalSize += fileInfo->size;
-// fprintf(stderr, "Keep in cache: %s %d %d total = %d\n", fileInfo->name.ascii(), fileInfo->size, fileInfo->age, totalSize);
- }
- }
- kdDebug () << appName << ": Current size of cache = " << totalSize << " kB." << endl;
- return 0;
-}
-
-
diff --git a/kioslave/http/http_cache_cleaner.desktop b/kioslave/http/http_cache_cleaner.desktop
deleted file mode 100644
index 33cebb731..000000000
--- a/kioslave/http/http_cache_cleaner.desktop
+++ /dev/null
@@ -1,168 +0,0 @@
-[Desktop Entry]
-Type=Service
-Name=HTTP Cache Cleaner
-Name[af]=Http Kas Skoonmaker
-Name[ar]=مزيل كاش HTTP
-Name[az]=HTTP Ön Yaddaş Təmizləyici
-Name[be]=ÐчыÑтка кÑшу HTTP
-Name[bg]=ИзчиÑтване на кеш-паметта на HTTP
-Name[bn]=à¦à¦‡à¦š-টি-টি-পি কà§à¦¯à¦¾à¦¶ কà§à¦²à§€à¦¨à¦¾à¦°
-Name[br]=Naeter Krubuilh HTTP
-Name[bs]=ÄŒistaÄ HTTP cache-a
-Name[ca]=Neteja la memòria cau del HTTP
-Name[cs]=Nástroj pro vyprázdnění cache protokolu HTTP
-Name[csb]=Czëszczenié cache HTTP
-Name[cy]=Glanhauwr Storfa HTTP
-Name[da]=HTTP-cache-rydder
-Name[de]=Aufräumprogramm für den HTTP-Zwischenspeicher
-Name[el]=ΚαθαÏιστής λανθάνουσας μνήμης HTTP
-Name[eo]=HTTP-Tenejpurigilo
-Name[es]=Limpiador del caché de HTTP
-Name[et]=HTTP vahemälu puhastaja
-Name[eu]=HTTP cache-garbitzailea
-Name[fa]=پاک‌کنندۀ نهانگاه قام
-Name[fi]=HTTP-välimuistin tyhjentäjä
-Name[fr]=Nettoyage du cache HTTP
-Name[fy]=HTTP Cache oprommer
-Name[ga]=Glantóir Taisce HTTP
-Name[gl]=Limpador da caché de HTTP
-Name[he]=מנקה מטמון ה־HTTP
-Name[hi]=HTTP कैश साफ करने वाला
-Name[hr]=Brisanje HTTP pohrane
-Name[hu]=HTTP gyorstártisztító
-Name[id]=Pembersih Cache HTTP
-Name[is]=Hreinsiforrit HTTP skyndiminnis
-Name[it]=Ripulitore della cache HTTP
-Name[ja]=HTTP キャッシュマãƒãƒ¼ã‚¸ãƒ£
-Name[ka]=HTTP ბუფერის გáƒáƒ¡áƒ£áƒ¤áƒ—áƒáƒ•áƒ”ბáƒ
-Name[kk]=HTTP бүркемеÑін боÑату
-Name[km]=កម្មវិធី​សម្អាážâ€‹ážƒáŸ’លាំង​សម្ងាážáŸ‹ HTTP
-Name[ko]=HTTP ìºì‹œ 정리
-Name[lb]=Opraumer fir den HTTP-Zwëschespäicher
-Name[lt]=HTTP krepšio ištuštintojas
-Name[lv]=HTTP KeÅ¡atmiņas tÄ«rÄ«tÄjs
-Name[mk]=Бришење на HTTP-кешот
-Name[mn]=HTTP-завÑрын хадгалагчийн цÑвÑрлÑгÑÑ
-Name[ms]=Pembersih Penyimpan HTTP
-Name[mt]=Tindif tal-cache HTTP
-Name[nb]=HTTP Mellomlagerrenser
-Name[nds]=Reenmaker för HTTP-Twischenspieker
-Name[ne]=HTTP कà¥à¤¯à¤¾à¤¸ कà¥à¤²à¥€à¤¨à¤°
-Name[nl]=HTTP Cache opschonen
-Name[nn]=HTTP-mellomlageropprensking
-Name[nso]=Sehlwekisi sa Polokelo ya HTTP
-Name[oc]=Netejador de cabia HTTP
-Name[pa]=HTTP ਕੈਂਚੇ ਸਾਫ਼
-Name[pl]=Czyszczenie bufora HTTP
-Name[pt]=Limpeza da Cache de HTTP
-Name[pt_BR]=Limpador de cache HTTP
-Name[ro]=Curăţător cache HTTP
-Name[ru]=ОчиÑтка кÑша HTTP
-Name[rw]=Musukura Ubwihisho HTTP
-Name[se]=HTTP gaskarádjosa buhtisteaddji
-Name[sk]=ÄŒistiÄ vyrovnávacej pamäti HTTP
-Name[sl]=ÄŒistilnik predpomnilnika HTTP
-Name[sq]=Pastrues për Depon e Fshehtësitëve të HTTP
-Name[sr]=ЧиÑтач HTTP кеша
-Name[sr@Latn]=ÄŒistaÄ HTTP keÅ¡a
-Name[sv]=HTTP-cacherensare
-Name[ta]=HTTP தறà¯à®•à®¾à®²à®¿à®• நினைவகதà¯à®¤à¯ˆ சà¯à®¤à¯à®¤à®®à¯ செயà¯à®¤à®²à¯
-Name[te]=హెచౠటిటిపి కోశం à°¶à±à°­à±à°°à°‚చేసేది
-Name[tg]=HTTP Софкунаки Махфӣ
-Name[th]=ตัวล้างà¹à¸„ช HTTP
-Name[tr]=HTTP Önbellek Temizleyici
-Name[tt]=HTTP Alxäteren Buşatqıç
-Name[uk]=Очищувач кешу HTTP
-Name[uz]=HTTP kesh boʻshatgich
-Name[uz@cyrillic]=HTTP кÑш бўшатгич
-Name[ven]=Tshikulumagi tsha HTTP Cache
-Name[vi]=Bộ làm sạch bộ nhớ tạm HTTP
-Name[xh]=Umcoci wendawo efihlakeleyo yokugcina we HTTP
-Name[zh_CN]=HTTP 缓存清除程åº
-Name[zh_HK]=HTTP å¿«å–清除程å¼
-Name[zh_TW]=HTTP å¿«å–清除程å¼
-Name[zu]=Umhlanzi we-Cache ye-HTTP
-Exec=kio_http_cache_cleaner
-Comment=Cleans up old entries from the HTTP cache
-Comment[af]=Skoonmaak begin ou inskrywings van die Http kas
-Comment[ar]=يزيل المداخل القديمة من كاش HTTP
-Comment[az]=HTTP ön yaddaşından köhnə girişləri silər
-Comment[be]=ВыдалÑе ÑÑ‚Ð°Ñ€Ñ‹Ñ Ð·Ð°Ð¿Ñ–ÑÑ‹ з кÑшу HTTP
-Comment[bg]=ИзчиÑтване на Ñтарите данни в кеш-паметта на HTTP
-Comment[bn]=HTTP কà§à¦¯à¦¾à¦¶ থেকে পà§à¦°à¦¨à§‹ তথà§à¦¯ মà§à¦›à§‡ ফেলে
-Comment[br]=Skarañ enmontoù kozh diwar ar grubuilh HTTP
-Comment[bs]=ÄŒisti stare datoteke iz HTTP cache-a
-Comment[ca]=Neteja les entrades antigues de la memòria cau del HTTP
-Comment[cs]=Odstraňuje staré položky z HTTP cache
-Comment[csb]=Rëmô stôré wpisënczi z cache HTTP
-Comment[cy]=Glanhau'r hen gofnodion o'r storfa HTTP
-Comment[da]=Rydder op i gamle indgange fra HTTP-cachen
-Comment[de]=Löscht alte Einträge aus dem HTTP-Zwischenspeicher
-Comment[el]=ΚαθαÏίζει παλιές καταχωÏήσεις από τη λανθάνουσα μνήμη HTTP
-Comment[eo]=Forigas malnovajn erojn el HTTP-tenejo
-Comment[es]=Elimina entradas antiguas del caché de HTTP
-Comment[et]=Puhastab HTTP vahemälu vanadest kirjetest
-Comment[eu]=HTTP cachearen sarrera zaharrak garbitzen ditu
-Comment[fa]=مدخلهای قدیمی را از نهانگاه قام پاک می‌کند
-Comment[fi]=Puhdistaa vanhat tiedot HTTP-välimuistista
-Comment[fr]=Efface les anciennes entrées du cache HTTP
-Comment[fy]=Ferwidert âlde items út de HTTP-cache
-Comment[ga]=Glanann seaniontrálacha ón taisce HTTP
-Comment[gl]=Elimina as entradas antigas da caché de HTTP
-Comment[he]=מנקה רשומות ישנות ממטמון ה־HTTP
-Comment[hi]=HTTP कैश से पà¥à¤°à¤¾à¤¨à¥€ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿ साफ करे
-Comment[hr]=Uklanjanje starih datoteka iz HTTP privremene lokalne pohrane
-Comment[hu]=Kitörli a régi bejegyzéseket a HTTP gyorstárból
-Comment[id]=Membersihkan entri lama dari cache HTTP
-Comment[is]=Hreinsar gamlar færslur úr HTTP skyndiminninu
-Comment[it]=Ripulisce la cache HTTP dalle voci vecchie
-Comment[ja]=HTTP キャッシュã‹ã‚‰å¤ã„エントリを削除ã—ã¾ã™
-Comment[ka]=HTTP ბუფერის მáƒáƒ«áƒ•áƒ”ლებელი ელემენტების
-Comment[kk]=HTTP бүркемеÑін еÑкі жазулардан тазалау
-Comment[km]=សម្អាážâ€‹áž’ាážáž»â€‹áž…ាស់ៗ​ពី​ឃ្លាំង​សម្ងាážáŸ‹ HTTP
-Comment[ko]=HTTP ìºì‹œì—ì„œ ì˜¤ëž˜ëœ ê²ƒë“¤ì„ ì •ë¦¬í•©ë‹ˆë‹¤
-Comment[lb]=Entfernt al Entréen aus dem HTTP-Zwëschespäicher
-Comment[lt]=Išvalo senus įrašus iš HTTP krepšio
-Comment[lv]=Iztīra vecos ierakstus no HTTP kešatmiņas
-Comment[mk]=Ги брише Ñтарите работи од HTTP кешот
-Comment[mn]=HTTP-завÑрын Ñ…Ð°Ð´Ð³Ð°Ð»Ð°Ð³Ñ‡Ð°Ð°Ñ Ñ…ÑƒÑƒÑ‡Ð¸Ð½ бичлÑгийг уÑтгах
-Comment[ms]=Membersihkan masukan lama daripada penyimpan HTTP
-Comment[mt]=Ineħħi fajls antiki mill-cache tal-HTTP
-Comment[nb]=Fjerner gamle oppføringer fra hurtiglageret for HTTP
-Comment[nds]=Smitt ole Indrääg ut den HTTP-Twischenspieker rut
-Comment[ne]=HTTP कà¥à¤¯à¤¾à¤¸à¤¬à¤¾à¤Ÿ पà¥à¤°à¤¾à¤¨à¤¾ पà¥à¤°à¤µà¤¿à¤·à¥à¤Ÿà¤¿à¤¹à¤°à¥‚ सफा गरà¥à¤¦à¤›
-Comment[nl]=Verwijdert oude items uit de HTTP-cache
-Comment[nn]=Reinskar opp i gamle oppføringar i HTTP-mellomlageret
-Comment[nso]=E hlwekisa ditsenyo tsa kgale gotswa polokelong ya HTTP
-Comment[oc]=Neteja les entrades antigues dèu cabia HTTP
-Comment[pa]=HTTP ਕੈਂਚੇ ਤੋਂ ਪà©à¨°à¨¾à¨£à©€à¨†à¨‚ ਇਕਾਈਆਂ ਸਾਫ
-Comment[pl]=Usuwa stare wpisy z bufora HTTP
-Comment[pt]=Limpa o conteúdo desactualizado da cache do HTTP
-Comment[pt_BR]=Limpa itens velhos do cache HTTP
-Comment[ro]=Elimină înregistrările vechi din cache-ul HTTP
-Comment[ru]=Удаление уÑтаревших Ñлементов из кÑша HTTP
-Comment[rw]=Isukura ibyinjijwe bishaje biri mu bwihisho HTTP
-Comment[se]=Buhtista boares merko3/4iid HTTP gaskarádjosis
-Comment[sk]=VyÄistiÅ¥ staré záznamy z vyrovnávacej pamäti HTTP
-Comment[sl]=Zbriše stare vnose iz pomnilnika HTTP
-Comment[sq]=I pastron hyrjet e vjetra nga depoja e fshehtësive të HTTP
-Comment[sr]=ЧиÑти Ñтаре Ñтавке из HTTP кеша
-Comment[sr@Latn]=Čisti stare stavke iz HTTP keša
-Comment[sv]=Rensar bort gamla poster från HTTP-cachen
-Comment[ta]=HTTP நினைவதà¯à®¤à®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯ பழைய உளà¯à®³à¯€à®Ÿà¯à®•à®³à¯ˆ சà¯à®¤à¯à®¤à®®à¯ செயà¯à®•à®¿à®±à®¤à¯
-Comment[te]=హెచౠటిటిపి కోశం à°¨à±à°‚à°šà°¿ పాత ఆరొపమà±à°²à°¨à± à°¶à±à°­à±à°°à°‚ చేసేది
-Comment[tg]=Ðддоштҳои Кӯҳна аз HTTP Махфӣ Тоза Кунед
-Comment[th]=ล้างรายà¸à¸²à¸£à¹€à¸à¹ˆà¸²à¹† จาà¸à¹à¸„ช HTTP
-Comment[tr]=HTTP önbelleğinden eski girişleri siler
-Comment[tt]=HTTP alxäterendä bulğan iske keremnär beterä
-Comment[uk]=Вичищає Ñтарі елементи з кешу HTTP
-Comment[uz]=HTTP keshidagi eski elementlarni oʻchiradi
-Comment[uz@cyrillic]=HTTP кÑшидаги ÑÑки Ñлементларни ўчиради
-Comment[ven]=I kulumaga zwithu zwakale u bva kha HTTP cache
-Comment[vi]=Xoá sạch các mục nhập cũ ra bộ nhớ tạm HTTP.
-Comment[xh]=Icoca amangeno amadala asuka twindawo efihlakeleyo yokugcina ye HTTP
-Comment[zh_CN]=从 HTTP 缓存中清除旧æ¡ç›®
-Comment[zh_HK]=從 HTTP å¿«å–中清除舊的項目
-Comment[zh_TW]=從 HTTP å¿«å–中清除舊的項目
-Comment[zu]=Ihlanza izingeniso ezindalam ezisuka kwi-cache ye-HTTP
-X-TDE-StartupNotify=false
diff --git a/kioslave/http/https.protocol b/kioslave/http/https.protocol
deleted file mode 100644
index 8a9c2f0da..000000000
--- a/kioslave/http/https.protocol
+++ /dev/null
@@ -1,12 +0,0 @@
-[Protocol]
-exec=kio_http
-protocol=https
-input=none
-output=filesystem
-reading=true
-defaultMimetype=application/octet-stream
-determineMimetypeFromExtension=false
-Icon=www
-config=http
-DocPath=kioslave/https.html
-Class=:internet
diff --git a/kioslave/http/kcookiejar/CMakeLists.txt b/kioslave/http/kcookiejar/CMakeLists.txt
deleted file mode 100644
index eef5e9654..000000000
--- a/kioslave/http/kcookiejar/CMakeLists.txt
+++ /dev/null
@@ -1,63 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}
- ${CMAKE_SOURCE_DIR}/dcop
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/tdeui
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES kcookiejar.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded )
-install( FILES kcookiescfg.upd DESTINATION ${KCONF_UPDATE_INSTALL_DIR} )
-install( FILES domain_info DESTINATION ${DATA_INSTALL_DIR}/khtml )
-
-
-##### kcookiejar ################################
-
-set( target kcookiejar )
-
-set( ${target}_SRCS
- main.cpp
-)
-
-tde_add_tdeinit_executable( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK tdecore-shared
-)
-
-
-##### kded_kcookiejar ###########################
-
-set( target kded_kcookiejar )
-
-set( ${target}_SRCS
- kcookiejar.cpp kcookieserver.cpp kcookiewin.cpp
- kcookieserver.skel
-)
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK tdeui-shared tdeinit_kded-shared
- DEPENDENCIES dcopidl
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/http/kcookiejar/Makefile.am b/kioslave/http/kcookiejar/Makefile.am
deleted file mode 100644
index 3cfb540fb..000000000
--- a/kioslave/http/kcookiejar/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-# Makefile.am of tdebase/kioslave/http
-
-SUBDIRS=tests
-INCLUDES= $(all_includes)
-
-####### Files
-
-bin_PROGRAMS =
-lib_LTLIBRARIES =
-tdeinit_LTLIBRARIES = kcookiejar.la
-kde_module_LTLIBRARIES = kded_kcookiejar.la
-
-kcookiejar_la_SOURCES = main.cpp
-METASOURCES = AUTO
-kcookiejar_la_LDFLAGS = $(all_libraries) -module -avoid-version
-kcookiejar_la_LIBADD = $(LIB_TDECORE) $(LIB_QT) $(top_builddir)/dcop/libDCOP.la
-
-kded_kcookiejar_la_SOURCES = kcookiejar.cpp kcookieserver.cpp \
- kcookieserver.skel kcookiewin.cpp
-kded_kcookiejar_la_LDFLAGS = $(all_libraries) -module -avoid-version
-kded_kcookiejar_la_LIBADD = $(LIB_KDED) $(LIB_QT) $(top_builddir)/dcop/libDCOP.la $(LIB_TDECORE) $(LIB_X11) $(LIB_TDEUI) $(top_builddir)/kded/libtdeinit_kded.la
-
-kded_DATA = kcookiejar.desktop
-kdeddir = $(kde_servicesdir)/kded
-
-update_DATA = kcookiescfg.upd
-updatedir = $(kde_datadir)/kconf_update
-
-cookie_DATA = domain_info
-cookiedir = $(kde_datadir)/khtml
-
diff --git a/kioslave/http/kcookiejar/domain_info b/kioslave/http/kcookiejar/domain_info
deleted file mode 100644
index 94baf8dae..000000000
--- a/kioslave/http/kcookiejar/domain_info
+++ /dev/null
@@ -1 +0,0 @@
-twoLevelTLD=name,ai,au,bd,bh,ck,eg,et,fk,il,in,kh,kr,mk,mt,na,np,nz,pg,pk,qa,sa,sb,sg,sv,ua,ug,uk,uy,vn,za,zw
diff --git a/kioslave/http/kcookiejar/kcookiejar.cpp b/kioslave/http/kcookiejar/kcookiejar.cpp
deleted file mode 100644
index ec0a423a6..000000000
--- a/kioslave/http/kcookiejar/kcookiejar.cpp
+++ /dev/null
@@ -1,1558 +0,0 @@
-/* This file is part of the KDE File Manager
-
- Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org)
- Copyright (C) 2000,2001 Dawit Alemayehu (adawit@kde.org)
-
- 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, 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.
-*/
-//----------------------------------------------------------------------------
-//
-// KDE File Manager -- HTTP Cookies
-// $Id$
-
-//
-// The cookie protocol is a mess. RFC2109 is a joke since nobody seems to
-// use it. Apart from that it is badly written.
-// We try to implement Netscape Cookies and try to behave us according to
-// RFC2109 as much as we can.
-//
-// We assume cookies do not contain any spaces (Netscape spec.)
-// According to RFC2109 this is allowed though.
-//
-
-#include <config.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifdef USE_SOLARIS
-#include <strings.h>
-#endif
-
-#include <stdlib.h>
-
-//#include <netinet/in.h>
-//#include <arpa/inet.h>
-
-#include <tqstring.h>
-#include <tqstrlist.h>
-#include <tqptrlist.h>
-#include <tqptrdict.h>
-#include <tqfile.h>
-#include <tqdir.h>
-#include <tqregexp.h>
-
-#include <kurl.h>
-#include <krfcdate.h>
-#include <kconfig.h>
-#include <ksavefile.h>
-#include <kdebug.h>
-
-#include "kcookiejar.h"
-
-
-// BR87227
-// Waba: Should the number of cookies be limited?
-// I am not convinced of the need of such limit
-// Mozilla seems to limit to 20 cookies / domain
-// but it is unclear which policy it uses to expire
-// cookies when it exceeds that amount
-#undef MAX_COOKIE_LIMIT
-
-#define MAX_COOKIES_PER_HOST 25
-#define READ_BUFFER_SIZE 8192
-#define IP_ADDRESS_EXPRESSION "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
-
-// Note with respect to TQString::fromLatin1( )
-// Cookies are stored as 8 bit data and passed to kio_http as
-// latin1 regardless of their actual encoding.
-
-// L1 is used to indicate latin1 constants
-#define L1(x) TQString::fromLatin1(x)
-
-template class TQPtrList<KHttpCookie>;
-template class TQPtrDict<KHttpCookieList>;
-
-TQString KCookieJar::adviceToStr(KCookieAdvice _advice)
-{
- switch( _advice )
- {
- case KCookieAccept: return L1("Accept");
- case KCookieReject: return L1("Reject");
- case KCookieAsk: return L1("Ask");
- default: return L1("Dunno");
- }
-}
-
-KCookieAdvice KCookieJar::strToAdvice(const TQString &_str)
-{
- if (_str.isEmpty())
- return KCookieDunno;
-
- TQCString advice = _str.lower().latin1();
-
- if (advice == "accept")
- return KCookieAccept;
- else if (advice == "reject")
- return KCookieReject;
- else if (advice == "ask")
- return KCookieAsk;
-
- return KCookieDunno;
-}
-
-// KHttpCookie
-///////////////////////////////////////////////////////////////////////////
-
-//
-// Cookie constructor
-//
-KHttpCookie::KHttpCookie(const TQString &_host,
- const TQString &_domain,
- const TQString &_path,
- const TQString &_name,
- const TQString &_value,
- time_t _expireDate,
- int _protocolVersion,
- bool _secure,
- bool _httpOnly,
- bool _explicitPath) :
- mHost(_host),
- mDomain(_domain),
- mPath(_path.isEmpty() ? TQString::null : _path),
- mName(_name),
- mValue(_value),
- mExpireDate(_expireDate),
- mProtocolVersion(_protocolVersion),
- mSecure(_secure),
- mHttpOnly(_httpOnly),
- mExplicitPath(_explicitPath)
-{
-}
-
-//
-// Checks if a cookie has been expired
-//
-bool KHttpCookie::isExpired(time_t currentDate)
-{
- return (mExpireDate != 0) && (mExpireDate < currentDate);
-}
-
-//
-// Returns a string for a HTTP-header
-//
-TQString KHttpCookie::cookieStr(bool useDOMFormat)
-{
- TQString result;
-
- if (useDOMFormat || (mProtocolVersion == 0))
- {
- if ( !mName.isEmpty() )
- result = mName + '=';
- result += mValue;
- }
- else
- {
- result = mName + '=' + mValue;
- if (mExplicitPath)
- result += L1("; $Path=\"") + mPath + L1("\"");
- if (!mDomain.isEmpty())
- result += L1("; $Domain=\"") + mDomain + L1("\"");
- }
- return result;
-}
-
-//
-// Returns whether this cookie should be send to this location.
-bool KHttpCookie::match(const TQString &fqdn, const TQStringList &domains,
- const TQString &path)
-{
- // Cookie domain match check
- if (mDomain.isEmpty())
- {
- if (fqdn != mHost)
- return false;
- }
- else if (!domains.contains(mDomain))
- {
- if (mDomain[0] == '.')
- return false;
-
- // Maybe the domain needs an extra dot.
- TQString domain = '.' + mDomain;
- if ( !domains.contains( domain ) )
- if ( fqdn != mDomain )
- return false;
- }
-
- // Cookie path match check
- if (mPath.isEmpty())
- return true;
-
- // According to the netscape spec both http://www.acme.com/foobar,
- // http://www.acme.com/foo.bar and http://www.acme.com/foo/bar
- // match http://www.acme.com/foo.
- // We only match http://www.acme.com/foo/bar
-
- if( path.startsWith(mPath) &&
- (
- (path.length() == mPath.length() ) || // Paths are exact match
- (path[mPath.length()-1] == '/') || // mPath ended with a slash
- (path[mPath.length()] == '/') // A slash follows.
- ))
- return true; // Path of URL starts with cookie-path
-
- return false;
-}
-
-// KHttpCookieList
-///////////////////////////////////////////////////////////////////////////
-
-int KHttpCookieList::compareItems( void * item1, void * item2)
-{
- int pathLen1 = ((KHttpCookie *)item1)->path().length();
- int pathLen2 = ((KHttpCookie *)item2)->path().length();
- if (pathLen1 > pathLen2)
- return -1;
- if (pathLen1 < pathLen2)
- return 1;
- return 0;
-}
-
-
-// KCookieJar
-///////////////////////////////////////////////////////////////////////////
-
-//
-// Constructs a new cookie jar
-//
-// One jar should be enough for all cookies.
-//
-KCookieJar::KCookieJar()
-{
- m_cookieDomains.setAutoDelete( true );
- m_globalAdvice = KCookieDunno;
- m_configChanged = false;
- m_cookiesChanged = false;
-
- KConfig cfg("khtml/domain_info", true, false, "data");
- TQStringList countries = cfg.readListEntry("twoLevelTLD");
- for(TQStringList::ConstIterator it = countries.begin();
- it != countries.end(); ++it)
- {
- m_twoLevelTLD.replace(*it, (int *) 1);
- }
-}
-
-//
-// Destructs the cookie jar
-//
-// Poor little cookies, they will all be eaten by the cookie monster!
-//
-KCookieJar::~KCookieJar()
-{
- // Not much to do here
-}
-
-static void removeDuplicateFromList(KHttpCookieList *list, KHttpCookie *cookiePtr, bool nameMatchOnly=false, bool updateWindowId=false)
-{
- TQString domain1 = cookiePtr->domain();
- if (domain1.isEmpty())
- domain1 = cookiePtr->host();
-
- for ( KHttpCookiePtr cookie=list->first(); cookie != 0; )
- {
- TQString domain2 = cookie->domain();
- if (domain2.isEmpty())
- domain2 = cookie->host();
-
- if (
- (cookiePtr->name() == cookie->name()) &&
- (
- nameMatchOnly ||
- ( (domain1 == domain2) && (cookiePtr->path() == cookie->path()) )
- )
- )
- {
- if (updateWindowId)
- {
- for(TQValueList<long>::ConstIterator it = cookie->windowIds().begin();
- it != cookie->windowIds().end(); ++it)
- {
- long windowId = *it;
- if (windowId && (cookiePtr->windowIds().find(windowId) == cookiePtr->windowIds().end()))
- {
- cookiePtr->windowIds().append(windowId);
- }
- }
- }
- KHttpCookiePtr old_cookie = cookie;
- cookie = list->next();
- list->removeRef( old_cookie );
- break;
- }
- else
- {
- cookie = list->next();
- }
- }
-}
-
-
-//
-// Looks for cookies in the cookie jar which are appropriate for _url.
-// Returned is a string containing all appropriate cookies in a format
-// which can be added to a HTTP-header without any additional processing.
-//
-TQString KCookieJar::findCookies(const TQString &_url, bool useDOMFormat, long windowId, KHttpCookieList *pendingCookies)
-{
- TQString cookieStr;
- TQStringList domains;
- TQString fqdn;
- TQString path;
- KHttpCookiePtr cookie;
- KCookieAdvice advice = m_globalAdvice;
-
- if (!parseURL(_url, fqdn, path))
- return cookieStr;
-
- bool secureRequest = (_url.find( L1("https://"), 0, false) == 0 ||
- _url.find( L1("webdavs://"), 0, false) == 0);
-
- // kdDebug(7104) << "findCookies: URL= " << _url << ", secure = " << secureRequest << endl;
-
- extractDomains(fqdn, domains);
-
- KHttpCookieList allCookies;
-
- for(TQStringList::ConstIterator it = domains.begin();
- true;
- ++it)
- {
- KHttpCookieList *cookieList;
- if (it == domains.end())
- {
- cookieList = pendingCookies; // Add pending cookies
- pendingCookies = 0;
- if (!cookieList)
- break;
- }
- else
- {
- TQString key = (*it).isNull() ? L1("") : (*it);
- cookieList = m_cookieDomains[key];
- if (!cookieList)
- continue; // No cookies for this domain
- }
-
- if (cookieList->getAdvice() != KCookieDunno)
- advice = cookieList->getAdvice();
-
- for ( cookie=cookieList->first(); cookie != 0; cookie=cookieList->next() )
- {
- // If the we are setup to automatically accept all session cookies and to
- // treat all cookies as session cookies or the current cookie is a session
- // cookie, then send the cookie back regardless of either policy.
- if (advice == KCookieReject &&
- !(m_autoAcceptSessionCookies &&
- (m_ignoreCookieExpirationDate || cookie->expireDate() == 0)))
- continue;
-
- if (!cookie->match(fqdn, domains, path))
- continue;
-
- if( cookie->isSecure() && !secureRequest )
- continue;
-
- if( cookie->isHttpOnly() && useDOMFormat )
- continue;
-
- // Do not send expired cookies.
- if ( cookie->isExpired (time(0)) )
- {
- // Note there is no need to actually delete the cookie here
- // since the cookieserver will invoke ::saveCookieJar because
- // of the state change below. This will then do the job of
- // deleting the cookie for us.
- m_cookiesChanged = true;
- continue;
- }
-
- if (windowId && (cookie->windowIds().find(windowId) == cookie->windowIds().end()))
- {
- cookie->windowIds().append(windowId);
- }
-
- if (it == domains.end()) // Only needed when processing pending cookies
- removeDuplicateFromList(&allCookies, cookie);
-
- allCookies.append(cookie);
- }
- if (it == domains.end())
- break; // Finished.
- }
-
- int cookieCount = 0;
-
- int protVersion=0;
- for ( cookie=allCookies.first(); cookie != 0; cookie=allCookies.next() )
- {
- if (cookie->protocolVersion() > protVersion)
- protVersion = cookie->protocolVersion();
- }
-
- for ( cookie=allCookies.first(); cookie != 0; cookie=allCookies.next() )
- {
- if (useDOMFormat)
- {
- if (cookieCount > 0)
- cookieStr += L1("; ");
- cookieStr += cookie->cookieStr(true);
- }
- else
- {
- if (cookieCount == 0)
- {
- cookieStr += L1("Cookie: ");
- if (protVersion > 0)
- {
- TQString version;
- version.sprintf("$Version=%d; ", protVersion); // Without quotes
- cookieStr += version;
- }
- }
- else
- {
- cookieStr += L1("; ");
- }
- cookieStr += cookie->cookieStr(false);
- }
- cookieCount++;
- }
-
- return cookieStr;
-}
-
-//
-// This function parses a string like 'my_name="my_value";' and returns
-// 'my_name' in Name and 'my_value' in Value.
-//
-// A pointer to the end of the parsed part is returned.
-// This pointer points either to:
-// '\0' - The end of the string has reached.
-// ';' - Another my_name="my_value" pair follows
-// ',' - Another cookie follows
-// '\n' - Another header follows
-static const char * parseNameValue(const char *header,
- TQString &Name,
- TQString &Value,
- bool keepQuotes=false,
- bool rfcQuotes=false)
-{
- const char *s = header;
- // Parse 'my_name' part
- for(; (*s != '='); s++)
- {
- if ((*s=='\0') || (*s==';') || (*s=='\n'))
- {
- // No '=' sign -> use string as the value, name is empty
- // (behavior found in Mozilla and IE)
- Name = "";
- Value = TQString::fromLatin1(header);
- Value.truncate( s - header );
- Value = Value.stripWhiteSpace();
- return (s);
- }
- }
-
- Name = header;
- Name.truncate( s - header );
- Name = Name.stripWhiteSpace();
-
- // *s == '='
- s++;
-
- // Skip any whitespace
- for(; (*s == ' ') || (*s == '\t'); s++)
- {
- if ((*s=='\0') || (*s==';') || (*s=='\n'))
- {
- // End of Name
- Value = "";
- return (s);
- }
- }
-
- if ((rfcQuotes || !keepQuotes) && (*s == '\"'))
- {
- // Parse '"my_value"' part (quoted value)
- if (keepQuotes)
- header = s++;
- else
- header = ++s; // skip "
- for(;(*s != '\"');s++)
- {
- if ((*s=='\0') || (*s=='\n'))
- {
- // End of Name
- Value = TQString::fromLatin1(header);
- Value.truncate(s - header);
- return (s);
- }
- }
- Value = TQString::fromLatin1(header);
- // *s == '\"';
- if (keepQuotes)
- Value.truncate( ++s - header );
- else
- Value.truncate( s++ - header );
-
- // Skip any remaining garbage
- for(;; s++)
- {
- if ((*s=='\0') || (*s==';') || (*s=='\n'))
- break;
- }
- }
- else
- {
- // Parse 'my_value' part (unquoted value)
- header = s;
- while ((*s != '\0') && (*s != ';') && (*s != '\n'))
- s++;
- // End of Name
- Value = TQString::fromLatin1(header);
- Value.truncate( s - header );
- Value = Value.stripWhiteSpace();
- }
- return (s);
-
-}
-
-void KCookieJar::stripDomain(const TQString &_fqdn, TQString &_domain)
-{
- TQStringList domains;
- extractDomains(_fqdn, domains);
- if (domains.count() > 3)
- _domain = domains[3];
- else
- _domain = domains[0];
-}
-
-TQString KCookieJar::stripDomain( KHttpCookiePtr cookiePtr)
-{
- TQString domain; // We file the cookie under this domain.
- if (cookiePtr->domain().isEmpty())
- stripDomain( cookiePtr->host(), domain);
- else
- stripDomain (cookiePtr->domain(), domain);
- return domain;
-}
-
-bool KCookieJar::parseURL(const TQString &_url,
- TQString &_fqdn,
- TQString &_path)
-{
- KURL kurl(_url);
- if (!kurl.isValid())
- return false;
-
- _fqdn = kurl.host().lower();
- if (kurl.port())
- {
- if (((kurl.protocol() == L1("http")) && (kurl.port() != 80)) ||
- ((kurl.protocol() == L1("https")) && (kurl.port() != 443)))
- {
- _fqdn = L1("%1:%2").arg(kurl.port()).arg(_fqdn);
- }
- }
-
- // Cookie spoofing protection. Since there is no way a path separator
- // or escape encoded character is allowed in the hostname according
- // to RFC 2396, reject attempts to include such things there!
- if(_fqdn.find('/') > -1 || _fqdn.find('%') > -1)
- {
- return false; // deny everything!!
- }
-
- _path = kurl.path();
- if (_path.isEmpty())
- _path = L1("/");
-
- TQRegExp exp(L1("[\\\\/]\\.\\.[\\\\/]"));
- // Weird path, cookie stealing attempt?
- if (exp.search(_path) != -1)
- return false; // Deny everything!!
-
- return true;
-}
-
-void KCookieJar::extractDomains(const TQString &_fqdn,
- TQStringList &_domains)
-{
- // Return numeric IPv6 addresses as is...
- if (_fqdn[0] == '[')
- {
- _domains.append( _fqdn );
- return;
- }
- // Return numeric IPv4 addresses as is...
- if ((_fqdn.at(0) >= TQChar('0')) && (_fqdn.at(0) <= TQChar('9')))
- {
- if (_fqdn.find(TQRegExp(IP_ADDRESS_EXPRESSION)) > -1)
- {
- _domains.append( _fqdn );
- return;
- }
- }
-
- TQStringList partList = TQStringList::split('.', _fqdn, false);
-
- if (partList.count())
- partList.remove(partList.begin()); // Remove hostname
-
- while(partList.count())
- {
-
- if (partList.count() == 1)
- break; // We only have a TLD left.
-
- if ((partList.count() == 2) && (m_twoLevelTLD[partList[1].lower()]))
- {
- // This domain uses two-level TLDs in the form xxxx.yy
- break;
- }
-
- if ((partList.count() == 2) && (partList[1].length() == 2))
- {
- // If this is a TLD, we should stop. (e.g. co.uk)
- // We assume this is a TLD if it ends with .xx.yy or .x.yy
- if (partList[0].length() <= 2)
- break; // This is a TLD.
-
- // Catch some TLDs that we miss with the previous check
- // e.g. com.au, org.uk, mil.co
- TQCString t = partList[0].lower().utf8();
- if ((t == "com") || (t == "net") || (t == "org") || (t == "gov") || (t == "edu") || (t == "mil") || (t == "int"))
- break;
- }
-
- TQString domain = partList.join(L1("."));
- _domains.append(domain);
- _domains.append('.' + domain);
- partList.remove(partList.begin()); // Remove part
- }
-
- // Always add the FQDN at the start of the list for
- // hostname == cookie-domainname checks!
- _domains.prepend( '.' + _fqdn );
- _domains.prepend( _fqdn );
-}
-
-
-/*
- Changes dates in from the following format
-
- Wed Sep 12 07:00:00 2007 GMT
- to
- Wed Sep 12 2007 07:00:00 GMT
-
- to allow KRFCDate::parseDate to properly parse expiration date formats
- used in cookies by some servers such as amazon.com. See BR# 145244.
-*/
-static TQString fixupDateTime(const TQString& dt)
-{
- const int index = dt.find(TQRegExp("[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}"));
-
- if (index > -1)
- {
- TQStringList dateStrList = TQStringList::split(' ', dt.mid(index));
- if (dateStrList.count() > 1)
- {
- TQString date = dateStrList[0];
- dateStrList[0] = dateStrList[1];
- dateStrList[1] = date;
- date = dt;
- return date.replace(index, date.length(), dateStrList.join(" "));
- }
- }
-
- return dt;
-}
-
-//
-// This function parses cookie_headers and returns a linked list of
-// KHttpCookie objects for all cookies found in cookie_headers.
-// If no cookies could be found 0 is returned.
-//
-// cookie_headers should be a concatenation of all lines of a HTTP-header
-// which start with "Set-Cookie". The lines should be separated by '\n's.
-//
-KHttpCookieList KCookieJar::makeCookies(const TQString &_url,
- const TQCString &cookie_headers,
- long windowId)
-{
- KHttpCookieList cookieList;
- KHttpCookieList cookieList2;
- KHttpCookiePtr lastCookie = 0;
- const char *cookieStr = cookie_headers.data();
- TQString Name;
- TQString Value;
- TQString fqdn;
- TQString path;
- bool crossDomain = false;
-
- if (!parseURL(_url, fqdn, path))
- {
- // Error parsing _url
- return KHttpCookieList();
- }
- TQString defaultPath;
- int i = path.findRev('/');
- if (i > 0)
- defaultPath = path.left(i);
-
- // The hard stuff :)
- for(;;)
- {
- // check for "Set-Cookie"
- if (strncmp(cookieStr, "Cross-Domain\n", 13) == 0)
- {
- cookieStr += 13;
- crossDomain = true;
- }
- else if (strncasecmp(cookieStr, "Set-Cookie:", 11) == 0)
- {
- cookieStr = parseNameValue(cookieStr+11, Name, Value, true);
-
- // Host = FQDN
- // Default domain = ""
- // Default path according to rfc2109
-
- KHttpCookie *cookie = new KHttpCookie(fqdn, L1(""), defaultPath, Name, Value);
- if (windowId)
- cookie->mWindowIds.append(windowId);
- cookie->mCrossDomain = crossDomain;
-
- // Insert cookie in chain
- cookieList.append(cookie);
- lastCookie = cookie;
- }
- else if (strncasecmp(cookieStr, "Set-Cookie2:", 12) == 0)
- {
- // Attempt to follow rfc2965
- cookieStr = parseNameValue(cookieStr+12, Name, Value, true, true);
-
- // Host = FQDN
- // Default domain = ""
- // Default path according to rfc2965
-
- KHttpCookie *cookie = new KHttpCookie(fqdn, L1(""), defaultPath, Name, Value);
- if (windowId)
- cookie->mWindowIds.append(windowId);
- cookie->mCrossDomain = crossDomain;
-
- // Insert cookie in chain
- cookieList2.append(cookie);
- lastCookie = cookie;
- }
- else
- {
- // This is not the start of a cookie header, skip till next line.
- while (*cookieStr && *cookieStr != '\n')
- cookieStr++;
-
- if (*cookieStr == '\n')
- cookieStr++;
-
- if (!*cookieStr)
- break; // End of cookie_headers
- else
- continue; // end of this header, continue with next.
- }
-
- while ((*cookieStr == ';') || (*cookieStr == ' '))
- {
- cookieStr++;
-
- // Name-Value pair follows
- cookieStr = parseNameValue(cookieStr, Name, Value);
-
- TQCString cName = Name.lower().latin1();
- if (cName == "domain")
- {
- TQString dom = Value.lower();
- // RFC2965 3.2.2: If an explicitly specified value does not
- // start with a dot, the user agent supplies a leading dot
- if(dom.length() && dom[0] != '.')
- dom.prepend(".");
- // remove a trailing dot
- if(dom.length() > 2 && dom[dom.length()-1] == '.')
- dom = dom.left(dom.length()-1);
-
- if(dom.contains('.') > 1 || dom == ".local")
- lastCookie->mDomain = dom;
- }
- else if (cName == "max-age")
- {
- int max_age = Value.toInt();
- if (max_age == 0)
- lastCookie->mExpireDate = 1;
- else
- lastCookie->mExpireDate = time(0)+max_age;
- }
- else if (cName == "expires")
- {
- // Parse brain-dead netscape cookie-format
- lastCookie->mExpireDate = KRFCDate::parseDate(Value);
-
- // Workaround for servers that send the expiration date in
- // 'Wed Sep 12 07:00:00 2007 GMT' format. See BR# 145244.
- if (lastCookie->mExpireDate == 0)
- lastCookie->mExpireDate = KRFCDate::parseDate(fixupDateTime(Value));
- }
- else if (cName == "path")
- {
- if (Value.isEmpty())
- lastCookie->mPath = TQString::null; // Catch "" <> TQString::null
- else
- lastCookie->mPath = KURL::decode_string(Value);
- lastCookie->mExplicitPath = true;
- }
- else if (cName == "version")
- {
- lastCookie->mProtocolVersion = Value.toInt();
- }
- else if ((cName == "secure") ||
- (cName.isEmpty() && Value.lower() == L1("secure")))
- {
- lastCookie->mSecure = true;
- }
- else if ((cName == "httponly") ||
- (cName.isEmpty() && Value.lower() == L1("httponly")))
- {
- lastCookie->mHttpOnly = true;
- }
- }
-
- if (*cookieStr == '\0')
- break; // End of header
-
- // Skip ';' or '\n'
- cookieStr++;
- }
-
- // RFC2965 cookies come last so that they override netscape cookies.
- while( !cookieList2.isEmpty() && (lastCookie = cookieList2.take(0)) )
- {
- removeDuplicateFromList(&cookieList, lastCookie, true);
- cookieList.append(lastCookie);
- }
-
- return cookieList;
-}
-
-/**
-* Parses cookie_domstr and returns a linked list of KHttpCookie objects.
-* cookie_domstr should be a semicolon-delimited list of "name=value"
-* pairs. Any whitespace before "name" or around '=' is discarded.
-* If no cookies are found, 0 is returned.
-*/
-KHttpCookieList KCookieJar::makeDOMCookies(const TQString &_url,
- const TQCString &cookie_domstring,
- long windowId)
-{
- // A lot copied from above
- KHttpCookieList cookieList;
- KHttpCookiePtr lastCookie = 0;
-
- const char *cookieStr = cookie_domstring.data();
- TQString Name;
- TQString Value;
- TQString fqdn;
- TQString path;
-
- if (!parseURL(_url, fqdn, path))
- {
- // Error parsing _url
- return KHttpCookieList();
- }
-
- // This time it's easy
- while(*cookieStr)
- {
- cookieStr = parseNameValue(cookieStr, Name, Value);
-
- // Host = FQDN
- // Default domain = ""
- // Default path = ""
- KHttpCookie *cookie = new KHttpCookie(fqdn, TQString::null, TQString::null,
- Name, Value );
- if (windowId)
- cookie->mWindowIds.append(windowId);
-
- cookieList.append(cookie);
- lastCookie = cookie;
-
- if (*cookieStr != '\0')
- cookieStr++; // Skip ';' or '\n'
- }
-
- return cookieList;
-}
-
-#ifdef MAX_COOKIE_LIMIT
-static void makeRoom(KHttpCookieList *cookieList, KHttpCookiePtr &cookiePtr)
-{
- // Too much cookies: throw one away, try to be somewhat clever
- KHttpCookiePtr lastCookie = 0;
- for(KHttpCookiePtr cookie = cookieList->first(); cookie; cookie = cookieList->next())
- {
- if (cookieList->compareItems(cookie, cookiePtr) < 0)
- break;
- lastCookie = cookie;
- }
- if (!lastCookie)
- lastCookie = cookieList->first();
- cookieList->removeRef(lastCookie);
-}
-#endif
-
-//
-// This function hands a KHttpCookie object over to the cookie jar.
-//
-// On return cookiePtr is set to 0.
-//
-void KCookieJar::addCookie(KHttpCookiePtr &cookiePtr)
-{
- TQStringList domains;
- KHttpCookieList *cookieList = 0L;
-
- // We always need to do this to make sure that the
- // that cookies of type hostname == cookie-domainname
- // are properly removed and/or updated as necessary!
- extractDomains( cookiePtr->host(), domains );
- for ( TQStringList::ConstIterator it = domains.begin();
- (it != domains.end() && !cookieList);
- ++it )
- {
- TQString key = (*it).isNull() ? L1("") : (*it);
- KHttpCookieList *list= m_cookieDomains[key];
- if ( !list ) continue;
-
- removeDuplicateFromList(list, cookiePtr, false, true);
- }
-
- TQString domain = stripDomain( cookiePtr );
- TQString key = domain.isNull() ? L1("") : domain;
- cookieList = m_cookieDomains[ key ];
- if (!cookieList)
- {
- // Make a new cookie list
- cookieList = new KHttpCookieList();
- cookieList->setAutoDelete(true);
-
- // All cookies whose domain is not already
- // known to us should be added with KCookieDunno.
- // KCookieDunno means that we use the global policy.
- cookieList->setAdvice( KCookieDunno );
-
- m_cookieDomains.insert( domain, cookieList);
-
- // Update the list of domains
- m_domainList.append(domain);
- }
-
- // Add the cookie to the cookie list
- // The cookie list is sorted 'longest path first'
- if (!cookiePtr->isExpired(time(0)))
- {
-#ifdef MAX_COOKIE_LIMIT
- if (cookieList->count() >= MAX_COOKIES_PER_HOST)
- makeRoom(cookieList, cookiePtr); // Delete a cookie
-#endif
- cookieList->inSort( cookiePtr );
- m_cookiesChanged = true;
- }
- else
- {
- delete cookiePtr;
- }
- cookiePtr = 0;
-}
-
-//
-// This function advices whether a single KHttpCookie object should
-// be added to the cookie jar.
-//
-KCookieAdvice KCookieJar::cookieAdvice(KHttpCookiePtr cookiePtr)
-{
- if (m_rejectCrossDomainCookies && cookiePtr->isCrossDomain())
- return KCookieReject;
-
- TQStringList domains;
-
- extractDomains(cookiePtr->host(), domains);
-
- // If the cookie specifies a domain, check whether it is valid. Otherwise,
- // accept the cookie anyways but remove the domain="" value to prevent
- // cross-site cookie injection.
- if (!cookiePtr->domain().isEmpty())
- {
- if (!domains.contains(cookiePtr->domain()) &&
- !cookiePtr->domain().endsWith("."+cookiePtr->host()))
- cookiePtr->fixDomain(TQString::null);
- }
-
- if (m_autoAcceptSessionCookies && (cookiePtr->expireDate() == 0 ||
- m_ignoreCookieExpirationDate))
- return KCookieAccept;
-
- KCookieAdvice advice = KCookieDunno;
- bool isFQDN = true; // First is FQDN
- TQStringList::Iterator it = domains.begin(); // Start with FQDN which first in the list.
- while( (advice == KCookieDunno) && (it != domains.end()))
- {
- TQString domain = *it;
- // Check if a policy for the FQDN/domain is set.
- if ( domain[0] == '.' || isFQDN )
- {
- isFQDN = false;
- KHttpCookieList *cookieList = m_cookieDomains[domain];
- if (cookieList)
- advice = cookieList->getAdvice();
- }
- domains.remove(it);
- it = domains.begin(); // Continue from begin of remaining list
- }
-
- if (advice == KCookieDunno)
- advice = m_globalAdvice;
-
- return advice;
-}
-
-//
-// This function gets the advice for all cookies originating from
-// _domain.
-//
-KCookieAdvice KCookieJar::getDomainAdvice(const TQString &_domain)
-{
- KHttpCookieList *cookieList = m_cookieDomains[_domain];
- KCookieAdvice advice;
-
- if (cookieList)
- {
- advice = cookieList->getAdvice();
- }
- else
- {
- advice = KCookieDunno;
- }
-
- return advice;
-}
-
-//
-// This function sets the advice for all cookies originating from
-// _domain.
-//
-void KCookieJar::setDomainAdvice(const TQString &_domain, KCookieAdvice _advice)
-{
- TQString domain(_domain);
- KHttpCookieList *cookieList = m_cookieDomains[domain];
-
- if (cookieList)
- {
- if (cookieList->getAdvice() != _advice)
- {
- m_configChanged = true;
- // domain is already known
- cookieList->setAdvice( _advice);
- }
-
- if ((cookieList->isEmpty()) &&
- (_advice == KCookieDunno))
- {
- // This deletes cookieList!
- m_cookieDomains.remove(domain);
- m_domainList.remove(domain);
- }
- }
- else
- {
- // domain is not yet known
- if (_advice != KCookieDunno)
- {
- // We should create a domain entry
- m_configChanged = true;
- // Make a new cookie list
- cookieList = new KHttpCookieList();
- cookieList->setAutoDelete(true);
- cookieList->setAdvice( _advice);
- m_cookieDomains.insert( domain, cookieList);
- // Update the list of domains
- m_domainList.append( domain);
- }
- }
-}
-
-//
-// This function sets the advice for all cookies originating from
-// the same domain as _cookie
-//
-void KCookieJar::setDomainAdvice(KHttpCookiePtr cookiePtr, KCookieAdvice _advice)
-{
- TQString domain;
- stripDomain(cookiePtr->host(), domain); // We file the cookie under this domain.
-
- setDomainAdvice(domain, _advice);
-}
-
-//
-// This function sets the global advice for cookies
-//
-void KCookieJar::setGlobalAdvice(KCookieAdvice _advice)
-{
- if (m_globalAdvice != _advice)
- m_configChanged = true;
- m_globalAdvice = _advice;
-}
-
-//
-// Get a list of all domains known to the cookie jar.
-//
-const TQStringList& KCookieJar::getDomainList()
-{
- return m_domainList;
-}
-
-//
-// Get a list of all cookies in the cookie jar originating from _domain.
-//
-const KHttpCookieList *KCookieJar::getCookieList(const TQString & _domain,
- const TQString & _fqdn )
-{
- TQString domain;
-
- if (_domain.isEmpty())
- stripDomain( _fqdn, domain );
- else
- domain = _domain;
-
- return m_cookieDomains[domain];
-}
-
-//
-// Eat a cookie out of the jar.
-// cookiePtr should be one of the cookies returned by getCookieList()
-//
-void KCookieJar::eatCookie(KHttpCookiePtr cookiePtr)
-{
- TQString domain = stripDomain(cookiePtr); // We file the cookie under this domain.
- KHttpCookieList *cookieList = m_cookieDomains[domain];
-
- if (cookieList)
- {
- // This deletes cookiePtr!
- if (cookieList->removeRef( cookiePtr ))
- m_cookiesChanged = true;
-
- if ((cookieList->isEmpty()) &&
- (cookieList->getAdvice() == KCookieDunno))
- {
- // This deletes cookieList!
- m_cookieDomains.remove(domain);
-
- m_domainList.remove(domain);
- }
- }
-}
-
-void KCookieJar::eatCookiesForDomain(const TQString &domain)
-{
- KHttpCookieList *cookieList = m_cookieDomains[domain];
- if (!cookieList || cookieList->isEmpty()) return;
-
- cookieList->clear();
- if (cookieList->getAdvice() == KCookieDunno)
- {
- // This deletes cookieList!
- m_cookieDomains.remove(domain);
- m_domainList.remove(domain);
- }
- m_cookiesChanged = true;
-}
-
-void KCookieJar::eatSessionCookies( long windowId )
-{
- if (!windowId)
- return;
-
- TQStringList::Iterator it=m_domainList.begin();
- for ( ; it != m_domainList.end(); ++it )
- eatSessionCookies( *it, windowId, false );
-}
-
-void KCookieJar::eatAllCookies()
-{
- for ( TQStringList::Iterator it=m_domainList.begin();
- it != m_domainList.end();)
- {
- TQString domain = *it++;
- // This might remove domain from domainList!
- eatCookiesForDomain(domain);
- }
-}
-
-void KCookieJar::eatSessionCookies( const TQString& fqdn, long windowId,
- bool isFQDN )
-{
- KHttpCookieList* cookieList;
- if ( !isFQDN )
- cookieList = m_cookieDomains[fqdn];
- else
- {
- TQString domain;
- stripDomain( fqdn, domain );
- cookieList = m_cookieDomains[domain];
- }
-
- if ( cookieList )
- {
- KHttpCookiePtr cookie=cookieList->first();
- for (; cookie != 0;)
- {
- if ((cookie->expireDate() != 0) && !m_ignoreCookieExpirationDate)
- {
- cookie = cookieList->next();
- continue;
- }
-
- TQValueList<long> &ids = cookie->windowIds();
- if (!ids.remove(windowId) || !ids.isEmpty())
- {
- cookie = cookieList->next();
- continue;
- }
- KHttpCookiePtr old_cookie = cookie;
- cookie = cookieList->next();
- cookieList->removeRef( old_cookie );
- }
- }
-}
-
-//
-// Saves all cookies to the file '_filename'.
-// On succes 'true' is returned.
-// On failure 'false' is returned.
-bool KCookieJar::saveCookies(const TQString &_filename)
-{
- KSaveFile saveFile(_filename, 0600);
-
- if (saveFile.status() != 0)
- return false;
-
- FILE *fStream = saveFile.fstream();
-
- time_t curTime = time(0);
-
- fprintf(fStream, "# KDE Cookie File v2\n#\n");
-
- fprintf(fStream, "%-20s %-20s %-12s %-10s %-4s %-20s %-4s %s\n",
- "# Host", "Domain", "Path", "Exp.date", "Prot",
- "Name", "Sec", "Value");
-
- for ( TQStringList::Iterator it=m_domainList.begin(); it != m_domainList.end();
- it++ )
- {
- const TQString &domain = *it;
- bool domainPrinted = false;
-
- KHttpCookieList *cookieList = m_cookieDomains[domain];
- KHttpCookiePtr cookie=cookieList->last();
-
- for (; cookie != 0;)
- {
- if (cookie->isExpired(curTime))
- {
- // Delete expired cookies
- KHttpCookiePtr old_cookie = cookie;
- cookie = cookieList->prev();
- cookieList->removeRef( old_cookie );
- }
- else if (cookie->expireDate() != 0 && !m_ignoreCookieExpirationDate)
- {
- if (!domainPrinted)
- {
- domainPrinted = true;
- fprintf(fStream, "[%s]\n", domain.local8Bit().data());
- }
- // Store persistent cookies
- TQString path = L1("\"");
- path += cookie->path();
- path += '"';
- TQString domain = L1("\"");
- domain += cookie->domain();
- domain += '"';
- fprintf(fStream, "%-20s %-20s %-12s %10lu %3d %-20s %-4i %s\n",
- cookie->host().latin1(), domain.latin1(),
- path.latin1(), (unsigned long) cookie->expireDate(),
- cookie->protocolVersion(),
- cookie->name().isEmpty() ? cookie->value().latin1() : cookie->name().latin1(),
- (cookie->isSecure() ? 1 : 0) + (cookie->isHttpOnly() ? 2 : 0) +
- (cookie->hasExplicitPath() ? 4 : 0) + (cookie->name().isEmpty() ? 8 : 0),
- cookie->value().latin1());
- cookie = cookieList->prev();
- }
- else
- {
- // Skip session-only cookies
- cookie = cookieList->prev();
- }
- }
- }
-
- return saveFile.close();
-}
-
-typedef char *charPtr;
-
-static const char *parseField(charPtr &buffer, bool keepQuotes=false)
-{
- char *result;
- if (!keepQuotes && (*buffer == '\"'))
- {
- // Find terminating "
- buffer++;
- result = buffer;
- while((*buffer != '\"') && (*buffer))
- buffer++;
- }
- else
- {
- // Find first white space
- result = buffer;
- while((*buffer != ' ') && (*buffer != '\t') && (*buffer != '\n') && (*buffer))
- buffer++;
- }
-
- if (!*buffer)
- return result; //
- *buffer++ = '\0';
-
- // Skip white-space
- while((*buffer == ' ') || (*buffer == '\t') || (*buffer == '\n'))
- buffer++;
-
- return result;
-}
-
-
-//
-// Reloads all cookies from the file '_filename'.
-// On succes 'true' is returned.
-// On failure 'false' is returned.
-bool KCookieJar::loadCookies(const TQString &_filename)
-{
- FILE *fStream = fopen( TQFile::encodeName(_filename), "r");
- if (fStream == 0)
- {
- return false;
- }
-
- time_t curTime = time(0);
-
- char *buffer = new char[READ_BUFFER_SIZE];
-
- bool err = false;
- err = (fgets(buffer, READ_BUFFER_SIZE, fStream) == 0);
-
- int version = 1;
- if (!err)
- {
- if (strcmp(buffer, "# KDE Cookie File\n") == 0)
- {
- // version 1
- }
- else if (sscanf(buffer, "# KDE Cookie File v%d\n", &version) != 1)
- {
- err = true;
- }
- }
-
- if (!err)
- {
- while(fgets(buffer, READ_BUFFER_SIZE, fStream) != 0)
- {
- char *line = buffer;
- // Skip lines which begin with '#' or '['
- if ((line[0] == '#') || (line[0] == '['))
- continue;
-
- const char *host( parseField(line) );
- const char *domain( parseField(line) );
- const char *path( parseField(line) );
- const char *expStr( parseField(line) );
- if (!expStr) continue;
- int expDate = (time_t) strtoul(expStr, 0, 10);
- const char *verStr( parseField(line) );
- if (!verStr) continue;
- int protVer = (time_t) strtoul(verStr, 0, 10);
- const char *name( parseField(line) );
- bool keepQuotes = false;
- bool secure = false;
- bool httpOnly = false;
- bool explicitPath = false;
- const char *value = 0;
- if ((version == 2) || (protVer >= 200))
- {
- if (protVer >= 200)
- protVer -= 200;
- int i = atoi( parseField(line) );
- secure = i & 1;
- httpOnly = i & 2;
- explicitPath = i & 4;
- if (i & 8)
- name = "";
- line[strlen(line)-1] = '\0'; // Strip LF.
- value = line;
- }
- else
- {
- if (protVer >= 100)
- {
- protVer -= 100;
- keepQuotes = true;
- }
- value = parseField(line, keepQuotes);
- secure = atoi( parseField(line) );
- }
-
- // Parse error
- if (!value) continue;
-
- // Expired or parse error
- if ((expDate == 0) || (expDate < curTime))
- continue;
-
- KHttpCookie *cookie = new KHttpCookie(TQString::fromLatin1(host),
- TQString::fromLatin1(domain),
- TQString::fromLatin1(path),
- TQString::fromLatin1(name),
- TQString::fromLatin1(value),
- expDate, protVer,
- secure, httpOnly, explicitPath);
- addCookie(cookie);
- }
- }
- delete [] buffer;
- m_cookiesChanged = false;
-
- fclose( fStream);
- return err;
-}
-
-//
-// Save the cookie configuration
-//
-
-void KCookieJar::saveConfig(KConfig *_config)
-{
- if (!m_configChanged)
- return;
-
- _config->setGroup("Cookie Dialog");
- _config->writeEntry("PreferredPolicy", m_preferredPolicy);
- _config->writeEntry("ShowCookieDetails", m_showCookieDetails );
- _config->setGroup("Cookie Policy");
- _config->writeEntry("CookieGlobalAdvice", adviceToStr( m_globalAdvice));
-
- TQStringList domainSettings;
- for ( TQStringList::Iterator it=m_domainList.begin();
- it != m_domainList.end();
- it++ )
- {
- const TQString &domain = *it;
- KCookieAdvice advice = getDomainAdvice( domain);
- if (advice != KCookieDunno)
- {
- TQString value(domain);
- value += ':';
- value += adviceToStr(advice);
- domainSettings.append(value);
- }
- }
- _config->writeEntry("CookieDomainAdvice", domainSettings);
- _config->sync();
- m_configChanged = false;
-}
-
-
-//
-// Load the cookie configuration
-//
-
-void KCookieJar::loadConfig(KConfig *_config, bool reparse )
-{
- if ( reparse )
- _config->reparseConfiguration();
-
- _config->setGroup("Cookie Dialog");
- m_showCookieDetails = _config->readBoolEntry( "ShowCookieDetails" );
- m_preferredPolicy = _config->readNumEntry( "PreferredPolicy", 0 );
-
- _config->setGroup("Cookie Policy");
- TQStringList domainSettings = _config->readListEntry("CookieDomainAdvice");
- m_rejectCrossDomainCookies = _config->readBoolEntry( "RejectCrossDomainCookies", true );
- m_autoAcceptSessionCookies = _config->readBoolEntry( "AcceptSessionCookies", true );
- m_ignoreCookieExpirationDate = _config->readBoolEntry( "IgnoreExpirationDate", false );
- TQString value = _config->readEntry("CookieGlobalAdvice", L1("Ask"));
- m_globalAdvice = strToAdvice(value);
-
- // Reset current domain settings first.
- for ( TQStringList::Iterator it=m_domainList.begin(); it != m_domainList.end(); )
- {
- // Make sure to update iterator before calling setDomainAdvice()
- // setDomainAdvice() might delete the domain from domainList.
- TQString domain = *it++;
- setDomainAdvice(domain, KCookieDunno);
- }
-
- // Now apply the domain settings read from config file...
- for ( TQStringList::Iterator it=domainSettings.begin();
- it != domainSettings.end(); )
- {
- const TQString &value = *it++;
-
- int sepPos = value.findRev(':');
-
- if (sepPos <= 0)
- continue;
-
- TQString domain(value.left(sepPos));
- KCookieAdvice advice = strToAdvice( value.mid(sepPos + 1) );
- setDomainAdvice(domain, advice);
- }
-}
diff --git a/kioslave/http/kcookiejar/kcookiejar.desktop b/kioslave/http/kcookiejar/kcookiejar.desktop
deleted file mode 100644
index ebc76e2f8..000000000
--- a/kioslave/http/kcookiejar/kcookiejar.desktop
+++ /dev/null
@@ -1,157 +0,0 @@
-[Desktop Entry]
-Type=Service
-Name=KDED Cookie Jar Module
-Name[af]=Kded Koekie Houer Module
-Name[ar]=وحدة Jar لكعكة KDED
-Name[az]=KDED Kökə Jar Modulu
-Name[be]=Модуль "печыва" KDED
-Name[bg]=Модул KDED Cookie Jar
-Name[bn]=KDED কà§à¦•à¦¿ জার মডিউল
-Name[bs]=KDED modul "Tegla sa keksima"
-Name[ca]=Mòdul Jar de cookies per a KDED
-Name[cs]=KDED modul pro cookies
-Name[csb]=Sprôwianié kùszkama
-Name[cy]=Modiwl Jar Cwci KDED
-Name[da]=KDED-cookie-jar-modul
-Name[de]=Cookie-Verwaltung
-Name[el]=ΆÏθÏωμα Cookie Jar του KDED
-Name[eo]=KDED-kuketotraktila modulo
-Name[es]=Módulo Jar de cookies de KDED
-Name[et]=KDED Cookie Jar moodul
-Name[eu]=KDED Cookie Jar modulua
-Name[fa]=پیمانۀ ظر٠کوکی KDED
-Name[fi]=KDED-evästemoduuli
-Name[fr]=Module Jar de cookie KDED
-Name[fy]=KDED-module foar it bewarjen fan Koekjes
-Name[gl]=Módulo Jar de cookies de KDED
-Name[he]=מודול צנצנת העוגיות של KDED
-Name[hi]=KDED कà¥à¤•à¥€ जार मॉडà¥à¤¯à¥‚ल
-Name[hr]=KDED modul za Äuvanje kolaÄića
-Name[hu]=KDED cookie-modul
-Name[id]=Modul Penyimpanan Cookies KDED
-Name[is]=KDED smákökukrukka
-Name[it]=Modulo Jar dei cookie per KDED
-Name[ja]=KDED クッキー Jar モジュール
-Name[ka]=KDED-ის ბმულების Jar მáƒáƒ“ული
-Name[kk]=KDED cookie модулі
-Name[km]=ម៉ូឌុល Jar នៃ​ážáž¼áž‚ី KDED
-Name[ko]=KDED 쿠키 JAR 모듈
-Name[lb]=KDED-Modul fir d'Verwaltung vun de Cookien
-Name[lt]=KDED slapukų rinkinio modulis
-Name[lv]=KDED Cepumu Jar modulis
-Name[mk]=KDED модул Тегла Ñо колачиња
-Name[ms]=Modul Balang Cecikut KDED
-Name[mt]=Modulu tal-"cookies" KDED
-Name[nb]=KDEDs modul for informasjonskapsler (Cookie Jar)
-Name[nds]=KDED-Kookjepleeg
-Name[ne]=KDED कà¥à¤•à¥€ जार मोडà¥à¤¯à¥à¤²
-Name[nl]=KDED-module voor het opslaan van cookies
-Name[nn]=KDED-informasjonskapselmodul
-Name[nso]=Seripa sa Jar ya Cookie ya KDED
-Name[pa]=KDED ਕੂਕੀਜ਼ Jar ਮੈਡੀਊਲ
-Name[pl]=ZarzÄ…dzanie ciasteczkami
-Name[pt]=Módulo de 'Cookies' do KDED
-Name[pt_BR]=Módulo de Cookie Jar do KDED
-Name[ro]=Modul Cookie JAR pentru KDED
-Name[ru]=Служба cookie
-Name[rw]=Igice Jar Inyandikonyakwirema KDED
-Name[se]=KDED gáhkošlihtti-moduvla
-Name[sk]=Modul pre cookies KDED
-Name[sl]=Modul posode za piškotke KDED
-Name[sq]=Modul i KDED-it për Qyp të keksave nga KDED
-Name[sr]=KDED модул тегле за колачиће
-Name[sr@Latn]=KDED modul tegle za kolaÄiće
-Name[sv]=KDED-kakburksmodul
-Name[ta]=KDED தறà¯à®•à®¾à®²à®¿à®• நினைவக சாடி பகà¯à®¤à®¿
-Name[te]=కెడిఈడి à°•à±à°•à±€ జాడి మాడà±à°¯à±‚à°²à±
-Name[tg]=Модули KDED Cookie Jar
-Name[th]=โมดูลโถคุà¸à¸à¸µ KDED
-Name[tr]=KDED Cookie Jar Modülü
-Name[tt]=KDED'nıñ Cookie Modulı
-Name[uk]=Модуль глечика з куками KDED
-Name[uz]=KDED kuki idish moduli
-Name[uz@cyrillic]=KDED куки идиш модули
-Name[ven]=Modulu wa Jar wa Cookie ya KDED
-Name[vi]=Mô-đun Cookie Jar của KDED
-Name[xh]=Isicatshulwa se KDED Cookie Jar
-Name[zh_CN]=KDED Cookie Jar 模å—
-Name[zh_HK]=KDED Cookie Jar 模組
-Name[zh_TW]=KDED Cookie Jar 模組
-Name[zu]=Ingxenye Yojeke ye-Cookie ye-KDED
-Comment=Keeps track of all cookies in the system
-Comment[af]=Hou tred van al die koekies in die stelsel
-Comment[ar]=يراقب جميع الكعكات الموجودة على النظام
-Comment[be]=Захоўвае звеÑткі пра "печыва"
-Comment[bg]=Контрол над вÑички биÑквитки в ÑиÑтемата
-Comment[bn]=সিসà§à¦Ÿà§‡à¦®à§‡ সমসà§à¦¤ কà§à¦•à¦¿-র খোà¦à¦œà¦–বর রাখে
-Comment[bs]=Prati sve kolaÄiće (cookije) na sistemu
-Comment[ca]=Segueix totes les galetes en el sistema
-Comment[cs]=Spravuje Cookies v poÄítaÄi
-Comment[csb]=Trzëmô wszëtczé kùszczi w systemie
-Comment[da]=Holder styr på alle cookier på systemet
-Comment[de]=Verwaltet die Cookies in KDED
-Comment[el]=ΔιατηÏεί αÏχείο από όλα τα cookies στο σÏστημα
-Comment[eo]=Registras ĉiujn kuketojn en la sistemo
-Comment[es]=Mantiene registro todas las cookies en el sistema
-Comment[et]=Hoiab silma peal kõigil süsteemi küpsistel
-Comment[eu]=Sistemaren cookie guztien jarraipena egiten du
-Comment[fa]=رد همۀ کوکیها را در سیستم نگه می‌دارد
-Comment[fi]=Seuraa järjestelmän evästeitä
-Comment[fr]=Conserve une trace de tous les cookies dans le système
-Comment[fy]=Hâld by wer alle koekjes binne
-Comment[gl]=Manter as pegadas de todas as Cookies no sistema
-Comment[he]=מבצע מעקב ×חרי כל העוגיות במערכת
-Comment[hi]=तंतà¥à¤° की सभी कà¥à¤•à¥€ की जानकारी रखता है
-Comment[hr]=VoÄ‘enje evidencije o svim kolaÄićima na sustavu
-Comment[hu]=Nyomon követi a rendszerben létrejövő cookie-kat
-Comment[id]=Menyimpan semua cookies pada sistem
-Comment[is]=Heldur utanum allar smákökur í kerfinu
-Comment[it]=Tiene traccia di tutti i cookie del sistema
-Comment[ja]=システムã®ã™ã¹ã¦ã®ã‚¯ãƒƒã‚­ãƒ¼ã‚’管ç†ã—ã¾ã™
-Comment[ka]=სისტემის ყველრბმულის თვáƒáƒšáƒ›áƒ˜áƒ“ევნებáƒ
-Comment[kk]=Жүйедегі бүкіл cookie файлдарды бақылау
-Comment[km]=រក្សា​ការážáž¶áž˜ážŠáž¶áž“​ážáž¼áž‚ី​ទាំងអស់​ក្នុង​ប្រពáŸáž“្ធ
-Comment[lb]=Iwwerwaacht all d'Cookie vum System
-Comment[lt]=Seka visus slapukus sistemoje
-Comment[lv]=Seko visiem sistÄ“mÄ esoÅ¡ajiem cepumiem
-Comment[mk]=Води Ñметка за Ñите колачиња во ÑиÑтемот
-Comment[ms]=Memerhati semua cecikut dalam sistem
-Comment[nb]=Holder rede på alle informasjonskapsler i systemet
-Comment[nds]=Passt all Kookjes in't Systeem
-Comment[ne]=पà¥à¤°à¤£à¤¾à¤²à¥€à¤®à¤¾ सबै कà¥à¤•à¥€à¤¹à¤°à¥‚को पदचिनà¥à¤¹ राखà¥à¤¦à¤›
-Comment[nl]=Houdt alle cookies in het systeem bij
-Comment[nn]=Held greie på informasjonskapslane
-Comment[pa]=ਸਿਸਟਮ ਦੇ ਸਾਰੇ ਕੂਕੀਜ਼ ਦਾ ਰਿਕਾਰਡ ਰੱਖੋ
-Comment[pl]=Przechowuje wszystkie ciasteczka w systemie
-Comment[pt]=Mantém um registo de todos os 'cookies' no sistema
-Comment[pt_BR]=Mantém informações sobre todos os cookies do sistema
-Comment[ro]=Administrează toate "cookie"-urile din sistem
-Comment[ru]=Управление закладками-cookie в KDED
-Comment[rw]=Iguma inzira y'inyandikonyakwirema zose muri sisitemu
-Comment[se]=HalddaÅ¡a buot diehtoÄoahkuid
-Comment[sk]=Sleduje všetky cookie v systéme
-Comment[sl]=Opazuje vse piškotke v sistemu
-Comment[sr]=Води евиденцију о Ñвим колачићима на ÑиÑтему
-Comment[sr@Latn]=Vodi evidenciju o svim kolaÄićima na sistemu
-Comment[sv]=Håller ordning på alla kakor i systemet
-Comment[ta]=கணினியின௠எலà¯à®²à®¾ தறà¯à®•à®¾à®²à®¿à®• நினைவகஙà¯à®•à®³à¯ˆà®¯à¯à®®à¯ கணà¯à®•à®¾à®£à®¿à®•à¯à®•à®¿à®±à®¤à¯
-Comment[te]=à°µà±à°¯à°µà°¸à±à°¥à°²à±‹à°¨à°¿ à°…à°¨à±à°¨à°¿ à°•à±à°•à±€à°² జాడని à°µà±à°‚à°šà±à°•à±à°‚à°Ÿà±à°‚ది
-Comment[tg]=Гузаргоҳи ҳамаша Cookies дар ÑиÑтема муҳофизат кунед
-Comment[th]=ใช้ติดตามคุà¸à¸à¸µà¸—ั้งหมดในระบบ
-Comment[tr]=Sistemdeki tüm çerezleri izler
-Comment[tt]=Sistemdäge bar cookie'larnı küz astında tota
-Comment[uk]=Стежить за вÑіма куками в ÑиÑтемі
-Comment[uz]=Tizimdagi hamma kukilarni kuzatadi
-Comment[uz@cyrillic]=Тизимдаги ҳамма кукиларни кузатади
-Comment[vi]=Theo dõi các tập tin cookie trong hệ thống.
-Comment[zh_CN]=将全部 cookies 的记录ä¿å­˜åœ¨ç³»ç»Ÿä¸­
-Comment[zh_TW]=追蹤系統所有的 cookies
-ServiceTypes=KDEDModule
-Exec=kcookiejar
-X-DCOP-ServiceType=Unique
-X-TDE-StartupNotify=false
-X-TDE-ModuleType=Library
-X-TDE-Library=kcookiejar
-X-TDE-FactoryName=kcookiejar
-X-TDE-Kded-autoload=false
-X-TDE-Kded-load-on-demand=true
diff --git a/kioslave/http/kcookiejar/kcookiejar.h b/kioslave/http/kcookiejar/kcookiejar.h
deleted file mode 100644
index eb64485ea..000000000
--- a/kioslave/http/kcookiejar/kcookiejar.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- This file is part of the KDE File Manager
-
- Copyright (C) 1998 Waldo Bastian (bastian@kde.org)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation.
-
- This software 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
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this library; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-//----------------------------------------------------------------------------
-//
-// KDE File Manager -- HTTP Cookies
-// $Id$
-
-#ifndef KCOOKIEJAR_H
-#define KCOOKIEJAR_H
-
-#include <tqstring.h>
-#include <tqstringlist.h>
-#include <tqdict.h>
-#include <tqptrlist.h>
-#include <time.h>
-
-class KConfig;
-class KCookieJar;
-class KHttpCookie;
-class KHttpCookieList;
-
-typedef KHttpCookie *KHttpCookiePtr;
-
-enum KCookieAdvice
-{
- KCookieDunno=0,
- KCookieAccept,
- KCookieReject,
- KCookieAsk
-};
-
-class KHttpCookie
-{
- friend class KCookieJar;
- friend class KHttpCookieList;
-
-protected:
- TQString mHost;
- TQString mDomain;
- TQString mPath;
- TQString mName;
- TQString mValue;
- time_t mExpireDate;
- int mProtocolVersion;
- bool mSecure;
- bool mCrossDomain;
- bool mHttpOnly;
- bool mExplicitPath;
- TQValueList<long> mWindowIds;
-
- TQString cookieStr(bool useDOMFormat);
-
-public:
- KHttpCookie(const TQString &_host=TQString::null,
- const TQString &_domain=TQString::null,
- const TQString &_path=TQString::null,
- const TQString &_name=TQString::null,
- const TQString &_value=TQString::null,
- time_t _expireDate=0,
- int _protocolVersion=0,
- bool _secure = false,
- bool _httpOnly = false,
- bool _explicitPath = false);
-
- TQString domain(void) { return mDomain; }
- TQString host(void) { return mHost; }
- TQString path(void) { return mPath; }
- TQString name(void) { return mName; }
- TQString value(void) { return mValue; }
- TQValueList<long> &windowIds(void) { return mWindowIds; }
- void fixDomain(const TQString &domain) { mDomain = domain; }
- time_t expireDate(void) { return mExpireDate; }
- int protocolVersion(void) { return mProtocolVersion; }
- bool isSecure(void) { return mSecure; }
- bool isExpired(time_t currentDate);
- bool isCrossDomain(void) { return mCrossDomain; }
- bool isHttpOnly(void) { return mHttpOnly; }
- bool hasExplicitPath(void) { return mExplicitPath; }
- bool match(const TQString &fqdn, const TQStringList &domainList, const TQString &path);
-};
-
-class KHttpCookieList : public TQPtrList<KHttpCookie>
-{
-public:
- KHttpCookieList() : TQPtrList<KHttpCookie>(), advice( KCookieDunno )
- { }
- virtual ~KHttpCookieList() { }
-
- virtual int compareItems( void * item1, void * item2);
- KCookieAdvice getAdvice(void) { return advice; }
- void setAdvice(KCookieAdvice _advice) { advice = _advice; }
-
-private:
- KCookieAdvice advice;
-};
-
-class KCookieJar
-{
-public:
- /**
- * Constructs a new cookie jar
- *
- * One jar should be enough for all cookies.
- */
- KCookieJar();
-
- /**
- * Destructs the cookie jar
- *
- * Poor little cookies, they will all be eaten by the cookie monster!
- */
- ~KCookieJar();
-
- /**
- * Returns whether the cookiejar has been changed
- */
- bool changed() const { return m_cookiesChanged || m_configChanged; }
-
- /**
- * Store all the cookies in a safe(?) place
- */
- bool saveCookies(const TQString &_filename);
-
- /**
- * Load all the cookies from file and add them to the cookie jar.
- */
- bool loadCookies(const TQString &_filename);
-
- /**
- * Save the cookie configuration
- */
- void saveConfig(KConfig *_config);
-
- /**
- * Load the cookie configuration
- */
- void loadConfig(KConfig *_config, bool reparse = false);
-
- /**
- * Looks for cookies in the cookie jar which are appropriate for _url.
- * Returned is a string containing all appropriate cookies in a format
- * which can be added to a HTTP-header without any additional processing.
- *
- * If @p useDOMFormat is true, the string is formatted in a format
- * in compliance with the DOM standard.
- * @p pendingCookies contains a list of cookies that have not been
- * approved yet by the user but that will be included in the result
- * none the less.
- */
- TQString findCookies(const TQString &_url, bool useDOMFormat, long windowId, KHttpCookieList *pendingCookies=0);
-
- /**
- * This function parses cookie_headers and returns a linked list of
- * valid KHttpCookie objects for all cookies found in cookie_headers.
- * If no cookies could be found 0 is returned.
- *
- * cookie_headers should be a concatenation of all lines of a HTTP-header
- * which start with "Set-Cookie". The lines should be separated by '\n's.
- */
- KHttpCookieList makeCookies(const TQString &_url, const TQCString &cookie_headers, long windowId);
-
- /**
- * This function parses cookie_headers and returns a linked list of
- * valid KHttpCookie objects for all cookies found in cookie_headers.
- * If no cookies could be found 0 is returned.
- *
- * cookie_domstr should be a concatenation of "name=value" pairs, separated
- * by a semicolon ';'.
- */
- KHttpCookieList makeDOMCookies(const TQString &_url, const TQCString &cookie_domstr, long windowId);
-
- /**
- * This function hands a KHttpCookie object over to the cookie jar.
- *
- * On return cookiePtr is set to 0.
- */
- void addCookie(KHttpCookiePtr &cookiePtr);
-
- /**
- * This function advices whether a single KHttpCookie object should
- * be added to the cookie jar.
- *
- * Possible return values are:
- * - KCookieAccept, the cookie should be added
- * - KCookieReject, the cookie should not be added
- * - KCookieAsk, the user should decide what to do
- */
- KCookieAdvice cookieAdvice(KHttpCookiePtr cookiePtr);
-
- /**
- * This function gets the advice for all cookies originating from
- * _domain.
- *
- * - KCookieDunno, no specific advice for _domain
- * - KCookieAccept, accept all cookies for _domain
- * - KCookieReject, reject all cookies for _domain
- * - KCookieAsk, the user decides what to do with cookies for _domain
- */
- KCookieAdvice getDomainAdvice(const TQString &_domain);
-
- /**
- * This function sets the advice for all cookies originating from
- * _domain.
- *
- * _advice can have the following values:
- * - KCookieDunno, no specific advice for _domain
- * - KCookieAccept, accept all cookies for _domain
- * - KCookieReject, reject all cookies for _domain
- * - KCookieAsk, the user decides what to do with cookies for _domain
- */
- void setDomainAdvice(const TQString &_domain, KCookieAdvice _advice);
-
- /**
- * This function sets the advice for all cookies originating from
- * the same domain as _cookie
- *
- * _advice can have the following values:
- * - KCookieDunno, no specific advice for _domain
- * - KCookieAccept, accept all cookies for _domain
- * - KCookieReject, reject all cookies for _domain
- * - KCookieAsk, the user decides what to do with cookies for _domain
- */
- void setDomainAdvice(KHttpCookiePtr _cookie, KCookieAdvice _advice);
-
- /**
- * Get the global advice for cookies
- *
- * The returned advice can have the following values:
- * - KCookieAccept, accept cookies
- * - KCookieReject, reject cookies
- * - KCookieAsk, the user decides what to do with cookies
- *
- * The global advice is used if the domain has no advice set.
- */
- KCookieAdvice getGlobalAdvice() { return m_globalAdvice; }
-
- /**
- * This function sets the global advice for cookies
- *
- * _advice can have the following values:
- * - KCookieAccept, accept cookies
- * - KCookieReject, reject cookies
- * - KCookieAsk, the user decides what to do with cookies
- *
- * The global advice is used if the domain has no advice set.
- */
- void setGlobalAdvice(KCookieAdvice _advice);
-
- /**
- * Get a list of all domains known to the cookie jar.
- * A domain is known to the cookie jar if:
- * - It has a cookie originating from the domain
- * - It has a specific advice set for the domain
- */
- const TQStringList& getDomainList();
-
- /**
- * Get a list of all cookies in the cookie jar originating from _domain.
- */
- const KHttpCookieList *getCookieList(const TQString & _domain,
- const TQString& _fqdn );
-
- /**
- * Remove & delete a cookie from the jar.
- *
- * cookiePtr should be one of the entries in a KHttpCookieList.
- * Update your KHttpCookieList by calling getCookieList after
- * calling this function.
- */
- void eatCookie(KHttpCookiePtr cookiePtr);
-
- /**
- * Remove & delete all cookies for @p domain.
- */
- void eatCookiesForDomain(const TQString &domain);
-
- /**
- * Remove & delete all cookies
- */
- void eatAllCookies();
-
- /**
- * Removes all end of session cookies set by the
- * session @p windId.
- */
- void eatSessionCookies( long windowId );
-
- /**
- * Removes all end of session cookies set by the
- * session @p windId.
- */
- void eatSessionCookies( const TQString& fqdn, long windowId, bool isFQDN = true );
-
- /**
- * Parses _url and returns the FQDN (_fqdn) and path (_path).
- */
- static bool parseURL(const TQString &_url,
- TQString &_fqdn,
- TQString &_path);
-
- /**
- * Returns a list of domains in @p _domainList relevant for this host.
- * The list is sorted with the FQDN listed first and the top-most
- * domain listed last
- */
- void extractDomains(const TQString &_fqdn,
- TQStringList &_domainList);
-
- static TQString adviceToStr(KCookieAdvice _advice);
- static KCookieAdvice strToAdvice(const TQString &_str);
-
- /** Returns the */
- int preferredDefaultPolicy() const { return m_preferredPolicy; }
-
- /** Returns the */
- bool showCookieDetails () const { return m_showCookieDetails; }
-
- /**
- * Sets the user's default preference cookie policy.
- */
- void setPreferredDefaultPolicy (int value) { m_preferredPolicy = value; }
-
- /**
- * Sets the user's preference of level of detail displayed
- * by the cookie dialog.
- */
- void setShowCookieDetails (bool value) { m_showCookieDetails = value; }
-
-protected:
- void stripDomain(const TQString &_fqdn, TQString &_domain);
- TQString stripDomain( KHttpCookiePtr cookiePtr);
-
-protected:
- TQStringList m_domainList;
- KCookieAdvice m_globalAdvice;
- TQDict<KHttpCookieList> m_cookieDomains;
- TQDict<int> m_twoLevelTLD;
-
- bool m_configChanged;
- bool m_cookiesChanged;
- bool m_showCookieDetails;
- bool m_rejectCrossDomainCookies;
- bool m_autoAcceptSessionCookies;
- bool m_ignoreCookieExpirationDate;
-
- int m_preferredPolicy;
-};
-#endif
diff --git a/kioslave/http/kcookiejar/kcookiescfg.upd b/kioslave/http/kcookiejar/kcookiescfg.upd
deleted file mode 100644
index 0ff26bde0..000000000
--- a/kioslave/http/kcookiejar/kcookiescfg.upd
+++ /dev/null
@@ -1,16 +0,0 @@
-# Update for old cookie config files, if present
-Id=kde2.2/b1
-File=kcookiejarrc
-Group=Browser Settings/HTTP,Cookie Policy
-
-# Update cookies config file...
-Id=trinity.1/cvs
-File=kcookiejarrc
-Group=<default>,Cookie Dialog
-Key=DefaultRadioButton,PreferredPolicy
-Key=ShowCookieDetails
-Group=Cookie Policy
-Key=AcceptTempCookies,AcceptSessionCookies
-Key=AutoAcceptSessionCookies,AcceptSessionCookies
-Key=RejectCrossDomain,RejectCrossDomainCookies
-Key=IgnoreCookieExpirationDate,IgnoreExpirationDate
diff --git a/kioslave/http/kcookiejar/kcookieserver.cpp b/kioslave/http/kcookiejar/kcookieserver.cpp
deleted file mode 100644
index da9c16ce7..000000000
--- a/kioslave/http/kcookiejar/kcookieserver.cpp
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
-This file is part of KDE
-
- Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org)
-
-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, 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.
- */
-//----------------------------------------------------------------------------
-//
-// KDE Cookie Server
-// $Id$
-
-#define SAVE_DELAY 3 // Save after 3 minutes
-
-#include <unistd.h>
-
-#include <tqtimer.h>
-#include <tqptrlist.h>
-#include <tqfile.h>
-
-#include <dcopclient.h>
-
-#include <kconfig.h>
-#include <kdebug.h>
-#include <kapplication.h>
-#include <kcmdlineargs.h>
-#include <kstandarddirs.h>
-
-#include "kcookiejar.h"
-#include "kcookiewin.h"
-#include "kcookieserver.h"
-
-extern "C" {
- KDE_EXPORT KDEDModule *create_kcookiejar(const TQCString &name)
- {
- return new KCookieServer(name);
- }
-}
-
-
-// Cookie field indexes
-enum CookieDetails { CF_DOMAIN=0, CF_PATH, CF_NAME, CF_HOST,
- CF_VALUE, CF_EXPIRE, CF_PROVER, CF_SECURE };
-
-
-class CookieRequest {
-public:
- DCOPClient *client;
- DCOPClientTransaction *transaction;
- TQString url;
- bool DOM;
- long windowId;
-};
-
-template class TQPtrList<CookieRequest>;
-
-class RequestList : public TQPtrList<CookieRequest>
-{
-public:
- RequestList() : TQPtrList<CookieRequest>() { }
-};
-
-KCookieServer::KCookieServer(const TQCString &name)
- :KDEDModule(name)
-{
- mOldCookieServer = new DCOPClient(); // backwards compatibility.
- mOldCookieServer->registerAs("kcookiejar", false);
- mOldCookieServer->setDaemonMode( true );
- mCookieJar = new KCookieJar;
- mPendingCookies = new KHttpCookieList;
- mPendingCookies->setAutoDelete(true);
- mRequestList = new RequestList;
- mAdvicePending = false;
- mTimer = new TQTimer();
- connect( mTimer, TQT_SIGNAL( timeout()), TQT_SLOT( slotSave()));
- mConfig = new KConfig("kcookiejarrc");
- mCookieJar->loadConfig( mConfig );
-
- TQString filename = locateLocal("data", "kcookiejar/cookies");
-
- // Stay backwards compatible!
- TQString filenameOld = locate("data", "kfm/cookies");
- if (!filenameOld.isEmpty())
- {
- mCookieJar->loadCookies( filenameOld );
- if (mCookieJar->saveCookies( filename))
- {
- unlink(TQFile::encodeName(filenameOld)); // Remove old kfm cookie file
- }
- }
- else
- {
- mCookieJar->loadCookies( filename);
- }
- connect(this, TQT_SIGNAL(windowUnregistered(long)),
- this, TQT_SLOT(slotDeleteSessionCookies(long)));
-}
-
-KCookieServer::~KCookieServer()
-{
- if (mCookieJar->changed())
- slotSave();
- delete mOldCookieServer;
- delete mCookieJar;
- delete mTimer;
- delete mPendingCookies;
- delete mConfig;
-}
-
-bool KCookieServer::cookiesPending( const TQString &url, KHttpCookieList *cookieList )
-{
- TQString fqdn;
- TQStringList domains;
- TQString path;
- // Check whether 'url' has cookies on the pending list
- if (mPendingCookies->isEmpty())
- return false;
- if (!KCookieJar::parseURL(url, fqdn, path))
- return false;
-
- mCookieJar->extractDomains( fqdn, domains );
- for( KHttpCookie *cookie = mPendingCookies->first();
- cookie != 0L;
- cookie = mPendingCookies->next())
- {
- if (cookie->match( fqdn, domains, path))
- {
- if (!cookieList)
- return true;
- cookieList->append(cookie);
- }
- }
- if (!cookieList)
- return false;
- return cookieList->isEmpty();
-}
-
-void KCookieServer::addCookies( const TQString &url, const TQCString &cookieHeader,
- long windowId, bool useDOMFormat )
-{
- KHttpCookieList cookieList;
- if (useDOMFormat)
- cookieList = mCookieJar->makeDOMCookies(url, cookieHeader, windowId);
- else
- cookieList = mCookieJar->makeCookies(url, cookieHeader, windowId);
-
- checkCookies(&cookieList);
-
- for(KHttpCookiePtr cookie = cookieList.first(); cookie; cookie = cookieList.first())
- mPendingCookies->append(cookieList.take());
-
- if (!mAdvicePending)
- {
- mAdvicePending = true;
- while (!mPendingCookies->isEmpty())
- {
- checkCookies(0);
- }
- mAdvicePending = false;
- }
-}
-
-void KCookieServer::checkCookies( KHttpCookieList *cookieList)
-{
- KHttpCookieList *list;
-
- if (cookieList)
- list = cookieList;
- else
- list = mPendingCookies;
-
- KHttpCookiePtr cookie = list->first();
- while (cookie)
- {
- kdDebug(7104) << "checkCookies: Asking cookie advice for " << cookie->host() << endl;
- KCookieAdvice advice = mCookieJar->cookieAdvice(cookie);
- switch(advice)
- {
- case KCookieAccept:
- list->take();
- mCookieJar->addCookie(cookie);
- cookie = list->current();
- break;
-
- case KCookieReject:
- list->take();
- delete cookie;
- cookie = list->current();
- break;
-
- default:
- cookie = list->next();
- break;
- }
- }
-
- if (cookieList || list->isEmpty())
- return;
-
- KHttpCookiePtr currentCookie = mPendingCookies->first();
-
- KHttpCookieList currentList;
- currentList.append(currentCookie);
- TQString currentHost = currentCookie->host();
-
- cookie = mPendingCookies->next();
- while (cookie)
- {
- if (cookie->host() == currentHost)
- {
- currentList.append(cookie);
- }
- cookie = mPendingCookies->next();
- }
-
- KCookieWin *kw = new KCookieWin( 0L, currentList,
- mCookieJar->preferredDefaultPolicy(),
- mCookieJar->showCookieDetails() );
- KCookieAdvice userAdvice = kw->advice(mCookieJar, currentCookie);
- delete kw;
- // Save the cookie config if it has changed
- mCookieJar->saveConfig( mConfig );
-
- // Apply the user's choice to all cookies that are currently
- // queued for this host.
- cookie = mPendingCookies->first();
- while (cookie)
- {
- if (cookie->host() == currentHost)
- {
- switch(userAdvice)
- {
- case KCookieAccept:
- mPendingCookies->take();
- mCookieJar->addCookie(cookie);
- cookie = mPendingCookies->current();
- break;
-
- case KCookieReject:
- mPendingCookies->take();
- delete cookie;
- cookie = mPendingCookies->current();
- break;
-
- default:
- tqWarning(__FILE__":%d Problem!", __LINE__);
- cookie = mPendingCookies->next();
- break;
- }
- }
- else
- {
- cookie = mPendingCookies->next();
- }
- }
-
-
- // Check if we can handle any request
- for ( CookieRequest *request = mRequestList->first(); request;)
- {
- if (!cookiesPending( request->url ))
- {
- TQCString replyType;
- TQByteArray replyData;
- TQString res = mCookieJar->findCookies( request->url, request->DOM, request->windowId );
-
- TQDataStream stream2(replyData, IO_WriteOnly);
- stream2 << res;
- replyType = "TQString";
- request->client->endTransaction( request->transaction,
- replyType, replyData);
- CookieRequest *tmp = request;
- request = mRequestList->next();
- mRequestList->removeRef( tmp );
- delete tmp;
- }
- else
- {
- request = mRequestList->next();
- }
- }
- if (mCookieJar->changed())
- saveCookieJar();
-}
-
-void KCookieServer::slotSave()
-{
- TQString filename = locateLocal("data", "kcookiejar/cookies");
- mCookieJar->saveCookies(filename);
-}
-
-void KCookieServer::saveCookieJar()
-{
- if( mTimer->isActive() )
- return;
-
- mTimer->start( 1000*60*SAVE_DELAY, true );
-}
-
-void KCookieServer::putCookie( TQStringList& out, KHttpCookie *cookie,
- const TQValueList<int>& fields )
-{
- TQValueList<int>::ConstIterator i = fields.begin();
- for ( ; i != fields.end(); ++i )
- {
- switch(*i)
- {
- case CF_DOMAIN :
- out << cookie->domain();
- break;
- case CF_NAME :
- out << cookie->name();
- break;
- case CF_PATH :
- out << cookie->path();
- break;
- case CF_HOST :
- out << cookie->host();
- break;
- case CF_VALUE :
- out << cookie->value();
- break;
- case CF_EXPIRE :
- out << TQString::number(cookie->expireDate());
- break;
- case CF_PROVER :
- out << TQString::number(cookie->protocolVersion());
- break;
- case CF_SECURE :
- out << TQString::number( cookie->isSecure() ? 1 : 0 );
- break;
- default :
- out << TQString::null;
- }
- }
-}
-
-bool KCookieServer::cookieMatches( KHttpCookiePtr c,
- TQString domain, TQString fqdn,
- TQString path, TQString name )
-{
- if( c )
- {
- bool hasDomain = !domain.isEmpty();
- return
- ((hasDomain && c->domain() == domain) ||
- fqdn == c->host()) &&
- (c->path() == path) &&
- (c->name() == name) &&
- (!c->isExpired(time(0)));
- }
- return false;
-}
-
-// DCOP function
-TQString
-KCookieServer::findCookies(TQString url)
-{
- return findCookies(url, 0);
-}
-
-// DCOP function
-TQString
-KCookieServer::findCookies(TQString url, long windowId)
-{
- if (cookiesPending(url))
- {
- CookieRequest *request = new CookieRequest;
- request->client = callingDcopClient();
- request->transaction = request->client->beginTransaction();
- request->url = url;
- request->DOM = false;
- request->windowId = windowId;
- mRequestList->append( request );
- return TQString::null; // Talk to you later :-)
- }
-
- TQString cookies = mCookieJar->findCookies(url, false, windowId);
-
- if (mCookieJar->changed())
- saveCookieJar();
-
- return cookies;
-}
-
-// DCOP function
-TQStringList
-KCookieServer::findDomains()
-{
- TQStringList result;
- const TQStringList domains = mCookieJar->getDomainList();
- for ( TQStringList::ConstIterator domIt = domains.begin();
- domIt != domains.end(); ++domIt )
- {
- // Ignore domains that have policy set for but contain
- // no cookies whatsoever...
- const KHttpCookieList* list = mCookieJar->getCookieList(*domIt, "");
- if ( list && !list->isEmpty() )
- result << *domIt;
- }
- return result;
-}
-
-// DCOP function
-TQStringList
-KCookieServer::findCookies(TQValueList<int> fields,
- TQString domain,
- TQString fqdn,
- TQString path,
- TQString name)
-{
- TQStringList result;
- bool allDomCookies = name.isEmpty();
-
- const KHttpCookieList* list = mCookieJar->getCookieList(domain, fqdn);
- if ( list && !list->isEmpty() )
- {
- TQPtrListIterator<KHttpCookie>it( *list );
- for ( ; it.current(); ++it )
- {
- if ( !allDomCookies )
- {
- if ( cookieMatches(it.current(), domain, fqdn, path, name) )
- {
- putCookie(result, it.current(), fields);
- break;
- }
- }
- else
- putCookie(result, it.current(), fields);
- }
- }
- return result;
-}
-
-// DCOP function
-TQString
-KCookieServer::findDOMCookies(TQString url)
-{
- return findDOMCookies(url, 0);
-}
-
-// DCOP function
-TQString
-KCookieServer::findDOMCookies(TQString url, long windowId)
-{
- // We don't wait for pending cookies because it locks up konqueror
- // which can cause a deadlock if it happens to have a popup-menu up.
- // Instead we just return pending cookies as if they had been accepted already.
- KHttpCookieList pendingCookies;
- cookiesPending(url, &pendingCookies);
-
- return mCookieJar->findCookies(url, true, windowId, &pendingCookies);
-}
-
-// DCOP function
-void
-KCookieServer::addCookies(TQString arg1, TQCString arg2, long arg3)
-{
- addCookies(arg1, arg2, arg3, false);
-}
-
-// DCOP function
-void
-KCookieServer::deleteCookie(TQString domain, TQString fqdn,
- TQString path, TQString name)
-{
- const KHttpCookieList* list = mCookieJar->getCookieList( domain, fqdn );
- if ( list && !list->isEmpty() )
- {
- TQPtrListIterator<KHttpCookie>it (*list);
- for ( ; it.current(); ++it )
- {
- if( cookieMatches(it.current(), domain, fqdn, path, name) )
- {
- mCookieJar->eatCookie( it.current() );
- saveCookieJar();
- break;
- }
- }
- }
-}
-
-// DCOP function
-void
-KCookieServer::deleteCookiesFromDomain(TQString domain)
-{
- mCookieJar->eatCookiesForDomain(domain);
- saveCookieJar();
-}
-
-
-// Qt function
-void
-KCookieServer::slotDeleteSessionCookies( long windowId )
-{
- deleteSessionCookies(windowId);
-}
-
-// DCOP function
-void
-KCookieServer::deleteSessionCookies( long windowId )
-{
- mCookieJar->eatSessionCookies( windowId );
- saveCookieJar();
-}
-
-void
-KCookieServer::deleteSessionCookiesFor(TQString fqdn, long windowId)
-{
- mCookieJar->eatSessionCookies( fqdn, windowId );
- saveCookieJar();
-}
-
-// DCOP function
-void
-KCookieServer::deleteAllCookies()
-{
- mCookieJar->eatAllCookies();
- saveCookieJar();
-}
-
-// DCOP function
-void
-KCookieServer::addDOMCookies(TQString arg1, TQCString arg2, long arg3)
-{
- addCookies(arg1, arg2, arg3, true);
-}
-
-// DCOP function
-void
-KCookieServer::setDomainAdvice(TQString url, TQString advice)
-{
- TQString fqdn;
- TQString dummy;
- if (KCookieJar::parseURL(url, fqdn, dummy))
- {
- TQStringList domains;
- mCookieJar->extractDomains(fqdn, domains);
-
- mCookieJar->setDomainAdvice(domains[domains.count() > 3 ? 3 : 0],
- KCookieJar::strToAdvice(advice));
- // Save the cookie config if it has changed
- mCookieJar->saveConfig( mConfig );
- }
-}
-
-// DCOP function
-TQString
-KCookieServer::getDomainAdvice(TQString url)
-{
- KCookieAdvice advice = KCookieDunno;
- TQString fqdn;
- TQString dummy;
- if (KCookieJar::parseURL(url, fqdn, dummy))
- {
- TQStringList domains;
- mCookieJar->extractDomains(fqdn, domains);
-
- TQStringList::ConstIterator it = domains.begin();
- while ( (advice == KCookieDunno) && (it != domains.end()) )
- {
- // Always check advice in both ".domain" and "domain". Note
- // that we only want to check "domain" if it matches the
- // fqdn of the requested URL.
- if ( (*it)[0] == '.' || (*it) == fqdn )
- advice = mCookieJar->getDomainAdvice(*it);
- ++it;
- }
- if (advice == KCookieDunno)
- advice = mCookieJar->getGlobalAdvice();
- }
- return KCookieJar::adviceToStr(advice);
-}
-
-// DCOP function
-void
-KCookieServer::reloadPolicy()
-{
- mCookieJar->loadConfig( mConfig, true );
-}
-
-// DCOP function
-void
-KCookieServer::shutdown()
-{
- deleteLater();
-}
-
-#include "kcookieserver.moc"
-
diff --git a/kioslave/http/kcookiejar/kcookieserver.h b/kioslave/http/kcookiejar/kcookieserver.h
deleted file mode 100644
index 0c36f10b1..000000000
--- a/kioslave/http/kcookiejar/kcookieserver.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- This file is part of the KDE File Manager
-
- Copyright (C) 1998 Waldo Bastian (bastian@kde.org)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation.
-
- This software 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
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this library; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-//----------------------------------------------------------------------------
-//
-// KDE Cookie Server
-// $Id$
-
-#ifndef KCOOKIESERVER_H
-#define KCOOKIESERVER_H
-
-#include <tqstringlist.h>
-#include <kded/kdedmodule.h>
-
-class KHttpCookieList;
-class KCookieJar;
-class KHttpCookie;
-class TQTimer;
-class RequestList;
-class DCOPClient;
-class KConfig;
-
-class KCookieServer : public KDEDModule
-{
- Q_OBJECT
- K_DCOP
-public:
- KCookieServer(const TQCString &);
- ~KCookieServer();
-
-k_dcop:
- TQString findCookies(TQString);
- TQString findCookies(TQString, long);
- TQStringList findDomains();
- TQStringList findCookies(TQValueList<int>,TQString,TQString,TQString,TQString);
- TQString findDOMCookies(TQString);
- TQString findDOMCookies(TQString, long);
- void addCookies(TQString, TQCString, long);
- void deleteCookie(TQString, TQString, TQString, TQString);
- void deleteCookiesFromDomain(TQString);
- void deleteSessionCookies(long);
- void deleteSessionCookiesFor(TQString, long);
- void deleteAllCookies();
- void addDOMCookies(TQString, TQCString, long);
- /**
- * Sets the cookie policy for the domain associated with the specified URL.
- */
- void setDomainAdvice(TQString url, TQString advice);
- /**
- * Returns the cookie policy in effect for the specified URL.
- */
- TQString getDomainAdvice(TQString url);
- void reloadPolicy();
- void shutdown();
-
-public:
- bool cookiesPending(const TQString &url, KHttpCookieList *cookieList=0);
- void addCookies(const TQString &url, const TQCString &cookieHeader,
- long windowId, bool useDOMFormat);
- void checkCookies(KHttpCookieList *cookieList);
-
-public slots:
- void slotSave();
- void slotDeleteSessionCookies(long);
-
-protected:
- KCookieJar *mCookieJar;
- KHttpCookieList *mPendingCookies;
- RequestList *mRequestList;
- TQTimer *mTimer;
- bool mAdvicePending;
- DCOPClient *mOldCookieServer;
- KConfig *mConfig;
-
-private:
- virtual int newInstance(TQValueList<TQCString>) { return 0; }
- bool cookieMatches(KHttpCookie*, TQString, TQString, TQString, TQString);
- void putCookie(TQStringList&, KHttpCookie*, const TQValueList<int>&);
- void saveCookieJar();
-};
-
-#endif
diff --git a/kioslave/http/kcookiejar/kcookiewin.cpp b/kioslave/http/kcookiejar/kcookiewin.cpp
deleted file mode 100644
index ca86e0a16..000000000
--- a/kioslave/http/kcookiejar/kcookiewin.cpp
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
-This file is part of KDE
-
- Copyright (C) 2000- Waldo Bastian <bastian@kde.org>
- Copyright (C) 2000- Dawit Alemayehu <adawit@kde.org>
-
-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, 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.
-*/
-//----------------------------------------------------------------------------
-//
-// KDE File Manager -- HTTP Cookie Dialogs
-// $Id$
-
-// The purpose of the QT_NO_TOOLTIP and QT_NO_WHATSTHIS ifdefs is because
-// this file is also used in Konqueror/Embedded. One of the aims of
-// Konqueror/Embedded is to be a small as possible to fit on embedded
-// devices. For this it's also useful to strip out unneeded features of
-// Qt, like for example TQToolTip or TQWhatsThis. The availability (or the
-// lack thereof) can be determined using these preprocessor defines.
-// The same applies to the QT_NO_ACCEL ifdef below. I hope it doesn't make
-// too much trouble... (Simon)
-
-#include <tqhbox.h>
-#include <tqvbox.h>
-#include <tqaccel.h>
-#include <tqlabel.h>
-#include <tqwidget.h>
-#include <tqlayout.h>
-#include <tqgroupbox.h>
-#include <tqdatetime.h>
-#include <tqmessagebox.h>
-#include <tqpushbutton.h>
-#include <tqradiobutton.h>
-#include <tqvbuttongroup.h>
-
-#ifndef QT_NO_TOOLTIP
-#include <tqtooltip.h>
-#endif
-
-#ifndef QT_NO_WHATSTHIS
-#include <tqwhatsthis.h>
-#endif
-
-#include <kidna.h>
-#include <twin.h>
-#include <klocale.h>
-#include <kglobal.h>
-#include <kurllabel.h>
-#include <klineedit.h>
-#include <kiconloader.h>
-#include <kapplication.h>
-
-#ifdef Q_WS_X11
-#include <X11/Xlib.h>
-#endif
-
-#include "kcookiejar.h"
-#include "kcookiewin.h"
-
-KCookieWin::KCookieWin( TQWidget *parent, KHttpCookieList cookieList,
- int defaultButton, bool showDetails )
- :KDialog( parent, "cookiealert", true )
-{
-#ifndef Q_WS_QWS //FIXME(E): Implement for Qt Embedded
- setCaption( i18n("Cookie Alert") );
- setIcon( SmallIcon("cookie") );
- // all cookies in the list should have the same window at this time, so let's take the first
-# ifdef Q_WS_X11
- if( cookieList.first()->windowIds().count() > 0 )
- {
- XSetTransientForHint( tqt_xdisplay(), winId(), cookieList.first()->windowIds().first());
- }
- else
- {
- // No window associated... make sure the user notices our dialog.
- KWin::setState( winId(), NET::KeepAbove );
- kapp->updateUserTimestamp();
- }
-# endif
-#endif
- // Main widget's layout manager...
- TQVBoxLayout* vlayout = new TQVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint() );
- vlayout->setResizeMode( TQLayout::Fixed );
-
- // Cookie image and message to user
- TQHBox* hBox = new TQHBox( this );
- hBox->setSpacing( KDialog::spacingHint() );
- TQLabel* icon = new TQLabel( hBox );
- icon->setPixmap( TQMessageBox::standardIcon(TQMessageBox::Warning) );
- icon->setAlignment( Qt::AlignCenter );
- icon->setFixedSize( 2*icon->sizeHint() );
-
- int count = cookieList.count();
-
- TQVBox* vBox = new TQVBox( hBox );
- TQString txt = i18n("You received a cookie from",
- "You received %n cookies from", count);
- TQLabel* lbl = new TQLabel( txt, vBox );
- lbl->setAlignment( Qt::AlignCenter );
- KHttpCookiePtr cookie = cookieList.first();
-
- TQString host (cookie->host());
- int pos = host.find(':');
- if ( pos > 0 )
- {
- TQString portNum = host.left(pos);
- host.remove(0, pos+1);
- host += ':';
- host += portNum;
- }
-
- txt = TQString("<b>%1</b>").arg( KIDNA::toUnicode(host) );
- if (cookie->isCrossDomain())
- txt += i18n(" <b>[Cross Domain!]</b>");
- lbl = new TQLabel( txt, vBox );
- lbl->setAlignment( Qt::AlignCenter );
- lbl = new TQLabel( i18n("Do you want to accept or reject?"), vBox );
- lbl->setAlignment( Qt::AlignCenter );
- vlayout->addWidget( hBox, 0, Qt::AlignLeft );
-
- // Cookie Details dialog...
- m_detailView = new KCookieDetail( cookieList, count, this );
- vlayout->addWidget( m_detailView );
- m_showDetails = showDetails;
- m_showDetails ? m_detailView->show():m_detailView->hide();
-
- // Cookie policy choice...
- m_btnGrp = new TQVButtonGroup( i18n("Apply Choice To"), this );
- m_btnGrp->setRadioButtonExclusive( true );
-
- txt = (count == 1)? i18n("&Only this cookie") : i18n("&Only these cookies");
- TQRadioButton* rb = new TQRadioButton( txt, m_btnGrp );
-#ifndef QT_NO_WHATSTHIS
- TQWhatsThis::add( rb, i18n("Select this option to accept/reject only this cookie. "
- "You will be prompted if another cookie is received. "
- "<em>(see WebBrowsing/Cookies in the Control Center)</em>." ) );
-#endif
- m_btnGrp->insert( rb );
- rb = new TQRadioButton( i18n("All cookies from this do&main"), m_btnGrp );
-#ifndef QT_NO_WHATSTHIS
- TQWhatsThis::add( rb, i18n("Select this option to accept/reject all cookies from "
- "this site. Choosing this option will add a new policy for "
- "the site this cookie originated from. This policy will be "
- "permanent until you manually change it from the Control Center "
- "<em>(see WebBrowsing/Cookies in the Control Center)</em>.") );
-#endif
- m_btnGrp->insert( rb );
- rb = new TQRadioButton( i18n("All &cookies"), m_btnGrp );
-#ifndef QT_NO_WHATSTHIS
- TQWhatsThis::add( rb, i18n("Select this option to accept/reject all cookies from "
- "anywhere. Choosing this option will change the global "
- "cookie policy set in the Control Center for all cookies "
- "<em>(see WebBrowsing/Cookies in the Control Center)</em>.") );
-#endif
- m_btnGrp->insert( rb );
- vlayout->addWidget( m_btnGrp );
-
- if ( defaultButton > -1 && defaultButton < 3 )
- m_btnGrp->setButton( defaultButton );
- else
- m_btnGrp->setButton( 1 );
-
- // Accept/Reject buttons
- TQWidget* bbox = new TQWidget( this );
- TQBoxLayout* bbLay = new TQHBoxLayout( bbox );
- bbLay->setSpacing( KDialog::spacingHint() );
- TQPushButton* btn = new TQPushButton( i18n("&Accept"), bbox );
- btn->setDefault( true );
- btn->setFocus();
- connect( btn, TQT_SIGNAL(clicked()), TQT_SLOT(accept()) );
- bbLay->addWidget( btn );
- btn = new TQPushButton( i18n("&Reject"), bbox );
- connect( btn, TQT_SIGNAL(clicked()), TQT_SLOT(reject()) );
- bbLay->addWidget( btn );
- bbLay->addStretch( 1 );
-#ifndef QT_NO_ACCEL
- TQAccel* a = new TQAccel( this );
- a->connectItem( a->insertItem(Qt::Key_Escape), btn, TQT_SLOT(animateClick()) );
-#endif
-
- m_button = new TQPushButton( bbox );
- m_button->setText( m_showDetails ? i18n("&Details <<"):i18n("&Details >>") );
- connect( m_button, TQT_SIGNAL(clicked()), TQT_SLOT(slotCookieDetails()) );
- bbLay->addWidget( m_button );
-#ifndef QT_NO_WHATSTHIS
- TQWhatsThis::add( m_button, i18n("See or modify the cookie information") );
-#endif
-
-
- vlayout->addWidget( bbox );
- setFixedSize( sizeHint() );
-}
-
-KCookieWin::~KCookieWin()
-{
-}
-
-void KCookieWin::slotCookieDetails()
-{
- if ( m_detailView->isVisible() )
- {
- m_detailView->setMaximumSize( 0, 0 );
- m_detailView->adjustSize();
- m_detailView->hide();
- m_button->setText( i18n( "&Details >>" ) );
- m_showDetails = false;
- }
- else
- {
- m_detailView->setMaximumSize( 1000, 1000 );
- m_detailView->adjustSize();
- m_detailView->show();
- m_button->setText( i18n( "&Details <<" ) );
- m_showDetails = true;
- }
-}
-
-KCookieAdvice KCookieWin::advice( KCookieJar *cookiejar, KHttpCookie* cookie )
-{
- int result = exec();
-
- cookiejar->setShowCookieDetails ( m_showDetails );
-
- KCookieAdvice advice = (result==TQDialog::Accepted) ? KCookieAccept:KCookieReject;
-
- int preferredPolicy = m_btnGrp->id( m_btnGrp->selected() );
- cookiejar->setPreferredDefaultPolicy( preferredPolicy );
-
- switch ( preferredPolicy )
- {
- case 2:
- cookiejar->setGlobalAdvice( advice );
- break;
- case 1:
- cookiejar->setDomainAdvice( cookie, advice );
- break;
- case 0:
- default:
- break;
- }
- return advice;
-}
-
-KCookieDetail::KCookieDetail( KHttpCookieList cookieList, int cookieCount,
- TQWidget* parent, const char* name )
- :TQGroupBox( parent, name )
-{
- setTitle( i18n("Cookie Details") );
- TQGridLayout* grid = new TQGridLayout( this, 9, 2,
- KDialog::spacingHint(),
- KDialog::marginHint() );
- grid->addRowSpacing( 0, fontMetrics().lineSpacing() );
- grid->setColStretch( 1, 3 );
-
- TQLabel* label = new TQLabel( i18n("Name:"), this );
- grid->addWidget( label, 1, 0 );
- m_name = new KLineEdit( this );
- m_name->setReadOnly( true );
- m_name->setMaximumWidth( fontMetrics().maxWidth() * 25 );
- grid->addWidget( m_name, 1 ,1 );
-
- //Add the value
- label = new TQLabel( i18n("Value:"), this );
- grid->addWidget( label, 2, 0 );
- m_value = new KLineEdit( this );
- m_value->setReadOnly( true );
- m_value->setMaximumWidth( fontMetrics().maxWidth() * 25 );
- grid->addWidget( m_value, 2, 1);
-
- label = new TQLabel( i18n("Expires:"), this );
- grid->addWidget( label, 3, 0 );
- m_expires = new KLineEdit( this );
- m_expires->setReadOnly( true );
- m_expires->setMaximumWidth(fontMetrics().maxWidth() * 25 );
- grid->addWidget( m_expires, 3, 1);
-
- label = new TQLabel( i18n("Path:"), this );
- grid->addWidget( label, 4, 0 );
- m_path = new KLineEdit( this );
- m_path->setReadOnly( true );
- m_path->setMaximumWidth( fontMetrics().maxWidth() * 25 );
- grid->addWidget( m_path, 4, 1);
-
- label = new TQLabel( i18n("Domain:"), this );
- grid->addWidget( label, 5, 0 );
- m_domain = new KLineEdit( this );
- m_domain->setReadOnly( true );
- m_domain->setMaximumWidth( fontMetrics().maxWidth() * 25 );
- grid->addWidget( m_domain, 5, 1);
-
- label = new TQLabel( i18n("Exposure:"), this );
- grid->addWidget( label, 6, 0 );
- m_secure = new KLineEdit( this );
- m_secure->setReadOnly( true );
- m_secure->setMaximumWidth( fontMetrics().maxWidth() * 25 );
- grid->addWidget( m_secure, 6, 1 );
-
- if ( cookieCount > 1 )
- {
- TQPushButton* btnNext = new TQPushButton( i18n("Next cookie","&Next >>"), this );
- btnNext->setFixedSize( btnNext->sizeHint() );
- grid->addMultiCellWidget( btnNext, 8, 8, 0, 1 );
- connect( btnNext, TQT_SIGNAL(clicked()), TQT_SLOT(slotNextCookie()) );
-#ifndef QT_NO_TOOLTIP
- TQToolTip::add( btnNext, i18n("Show details of the next cookie") );
-#endif
- }
- m_cookieList = cookieList;
- m_cookie = 0;
- slotNextCookie();
-}
-
-KCookieDetail::~KCookieDetail()
-{
-}
-
-void KCookieDetail::slotNextCookie()
-{
- KHttpCookiePtr cookie = m_cookieList.first();
- if (m_cookie) while(cookie)
- {
- if (cookie == m_cookie)
- {
- cookie = m_cookieList.next();
- break;
- }
- cookie = m_cookieList.next();
- }
- m_cookie = cookie;
- if (!m_cookie)
- m_cookie = m_cookieList.first();
-
- if ( m_cookie )
- {
- m_name->setText( m_cookie->name() );
- m_value->setText( ( m_cookie->value() ) );
- if ( m_cookie->domain().isEmpty() )
- m_domain->setText( i18n("Not specified") );
- else
- m_domain->setText( m_cookie->domain() );
- m_path->setText( m_cookie->path() );
- TQDateTime cookiedate;
- cookiedate.setTime_t( m_cookie->expireDate() );
- if ( m_cookie->expireDate() )
- m_expires->setText( KGlobal::locale()->formatDateTime(cookiedate) );
- else
- m_expires->setText( i18n("End of Session") );
- TQString sec;
- if (m_cookie->isSecure())
- {
- if (m_cookie->isHttpOnly())
- sec = i18n("Secure servers only");
- else
- sec = i18n("Secure servers, page scripts");
- }
- else
- {
- if (m_cookie->isHttpOnly())
- sec = i18n("Servers");
- else
- sec = i18n("Servers, page scripts");
- }
- m_secure->setText( sec );
- }
-}
-
-#include "kcookiewin.moc"
diff --git a/kioslave/http/kcookiejar/kcookiewin.h b/kioslave/http/kcookiejar/kcookiewin.h
deleted file mode 100644
index d739732dc..000000000
--- a/kioslave/http/kcookiejar/kcookiewin.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- This file is part of the KDE File Manager
-
- Copyright (C) 1998- Waldo Bastian (bastian@kde.org)
- Copyright (C) 2000- Dawit Alemayehu (adawit@kde.org)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This software 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
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this library; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-//----------------------------------------------------------------------------
-//
-// KDE File Manager -- HTTP Cookie Dialogs
-// $Id$
-
-#ifndef _KCOOKIEWIN_H_
-#define _KCOOKIEWIN_H_
-
-#include <tqgroupbox.h>
-
-#include <kdialog.h>
-#include "kcookiejar.h"
-
-class KLineEdit;
-class TQPushButton;
-class TQVButtonGroup;
-class KURLLabel;
-
-class KCookieDetail : public TQGroupBox
-{
- Q_OBJECT
-
-public :
- KCookieDetail( KHttpCookieList cookieList, int cookieCount, TQWidget *parent=0,
- const char *name=0 );
- ~KCookieDetail();
-
-private :
- KLineEdit* m_name;
- KLineEdit* m_value;
- KLineEdit* m_expires;
- KLineEdit* m_domain;
- KLineEdit* m_path;
- KLineEdit* m_secure;
-
- KHttpCookieList m_cookieList;
- KHttpCookiePtr m_cookie;
-
-private slots:
- void slotNextCookie();
-};
-
-class KCookieWin : public KDialog
-{
- Q_OBJECT
-
-public :
- KCookieWin( TQWidget *parent, KHttpCookieList cookieList, int defaultButton=0,
- bool showDetails=false );
- ~KCookieWin();
-
- KCookieAdvice advice( KCookieJar *cookiejar, KHttpCookie* cookie );
-
-private :
- TQPushButton* m_button;
- TQVButtonGroup* m_btnGrp;
- KCookieDetail* m_detailView;
- bool m_showDetails;
-
-private slots:
- void slotCookieDetails();
-};
-#endif
diff --git a/kioslave/http/kcookiejar/main.cpp b/kioslave/http/kcookiejar/main.cpp
deleted file mode 100644
index 67177823b..000000000
--- a/kioslave/http/kcookiejar/main.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-This file is part of KDE
-
- Copyright (C) 1998-2000 Waldo Bastian (bastian@kde.org)
-
-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, 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.
-*/
-
-#include <dcopclient.h>
-#include <kcmdlineargs.h>
-#include <klocale.h>
-#include <kapplication.h>
-
-static const char description[] =
- I18N_NOOP("HTTP Cookie Daemon");
-
-static const char version[] = "1.0";
-
-static const KCmdLineOptions options[] =
-{
- { "shutdown", I18N_NOOP("Shut down cookie jar"), 0 },
- { "remove <domain>", I18N_NOOP("Remove cookies for domain"), 0 },
- { "remove-all", I18N_NOOP("Remove all cookies"), 0 },
- { "reload-config", I18N_NOOP("Reload configuration file"), 0 },
- KCmdLineLastOption
-};
-
-extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
-{
- KLocale::setMainCatalogue("tdelibs");
- KCmdLineArgs::init(argc, argv, "kcookiejar", I18N_NOOP("HTTP cookie daemon"),
- description, version);
-
- KCmdLineArgs::addCmdLineOptions( options );
-
- KInstance a("kcookiejar");
-
- kapp->dcopClient()->attach();
-
- KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
- TQCString replyType;
- TQByteArray replyData;
- if (args->isSet("remove-all"))
- {
- kapp->dcopClient()->call( "kded", "kcookiejar", "deleteAllCookies()", TQByteArray(), replyType, replyData);
- }
- if (args->isSet("remove"))
- {
- TQString domain = args->getOption("remove");
- TQByteArray params;
- TQDataStream stream(params, IO_WriteOnly);
- stream << domain;
- kapp->dcopClient()->call( "kded", "kcookiejar", "deleteCookiesFromDomain(TQString)", params, replyType, replyData);
- }
- if (args->isSet("shutdown"))
- {
- TQCString module = "kcookiejar";
- TQByteArray params;
- TQDataStream stream(params, IO_WriteOnly);
- stream << module;
- kapp->dcopClient()->call( "kded", "kded", "unloadModule(TQCString)", params, replyType, replyData);
- }
- else if(args->isSet("reload-config"))
- {
- kapp->dcopClient()->call( "kded", "kcookiejar", "reloadPolicy()", TQByteArray(), replyType, replyData);
- }
- else
- {
- TQCString module = "kcookiejar";
- TQByteArray params;
- TQDataStream stream(params, IO_WriteOnly);
- stream << module;
- kapp->dcopClient()->call( "kded", "kded", "loadModule(TQCString)", params, replyType, replyData);
- }
-
- return 0;
-}
diff --git a/kioslave/http/kcookiejar/netscape_cookie_spec.html b/kioslave/http/kcookiejar/netscape_cookie_spec.html
deleted file mode 100644
index eb190f2e3..000000000
--- a/kioslave/http/kcookiejar/netscape_cookie_spec.html
+++ /dev/null
@@ -1,331 +0,0 @@
-<HTML>
-<HEAD>
-<TITLE>Client Side State - HTTP Cookies</TITLE>
-</HEAD>
-
-<BODY BGCOLOR="#ffffff" LINK="#0000ff" VLINK="#ff0000" ALINK="#ff0000" TEXT="#000000" >
-
-
-<CENTER>
-<!-- BANNER:s3 -->
-<A HREF="/maps/banners/documentation_s3.map"><IMG SRC="/images/banners/documentation_s3.gif" ALT="Documentation" BORDER=0 WIDTH=612 HEIGHT=50 ISMAP USEMAP="#banner_nav"></A>
-<MAP NAME="banner_nav">
-<AREA SHAPE=RECT COORDS="62,11,91,40" HREF="/">
-<AREA SHAPE=RECT COORDS="153,41,221,50" HREF="/">
-<AREA SHAPE=RECT COORDS="298,8,374,34" HREF="/support/index.html">
-<AREA SHAPE=RECT COORDS="381,15,586,43" HREF="http://help.netscape.com/browse/index.html">
-<AREA SHAPE=default NOHREF>
-</MAP>
-
-<!-- BANNER:s3 -->
-
-<H2>
-<FONT SIZE=+3>P</FONT>ERSISTENT
-<FONT SIZE=+3>C</FONT>LIENT
-<FONT SIZE=+3>S</FONT>TATE<BR>
-<FONT SIZE=+3>HTTP C</FONT>OOKIES
-</H2>
-
-<H3>Preliminary Specification - Use with caution</H3>
-</CENTER>
-
-<HR SIZE=4>
-
-<CENTER>
-<H3>
-<FONT SIZE=+2>I</FONT>NTRODUCTION
-</H3>
-</CENTER>
-
-Cookies are a general mechanism which server side connections (such as
-CGI scripts) can use to both store and retrieve information on the
-client side of the connection. The addition of a simple, persistent,
-client-side state significantly extends the capabilities of Web-based
-client/server applications.<P>
-
-<CENTER>
-<H3>
-<FONT SIZE=+2>O</FONT>VERVIEW
-</H3>
-</CENTER>
-
-A server, when returning an HTTP object to a client, may also send a
-piece of state information which the client will store. Included in that
-state object is a description of the range of URLs for which that state is
-valid. Any future HTTP requests made by the client which fall in that
-range will include a transmittal of the current value of the state
-object from the client back to the server. The state object is called
-a <B>cookie</B>, for no compelling reason. <P>
-This simple mechanism provides a powerful new tool which enables a host
-of new types of applications to be written for web-based environments.
-Shopping applications can now store information about the currently
-selected items, for fee services can send back registration information
-and free the client from retyping a user-id on next connection,
-sites can store per-user preferences on the client, and have the client supply
-those preferences every time that site is connected to.
-
-<CENTER>
-<H3>
-<FONT SIZE=+2>S</FONT>PECIFICATION
-</H3>
-</CENTER>
-
-A cookie is introduced to the client by including a <B>Set-Cookie</B>
-header as part of an HTTP response, typically this will be generated
-by a CGI script.
-
-<H3>Syntax of the Set-Cookie HTTP Response Header</H3>
-
-This is the format a CGI script would use to add to the HTTP headers
-a new piece of data which is to be stored by the client for later retrieval.
-
-<PRE>
-Set-Cookie: <I>NAME</I>=<I>VALUE</I>; expires=<I>DATE</I>;
-path=<I>PATH</I>; domain=<I>DOMAIN_NAME</I>; secure
-</PRE>
-<DL>
-<DT> <I>NAME</I>=<I>VALUE</I><DD>
-This string is a sequence of characters excluding semi-colon, comma and white
-space. If there is a need to place such data in the name or value, some
-encoding method such as URL style %XX encoding is recommended, though no
-encoding is defined or required. <P> This is the only required attribute
-on the <B>Set-Cookie</B> header. <P>
-<DT><B>expires</B>=<I>DATE</I>
-<DD>
-The <B>expires</B> attribute specifies a date string that
-defines the valid life time of that cookie. Once the expiration
-date has been reached, the cookie will no longer be stored or
-given out. <P>
-The date string is formatted as:
-<BLOCKQUOTE> <TT>Wdy, DD-Mon-YYYY HH:MM:SS GMT</TT></BLOCKQUOTE>
-This is based on
-<A TARGET="_top" HREF="http://ds.internic.net/rfc/rfc822.txt">RFC 822</A>,
-<A TARGET="_top" HREF="http://ds.internic.net/rfc/rfc850.txt">RFC 850</A>,
-<A TARGET="_top" HREF="http://www.w3.org/hypertext/WWW/Protocols/rfc1036/rfc1036.html#z6">
-RFC 1036</A>, and
-<A TARGET="_top" HREF="http://ds1.internic.net/rfc/rfc1123.txt">
-RFC 1123</A>,
-with the variations that the only legal time zone is <B>GMT</B> and
-the separators between the elements of the date must be dashes.
-<P>
-<B>expires</B> is an optional attribute. If not specified, the cookie will
-expire when the user's session ends. <P>
-<B>Note:</B> There is a bug in Netscape Navigator version 1.1 and earlier.
-Only cookies whose <B>path</B> attribute is set explicitly to "/" will
-be properly saved between sessions if they have an <B>expires</B>
-attribute.<P>
-
-<DT> <B>domain</B>=<I>DOMAIN_NAME</I>
-<DD>
-When searching the cookie list for valid cookies, a comparison of the
-<B>domain</B>
-attributes of the cookie is made with the Internet domain name of the
-host from which the URL will be fetched. If there is a tail match,
-then the cookie will go through <B>path</B> matching to see if it
-should be sent. "Tail matching" means that <B>domain</B> attribute
-is matched against the tail of the fully qualified domain name of
-the host. A <B>domain</B> attribute of "acme.com" would match
-host names "anvil.acme.com" as well as "shipping.crate.acme.com". <P>
-
-Only hosts within the specified domain
-can set a cookie for a domain and domains must have at least two (2)
-or three (3) periods in them to prevent domains of the form:
-".com", ".edu", and "va.us". Any domain that fails within
-one of the seven special top level domains listed below only require
-two periods. Any other domain requires at least three. The
-seven special top level domains are: "COM", "EDU", "NET", "ORG",
-"GOV", "MIL", and "INT".
-
- <P>
-The default value of <B>domain</B> is the host name of the server
-which generated the cookie response. <P>
-<DT> <B>path</B>=<I>PATH</I>
-<DD>
-The <B>path</B> attribute is used to specify the subset of URLs in a
-domain for
-which the cookie is valid. If a cookie has already passed <B>domain</B>
-matching, then the pathname component
-of the URL is compared with the path attribute, and if there is
-a match, the cookie is considered valid and is sent along with
-the URL request. The path "/foo"
-would match "/foobar" and "/foo/bar.html". The path "/" is the most
-general path. <P>
-If the <B>path</B> is not specified, it as assumed to be the same path
-as the document being described by the header which contains the cookie.
-<P>
-<DT> <B>secure</B>
-<DD>
-If a cookie is marked <B>secure</B>, it will only be transmitted if the
-communications channel with the host is a secure one. Currently
-this means that secure cookies will only be sent to HTTPS (HTTP over SSL)
-servers. <P>
-If <B>secure</B> is not specified, a cookie is considered safe to be sent
-in the clear over unsecured channels.
-</DL>
-
-<H3>Syntax of the Cookie HTTP Request Header</H3>
-
-When requesting a URL from an HTTP server, the browser will match
-the URL against all cookies and if any of them match, a line
-containing the name/value pairs of all matching cookies will
-be included in the HTTP request. Here is the format of that line:
-<PRE>
-Cookie: <I>NAME1=OPAQUE_STRING1</I>; <I>NAME2=OPAQUE_STRING2 ...</I>
-</PRE>
-
-<H3>Additional Notes</H3>
-
-<UL>
-<LI>Multiple <B>Set-Cookie</B> headers can be issued in a single server
-response.
-<p>
-<LI>Instances of the same path and name will overwrite each other, with the
-latest instance taking precedence. Instances of the same path but
-different names will add additional mappings.
-<p>
-<LI>Setting the path to a higher-level value does not override other more
-specific path mappings. If there are multiple matches for a given cookie
-name, but with separate paths, all the matching cookies will be sent.
-(See examples below.)
-<p>
-<LI>The
-expires header lets the client know when it is safe to purge the mapping
-but the client is not required to do so. A client may also delete a
-cookie before it's expiration date arrives if the number of cookies
-exceeds its internal limits.
-<p>
-<LI>When sending cookies to a server, all cookies with a more specific
-path mapping should be sent before cookies with less specific path
-mappings. For example, a cookie "name1=foo" with a path mapping
-of "/" should be sent after a cookie "name1=foo2" with
-a path mapping of "/bar" if they are both to be sent.
-<p>
-<LI>There are limitations on the number of cookies that a client
-can store at any one time. This is a specification of the minimum
-number of cookies that a client should be prepared to receive and
-store.
-
-<UL>
- <LI>300 total cookies
- <LI>4 kilobytes per cookie, where the name and the OPAQUE_STRING
- combine to form the 4 kilobyte limit.
- <LI>20 cookies per server or domain. (note that completely
- specified hosts and domains are treated as separate entities
- and have a 20 cookie limitation for each, not combined)
-</UL>
-Servers should not expect clients to be able to exceed these limits.
-When the 300 cookie limit or the 20 cookie per server limit
-is exceeded, clients should delete the least recently used cookie.
-When a cookie larger than 4 kilobytes is encountered the cookie
-should be trimmed to fit, but the name should remain intact
-as long as it is less than 4 kilobytes.
- <P>
-<LI>If a CGI script wishes to delete a cookie, it can do so by
-returning a cookie with the same name, and an <B>expires</B> time
-which is in the past. The path and name must match exactly
-in order for the expiring cookie to replace the valid cookie.
-This requirement makes it difficult for anyone but the originator
-of a cookie to delete a cookie.
-<P><LI>When caching HTTP, as a proxy server might do, the <B>Set-cookie</B>
-response header should never be cached.
-<P><LI>If a proxy server receives a response which
-contains a <B>Set-cookie</B> header, it should propagate the <B>Set-cookie</B>
-header to the client, regardless of whether the response was 304
-(Not Modified) or 200 (OK).
-<P>Similarly, if a client request contains a Cookie: header, it
-should be forwarded through a proxy, even if the conditional
-If-modified-since request is being made.
-</UL>
-
-<CENTER>
-<H3>
-<FONT SIZE=+2>E</FONT>XAMPLES
-</H3>
-</CENTER>
-
-Here are some sample exchanges which are designed to illustrate the use
-of cookies.
-<H3>First Example transaction sequence:</H3>
-<DL>
-<dt>Client requests a document, and receives in the response:<dd>
-<PRE>
-Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT</PRE>
-<dt>When client requests a URL in path "/" on this server, it sends:<DD>
-<PRE>Cookie: CUSTOMER=WILE_E_COYOTE</PRE>
-<dt>Client requests a document, and receives in the response:<dd>
-<PRE>Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/</PRE>
-<dt>When client requests a URL in path "/" on this server, it sends:<dd>
-<PRE>Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001</PRE>
-<dt>Client receives:<dd>
-<PRE>Set-Cookie: SHIPPING=FEDEX; path=/foo</PRE>
-<dt>When client requests a URL in path "/" on this server, it sends:<dd>
-<PRE>Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001</PRE>
-<dt>When client requests a URL in path "/foo" on this server, it sends:<dd>
-<PRE>Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX</PRE>
-</DL>
-<H3>Second Example transaction sequence:</H3>
-<DL>
-<dt>Assume all mappings from above have been cleared.<p>
-<dt>Client receives:<dd>
-<PRE>Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/</PRE>
-<dt>When client requests a URL in path "/" on this server, it sends:<dd>
-<PRE>Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001</PRE>
-<dt>Client receives:<dd>
-<PRE>Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo</PRE>
-<dt>When client requests a URL in path "/ammo" on this server, it sends:<dd>
-<PRE>Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001</PRE>
-<dd>NOTE: There are two name/value pairs named "PART_NUMBER" due to the
-inheritance
-of the "/" mapping in addition to the "/ammo" mapping.
-</DL>
-
-<HR SIZE=4>
-<P>
-
-<CENTER>
-
-
-<!-- footer -->
-<TABLE WIDTH=600 BORDER=0 CELLPADDING=0 CELLSPACING=0>
-<TR>
-<TD WIDTH=600 HEIGHT=8><HR SIZE=1 NOSHADE></TD></TR>
-<TR><TD ALIGN=LEFT VALIGN=TOP><FONT FACE="sans-serif, Arial, Helvetica" SIZE=-2><A HREF="http://home.netscape.com/misc/nav_redir/help.html" TARGET="_top">Help</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<A
-HREF="http://home.netscape.com/misc/nav_redir/site_map.html" TARGET="_top">Site&nbsp;Map</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<A
-HREF="http://home.netscape.com/misc/nav_redir/howtoget.html" TARGET="_top">How&nbsp;to&nbsp;Get&nbsp;Netscape&nbsp;Products</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<A HREF="http://home.netscape.com/misc/nav_redir/ad.html" TARGET="_top">Advertise&nbsp;With&nbsp;Us</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/addsite.html" TARGET="_top">Add Site</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;<A HREF="http://home.netscape.com/misc/nav_redir/custom_browser.html" TARGET="_top">Custom Browser Program</A></FONT></TD></TR>
-<TR>
-<TD WIDTH=600 HEIGHT=8 COLSPAN=0></TD>
-</TR>
-
-<TR>
-<TD ALIGN=LEFT VALIGN=TOP>
-<!-- Channels -->
-<FONT FACE="sans-serif, Arial, Helvetica" SIZE=-2><A HREF="http://home.netscape.com/misc/nav_redir/channels/autos.html" TARGET="_top">Autos</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A
-HREF="http://home.netscape.com/misc/nav_redir/channels/business.html" TARGET="_top">Business</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/computers_internet.html" TARGET="_top">Computing&nbsp;&amp;&nbsp;Internet</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/entertainment.html" TARGET="_top">Entertainment</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A
-HREF="http://home.netscape.com/misc/nav_redir/channels/kids_family.html" TARGET="_top">Family</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A
-HREF="http://home.netscape.com/misc/nav_redir/channels/games.html" TARGET="_top">Games</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/health.html" TARGET="_top">Health</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/lifestyles.html" TARGET="_top">Lifestyles</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A
-HREF="http://home.netscape.com/misc/nav_redir/channels/local.html" TARGET="_top">Local</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/netscape.html" TARGET="_top">Netscape</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/open_directory.html">Netscape&nbsp;Open&nbsp;Directory</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A
-HREF="http://home.netscape.com/misc/nav_redir/channels/news.html" TARGET="_top">News</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/personalize_finance.html" TARGET="_top">Personal&nbsp;Finance</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A
-HREF="http://home.netscape.com/misc/nav_redir/channels/real_estate.html" TARGET="_top">Real Estate</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/education.html" TARGET="_top">Research&nbsp;&amp;&nbsp;Learn</A>&nbsp;&nbsp;&nbsp;|&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/shopping.html" TARGET="_top">Shopping</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/smallbiz.html" TARGET="_top">Small Business</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A
-HREF="http://home.netscape.com/misc/nav_redir/channels/sports.html" TARGET="_top">Sports</A>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp; <A HREF="http://home.netscape.com/misc/nav_redir/channels/travel.html" TARGET="_top">Travel</A></FONT></TD></TR>
-</TABLE>
-
-<TABLE WIDTH=600 BORDER=0 CELLPADDING=0 CELLSPACING=0>
-<TR><TD WIDTH=600 HEIGHT=8 COLSPAN=0></TD></TR>
-<TR>
-<TD WIDTH=600 COLSPAN=5 VALIGN=TOP ALIGN=LEFT>
-<FONT FACE="sans-serif, Arial, Helvetica" SIZE=-2>
-&copy; 1999 Netscape, All Rights Reserved. <A HREF="http://home.netscape.com/legal_notices/index.html">Legal & Privacy Notices</A><BR>This site powered by <A HREF="http://home.netscape.com/comprod/server_central/index.html" TARGET="_top">Netscape SuiteSpot servers</A>.</FONT></TD>
-</TR>
-</TABLE>
-<!-- end footer -->
-
-
-
-
-</CENTER>
-<P>
-
-
-
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/kioslave/http/kcookiejar/rfc2109 b/kioslave/http/kcookiejar/rfc2109
deleted file mode 100644
index 432fdcc6e..000000000
--- a/kioslave/http/kcookiejar/rfc2109
+++ /dev/null
@@ -1,1179 +0,0 @@
-
-
-
-
-
-
-Network Working Group D. Kristol
-Request for Comments: 2109 Bell Laboratories, Lucent Technologies
-Category: Standards Track L. Montulli
- Netscape Communications
- February 1997
-
-
- HTTP State Management Mechanism
-
-Status of this Memo
-
- This document specifies an Internet standards track protocol for the
- Internet community, and requests discussion and suggestions for
- improvements. Please refer to the current edition of the "Internet
- Official Protocol Standards" (STD 1) for the standardization state
- and status of this protocol. Distribution of this memo is unlimited.
-
-1. ABSTRACT
-
- This document specifies a way to create a stateful session with HTTP
- requests and responses. It describes two new headers, Cookie and
- Set-Cookie, which carry state information between participating
- origin servers and user agents. The method described here differs
- from Netscape's Cookie proposal, but it can interoperate with
- HTTP/1.0 user agents that use Netscape's method. (See the HISTORICAL
- section.)
-
-2. TERMINOLOGY
-
- The terms user agent, client, server, proxy, and origin server have
- the same meaning as in the HTTP/1.0 specification.
-
- Fully-qualified host name (FQHN) means either the fully-qualified
- domain name (FQDN) of a host (i.e., a completely specified domain
- name ending in a top-level domain such as .com or .uk), or the
- numeric Internet Protocol (IP) address of a host. The fully
- qualified domain name is preferred; use of numeric IP addresses is
- strongly discouraged.
-
- The terms request-host and request-URI refer to the values the client
- would send to the server as, respectively, the host (but not port)
- and abs_path portions of the absoluteURI (http_URL) of the HTTP
- request line. Note that request-host must be a FQHN.
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 1]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- Hosts names can be specified either as an IP address or a FQHN
- string. Sometimes we compare one host name with another. Host A's
- name domain-matches host B's if
-
- * both host names are IP addresses and their host name strings match
- exactly; or
-
- * both host names are FQDN strings and their host name strings match
- exactly; or
-
- * A is a FQDN string and has the form NB, where N is a non-empty name
- string, B has the form .B', and B' is a FQDN string. (So, x.y.com
- domain-matches .y.com but not y.com.)
-
- Note that domain-match is not a commutative operation: a.b.c.com
- domain-matches .c.com, but not the reverse.
-
- Because it was used in Netscape's original implementation of state
- management, we will use the term cookie to refer to the state
- information that passes between an origin server and user agent, and
- that gets stored by the user agent.
-
-3. STATE AND SESSIONS
-
- This document describes a way to create stateful sessions with HTTP
- requests and responses. Currently, HTTP servers respond to each
- client request without relating that request to previous or
- subsequent requests; the technique allows clients and servers that
- wish to exchange state information to place HTTP requests and
- responses within a larger context, which we term a "session". This
- context might be used to create, for example, a "shopping cart", in
- which user selections can be aggregated before purchase, or a
- magazine browsing system, in which a user's previous reading affects
- which offerings are presented.
-
- There are, of course, many different potential contexts and thus many
- different potential types of session. The designers' paradigm for
- sessions created by the exchange of cookies has these key attributes:
-
- 1. Each session has a beginning and an end.
-
- 2. Each session is relatively short-lived.
-
- 3. Either the user agent or the origin server may terminate a
- session.
-
- 4. The session is implicit in the exchange of state information.
-
-
-
-
-Kristol & Montulli Standards Track [Page 2]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
-4. OUTLINE
-
- We outline here a way for an origin server to send state information
- to the user agent, and for the user agent to return the state
- information to the origin server. The goal is to have a minimal
- impact on HTTP and user agents. Only origin servers that need to
- maintain sessions would suffer any significant impact, and that
- impact can largely be confined to Common Gateway Interface (CGI)
- programs, unless the server provides more sophisticated state
- management support. (See Implementation Considerations, below.)
-
-4.1 Syntax: General
-
- The two state management headers, Set-Cookie and Cookie, have common
- syntactic properties involving attribute-value pairs. The following
- grammar uses the notation, and tokens DIGIT (decimal digits) and
- token (informally, a sequence of non-special, non-white space
- characters) from the HTTP/1.1 specification [RFC 2068] to describe
- their syntax.
-
- av-pairs = av-pair *(";" av-pair)
- av-pair = attr ["=" value] ; optional value
- attr = token
- value = word
- word = token | quoted-string
-
- Attributes (names) (attr) are case-insensitive. White space is
- permitted between tokens. Note that while the above syntax
- description shows value as optional, most attrs require them.
-
- NOTE: The syntax above allows whitespace between the attribute and
- the = sign.
-
-4.2 Origin Server Role
-
-4.2.1 General
-
- The origin server initiates a session, if it so desires. (Note that
- "session" here does not refer to a persistent network connection but
- to a logical session created from HTTP requests and responses. The
- presence or absence of a persistent connection should have no effect
- on the use of cookie-derived sessions). To initiate a session, the
- origin server returns an extra response header to the client, Set-
- Cookie. (The details follow later.)
-
- A user agent returns a Cookie request header (see below) to the
- origin server if it chooses to continue a session. The origin server
- may ignore it or use it to determine the current state of the
-
-
-
-Kristol & Montulli Standards Track [Page 3]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- session. It may send back to the client a Set-Cookie response header
- with the same or different information, or it may send no Set-Cookie
- header at all. The origin server effectively ends a session by
- sending the client a Set-Cookie header with Max-Age=0.
-
- Servers may return a Set-Cookie response headers with any response.
- User agents should send Cookie request headers, subject to other
- rules detailed below, with every request.
-
- An origin server may include multiple Set-Cookie headers in a
- response. Note that an intervening gateway could fold multiple such
- headers into a single header.
-
-4.2.2 Set-Cookie Syntax
-
- The syntax for the Set-Cookie response header is
-
- set-cookie = "Set-Cookie:" cookies
- cookies = 1#cookie
- cookie = NAME "=" VALUE *(";" cookie-av)
- NAME = attr
- VALUE = value
- cookie-av = "Comment" "=" value
- | "Domain" "=" value
- | "Max-Age" "=" value
- | "Path" "=" value
- | "Secure"
- | "Version" "=" 1*DIGIT
-
- Informally, the Set-Cookie response header comprises the token Set-
- Cookie:, followed by a comma-separated list of one or more cookies.
- Each cookie begins with a NAME=VALUE pair, followed by zero or more
- semi-colon-separated attribute-value pairs. The syntax for
- attribute-value pairs was shown earlier. The specific attributes and
- the semantics of their values follows. The NAME=VALUE attribute-
- value pair must come first in each cookie. The others, if present,
- can occur in any order. If an attribute appears more than once in a
- cookie, the behavior is undefined.
-
- NAME=VALUE
- Required. The name of the state information ("cookie") is NAME,
- and its value is VALUE. NAMEs that begin with $ are reserved for
- other uses and must not be used by applications.
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 4]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- The VALUE is opaque to the user agent and may be anything the
- origin server chooses to send, possibly in a server-selected
- printable ASCII encoding. "Opaque" implies that the content is of
- interest and relevance only to the origin server. The content
- may, in fact, be readable by anyone that examines the Set-Cookie
- header.
-
- Comment=comment
- Optional. Because cookies can contain private information about a
- user, the Cookie attribute allows an origin server to document its
- intended use of a cookie. The user can inspect the information to
- decide whether to initiate or continue a session with this cookie.
-
- Domain=domain
- Optional. The Domain attribute specifies the domain for which the
- cookie is valid. An explicitly specified domain must always start
- with a dot.
-
- Max-Age=delta-seconds
- Optional. The Max-Age attribute defines the lifetime of the
- cookie, in seconds. The delta-seconds value is a decimal non-
- negative integer. After delta-seconds seconds elapse, the client
- should discard the cookie. A value of zero means the cookie
- should be discarded immediately.
-
- Path=path
- Optional. The Path attribute specifies the subset of URLs to
- which this cookie applies.
-
- Secure
- Optional. The Secure attribute (with no value) directs the user
- agent to use only (unspecified) secure means to contact the origin
- server whenever it sends back this cookie.
-
- The user agent (possibly under the user's control) may determine
- what level of security it considers appropriate for "secure"
- cookies. The Secure attribute should be considered security
- advice from the server to the user agent, indicating that it is in
- the session's interest to protect the cookie contents.
-
- Version=version
- Required. The Version attribute, a decimal integer, identifies to
- which version of the state management specification the cookie
- conforms. For this specification, Version=1 applies.
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 5]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
-4.2.3 Controlling Caching
-
- An origin server must be cognizant of the effect of possible caching
- of both the returned resource and the Set-Cookie header. Caching
- "public" documents is desirable. For example, if the origin server
- wants to use a public document such as a "front door" page as a
- sentinel to indicate the beginning of a session for which a Set-
- Cookie response header must be generated, the page should be stored
- in caches "pre-expired" so that the origin server will see further
- requests. "Private documents", for example those that contain
- information strictly private to a session, should not be cached in
- shared caches.
-
- If the cookie is intended for use by a single user, the Set-cookie
- header should not be cached. A Set-cookie header that is intended to
- be shared by multiple users may be cached.
-
- The origin server should send the following additional HTTP/1.1
- response headers, depending on circumstances:
-
- * To suppress caching of the Set-Cookie header: Cache-control: no-
- cache="set-cookie".
-
- and one of the following:
-
- * To suppress caching of a private document in shared caches: Cache-
- control: private.
-
- * To allow caching of a document and require that it be validated
- before returning it to the client: Cache-control: must-revalidate.
-
- * To allow caching of a document, but to require that proxy caches
- (not user agent caches) validate it before returning it to the
- client: Cache-control: proxy-revalidate.
-
- * To allow caching of a document and request that it be validated
- before returning it to the client (by "pre-expiring" it):
- Cache-control: max-age=0. Not all caches will revalidate the
- document in every case.
-
- HTTP/1.1 servers must send Expires: old-date (where old-date is a
- date long in the past) on responses containing Set-Cookie response
- headers unless they know for certain (by out of band means) that
- there are no downsteam HTTP/1.0 proxies. HTTP/1.1 servers may send
- other Cache-Control directives that permit caching by HTTP/1.1
- proxies in addition to the Expires: old-date directive; the Cache-
- Control directive will override the Expires: old-date for HTTP/1.1
- proxies.
-
-
-
-Kristol & Montulli Standards Track [Page 6]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
-4.3 User Agent Role
-
-4.3.1 Interpreting Set-Cookie
-
- The user agent keeps separate track of state information that arrives
- via Set-Cookie response headers from each origin server (as
- distinguished by name or IP address and port). The user agent
- applies these defaults for optional attributes that are missing:
-
- VersionDefaults to "old cookie" behavior as originally specified by
- Netscape. See the HISTORICAL section.
-
- Domain Defaults to the request-host. (Note that there is no dot at
- the beginning of request-host.)
-
- Max-AgeThe default behavior is to discard the cookie when the user
- agent exits.
-
- Path Defaults to the path of the request URL that generated the
- Set-Cookie response, up to, but not including, the
- right-most /.
-
- Secure If absent, the user agent may send the cookie over an
- insecure channel.
-
-4.3.2 Rejecting Cookies
-
- To prevent possible security or privacy violations, a user agent
- rejects a cookie (shall not store its information) if any of the
- following is true:
-
- * The value for the Path attribute is not a prefix of the request-
- URI.
-
- * The value for the Domain attribute contains no embedded dots or
- does not start with a dot.
-
- * The value for the request-host does not domain-match the Domain
- attribute.
-
- * The request-host is a FQDN (not IP address) and has the form HD,
- where D is the value of the Domain attribute, and H is a string
- that contains one or more dots.
-
- Examples:
-
- * A Set-Cookie from request-host y.x.foo.com for Domain=.foo.com
- would be rejected, because H is y.x and contains a dot.
-
-
-
-Kristol & Montulli Standards Track [Page 7]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- * A Set-Cookie from request-host x.foo.com for Domain=.foo.com would
- be accepted.
-
- * A Set-Cookie with Domain=.com or Domain=.com., will always be
- rejected, because there is no embedded dot.
-
- * A Set-Cookie with Domain=ajax.com will be rejected because the
- value for Domain does not begin with a dot.
-
-4.3.3 Cookie Management
-
- If a user agent receives a Set-Cookie response header whose NAME is
- the same as a pre-existing cookie, and whose Domain and Path
- attribute values exactly (string) match those of a pre-existing
- cookie, the new cookie supersedes the old. However, if the Set-
- Cookie has a value for Max-Age of zero, the (old and new) cookie is
- discarded. Otherwise cookies accumulate until they expire (resources
- permitting), at which time they are discarded.
-
- Because user agents have finite space in which to store cookies, they
- may also discard older cookies to make space for newer ones, using,
- for example, a least-recently-used algorithm, along with constraints
- on the maximum number of cookies that each origin server may set.
-
- If a Set-Cookie response header includes a Comment attribute, the
- user agent should store that information in a human-readable form
- with the cookie and should display the comment text as part of a
- cookie inspection user interface.
-
- User agents should allow the user to control cookie destruction. An
- infrequently-used cookie may function as a "preferences file" for
- network applications, and a user may wish to keep it even if it is
- the least-recently-used cookie. One possible implementation would be
- an interface that allows the permanent storage of a cookie through a
- checkbox (or, conversely, its immediate destruction).
-
- Privacy considerations dictate that the user have considerable
- control over cookie management. The PRIVACY section contains more
- information.
-
-4.3.4 Sending Cookies to the Origin Server
-
- When it sends a request to an origin server, the user agent sends a
- Cookie request header to the origin server if it has cookies that are
- applicable to the request, based on
-
- * the request-host;
-
-
-
-
-Kristol & Montulli Standards Track [Page 8]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- * the request-URI;
-
- * the cookie's age.
-
- The syntax for the header is:
-
- cookie = "Cookie:" cookie-version
- 1*((";" | ",") cookie-value)
- cookie-value = NAME "=" VALUE [";" path] [";" domain]
- cookie-version = "$Version" "=" value
- NAME = attr
- VALUE = value
- path = "$Path" "=" value
- domain = "$Domain" "=" value
-
- The value of the cookie-version attribute must be the value from the
- Version attribute, if any, of the corresponding Set-Cookie response
- header. Otherwise the value for cookie-version is 0. The value for
- the path attribute must be the value from the Path attribute, if any,
- of the corresponding Set-Cookie response header. Otherwise the
- attribute should be omitted from the Cookie request header. The
- value for the domain attribute must be the value from the Domain
- attribute, if any, of the corresponding Set-Cookie response header.
- Otherwise the attribute should be omitted from the Cookie request
- header.
-
- Note that there is no Comment attribute in the Cookie request header
- corresponding to the one in the Set-Cookie response header. The user
- agent does not return the comment information to the origin server.
-
- The following rules apply to choosing applicable cookie-values from
- among all the cookies the user agent has.
-
- Domain Selection
- The origin server's fully-qualified host name must domain-match
- the Domain attribute of the cookie.
-
- Path Selection
- The Path attribute of the cookie must match a prefix of the
- request-URI.
-
- Max-Age Selection
- Cookies that have expired should have been discarded and thus
- are not forwarded to an origin server.
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 9]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- If multiple cookies satisfy the criteria above, they are ordered in
- the Cookie header such that those with more specific Path attributes
- precede those with less specific. Ordering with respect to other
- attributes (e.g., Domain) is unspecified.
-
- Note: For backward compatibility, the separator in the Cookie header
- is semi-colon (;) everywhere. A server should also accept comma (,)
- as the separator between cookie-values for future compatibility.
-
-4.3.5 Sending Cookies in Unverifiable Transactions
-
- Users must have control over sessions in order to ensure privacy.
- (See PRIVACY section below.) To simplify implementation and to
- prevent an additional layer of complexity where adequate safeguards
- exist, however, this document distinguishes between transactions that
- are verifiable and those that are unverifiable. A transaction is
- verifiable if the user has the option to review the request-URI prior
- to its use in the transaction. A transaction is unverifiable if the
- user does not have that option. Unverifiable transactions typically
- arise when a user agent automatically requests inlined or embedded
- entities or when it resolves redirection (3xx) responses from an
- origin server. Typically the origin transaction, the transaction
- that the user initiates, is verifiable, and that transaction may
- directly or indirectly induce the user agent to make unverifiable
- transactions.
-
- When it makes an unverifiable transaction, a user agent must enable a
- session only if a cookie with a domain attribute D was sent or
- received in its origin transaction, such that the host name in the
- Request-URI of the unverifiable transaction domain-matches D.
-
- This restriction prevents a malicious service author from using
- unverifiable transactions to induce a user agent to start or continue
- a session with a server in a different domain. The starting or
- continuation of such sessions could be contrary to the privacy
- expectations of the user, and could also be a security problem.
-
- User agents may offer configurable options that allow the user agent,
- or any autonomous programs that the user agent executes, to ignore
- the above rule, so long as these override options default to "off".
-
- Many current user agents already provide a review option that would
- render many links verifiable. For instance, some user agents display
- the URL that would be referenced for a particular link when the mouse
- pointer is placed over that link. The user can therefore determine
- whether to visit that site before causing the browser to do so.
- (Though not implemented on current user agents, a similar technique
- could be used for a button used to submit a form -- the user agent
-
-
-
-Kristol & Montulli Standards Track [Page 10]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- could display the action to be taken if the user were to select that
- button.) However, even this would not make all links verifiable; for
- example, links to automatically loaded images would not normally be
- subject to "mouse pointer" verification.
-
- Many user agents also provide the option for a user to view the HTML
- source of a document, or to save the source to an external file where
- it can be viewed by another application. While such an option does
- provide a crude review mechanism, some users might not consider it
- acceptable for this purpose.
-
-4.4 How an Origin Server Interprets the Cookie Header
-
- A user agent returns much of the information in the Set-Cookie header
- to the origin server when the Path attribute matches that of a new
- request. When it receives a Cookie header, the origin server should
- treat cookies with NAMEs whose prefix is $ specially, as an attribute
- for the adjacent cookie. The value for such a NAME is to be
- interpreted as applying to the lexically (left-to-right) most recent
- cookie whose name does not have the $ prefix. If there is no
- previous cookie, the value applies to the cookie mechanism as a
- whole. For example, consider the cookie
-
- Cookie: $Version="1"; Customer="WILE_E_COYOTE";
- $Path="/acme"
-
- $Version applies to the cookie mechanism as a whole (and gives the
- version number for the cookie mechanism). $Path is an attribute
- whose value (/acme) defines the Path attribute that was used when the
- Customer cookie was defined in a Set-Cookie response header.
-
-4.5 Caching Proxy Role
-
- One reason for separating state information from both a URL and
- document content is to facilitate the scaling that caching permits.
- To support cookies, a caching proxy must obey these rules already in
- the HTTP specification:
-
- * Honor requests from the cache, if possible, based on cache validity
- rules.
-
- * Pass along a Cookie request header in any request that the proxy
- must make of another server.
-
- * Return the response to the client. Include any Set-Cookie response
- header.
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 11]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- * Cache the received response subject to the control of the usual
- headers, such as Expires, Cache-control: no-cache, and Cache-
- control: private,
-
- * Cache the Set-Cookie subject to the control of the usual header,
- Cache-control: no-cache="set-cookie". (The Set-Cookie header
- should usually not be cached.)
-
- Proxies must not introduce Set-Cookie (Cookie) headers of their own
- in proxy responses (requests).
-
-5. EXAMPLES
-
-5.1 Example 1
-
- Most detail of request and response headers has been omitted. Assume
- the user agent has no stored cookies.
-
- 1. User Agent -> Server
-
- POST /acme/login HTTP/1.1
- [form data]
-
- User identifies self via a form.
-
- 2. Server -> User Agent
-
- HTTP/1.1 200 OK
- Set-Cookie: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
-
- Cookie reflects user's identity.
-
- 3. User Agent -> Server
-
- POST /acme/pickitem HTTP/1.1
- Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
- [form data]
-
- User selects an item for "shopping basket."
-
- 4. Server -> User Agent
-
- HTTP/1.1 200 OK
- Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";
- Path="/acme"
-
- Shopping basket contains an item.
-
-
-
-
-Kristol & Montulli Standards Track [Page 12]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- 5. User Agent -> Server
-
- POST /acme/shipping HTTP/1.1
- Cookie: $Version="1";
- Customer="WILE_E_COYOTE"; $Path="/acme";
- Part_Number="Rocket_Launcher_0001"; $Path="/acme"
- [form data]
-
- User selects shipping method from form.
-
- 6. Server -> User Agent
-
- HTTP/1.1 200 OK
- Set-Cookie: Shipping="FedEx"; Version="1"; Path="/acme"
-
- New cookie reflects shipping method.
-
- 7. User Agent -> Server
-
- POST /acme/process HTTP/1.1
- Cookie: $Version="1";
- Customer="WILE_E_COYOTE"; $Path="/acme";
- Part_Number="Rocket_Launcher_0001"; $Path="/acme";
- Shipping="FedEx"; $Path="/acme"
- [form data]
-
- User chooses to process order.
-
- 8. Server -> User Agent
-
- HTTP/1.1 200 OK
-
- Transaction is complete.
-
- The user agent makes a series of requests on the origin server, after
- each of which it receives a new cookie. All the cookies have the
- same Path attribute and (default) domain. Because the request URLs
- all have /acme as a prefix, and that matches the Path attribute, each
- request contains all the cookies received so far.
-
-5.2 Example 2
-
- This example illustrates the effect of the Path attribute. All
- detail of request and response headers has been omitted. Assume the
- user agent has no stored cookies.
-
- Imagine the user agent has received, in response to earlier requests,
- the response headers
-
-
-
-Kristol & Montulli Standards Track [Page 13]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- Set-Cookie: Part_Number="Rocket_Launcher_0001"; Version="1";
- Path="/acme"
-
- and
-
- Set-Cookie: Part_Number="Riding_Rocket_0023"; Version="1";
- Path="/acme/ammo"
-
- A subsequent request by the user agent to the (same) server for URLs
- of the form /acme/ammo/... would include the following request
- header:
-
- Cookie: $Version="1";
- Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo";
- Part_Number="Rocket_Launcher_0001"; $Path="/acme"
-
- Note that the NAME=VALUE pair for the cookie with the more specific
- Path attribute, /acme/ammo, comes before the one with the less
- specific Path attribute, /acme. Further note that the same cookie
- name appears more than once.
-
- A subsequent request by the user agent to the (same) server for a URL
- of the form /acme/parts/ would include the following request header:
-
- Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"
-
- Here, the second cookie's Path attribute /acme/ammo is not a prefix
- of the request URL, /acme/parts/, so the cookie does not get
- forwarded to the server.
-
-6. IMPLEMENTATION CONSIDERATIONS
-
- Here we speculate on likely or desirable details for an origin server
- that implements state management.
-
-6.1 Set-Cookie Content
-
- An origin server's content should probably be divided into disjoint
- application areas, some of which require the use of state
- information. The application areas can be distinguished by their
- request URLs. The Set-Cookie header can incorporate information
- about the application areas by setting the Path attribute for each
- one.
-
- The session information can obviously be clear or encoded text that
- describes state. However, if it grows too large, it can become
- unwieldy. Therefore, an implementor might choose for the session
- information to be a key to a server-side resource. Of course, using
-
-
-
-Kristol & Montulli Standards Track [Page 14]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- a database creates some problems that this state management
- specification was meant to avoid, namely:
-
- 1. keeping real state on the server side;
-
- 2. how and when to garbage-collect the database entry, in case the
- user agent terminates the session by, for example, exiting.
-
-6.2 Stateless Pages
-
- Caching benefits the scalability of WWW. Therefore it is important
- to reduce the number of documents that have state embedded in them
- inherently. For example, if a shopping-basket-style application
- always displays a user's current basket contents on each page, those
- pages cannot be cached, because each user's basket's contents would
- be different. On the other hand, if each page contains just a link
- that allows the user to "Look at My Shopping Basket", the page can be
- cached.
-
-6.3 Implementation Limits
-
- Practical user agent implementations have limits on the number and
- size of cookies that they can store. In general, user agents' cookie
- support should have no fixed limits. They should strive to store as
- many frequently-used cookies as possible. Furthermore, general-use
- user agents should provide each of the following minimum capabilities
- individually, although not necessarily simultaneously:
-
- * at least 300 cookies
-
- * at least 4096 bytes per cookie (as measured by the size of the
- characters that comprise the cookie non-terminal in the syntax
- description of the Set-Cookie header)
-
- * at least 20 cookies per unique host or domain name
-
- User agents created for specific purposes or for limited-capacity
- devices should provide at least 20 cookies of 4096 bytes, to ensure
- that the user can interact with a session-based origin server.
-
- The information in a Set-Cookie response header must be retained in
- its entirety. If for some reason there is inadequate space to store
- the cookie, it must be discarded, not truncated.
-
- Applications should use as few and as small cookies as possible, and
- they should cope gracefully with the loss of a cookie.
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 15]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
-6.3.1 Denial of Service Attacks
-
- User agents may choose to set an upper bound on the number of cookies
- to be stored from a given host or domain name or on the size of the
- cookie information. Otherwise a malicious server could attempt to
- flood a user agent with many cookies, or large cookies, on successive
- responses, which would force out cookies the user agent had received
- from other servers. However, the minima specified above should still
- be supported.
-
-7. PRIVACY
-
-7.1 User Agent Control
-
- An origin server could create a Set-Cookie header to track the path
- of a user through the server. Users may object to this behavior as
- an intrusive accumulation of information, even if their identity is
- not evident. (Identity might become evident if a user subsequently
- fills out a form that contains identifying information.) This state
- management specification therefore requires that a user agent give
- the user control over such a possible intrusion, although the
- interface through which the user is given this control is left
- unspecified. However, the control mechanisms provided shall at least
- allow the user
-
- * to completely disable the sending and saving of cookies.
-
- * to determine whether a stateful session is in progress.
-
- * to control the saving of a cookie on the basis of the cookie's
- Domain attribute.
-
- Such control could be provided by, for example, mechanisms
-
- * to notify the user when the user agent is about to send a cookie
- to the origin server, offering the option not to begin a session.
-
- * to display a visual indication that a stateful session is in
- progress.
-
- * to let the user decide which cookies, if any, should be saved
- when the user concludes a window or user agent session.
-
- * to let the user examine the contents of a cookie at any time.
-
- A user agent usually begins execution with no remembered state
- information. It should be possible to configure a user agent never
- to send Cookie headers, in which case it can never sustain state with
-
-
-
-Kristol & Montulli Standards Track [Page 16]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- an origin server. (The user agent would then behave like one that is
- unaware of how to handle Set-Cookie response headers.)
-
- When the user agent terminates execution, it should let the user
- discard all state information. Alternatively, the user agent may ask
- the user whether state information should be retained; the default
- should be "no". If the user chooses to retain state information, it
- would be restored the next time the user agent runs.
-
- NOTE: User agents should probably be cautious about using files to
- store cookies long-term. If a user runs more than one instance of
- the user agent, the cookies could be commingled or otherwise messed
- up.
-
-7.2 Protocol Design
-
- The restrictions on the value of the Domain attribute, and the rules
- concerning unverifiable transactions, are meant to reduce the ways
- that cookies can "leak" to the "wrong" site. The intent is to
- restrict cookies to one, or a closely related set of hosts.
- Therefore a request-host is limited as to what values it can set for
- Domain. We consider it acceptable for hosts host1.foo.com and
- host2.foo.com to share cookies, but not a.com and b.com.
-
- Similarly, a server can only set a Path for cookies that are related
- to the request-URI.
-
-8. SECURITY CONSIDERATIONS
-
-8.1 Clear Text
-
- The information in the Set-Cookie and Cookie headers is unprotected.
- Two consequences are:
-
- 1. Any sensitive information that is conveyed in them is exposed
- to intruders.
-
- 2. A malicious intermediary could alter the headers as they travel
- in either direction, with unpredictable results.
-
- These facts imply that information of a personal and/or financial
- nature should only be sent over a secure channel. For less sensitive
- information, or when the content of the header is a database key, an
- origin server should be vigilant to prevent a bad Cookie value from
- causing failures.
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 17]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
-8.2 Cookie Spoofing
-
- Proper application design can avoid spoofing attacks from related
- domains. Consider:
-
- 1. User agent makes request to victim.cracker.edu, gets back
- cookie session_id="1234" and sets the default domain
- victim.cracker.edu.
-
- 2. User agent makes request to spoof.cracker.edu, gets back
- cookie session-id="1111", with Domain=".cracker.edu".
-
- 3. User agent makes request to victim.cracker.edu again, and
- passes
-
- Cookie: $Version="1";
- session_id="1234";
- session_id="1111"; $Domain=".cracker.edu"
-
- The server at victim.cracker.edu should detect that the second
- cookie was not one it originated by noticing that the Domain
- attribute is not for itself and ignore it.
-
-8.3 Unexpected Cookie Sharing
-
- A user agent should make every attempt to prevent the sharing of
- session information between hosts that are in different domains.
- Embedded or inlined objects may cause particularly severe privacy
- problems if they can be used to share cookies between disparate
- hosts. For example, a malicious server could embed cookie
- information for host a.com in a URI for a CGI on host b.com. User
- agent implementors are strongly encouraged to prevent this sort of
- exchange whenever possible.
-
-9. OTHER, SIMILAR, PROPOSALS
-
- Three other proposals have been made to accomplish similar goals.
- This specification is an amalgam of Kristol's State-Info proposal and
- Netscape's Cookie proposal.
-
- Brian Behlendorf proposed a Session-ID header that would be user-
- agent-initiated and could be used by an origin server to track
- "clicktrails". It would not carry any origin-server-defined state,
- however. Phillip Hallam-Baker has proposed another client-defined
- session ID mechanism for similar purposes.
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 18]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
- While both session IDs and cookies can provide a way to sustain
- stateful sessions, their intended purpose is different, and,
- consequently, the privacy requirements for them are different. A
- user initiates session IDs to allow servers to track progress through
- them, or to distinguish multiple users on a shared machine. Cookies
- are server-initiated, so the cookie mechanism described here gives
- users control over something that would otherwise take place without
- the users' awareness. Furthermore, cookies convey rich, server-
- selected information, whereas session IDs comprise user-selected,
- simple information.
-
-10. HISTORICAL
-
-10.1 Compatibility With Netscape's Implementation
-
- HTTP/1.0 clients and servers may use Set-Cookie and Cookie headers
- that reflect Netscape's original cookie proposal. These notes cover
- inter-operation between "old" and "new" cookies.
-
-10.1.1 Extended Cookie Header
-
- This proposal adds attribute-value pairs to the Cookie request header
- in a compatible way. An "old" client that receives a "new" cookie
- will ignore attributes it does not understand; it returns what it
- does understand to the origin server. A "new" client always sends
- cookies in the new form.
-
- An "old" server that receives a "new" cookie will see what it thinks
- are many cookies with names that begin with a $, and it will ignore
- them. (The "old" server expects these cookies to be separated by
- semi-colon, not comma.) A "new" server can detect cookies that have
- passed through an "old" client, because they lack a $Version
- attribute.
-
-10.1.2 Expires and Max-Age
-
- Netscape's original proposal defined an Expires header that took a
- date value in a fixed-length variant format in place of Max-Age:
-
- Wdy, DD-Mon-YY HH:MM:SS GMT
-
- Note that the Expires date format contains embedded spaces, and that
- "old" cookies did not have quotes around values. Clients that
- implement to this specification should be aware of "old" cookies and
- Expires.
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 19]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
-10.1.3 Punctuation
-
- In Netscape's original proposal, the values in attribute-value pairs
- did not accept "-quoted strings. Origin servers should be cautious
- about sending values that require quotes unless they know the
- receiving user agent understands them (i.e., "new" cookies). A
- ("new") user agent should only use quotes around values in Cookie
- headers when the cookie's version(s) is (are) all compliant with this
- specification or later.
-
- In Netscape's original proposal, no whitespace was permitted around
- the = that separates attribute-value pairs. Therefore such
- whitespace should be used with caution in new implementations.
-
-10.2 Caching and HTTP/1.0
-
- Some caches, such as those conforming to HTTP/1.0, will inevitably
- cache the Set-Cookie header, because there was no mechanism to
- suppress caching of headers prior to HTTP/1.1. This caching can lead
- to security problems. Documents transmitted by an origin server
- along with Set-Cookie headers will usually either be uncachable, or
- will be "pre-expired". As long as caches obey instructions not to
- cache documents (following Expires: <a date in the past> or Pragma:
- no-cache (HTTP/1.0), or Cache-control: no-cache (HTTP/1.1))
- uncachable documents present no problem. However, pre-expired
- documents may be stored in caches. They require validation (a
- conditional GET) on each new request, but some cache operators loosen
- the rules for their caches, and sometimes serve expired documents
- without first validating them. This combination of factors can lead
- to cookies meant for one user later being sent to another user. The
- Set-Cookie header is stored in the cache, and, although the document
- is stale (expired), the cache returns the document in response to
- later requests, including cached headers.
-
-11. ACKNOWLEDGEMENTS
-
- This document really represents the collective efforts of the
- following people, in addition to the authors: Roy Fielding, Marc
- Hedlund, Ted Hardie, Koen Holtman, Shel Kaphan, Rohit Khare.
-
-
-
-
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 20]
-
-RFC 2109 HTTP State Management Mechanism February 1997
-
-
-12. AUTHORS' ADDRESSES
-
- David M. Kristol
- Bell Laboratories, Lucent Technologies
- 600 Mountain Ave. Room 2A-227
- Murray Hill, NJ 07974
-
- Phone: (908) 582-2250
- Fax: (908) 582-5809
- EMail: dmk@bell-labs.com
-
-
- Lou Montulli
- Netscape Communications Corp.
- 501 E. Middlefield Rd.
- Mountain View, CA 94043
-
- Phone: (415) 528-2600
- EMail: montulli@netscape.com
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 21]
-
diff --git a/kioslave/http/kcookiejar/rfc2965 b/kioslave/http/kcookiejar/rfc2965
deleted file mode 100644
index 8a4d02b17..000000000
--- a/kioslave/http/kcookiejar/rfc2965
+++ /dev/null
@@ -1,1459 +0,0 @@
-
-
-
-
-
-
-Network Working Group D. Kristol
-Request for Comments: 2965 Bell Laboratories, Lucent Technologies
-Obsoletes: 2109 L. Montulli
-Category: Standards Track Epinions.com, Inc.
- October 2000
-
-
- HTTP State Management Mechanism
-
-Status of this Memo
-
- This document specifies an Internet standards track protocol for the
- Internet community, and requests discussion and suggestions for
- improvements. Please refer to the current edition of the "Internet
- Official Protocol Standards" (STD 1) for the standardization state
- and status of this protocol. Distribution of this memo is unlimited.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2000). All Rights Reserved.
-
-IESG Note
-
- The IESG notes that this mechanism makes use of the .local top-level
- domain (TLD) internally when handling host names that don't contain
- any dots, and that this mechanism might not work in the expected way
- should an actual .local TLD ever be registered.
-
-Abstract
-
- This document specifies a way to create a stateful session with
- Hypertext Transfer Protocol (HTTP) requests and responses. It
- describes three new headers, Cookie, Cookie2, and Set-Cookie2, which
- carry state information between participating origin servers and user
- agents. The method described here differs from Netscape's Cookie
- proposal [Netscape], but it can interoperate with HTTP/1.0 user
- agents that use Netscape's method. (See the HISTORICAL section.)
-
- This document reflects implementation experience with RFC 2109 and
- obsoletes it.
-
-1. TERMINOLOGY
-
- The terms user agent, client, server, proxy, origin server, and
- http_URL have the same meaning as in the HTTP/1.1 specification
- [RFC2616]. The terms abs_path and absoluteURI have the same meaning
- as in the URI Syntax specification [RFC2396].
-
-
-
-
-Kristol & Montulli Standards Track [Page 1]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- Host name (HN) means either the host domain name (HDN) or the numeric
- Internet Protocol (IP) address of a host. The fully qualified domain
- name is preferred; use of numeric IP addresses is strongly
- discouraged.
-
- The terms request-host and request-URI refer to the values the client
- would send to the server as, respectively, the host (but not port)
- and abs_path portions of the absoluteURI (http_URL) of the HTTP
- request line. Note that request-host is a HN.
-
- The term effective host name is related to host name. If a host name
- contains no dots, the effective host name is that name with the
- string .local appended to it. Otherwise the effective host name is
- the same as the host name. Note that all effective host names
- contain at least one dot.
-
- The term request-port refers to the port portion of the absoluteURI
- (http_URL) of the HTTP request line. If the absoluteURI has no
- explicit port, the request-port is the HTTP default, 80. The
- request-port of a cookie is the request-port of the request in which
- a Set-Cookie2 response header was returned to the user agent.
-
- Host names can be specified either as an IP address or a HDN string.
- Sometimes we compare one host name with another. (Such comparisons
- SHALL be case-insensitive.) Host A's name domain-matches host B's if
-
- * their host name strings string-compare equal; or
-
- * A is a HDN string and has the form NB, where N is a non-empty
- name string, B has the form .B', and B' is a HDN string. (So,
- x.y.com domain-matches .Y.com but not Y.com.)
-
- Note that domain-match is not a commutative operation: a.b.c.com
- domain-matches .c.com, but not the reverse.
-
- The reach R of a host name H is defined as follows:
-
- * If
-
- - H is the host domain name of a host; and,
-
- - H has the form A.B; and
-
- - A has no embedded (that is, interior) dots; and
-
- - B has at least one embedded dot, or B is the string "local".
- then the reach of H is .B.
-
-
-
-
-Kristol & Montulli Standards Track [Page 2]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- * Otherwise, the reach of H is H.
-
- For two strings that represent paths, P1 and P2, P1 path-matches P2
- if P2 is a prefix of P1 (including the case where P1 and P2 string-
- compare equal). Thus, the string /tec/waldo path-matches /tec.
-
- Because it was used in Netscape's original implementation of state
- management, we will use the term cookie to refer to the state
- information that passes between an origin server and user agent, and
- that gets stored by the user agent.
-
-1.1 Requirements
-
- The key words "MAY", "MUST", "MUST NOT", "OPTIONAL", "RECOMMENDED",
- "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT" in this
- document are to be interpreted as described in RFC 2119 [RFC2119].
-
-2. STATE AND SESSIONS
-
- This document describes a way to create stateful sessions with HTTP
- requests and responses. Currently, HTTP servers respond to each
- client request without relating that request to previous or
- subsequent requests; the state management mechanism allows clients
- and servers that wish to exchange state information to place HTTP
- requests and responses within a larger context, which we term a
- "session". This context might be used to create, for example, a
- "shopping cart", in which user selections can be aggregated before
- purchase, or a magazine browsing system, in which a user's previous
- reading affects which offerings are presented.
-
- Neither clients nor servers are required to support cookies. A
- server MAY refuse to provide content to a client that does not return
- the cookies it sends.
-
-3. DESCRIPTION
-
- We describe here a way for an origin server to send state information
- to the user agent, and for the user agent to return the state
- information to the origin server. The goal is to have a minimal
- impact on HTTP and user agents.
-
-3.1 Syntax: General
-
- The two state management headers, Set-Cookie2 and Cookie, have common
- syntactic properties involving attribute-value pairs. The following
- grammar uses the notation, and tokens DIGIT (decimal digits), token
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 3]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- (informally, a sequence of non-special, non-white space characters),
- and http_URL from the HTTP/1.1 specification [RFC2616] to describe
- their syntax.
-
- av-pairs = av-pair *(";" av-pair)
- av-pair = attr ["=" value] ; optional value
- attr = token
- value = token | quoted-string
-
- Attributes (names) (attr) are case-insensitive. White space is
- permitted between tokens. Note that while the above syntax
- description shows value as optional, most attrs require them.
-
- NOTE: The syntax above allows whitespace between the attribute and
- the = sign.
-
-3.2 Origin Server Role
-
- 3.2.1 General The origin server initiates a session, if it so
- desires. To do so, it returns an extra response header to the
- client, Set-Cookie2. (The details follow later.)
-
- A user agent returns a Cookie request header (see below) to the
- origin server if it chooses to continue a session. The origin server
- MAY ignore it or use it to determine the current state of the
- session. It MAY send back to the client a Set-Cookie2 response
- header with the same or different information, or it MAY send no
- Set-Cookie2 header at all. The origin server effectively ends a
- session by sending the client a Set-Cookie2 header with Max-Age=0.
-
- Servers MAY return Set-Cookie2 response headers with any response.
- User agents SHOULD send Cookie request headers, subject to other
- rules detailed below, with every request.
-
- An origin server MAY include multiple Set-Cookie2 headers in a
- response. Note that an intervening gateway could fold multiple such
- headers into a single header.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 4]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- 3.2.2 Set-Cookie2 Syntax The syntax for the Set-Cookie2 response
- header is
-
- set-cookie = "Set-Cookie2:" cookies
- cookies = 1#cookie
- cookie = NAME "=" VALUE *(";" set-cookie-av)
- NAME = attr
- VALUE = value
- set-cookie-av = "Comment" "=" value
- | "CommentURL" "=" <"> http_URL <">
- | "Discard"
- | "Domain" "=" value
- | "Max-Age" "=" value
- | "Path" "=" value
- | "Port" [ "=" <"> portlist <"> ]
- | "Secure"
- | "Version" "=" 1*DIGIT
- portlist = 1#portnum
- portnum = 1*DIGIT
-
- Informally, the Set-Cookie2 response header comprises the token Set-
- Cookie2:, followed by a comma-separated list of one or more cookies.
- Each cookie begins with a NAME=VALUE pair, followed by zero or more
- semi-colon-separated attribute-value pairs. The syntax for
- attribute-value pairs was shown earlier. The specific attributes and
- the semantics of their values follows. The NAME=VALUE attribute-
- value pair MUST come first in each cookie. The others, if present,
- can occur in any order. If an attribute appears more than once in a
- cookie, the client SHALL use only the value associated with the first
- appearance of the attribute; a client MUST ignore values after the
- first.
-
- The NAME of a cookie MAY be the same as one of the attributes in this
- specification. However, because the cookie's NAME must come first in
- a Set-Cookie2 response header, the NAME and its VALUE cannot be
- confused with an attribute-value pair.
-
- NAME=VALUE
- REQUIRED. The name of the state information ("cookie") is NAME,
- and its value is VALUE. NAMEs that begin with $ are reserved and
- MUST NOT be used by applications.
-
- The VALUE is opaque to the user agent and may be anything the
- origin server chooses to send, possibly in a server-selected
- printable ASCII encoding. "Opaque" implies that the content is of
- interest and relevance only to the origin server. The content
- may, in fact, be readable by anyone that examines the Set-Cookie2
- header.
-
-
-
-Kristol & Montulli Standards Track [Page 5]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- Comment=value
- OPTIONAL. Because cookies can be used to derive or store private
- information about a user, the value of the Comment attribute
- allows an origin server to document how it intends to use the
- cookie. The user can inspect the information to decide whether to
- initiate or continue a session with this cookie. Characters in
- value MUST be in UTF-8 encoding. [RFC2279]
-
- CommentURL="http_URL"
- OPTIONAL. Because cookies can be used to derive or store private
- information about a user, the CommentURL attribute allows an
- origin server to document how it intends to use the cookie. The
- user can inspect the information identified by the URL to decide
- whether to initiate or continue a session with this cookie.
-
- Discard
- OPTIONAL. The Discard attribute instructs the user agent to
- discard the cookie unconditionally when the user agent terminates.
-
- Domain=value
- OPTIONAL. The value of the Domain attribute specifies the domain
- for which the cookie is valid. If an explicitly specified value
- does not start with a dot, the user agent supplies a leading dot.
-
- Max-Age=value
- OPTIONAL. The value of the Max-Age attribute is delta-seconds,
- the lifetime of the cookie in seconds, a decimal non-negative
- integer. To handle cached cookies correctly, a client SHOULD
- calculate the age of the cookie according to the age calculation
- rules in the HTTP/1.1 specification [RFC2616]. When the age is
- greater than delta-seconds seconds, the client SHOULD discard the
- cookie. A value of zero means the cookie SHOULD be discarded
- immediately.
-
- Path=value
- OPTIONAL. The value of the Path attribute specifies the subset of
- URLs on the origin server to which this cookie applies.
-
- Port[="portlist"]
- OPTIONAL. The Port attribute restricts the port to which a cookie
- may be returned in a Cookie request header. Note that the syntax
- REQUIREs quotes around the OPTIONAL portlist even if there is only
- one portnum in portlist.
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 6]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- Secure
- OPTIONAL. The Secure attribute (with no value) directs the user
- agent to use only (unspecified) secure means to contact the origin
- server whenever it sends back this cookie, to protect the
- confidentially and authenticity of the information in the cookie.
-
- The user agent (possibly with user interaction) MAY determine what
- level of security it considers appropriate for "secure" cookies.
- The Secure attribute should be considered security advice from the
- server to the user agent, indicating that it is in the session's
- interest to protect the cookie contents. When it sends a "secure"
- cookie back to a server, the user agent SHOULD use no less than
- the same level of security as was used when it received the cookie
- from the server.
-
- Version=value
- REQUIRED. The value of the Version attribute, a decimal integer,
- identifies the version of the state management specification to
- which the cookie conforms. For this specification, Version=1
- applies.
-
- 3.2.3 Controlling Caching An origin server must be cognizant of the
- effect of possible caching of both the returned resource and the
- Set-Cookie2 header. Caching "public" documents is desirable. For
- example, if the origin server wants to use a public document such as
- a "front door" page as a sentinel to indicate the beginning of a
- session for which a Set-Cookie2 response header must be generated,
- the page SHOULD be stored in caches "pre-expired" so that the origin
- server will see further requests. "Private documents", for example
- those that contain information strictly private to a session, SHOULD
- NOT be cached in shared caches.
-
- If the cookie is intended for use by a single user, the Set-Cookie2
- header SHOULD NOT be cached. A Set-Cookie2 header that is intended
- to be shared by multiple users MAY be cached.
-
- The origin server SHOULD send the following additional HTTP/1.1
- response headers, depending on circumstances:
-
- * To suppress caching of the Set-Cookie2 header:
-
- Cache-control: no-cache="set-cookie2"
-
- and one of the following:
-
- * To suppress caching of a private document in shared caches:
-
- Cache-control: private
-
-
-
-Kristol & Montulli Standards Track [Page 7]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- * To allow caching of a document and require that it be validated
- before returning it to the client:
-
- Cache-Control: must-revalidate, max-age=0
-
- * To allow caching of a document, but to require that proxy
- caches (not user agent caches) validate it before returning it
- to the client:
-
- Cache-Control: proxy-revalidate, max-age=0
-
- * To allow caching of a document and request that it be validated
- before returning it to the client (by "pre-expiring" it):
-
- Cache-control: max-age=0
-
- Not all caches will revalidate the document in every case.
-
- HTTP/1.1 servers MUST send Expires: old-date (where old-date is a
- date long in the past) on responses containing Set-Cookie2 response
- headers unless they know for certain (by out of band means) that
- there are no HTTP/1.0 proxies in the response chain. HTTP/1.1
- servers MAY send other Cache-Control directives that permit caching
- by HTTP/1.1 proxies in addition to the Expires: old-date directive;
- the Cache-Control directive will override the Expires: old-date for
- HTTP/1.1 proxies.
-
-3.3 User Agent Role
-
- 3.3.1 Interpreting Set-Cookie2 The user agent keeps separate track
- of state information that arrives via Set-Cookie2 response headers
- from each origin server (as distinguished by name or IP address and
- port). The user agent MUST ignore attribute-value pairs whose
- attribute it does not recognize. The user agent applies these
- defaults for optional attributes that are missing:
-
- Discard The default behavior is dictated by the presence or absence
- of a Max-Age attribute.
-
- Domain Defaults to the effective request-host. (Note that because
- there is no dot at the beginning of effective request-host,
- the default Domain can only domain-match itself.)
-
- Max-Age The default behavior is to discard the cookie when the user
- agent exits.
-
- Path Defaults to the path of the request URL that generated the
- Set-Cookie2 response, up to and including the right-most /.
-
-
-
-Kristol & Montulli Standards Track [Page 8]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- Port The default behavior is that a cookie MAY be returned to any
- request-port.
-
- Secure If absent, the user agent MAY send the cookie over an
- insecure channel.
-
- 3.3.2 Rejecting Cookies To prevent possible security or privacy
- violations, a user agent rejects a cookie according to rules below.
- The goal of the rules is to try to limit the set of servers for which
- a cookie is valid, based on the values of the Path, Domain, and Port
- attributes and the request-URI, request-host and request-port.
-
- A user agent rejects (SHALL NOT store its information) if the Version
- attribute is missing. Moreover, a user agent rejects (SHALL NOT
- store its information) if any of the following is true of the
- attributes explicitly present in the Set-Cookie2 response header:
-
- * The value for the Path attribute is not a prefix of the
- request-URI.
-
- * The value for the Domain attribute contains no embedded dots,
- and the value is not .local.
-
- * The effective host name that derives from the request-host does
- not domain-match the Domain attribute.
-
- * The request-host is a HDN (not IP address) and has the form HD,
- where D is the value of the Domain attribute, and H is a string
- that contains one or more dots.
-
- * The Port attribute has a "port-list", and the request-port was
- not in the list.
-
- Examples:
-
- * A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com
- would be rejected, because H is y.x and contains a dot.
-
- * A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com
- would be accepted.
-
- * A Set-Cookie2 with Domain=.com or Domain=.com., will always be
- rejected, because there is no embedded dot.
-
- * A Set-Cookie2 with Domain=ajax.com will be accepted, and the
- value for Domain will be taken to be .ajax.com, because a dot
- gets prepended to the value.
-
-
-
-
-Kristol & Montulli Standards Track [Page 9]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- * A Set-Cookie2 with Port="80,8000" will be accepted if the
- request was made to port 80 or 8000 and will be rejected
- otherwise.
-
- * A Set-Cookie2 from request-host example for Domain=.local will
- be accepted, because the effective host name for the request-
- host is example.local, and example.local domain-matches .local.
-
- 3.3.3 Cookie Management If a user agent receives a Set-Cookie2
- response header whose NAME is the same as that of a cookie it has
- previously stored, the new cookie supersedes the old when: the old
- and new Domain attribute values compare equal, using a case-
- insensitive string-compare; and, the old and new Path attribute
- values string-compare equal (case-sensitive). However, if the Set-
- Cookie2 has a value for Max-Age of zero, the (old and new) cookie is
- discarded. Otherwise a cookie persists (resources permitting) until
- whichever happens first, then gets discarded: its Max-Age lifetime is
- exceeded; or, if the Discard attribute is set, the user agent
- terminates the session.
-
- Because user agents have finite space in which to store cookies, they
- MAY also discard older cookies to make space for newer ones, using,
- for example, a least-recently-used algorithm, along with constraints
- on the maximum number of cookies that each origin server may set.
-
- If a Set-Cookie2 response header includes a Comment attribute, the
- user agent SHOULD store that information in a human-readable form
- with the cookie and SHOULD display the comment text as part of a
- cookie inspection user interface.
-
- If a Set-Cookie2 response header includes a CommentURL attribute, the
- user agent SHOULD store that information in a human-readable form
- with the cookie, or, preferably, SHOULD allow the user to follow the
- http_URL link as part of a cookie inspection user interface.
-
- The cookie inspection user interface may include a facility whereby a
- user can decide, at the time the user agent receives the Set-Cookie2
- response header, whether or not to accept the cookie. A potentially
- confusing situation could arise if the following sequence occurs:
-
- * the user agent receives a cookie that contains a CommentURL
- attribute;
-
- * the user agent's cookie inspection interface is configured so
- that it presents a dialog to the user before the user agent
- accepts the cookie;
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 10]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- * the dialog allows the user to follow the CommentURL link when
- the user agent receives the cookie; and,
-
- * when the user follows the CommentURL link, the origin server
- (or another server, via other links in the returned content)
- returns another cookie.
-
- The user agent SHOULD NOT send any cookies in this context. The user
- agent MAY discard any cookie it receives in this context that the
- user has not, through some user agent mechanism, deemed acceptable.
-
- User agents SHOULD allow the user to control cookie destruction, but
- they MUST NOT extend the cookie's lifetime beyond that controlled by
- the Discard and Max-Age attributes. An infrequently-used cookie may
- function as a "preferences file" for network applications, and a user
- may wish to keep it even if it is the least-recently-used cookie. One
- possible implementation would be an interface that allows the
- permanent storage of a cookie through a checkbox (or, conversely, its
- immediate destruction).
-
- Privacy considerations dictate that the user have considerable
- control over cookie management. The PRIVACY section contains more
- information.
-
- 3.3.4 Sending Cookies to the Origin Server When it sends a request
- to an origin server, the user agent includes a Cookie request header
- if it has stored cookies that are applicable to the request, based on
-
- * the request-host and request-port;
-
- * the request-URI;
-
- * the cookie's age.
-
- The syntax for the header is:
-
-cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value)
-cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port]
-cookie-version = "$Version" "=" value
-NAME = attr
-VALUE = value
-path = "$Path" "=" value
-domain = "$Domain" "=" value
-port = "$Port" [ "=" <"> value <"> ]
-
- The value of the cookie-version attribute MUST be the value from the
- Version attribute of the corresponding Set-Cookie2 response header.
- Otherwise the value for cookie-version is 0. The value for the path
-
-
-
-Kristol & Montulli Standards Track [Page 11]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- attribute MUST be the value from the Path attribute, if one was
- present, of the corresponding Set-Cookie2 response header. Otherwise
- the attribute SHOULD be omitted from the Cookie request header. The
- value for the domain attribute MUST be the value from the Domain
- attribute, if one was present, of the corresponding Set-Cookie2
- response header. Otherwise the attribute SHOULD be omitted from the
- Cookie request header.
-
- The port attribute of the Cookie request header MUST mirror the Port
- attribute, if one was present, in the corresponding Set-Cookie2
- response header. That is, the port attribute MUST be present if the
- Port attribute was present in the Set-Cookie2 header, and it MUST
- have the same value, if any. Otherwise, if the Port attribute was
- absent from the Set-Cookie2 header, the attribute likewise MUST be
- omitted from the Cookie request header.
-
- Note that there is neither a Comment nor a CommentURL attribute in
- the Cookie request header corresponding to the ones in the Set-
- Cookie2 response header. The user agent does not return the comment
- information to the origin server.
-
- The user agent applies the following rules to choose applicable
- cookie-values to send in Cookie request headers from among all the
- cookies it has received.
-
- Domain Selection
- The origin server's effective host name MUST domain-match the
- Domain attribute of the cookie.
-
- Port Selection
- There are three possible behaviors, depending on the Port
- attribute in the Set-Cookie2 response header:
-
- 1. By default (no Port attribute), the cookie MAY be sent to any
- port.
-
- 2. If the attribute is present but has no value (e.g., Port), the
- cookie MUST only be sent to the request-port it was received
- from.
-
- 3. If the attribute has a port-list, the cookie MUST only be
- returned if the new request-port is one of those listed in
- port-list.
-
- Path Selection
- The request-URI MUST path-match the Path attribute of the cookie.
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 12]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- Max-Age Selection
- Cookies that have expired should have been discarded and thus are
- not forwarded to an origin server.
-
- If multiple cookies satisfy the criteria above, they are ordered in
- the Cookie header such that those with more specific Path attributes
- precede those with less specific. Ordering with respect to other
- attributes (e.g., Domain) is unspecified.
-
- Note: For backward compatibility, the separator in the Cookie header
- is semi-colon (;) everywhere. A server SHOULD also accept comma (,)
- as the separator between cookie-values for future compatibility.
-
- 3.3.5 Identifying What Version is Understood: Cookie2 The Cookie2
- request header facilitates interoperation between clients and servers
- that understand different versions of the cookie specification. When
- the client sends one or more cookies to an origin server, if at least
- one of those cookies contains a $Version attribute whose value is
- different from the version that the client understands, then the
- client MUST also send a Cookie2 request header, the syntax for which
- is
-
- cookie2 = "Cookie2:" cookie-version
-
- Here the value for cookie-version is the highest version of cookie
- specification (currently 1) that the client understands. The client
- needs to send at most one such request header per request.
-
- 3.3.6 Sending Cookies in Unverifiable Transactions Users MUST have
- control over sessions in order to ensure privacy. (See PRIVACY
- section below.) To simplify implementation and to prevent an
- additional layer of complexity where adequate safeguards exist,
- however, this document distinguishes between transactions that are
- verifiable and those that are unverifiable. A transaction is
- verifiable if the user, or a user-designated agent, has the option to
- review the request-URI prior to its use in the transaction. A
- transaction is unverifiable if the user does not have that option.
- Unverifiable transactions typically arise when a user agent
- automatically requests inlined or embedded entities or when it
- resolves redirection (3xx) responses from an origin server.
- Typically the origin transaction, the transaction that the user
- initiates, is verifiable, and that transaction may directly or
- indirectly induce the user agent to make unverifiable transactions.
-
- An unverifiable transaction is to a third-party host if its request-
- host U does not domain-match the reach R of the request-host O in the
- origin transaction.
-
-
-
-
-Kristol & Montulli Standards Track [Page 13]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- When it makes an unverifiable transaction, a user agent MUST disable
- all cookie processing (i.e., MUST NOT send cookies, and MUST NOT
- accept any received cookies) if the transaction is to a third-party
- host.
-
- This restriction prevents a malicious service author from using
- unverifiable transactions to induce a user agent to start or continue
- a session with a server in a different domain. The starting or
- continuation of such sessions could be contrary to the privacy
- expectations of the user, and could also be a security problem.
-
- User agents MAY offer configurable options that allow the user agent,
- or any autonomous programs that the user agent executes, to ignore
- the above rule, so long as these override options default to "off".
-
- (N.B. Mechanisms may be proposed that will automate overriding the
- third-party restrictions under controlled conditions.)
-
- Many current user agents already provide a review option that would
- render many links verifiable. For instance, some user agents display
- the URL that would be referenced for a particular link when the mouse
- pointer is placed over that link. The user can therefore determine
- whether to visit that site before causing the browser to do so.
- (Though not implemented on current user agents, a similar technique
- could be used for a button used to submit a form -- the user agent
- could display the action to be taken if the user were to select that
- button.) However, even this would not make all links verifiable; for
- example, links to automatically loaded images would not normally be
- subject to "mouse pointer" verification.
-
- Many user agents also provide the option for a user to view the HTML
- source of a document, or to save the source to an external file where
- it can be viewed by another application. While such an option does
- provide a crude review mechanism, some users might not consider it
- acceptable for this purpose.
-
-3.4 How an Origin Server Interprets the Cookie Header
-
- A user agent returns much of the information in the Set-Cookie2
- header to the origin server when the request-URI path-matches the
- Path attribute of the cookie. When it receives a Cookie header, the
- origin server SHOULD treat cookies with NAMEs whose prefix is $
- specially, as an attribute for the cookie.
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 14]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
-3.5 Caching Proxy Role
-
- One reason for separating state information from both a URL and
- document content is to facilitate the scaling that caching permits.
- To support cookies, a caching proxy MUST obey these rules already in
- the HTTP specification:
-
- * Honor requests from the cache, if possible, based on cache
- validity rules.
-
- * Pass along a Cookie request header in any request that the
- proxy must make of another server.
-
- * Return the response to the client. Include any Set-Cookie2
- response header.
-
- * Cache the received response subject to the control of the usual
- headers, such as Expires,
-
- Cache-control: no-cache
-
- and
-
- Cache-control: private
-
- * Cache the Set-Cookie2 subject to the control of the usual
- header,
-
- Cache-control: no-cache="set-cookie2"
-
- (The Set-Cookie2 header should usually not be cached.)
-
- Proxies MUST NOT introduce Set-Cookie2 (Cookie) headers of their own
- in proxy responses (requests).
-
-4. EXAMPLES
-
-4.1 Example 1
-
- Most detail of request and response headers has been omitted. Assume
- the user agent has no stored cookies.
-
- 1. User Agent -> Server
-
- POST /acme/login HTTP/1.1
- [form data]
-
- User identifies self via a form.
-
-
-
-Kristol & Montulli Standards Track [Page 15]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- 2. Server -> User Agent
-
- HTTP/1.1 200 OK
- Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"
-
- Cookie reflects user's identity.
-
- 3. User Agent -> Server
-
- POST /acme/pickitem HTTP/1.1
- Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"
- [form data]
-
- User selects an item for "shopping basket".
-
- 4. Server -> User Agent
-
- HTTP/1.1 200 OK
- Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
- Path="/acme"
-
- Shopping basket contains an item.
-
- 5. User Agent -> Server
-
- POST /acme/shipping HTTP/1.1
- Cookie: $Version="1";
- Customer="WILE_E_COYOTE"; $Path="/acme";
- Part_Number="Rocket_Launcher_0001"; $Path="/acme"
- [form data]
-
- User selects shipping method from form.
-
- 6. Server -> User Agent
-
- HTTP/1.1 200 OK
- Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme"
-
- New cookie reflects shipping method.
-
- 7. User Agent -> Server
-
- POST /acme/process HTTP/1.1
- Cookie: $Version="1";
- Customer="WILE_E_COYOTE"; $Path="/acme";
- Part_Number="Rocket_Launcher_0001"; $Path="/acme";
- Shipping="FedEx"; $Path="/acme"
- [form data]
-
-
-
-Kristol & Montulli Standards Track [Page 16]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- User chooses to process order.
-
- 8. Server -> User Agent
-
- HTTP/1.1 200 OK
-
- Transaction is complete.
-
- The user agent makes a series of requests on the origin server, after
- each of which it receives a new cookie. All the cookies have the
- same Path attribute and (default) domain. Because the request-URIs
- all path-match /acme, the Path attribute of each cookie, each request
- contains all the cookies received so far.
-
-4.2 Example 2
-
- This example illustrates the effect of the Path attribute. All
- detail of request and response headers has been omitted. Assume the
- user agent has no stored cookies.
-
- Imagine the user agent has received, in response to earlier requests,
- the response headers
-
- Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";
- Path="/acme"
-
- and
-
- Set-Cookie2: Part_Number="Riding_Rocket_0023"; Version="1";
- Path="/acme/ammo"
-
- A subsequent request by the user agent to the (same) server for URLs
- of the form /acme/ammo/... would include the following request
- header:
-
- Cookie: $Version="1";
- Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo";
- Part_Number="Rocket_Launcher_0001"; $Path="/acme"
-
- Note that the NAME=VALUE pair for the cookie with the more specific
- Path attribute, /acme/ammo, comes before the one with the less
- specific Path attribute, /acme. Further note that the same cookie
- name appears more than once.
-
- A subsequent request by the user agent to the (same) server for a URL
- of the form /acme/parts/ would include the following request header:
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 17]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001";
- $Path="/acme"
-
- Here, the second cookie's Path attribute /acme/ammo is not a prefix
- of the request URL, /acme/parts/, so the cookie does not get
- forwarded to the server.
-
-5. IMPLEMENTATION CONSIDERATIONS
-
- Here we provide guidance on likely or desirable details for an origin
- server that implements state management.
-
-5.1 Set-Cookie2 Content
-
- An origin server's content should probably be divided into disjoint
- application areas, some of which require the use of state
- information. The application areas can be distinguished by their
- request URLs. The Set-Cookie2 header can incorporate information
- about the application areas by setting the Path attribute for each
- one.
-
- The session information can obviously be clear or encoded text that
- describes state. However, if it grows too large, it can become
- unwieldy. Therefore, an implementor might choose for the session
- information to be a key to a server-side resource. Of course, using
- a database creates some problems that this state management
- specification was meant to avoid, namely:
-
- 1. keeping real state on the server side;
-
- 2. how and when to garbage-collect the database entry, in case the
- user agent terminates the session by, for example, exiting.
-
-5.2 Stateless Pages
-
- Caching benefits the scalability of WWW. Therefore it is important
- to reduce the number of documents that have state embedded in them
- inherently. For example, if a shopping-basket-style application
- always displays a user's current basket contents on each page, those
- pages cannot be cached, because each user's basket's contents would
- be different. On the other hand, if each page contains just a link
- that allows the user to "Look at My Shopping Basket", the page can be
- cached.
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 18]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
-5.3 Implementation Limits
-
- Practical user agent implementations have limits on the number and
- size of cookies that they can store. In general, user agents' cookie
- support should have no fixed limits. They should strive to store as
- many frequently-used cookies as possible. Furthermore, general-use
- user agents SHOULD provide each of the following minimum capabilities
- individually, although not necessarily simultaneously:
-
- * at least 300 cookies
-
- * at least 4096 bytes per cookie (as measured by the characters
- that comprise the cookie non-terminal in the syntax description
- of the Set-Cookie2 header, and as received in the Set-Cookie2
- header)
-
- * at least 20 cookies per unique host or domain name
-
- User agents created for specific purposes or for limited-capacity
- devices SHOULD provide at least 20 cookies of 4096 bytes, to ensure
- that the user can interact with a session-based origin server.
-
- The information in a Set-Cookie2 response header MUST be retained in
- its entirety. If for some reason there is inadequate space to store
- the cookie, it MUST be discarded, not truncated.
-
- Applications should use as few and as small cookies as possible, and
- they should cope gracefully with the loss of a cookie.
-
- 5.3.1 Denial of Service Attacks User agents MAY choose to set an
- upper bound on the number of cookies to be stored from a given host
- or domain name or on the size of the cookie information. Otherwise a
- malicious server could attempt to flood a user agent with many
- cookies, or large cookies, on successive responses, which would force
- out cookies the user agent had received from other servers. However,
- the minima specified above SHOULD still be supported.
-
-6. PRIVACY
-
- Informed consent should guide the design of systems that use cookies.
- A user should be able to find out how a web site plans to use
- information in a cookie and should be able to choose whether or not
- those policies are acceptable. Both the user agent and the origin
- server must assist informed consent.
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 19]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
-6.1 User Agent Control
-
- An origin server could create a Set-Cookie2 header to track the path
- of a user through the server. Users may object to this behavior as
- an intrusive accumulation of information, even if their identity is
- not evident. (Identity might become evident, for example, if a user
- subsequently fills out a form that contains identifying information.)
- This state management specification therefore requires that a user
- agent give the user control over such a possible intrusion, although
- the interface through which the user is given this control is left
- unspecified. However, the control mechanisms provided SHALL at least
- allow the user
-
- * to completely disable the sending and saving of cookies.
-
- * to determine whether a stateful session is in progress.
-
- * to control the saving of a cookie on the basis of the cookie's
- Domain attribute.
-
- Such control could be provided, for example, by mechanisms
-
- * to notify the user when the user agent is about to send a
- cookie to the origin server, to offer the option not to begin a
- session.
-
- * to display a visual indication that a stateful session is in
- progress.
-
- * to let the user decide which cookies, if any, should be saved
- when the user concludes a window or user agent session.
-
- * to let the user examine and delete the contents of a cookie at
- any time.
-
- A user agent usually begins execution with no remembered state
- information. It SHOULD be possible to configure a user agent never
- to send Cookie headers, in which case it can never sustain state with
- an origin server. (The user agent would then behave like one that is
- unaware of how to handle Set-Cookie2 response headers.)
-
- When the user agent terminates execution, it SHOULD let the user
- discard all state information. Alternatively, the user agent MAY ask
- the user whether state information should be retained; the default
- should be "no". If the user chooses to retain state information, it
- would be restored the next time the user agent runs.
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 20]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- NOTE: User agents should probably be cautious about using files to
- store cookies long-term. If a user runs more than one instance of
- the user agent, the cookies could be commingled or otherwise
- corrupted.
-
-6.2 Origin Server Role
-
- An origin server SHOULD promote informed consent by adding CommentURL
- or Comment information to the cookies it sends. CommentURL is
- preferred because of the opportunity to provide richer information in
- a multiplicity of languages.
-
-6.3 Clear Text
-
- The information in the Set-Cookie2 and Cookie headers is unprotected.
- As a consequence:
-
- 1. Any sensitive information that is conveyed in them is exposed
- to intruders.
-
- 2. A malicious intermediary could alter the headers as they travel
- in either direction, with unpredictable results.
-
- These facts imply that information of a personal and/or financial
- nature should only be sent over a secure channel. For less sensitive
- information, or when the content of the header is a database key, an
- origin server should be vigilant to prevent a bad Cookie value from
- causing failures.
-
- A user agent in a shared user environment poses a further risk.
- Using a cookie inspection interface, User B could examine the
- contents of cookies that were saved when User A used the machine.
-
-7. SECURITY CONSIDERATIONS
-
-7.1 Protocol Design
-
- The restrictions on the value of the Domain attribute, and the rules
- concerning unverifiable transactions, are meant to reduce the ways
- that cookies can "leak" to the "wrong" site. The intent is to
- restrict cookies to one host, or a closely related set of hosts.
- Therefore a request-host is limited as to what values it can set for
- Domain. We consider it acceptable for hosts host1.foo.com and
- host2.foo.com to share cookies, but not a.com and b.com.
-
- Similarly, a server can set a Path only for cookies that are related
- to the request-URI.
-
-
-
-
-Kristol & Montulli Standards Track [Page 21]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
-7.2 Cookie Spoofing
-
- Proper application design can avoid spoofing attacks from related
- domains. Consider:
-
- 1. User agent makes request to victim.cracker.edu, gets back
- cookie session_id="1234" and sets the default domain
- victim.cracker.edu.
-
- 2. User agent makes request to spoof.cracker.edu, gets back cookie
- session-id="1111", with Domain=".cracker.edu".
-
- 3. User agent makes request to victim.cracker.edu again, and
- passes
-
- Cookie: $Version="1"; session_id="1234",
- $Version="1"; session_id="1111"; $Domain=".cracker.edu"
-
- The server at victim.cracker.edu should detect that the second
- cookie was not one it originated by noticing that the Domain
- attribute is not for itself and ignore it.
-
-7.3 Unexpected Cookie Sharing
-
- A user agent SHOULD make every attempt to prevent the sharing of
- session information between hosts that are in different domains.
- Embedded or inlined objects may cause particularly severe privacy
- problems if they can be used to share cookies between disparate
- hosts. For example, a malicious server could embed cookie
- information for host a.com in a URI for a CGI on host b.com. User
- agent implementors are strongly encouraged to prevent this sort of
- exchange whenever possible.
-
-7.4 Cookies For Account Information
-
- While it is common practice to use them this way, cookies are not
- designed or intended to be used to hold authentication information,
- such as account names and passwords. Unless such cookies are
- exchanged over an encrypted path, the account information they
- contain is highly vulnerable to perusal and theft.
-
-8. OTHER, SIMILAR, PROPOSALS
-
- Apart from RFC 2109, three other proposals have been made to
- accomplish similar goals. This specification began as an amalgam of
- Kristol's State-Info proposal [DMK95] and Netscape's Cookie proposal
- [Netscape].
-
-
-
-
-Kristol & Montulli Standards Track [Page 22]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- Brian Behlendorf proposed a Session-ID header that would be user-
- agent-initiated and could be used by an origin server to track
- "clicktrails". It would not carry any origin-server-defined state,
- however. Phillip Hallam-Baker has proposed another client-defined
- session ID mechanism for similar purposes.
-
- While both session IDs and cookies can provide a way to sustain
- stateful sessions, their intended purpose is different, and,
- consequently, the privacy requirements for them are different. A
- user initiates session IDs to allow servers to track progress through
- them, or to distinguish multiple users on a shared machine. Cookies
- are server-initiated, so the cookie mechanism described here gives
- users control over something that would otherwise take place without
- the users' awareness. Furthermore, cookies convey rich, server-
- selected information, whereas session IDs comprise user-selected,
- simple information.
-
-9. HISTORICAL
-
-9.1 Compatibility with Existing Implementations
-
- Existing cookie implementations, based on the Netscape specification,
- use the Set-Cookie (not Set-Cookie2) header. User agents that
- receive in the same response both a Set-Cookie and Set-Cookie2
- response header for the same cookie MUST discard the Set-Cookie
- information and use only the Set-Cookie2 information. Furthermore, a
- user agent MUST assume, if it received a Set-Cookie2 response header,
- that the sending server complies with this document and will
- understand Cookie request headers that also follow this
- specification.
-
- New cookies MUST replace both equivalent old- and new-style cookies.
- That is, if a user agent that follows both this specification and
- Netscape's original specification receives a Set-Cookie2 response
- header, and the NAME and the Domain and Path attributes match (per
- the Cookie Management section) a Netscape-style cookie, the
- Netscape-style cookie MUST be discarded, and the user agent MUST
- retain only the cookie adhering to this specification.
-
- Older user agents that do not understand this specification, but that
- do understand Netscape's original specification, will not recognize
- the Set-Cookie2 response header and will receive and send cookies
- according to the older specification.
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 23]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
- A user agent that supports both this specification and Netscape-style
- cookies SHOULD send a Cookie request header that follows the older
- Netscape specification if it received the cookie in a Set-Cookie
- response header and not in a Set-Cookie2 response header. However,
- it SHOULD send the following request header as well:
-
- Cookie2: $Version="1"
-
- The Cookie2 header advises the server that the user agent understands
- new-style cookies. If the server understands new-style cookies, as
- well, it SHOULD continue the stateful session by sending a Set-
- Cookie2 response header, rather than Set-Cookie. A server that does
- not understand new-style cookies will simply ignore the Cookie2
- request header.
-
-9.2 Caching and HTTP/1.0
-
- Some caches, such as those conforming to HTTP/1.0, will inevitably
- cache the Set-Cookie2 and Set-Cookie headers, because there was no
- mechanism to suppress caching of headers prior to HTTP/1.1. This
- caching can lead to security problems. Documents transmitted by an
- origin server along with Set-Cookie2 and Set-Cookie headers usually
- either will be uncachable, or will be "pre-expired". As long as
- caches obey instructions not to cache documents (following Expires:
- <a date in the past> or Pragma: no-cache (HTTP/1.0), or Cache-
- control: no-cache (HTTP/1.1)) uncachable documents present no
- problem. However, pre-expired documents may be stored in caches.
- They require validation (a conditional GET) on each new request, but
- some cache operators loosen the rules for their caches, and sometimes
- serve expired documents without first validating them. This
- combination of factors can lead to cookies meant for one user later
- being sent to another user. The Set-Cookie2 and Set-Cookie headers
- are stored in the cache, and, although the document is stale
- (expired), the cache returns the document in response to later
- requests, including cached headers.
-
-10. ACKNOWLEDGEMENTS
-
- This document really represents the collective efforts of the HTTP
- Working Group of the IETF and, particularly, the following people, in
- addition to the authors: Roy Fielding, Yaron Goland, Marc Hedlund,
- Ted Hardie, Koen Holtman, Shel Kaphan, Rohit Khare, Foteos Macrides,
- David W. Morris.
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 24]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
-11. AUTHORS' ADDRESSES
-
- David M. Kristol
- Bell Laboratories, Lucent Technologies
- 600 Mountain Ave. Room 2A-333
- Murray Hill, NJ 07974
-
- Phone: (908) 582-2250
- Fax: (908) 582-1239
- EMail: dmk@bell-labs.com
-
-
- Lou Montulli
- Epinions.com, Inc.
- 2037 Landings Dr.
- Mountain View, CA 94301
-
- EMail: lou@montulli.org
-
-12. REFERENCES
-
- [DMK95] Kristol, D.M., "Proposed HTTP State-Info Mechanism",
- available at <http://portal.research.bell-
- labs.com/~dmk/state-info.html>, September, 1995.
-
- [Netscape] "Persistent Client State -- HTTP Cookies", available at
- <http://www.netscape.com/newsref/std/cookie_spec.html>,
- undated.
-
- [RFC2109] Kristol, D. and L. Montulli, "HTTP State Management
- Mechanism", RFC 2109, February 1997.
-
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
- Requirement Levels", BCP 14, RFC 2119, March 1997.
-
- [RFC2279] Yergeau, F., "UTF-8, a transformation format of Unicode
- and ISO-10646", RFC 2279, January 1998.
-
- [RFC2396] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform
- Resource Identifiers (URI): Generic Syntax", RFC 2396,
- August 1998.
-
- [RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H. and T.
- Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1",
- RFC 2616, June 1999.
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 25]
-
-RFC 2965 HTTP State Management Mechanism October 2000
-
-
-13. Full Copyright Statement
-
- Copyright (C) The Internet Society (2000). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assigns.
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-Acknowledgement
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Kristol & Montulli Standards Track [Page 26]
-
diff --git a/kioslave/http/kcookiejar/tests/Makefile.am b/kioslave/http/kcookiejar/tests/Makefile.am
deleted file mode 100644
index 44a453feb..000000000
--- a/kioslave/http/kcookiejar/tests/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-# $Id$
-# Makefile.am of tdebase/kioslave/http
-
-INCLUDES= $(all_includes)
-
-####### Files
-
-check_PROGRAMS = kcookiejartest
-
-kcookiejartest_SOURCES = kcookiejartest.cpp
-kcookiejartest_LDADD = $(LIB_KIO)
-kcookiejartest_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor
-
-check-local: kcookiejartest
- ./kcookiejartest $(srcdir)/cookie.test
- ./kcookiejartest $(srcdir)/cookie_rfc.test
- ./kcookiejartest $(srcdir)/cookie_saving.test
- ./kcookiejartest $(srcdir)/cookie_settings.test
diff --git a/kioslave/http/kcookiejar/tests/cookie.test b/kioslave/http/kcookiejar/tests/cookie.test
deleted file mode 100644
index 6619bf82d..000000000
--- a/kioslave/http/kcookiejar/tests/cookie.test
+++ /dev/null
@@ -1,162 +0,0 @@
-## Check setting of cookies
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value1; Path="/"; expires=%NEXTYEAR%
-CHECK http://w.y.z/ Cookie: some_value=value1
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value2; Path="/"
-CHECK http://a.b.c/ Cookie: some_value=value2
-## Check if clearing cookie jar works
-CLEAR COOKIES
-CHECK http://w.y.z/
-CHECK http://a.b.c/
-## Check cookie syntax
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value with spaces
-CHECK http://w.y.z/ Cookie: some_value=value with spaces
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value="quoted value"
-CHECK http://a.b.c/ Cookie: some_value="quoted value"
-# Without a = sign, the cookie gets interpreted as the value for a cookie with no name
-# This is what IE and Netscape does
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value
-CHECK http://a.b.c/ Cookie: some_value; some_value="quoted value"
-COOKIE ASK http://a.b.c/ Set-Cookie: some_other_value
-CHECK http://a.b.c/ Cookie: some_other_value; some_value="quoted value"
-CLEAR COOKIES
-# This doesn't work with old-style netscape cookies, it should work with RFC2965 cookies
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value="quoted value; and such"
-# IE & Netscape does this:
-CHECK http://a.b.c/ Cookie: some_value="quoted value
-# Mozilla does:
-# CHECK http://a.b.c/ Cookie: some_value="quoted value; and such"
-# COOKIE ASK http://a.b.c/ Set-Cookie: some_value="quoted value;
-# CHECK http://a.b.c/ Cookie: some_value=
-# Note that we parse RFC2965 cookies like Mozilla does
-CLEAR COOKIES
-## Check if deleting cookies works
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value1; Path="/"; expires=%NEXTYEAR%
-CHECK http://w.y.z/ Cookie: some_value=value1
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value1; Path="/"; expires=%LASTYEAR%
-CHECK http://w.y.z/
-## Check if updating cookies works
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value2; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value3; Path="/"; expires=%NEXTYEAR%
-CHECK http://w.y.z/ Cookie: some_value=value3
-## Check if multiple cookies work
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value2=foobar; Path="/"; expires=%NEXTYEAR%
-CHECK http://w.y.z/ Cookie: some_value2=foobar; some_value=value3
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=; Path="/"; expires=%LASTYEAR%
-CHECK http://w.y.z/ Cookie: some_value2=foobar
-CLEAR COOKIES
-## Check if path restrictions work
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value1; Path="/Foo"; expires=%NEXTYEAR%
-CHECK http://w.y.z/
-CHECK http://w.y.z/Foo Cookie: some_value=value1
-CHECK http://w.y.z/Foo/ Cookie: some_value=value1
-CHECK http://w.y.z/Foo/bar Cookie: some_value=value1
-CLEAR COOKIES
-## Check if default path works
-# RFC2965 says that we should default to the URL path, but netscape cookies default to /
-COOKIE ASK http://w.y.z/Foo/ Set-Cookie: some_value=value1; expires=%NEXTYEAR%
-CHECK http://w.y.z/
-CHECK http://w.y.z/Foo Cookie: some_value=value1
-CHECK http://w.y.z/FooBar
-CHECK http://w.y.z/Foo/ Cookie: some_value=value1
-CHECK http://w.y.z/Foo/bar Cookie: some_value=value1
-CLEAR COOKIES
-## Check if cookies are correctly ordered based on path
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value1; Path="/Foo"; expires=%NEXTYEAR%
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value2=value2; Path="/Foo/Bar"; expires=%NEXTYEAR%
-CHECK http://w.y.z/Foo/Bar Cookie: some_value2=value2; some_value=value1
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value3=value3; Path="/"; expires=%NEXTYEAR%
-CHECK http://w.y.z/Foo/Bar Cookie: some_value2=value2; some_value=value1; some_value3=value3
-CLEAR COOKIES
-## Check cookies with same name but different paths
-COOKIE ASK http://w.y.z/Foo/ Set-Cookie: some_value=value1; expires=%NEXTYEAR%
-COOKIE ASK http://w.y.z/Bar/ Set-Cookie: some_value=value2; expires=%NEXTYEAR%
-CHECK http://w.y.z/Foo/Bar Cookie: some_value=value1
-CHECK http://w.y.z/Bar/Foo Cookie: some_value=value2
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value3; expires=%NEXTYEAR%
-CHECK http://w.y.z/Foo/Bar Cookie: some_value=value1; some_value=value3
-## Check secure cookie handling
-COOKIE ASK https://secure.y.z/ Set-Cookie: some_value2=value2; Path="/"; expires=%NEXTYEAR%; secure
-CHECK https://secure.y.z/Foo/bar Cookie: some_value2=value2
-CHECK http://secure.y.z/Foo/bar
-CLEAR COOKIES
-COOKIE ASK http://secure.y.z/ Set-Cookie: some_value3=value3; Path="/"; expires=%NEXTYEAR%; secure
-CHECK https://secure.y.z/Foo/bar Cookie: some_value3=value3
-CHECK http://secure.y.z/Foo/bar
-CLEAR COOKIES
-## Check domain restrictions #1
-COOKIE ASK http://www.acme.com/ Set-Cookie: some_value=value1; Domain=".acme.com"; expires=%NEXTYEAR%
-CHECK http://www.acme.com/ Cookie: some_value=value1
-CHECK http://www.abc.com/
-CHECK http://frop.acme.com/ Cookie: some_value=value1
-CLEAR COOKIES
-## Check domain restrictions #2
-COOKIE ASK http://novell.com/ Set-Cookie: some_value=value1; Domain=".novell.com"; expires=%NEXTYEAR%
-CHECK http://novell.com/ Cookie: some_value=value1
-CHECK http://www.novell.com/ Cookie: some_value=value1
-CLEAR COOKIES
-COOKIE ASK http://novell.com/ Set-Cookie: some_value=value1; Domain="novell.com"; expires=%NEXTYEAR%
-CHECK http://novell.com/ Cookie: some_value=value1
-CHECK http://www.novell.com/ Cookie: some_value=value1
-CLEAR COOKIES
-## Check domain restrictions #3
-COOKIE ASK http://novell.com/ Set-Cookie: some_value=value1; expires=%NEXTYEAR%
-CHECK http://novell.com/ Cookie: some_value=value1
-# FIXME: Allegedly IE sends cookies to sub-domains as well!
-# See e.g. https://bugzilla.mozilla.org/show_bug.cgi?id=223027
-CHECK http://www.novell.com/
-CLEAR COOKIES
-## Check domain restrictions #4
-COOKIE ASK http://novell.com/ Set-Cookie: some_value=value1; Domain=".com"; expires=%NEXTYEAR%
-CHECK http://novell.com/ Cookie: some_value=value1
-# If the specified domain is too broad, we default to host only
-CHECK http://www.novell.com/
-CHECK http://com/
-CHECK http://sun.com/
-## Check domain restrictions #5
-CLEAR COOKIES
-COOKIE ASK http://novell.co.uk/ Set-Cookie: some_value=value1; Domain=".co.uk"; expires=%NEXTYEAR%
-CHECK http://novell.co.uk/ Cookie: some_value=value1
-# If the specified domain is too broad, we default to host only
-CHECK http://www.novell.co.uk/
-CHECK http://co.uk/
-CHECK http://sun.co.uk/
-COOKIE ASK http://x.y.z.foobar.com/ Set-Cookie: set_by=x.y.z.foobar.com; Domain=".foobar.com"; expires=%NEXTYEAR%
-CHECK http://x.y.z.foobar.com/ Cookie: set_by=x.y.z.foobar.com
-CHECK http://y.z.foobar.com/ Cookie: set_by=x.y.z.foobar.com
-CHECK http://z.foobar.com/ Cookie: set_by=x.y.z.foobar.com
-CHECK http://www.foobar.com/ Cookie: set_by=x.y.z.foobar.com
-CHECK http://foobar.com/ Cookie: set_by=x.y.z.foobar.com
-CLEAR COOKIES
-## Check domain restrictions #6
-COOKIE ASK http://x.y.z.frop.com/ Set-Cookie: set_by=x.y.z.frop.com; Domain=".foobar.com"; expires=%NEXTYEAR%
-COOKIE ASK http://x.y.z.frop.com/ Set-Cookie: set_by2=x.y.z.frop.com; Domain=".com"; expires=%NEXTYEAR%
-CHECK http://x.y.z.foobar.com/
-CHECK http://y.z.foobar.com/
-CHECK http://z.foobar.com/
-CHECK http://www.foobar.com/
-CHECK http://foobar.com/
-CLEAR COOKIES
-## Check domain restrictions #7
-COOKIE ASK http://frop.com/ Set-Cookie: set_by=x.y.z.frop.com; Domain=".foobar.com"; expires=%NEXTYEAR%
-COOKIE ASK http://frop.com/ Set-Cookie: set_by2=x.y.z.frop.com; Domain=".com"; expires=%NEXTYEAR%
-CHECK http://x.y.z.foobar.com/
-CHECK http://y.z.foobar.com/
-CHECK http://z.foobar.com/
-CHECK http://www.foobar.com/
-CHECK http://foobar.com/
-CLEAR COOKIES
-## Check domain restrictions #8
-CONFIG AcceptSessionCookies true
-COOKIE ACCEPT http://www.foobar.com Set-Cookie: from=foobar.com; domain=bar.com; Path="/"
-CHECK http://bar.com
-CLEAR COOKIES
-## Check cookies with IP address hostnames
-COOKIE ASK http://192.168.0.1 Set-Cookie: name1=value1; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://192.168.0.1 Set-Cookie: name11=value11; domain="test.local"; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://192.168.0.1:8080 Set-Cookie: name2=value2; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK https://192.168.0.1 Set-Cookie: name3=value3; Path="/"; expires=%NEXTYEAR%; secure
-CHECK http://192.168.0.1 Cookie: name11=value11; name1=value1
-CHECK http://192.168.0.1:8080 Cookie: name2=value2
-CHECK https://192.168.0.1 Cookie: name3=value3; name11=value11; name1=value1
-CHECK http://192.168.0.10
-CHECK http://192.168.0
diff --git a/kioslave/http/kcookiejar/tests/cookie_rfc.test b/kioslave/http/kcookiejar/tests/cookie_rfc.test
deleted file mode 100644
index e1d8a40de..000000000
--- a/kioslave/http/kcookiejar/tests/cookie_rfc.test
+++ /dev/null
@@ -1,148 +0,0 @@
-## Check setting of cookies
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value="value1"; Version=1; Path="/"; Max-Age=3600
-# Although the examples in RFC2965 uses $Version="1" the syntax description suggests that
-# such quotes are not allowed, KDE BR59990 reports that the Sun Java server fails to handle
-# cookies that use $Version="1"
-CHECK http://w.y.z/ Cookie: $Version=1; some_value="value1"; $Path="/"
-COOKIE ASK http://a.b.c/ Set-Cookie2: some_value="value2"; Version=1; Path="/"
-CHECK http://a.b.c/ Cookie: $Version=1; some_value="value2"; $Path="/"
-## Check if clearing cookie jar works
-CLEAR COOKIES
-CHECK http://w.y.z/
-CHECK http://a.b.c/
-## Check cookie syntax
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value="value with spaces"; Version=1
-CHECK http://w.y.z/ Cookie: $Version=1; some_value="value with spaces"
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value ="extra space 1"; Version=1
-CHECK http://w.y.z/ Cookie: $Version=1; some_value="extra space 1"
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value= "extra space 2"; Version=1
-CHECK http://w.y.z/ Cookie: $Version=1; some_value="extra space 2"
-COOKIE ASK http://a.b.c/ Set-Cookie2: some_value=unquoted; Version=1
-CHECK http://a.b.c/ Cookie: $Version=1; some_value=unquoted
-# Note that we parse this different for Netscape-style cookies!
-COOKIE ASK http://a.b.c/ Set-Cookie2: some_value="quoted value; and such"; Version=1;
-CHECK http://a.b.c/ Cookie: $Version=1; some_value="quoted value; and such"
-CLEAR COOKIES
-## Check if deleting cookies works #1
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value="value1"; Version=1; Path="/"; Max-Age=3600
-CHECK http://w.y.z/ Cookie: $Version=1; some_value="value1"; $Path="/"
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value1; Version=1; Path="/"; Max-Age=0
-CHECK http://w.y.z/
-## Check if updating cookies works
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value2; Version=1; Path="/"; Max-Age=3600
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value3; Version=1; Path="/"; Max-Age=3600
-CHECK http://w.y.z/ Cookie: $Version=1; some_value=value3; $Path="/"
-## Check if multiple cookies work
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value2=foobar; Version=1; Path="/"; Max-Age=3600
-CHECK http://w.y.z/ Cookie: $Version=1; some_value2=foobar; $Path="/"; some_value=value3; $Path="/"
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=; Version=1; Path="/"; Max-Age=0
-CHECK http://w.y.z/ Cookie: $Version=1; some_value2=foobar; $Path="/"
-CLEAR COOKIES
-## Check if we prepend domain with a dot
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value2; Version=1; Path="/"; Domain=.y.z; Max-Age=3600
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value3; Version=1; Path="/"; Domain=y.z.; Max-Age=3600
-CHECK http://w.y.z/ Cookie: $Version=1; some_value=value3; $Path="/"; $Domain=".y.z"
-CLEAR COOKIES
-## Check if multiple cookies on a single line work
-## FIXME
-#COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value3; Version=1; Path="/"; Max-Age=3600, some_value2=foobar; Version=1; Path="/"; Max-Age=3600
-# CHECK http://w.y.z/ Cookie: $Version=1; some_value2=foobar; $Path="/"; some_value=value3; $Path="/"
-# COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=; Version=1; Path="/"; Max-Age=0
-# CHECK http://w.y.z/ Cookie: $Version=1; some_value2=foobar; $Path="/"
-CLEAR COOKIES
-## Check if path restrictions work
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value1; Version=1; Path="/Foo"; Max-Age=3600
-CHECK http://w.y.z/
-CHECK http://w.y.z/Foo Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y.z/Foo/ Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y.z/Foo/bar Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CLEAR COOKIES
-## Check if default path works
-# RFC2965 says that we should default to the URL path
-COOKIE ASK http://w.y.z/Foo/ Set-Cookie2: some_value=value1; Version=1; Max-Age=3600
-CHECK http://w.y.z/
-CHECK http://w.y.z/Foo Cookie: $Version=1; some_value=value1
-CHECK http://w.y.z/FooBar
-CHECK http://w.y.z/Foo/ Cookie: $Version=1; some_value=value1
-CHECK http://w.y.z/Foo/bar Cookie: $Version=1; some_value=value1
-CLEAR COOKIES
-## Check if cookies are correctly ordered based on path
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value1; Version=1; Path="/Foo"; Max-Age=3600
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value2=value2; Version=1; Path="/Foo/Bar"; Max-Age=3600
-CHECK http://w.y.z/Foo/Bar Cookie: $Version=1; some_value2=value2; $Path="/Foo/Bar"; some_value=value1; $Path="/Foo"
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value3=value3; Version=1; Path="/"; Max-Age=3600
-CHECK http://w.y.z/Foo/Bar Cookie: $Version=1; some_value2=value2; $Path="/Foo/Bar"; some_value=value1; $Path="/Foo"; some_value3=value3; $Path="/"
-CLEAR COOKIES
-## Check cookies with same name but different paths
-COOKIE ASK http://w.y.z/Foo/ Set-Cookie2: some_value=value1; Version=1; Max-Age=3600
-COOKIE ASK http://w.y.z/Bar/ Set-Cookie2: some_value=value2; Version=1; Max-Age=3600
-CHECK http://w.y.z/Foo/Bar Cookie: $Version=1; some_value=value1
-CHECK http://w.y.z/Bar/Foo Cookie: $Version=1; some_value=value2
-COOKIE ASK http://w.y.z/ Set-Cookie2: some_value=value3; Version=1; Max-Age=3600
-CHECK http://w.y.z/Foo/Bar Cookie: $Version=1; some_value=value1; some_value=value3
-## Check secure cookie handling
-COOKIE ASK https://secure.y.z/ Set-Cookie2: some_value2=value2; Version=1; Path="/"; Max-Age=3600; Secure
-CHECK https://secure.y.z/Foo/bar Cookie: $Version=1; some_value2=value2; $Path="/"
-CHECK http://secure.y.z/Foo/bar
-CLEAR COOKIES
-COOKIE ASK http://secure.y.z/ Set-Cookie2: some_value3=value3; Version=1; Path="/"; Max-Age=3600; Secure
-CHECK https://secure.y.z/Foo/bar Cookie: $Version=1; some_value3=value3; $Path="/"
-CHECK http://secure.y.z/Foo/bar
-CLEAR COOKIES
-## Check domain restrictions #1
-COOKIE ASK http://www.acme.com/ Set-Cookie2: some_value=value1; Version=1; Domain=".acme.com"; Max-Age=3600
-CHECK http://www.acme.com/ Cookie: $Version=1; some_value=value1; $Domain=".acme.com"
-CHECK http://www.abc.com/
-CHECK http://frop.acme.com/ Cookie: $Version=1; some_value=value1; $Domain=".acme.com"
-CLEAR COOKIES
-## Check domain restrictions #2
-COOKIE ASK http://novell.com/ Set-Cookie2: some_value=value1; Version=1; Domain=".novell.com"; Max-Age=3600
-CHECK http://novell.com/ Cookie: $Version=1; some_value=value1; $Domain=".novell.com"
-CHECK http://www.novell.com/ Cookie: $Version=1; some_value=value1; $Domain=".novell.com"
-CLEAR COOKIES
-## Check domain restrictions #3
-COOKIE ASK http://novell.com/ Set-Cookie2: some_value=value1; Version=1; Max-Age=3600
-CHECK http://novell.com/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell.com/
-CLEAR COOKIES
-## Check domain restrictions #4
-COOKIE ASK http://novell.com/ Set-Cookie2: some_value=value1; Version=1; Domain=".com"; Max-Age=3600
-# If the specified domain is too broad, we ignore the Domain
-# FIXME: RFC2965 says we should ignore the cookie completely
-CHECK http://novell.com/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell.com/
-CHECK http://com/
-CHECK http://sun.com/
-## Check domain restrictions #5
-CLEAR COOKIES
-COOKIE ASK http://novell.co.uk/ Set-Cookie2: some_value=value1; Version=1; Domain=".co.uk"; Max-Age=3600
-# If the specified domain is too broad, we default to host only
-# FIXME: RFC2965 says we should ignore the cookie completely
-CHECK http://novell.co.uk/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell.co.uk/
-CHECK http://co.uk/
-CHECK http://sun.co.uk/
-COOKIE ASK http://x.y.z.foobar.com/ Set-Cookie2: set_by=x.y.z.foobar.com; Version=1; Domain=".foobar.com"; Max-Age=3600
-CHECK http://x.y.z.foobar.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar.com"
-CHECK http://y.z.foobar.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar.com"
-CHECK http://z.foobar.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar.com"
-CHECK http://www.foobar.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar.com"
-CHECK http://foobar.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar.com"
-CLEAR COOKIES
-## Check domain restrictions #6
-COOKIE ASK http://x.y.z.frop.com/ Set-Cookie2: set_by=x.y.z.frop.com; Version=1; Domain=".foobar.com"; Max-Age=3600
-COOKIE ASK http://x.y.z.frop.com/ Set-Cookie2: set_by2=x.y.z.frop.com; Version=1; Domain=".com"; Max-Age=3600
-CHECK http://x.y.z.foobar.com/
-CHECK http://y.z.foobar.com/
-CHECK http://z.foobar.com/
-CHECK http://www.foobar.com/
-CHECK http://foobar.com/
-CLEAR COOKIES
-## Check domain restrictions #7
-COOKIE ASK http://frop.com/ Set-Cookie2: set_by=x.y.z.frop.com; Version=1; Domain=".foobar.com"; Max-Age=3600
-COOKIE ASK http://frop.com/ Set-Cookie2: set_by2=x.y.z.frop.com; Version=1; Domain=".com"; Max-Age=3600
-CHECK http://x.y.z.foobar.com/
-CHECK http://y.z.foobar.com/
-CHECK http://z.foobar.com/
-CHECK http://www.foobar.com/
-CHECK http://foobar.com/
diff --git a/kioslave/http/kcookiejar/tests/cookie_saving.test b/kioslave/http/kcookiejar/tests/cookie_saving.test
deleted file mode 100644
index cb9f34c42..000000000
--- a/kioslave/http/kcookiejar/tests/cookie_saving.test
+++ /dev/null
@@ -1,430 +0,0 @@
-## Check setting of cookies
-COOKIE ASK http://w.y.z/ Set-Cookie: some_value=value1; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value2; Path="/"
-## Check if clearing cookie jar works
-CLEAR COOKIES
-## Check cookie syntax
-COOKIE ASK http://w.y1.z/ Set-Cookie: some_value=value with spaces; expires=%NEXTYEAR%
-COOKIE ASK http://a.b1.c/ Set-Cookie: some_value="quoted value"; expires=%NEXTYEAR%
-# Without a = sign, the cookie gets interpreted as the value for a cookie with no name
-# This is what IE and Netscape does
-COOKIE ASK http://a.b1.c/ Set-Cookie: some_value
-COOKIE ASK http://a.b1.c/ Set-Cookie: some_other_value; expires=%NEXTYEAR%
-# This doesn't work with old-style netscape cookies, it should work with RFC2965 cookies
-COOKIE ASK http://a.b2.c/ Set-Cookie: some_value="quoted value; and such"; expires=%NEXTYEAR%
-# IE & Netscape does this:
-## Check if deleting cookies works
-COOKIE ASK http://w.y3.z/ Set-Cookie: some_value=value1; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://w.y3.z/ Set-Cookie: some_value=value1; Path="/"; expires=%LASTYEAR%
-## Check if updating cookies works
-COOKIE ASK http://w.y3.z/ Set-Cookie: some_value=value2; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://w.y3.z/ Set-Cookie: some_value=value3; Path="/"; expires=%NEXTYEAR%
-## Check if multiple cookies work
-COOKIE ASK http://w.y3.z/ Set-Cookie: some_value2=foobar; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://w.y3.z/ Set-Cookie: some_value=; Path="/"; expires=%LASTYEAR%
-## Check if path restrictions work
-COOKIE ASK http://w.y4.z/ Set-Cookie: some_value=value1; Path="/Foo"; expires=%NEXTYEAR%
-## Check if default path works
-COOKIE ASK http://w.y5.z/Foo/ Set-Cookie: some_value=value1; expires=%NEXTYEAR%
-## Check if cookies are correctly ordered based on path
-COOKIE ASK http://w.y6.z/ Set-Cookie: some_value=value1; Path="/Foo"; expires=%NEXTYEAR%
-COOKIE ASK http://w.y6.z/ Set-Cookie: some_value2=value2; Path="/Foo/Bar"; expires=%NEXTYEAR%
-COOKIE ASK http://w.y6.z/ Set-Cookie: some_value3=value3; Path="/"; expires=%NEXTYEAR%
-## Check cookies with same name but different paths
-COOKIE ASK http://w.y7.z/Foo/ Set-Cookie: some_value=value1; expires=%NEXTYEAR%
-COOKIE ASK http://w.y7.z/Bar/ Set-Cookie: some_value=value2; expires=%NEXTYEAR%
-COOKIE ASK http://w.y7.z/ Set-Cookie: some_value=value3; expires=%NEXTYEAR%
-## Check secure cookie handling
-COOKIE ASK https://secure.y7.z/ Set-Cookie: some_value2=value2; Path="/"; expires=%NEXTYEAR%; secure
-COOKIE ASK http://secure.y8.z/ Set-Cookie: some_value3=value3; Path="/"; expires=%NEXTYEAR%; secure
-## Check domain restrictions #1
-COOKIE ASK http://www.acme9.com/ Set-Cookie: some_value=value1; Domain=".acme9.com"; expires=%NEXTYEAR%
-## Check domain restrictions #2
-COOKIE ASK http://novell10.com/ Set-Cookie: some_value=value1; Domain=".novell10.com"; expires=%NEXTYEAR%
-COOKIE ASK http://novell11.com/ Set-Cookie: some_value=value1; Domain="novell11.com"; expires=%NEXTYEAR%
-## Check domain restrictions #3
-COOKIE ASK http://novell12.com/ Set-Cookie: some_value=value1; expires=%NEXTYEAR%
-## Check domain restrictions #4
-COOKIE ASK http://novell13.com/ Set-Cookie: some_value=value1; Domain=".com"; expires=%NEXTYEAR%
-# If the specified domain is too broad, we default to host only
-## Check domain restrictions #5
-COOKIE ASK http://novell14.co.uk/ Set-Cookie: some_value=value1; Domain=".co.uk"; expires=%NEXTYEAR%
-COOKIE ASK http://x.y.z.foobar14.com/ Set-Cookie: set_by=x.y.z.foobar14.com; Domain=".foobar14.com"; expires=%NEXTYEAR%
-## Check domain restrictions #6
-COOKIE ASK http://x.y.z.frop15.com/ Set-Cookie: set_by=x.y.z.frop15.com; Domain=".foobar15.com"; expires=%NEXTYEAR%
-COOKIE ASK http://x.y.z.frop15.com/ Set-Cookie: set_by2=x.y.z.frop15.com; Domain=".com"; expires=%NEXTYEAR%
-## Check domain restrictions #7
-COOKIE ASK http://frop16.com/ Set-Cookie: set_by=x.y.z.frop16.com; Domain=".foobar16.com"; expires=%NEXTYEAR%
-COOKIE ASK http://frop16.com/ Set-Cookie: set_by2=x.y.z.frop16.com; Domain=".com"; expires=%NEXTYEAR%
-## RFC Cookies
-## Check setting of cookies
-COOKIE ASK http://w.y20.z/ Set-Cookie2: some_value="value1"; Version=1; Path="/"; Max-Age=3600
-# Although the examples in RFC2965 uses $Version="1" the syntax description suggests that
-# such quotes are not allowed, KDE BR59990 reports that the Sun Java server fails to handle
-# cookies that use $Version="1"
-COOKIE ASK http://a.b20.c/ Set-Cookie2: some_value="value2"; Version=1; Path="/"; Max-Age=3600
-## Check cookie syntax
-COOKIE ASK http://w.y21.z/ Set-Cookie2: some_value="value with spaces"; Version=1; Max-Age=3600
-COOKIE ASK http://w.y21.z/ Set-Cookie2: some_value ="extra space 1"; Version=1; Max-Age=3600
-COOKIE ASK http://w.y21.z/ Set-Cookie2: some_value= "extra space 2"; Version=1; Max-Age=3600
-COOKIE ASK http://a.b21.c/ Set-Cookie2: some_value=unquoted; Version=1; Max-Age=3600
-# Note that we parse this different for Netscape-style cookies!
-COOKIE ASK http://a.b21.c/ Set-Cookie2: some_value="quoted value; and such"; Version=1; Max-Age=3600
-## Check if deleting cookies works #1
-COOKIE ASK http://w.y22.z/ Set-Cookie2: some_value="value1"; Version=1; Path="/"; Max-Age=3600
-COOKIE ASK http://w.y22.z/ Set-Cookie2: some_value=value1; Version=1; Path="/"; Max-Age=0
-## Check if updating cookies works
-COOKIE ASK http://w.y22.z/ Set-Cookie2: some_value=value2; Version=1; Path="/"; Max-Age=3600
-COOKIE ASK http://w.y22.z/ Set-Cookie2: some_value=value3; Version=1; Path="/"; Max-Age=3600
-## Check if multiple cookies work
-COOKIE ASK http://w.y22.z/ Set-Cookie2: some_value2=foobar; Version=1; Path="/"; Max-Age=3600
-COOKIE ASK http://w.y22.z/ Set-Cookie2: some_value=; Version=1; Path="/"; Max-Age=0
-## Check if path restrictions work
-COOKIE ASK http://w.y23.z/ Set-Cookie2: some_value=value1; Version=1; Path="/Foo"; Max-Age=3600
-## Check if default path works
-# RFC2965 says that we should default to the URL path
-COOKIE ASK http://w.y24.z/Foo/ Set-Cookie2: some_value=value1; Version=1; Max-Age=3600
-## Check if cookies are correctly ordered based on path
-COOKIE ASK http://w.y25.z/ Set-Cookie2: some_value=value1; Version=1; Path="/Foo"; Max-Age=3600
-COOKIE ASK http://w.y25.z/ Set-Cookie2: some_value2=value2; Version=1; Path="/Foo/Bar"; Max-Age=3600
-COOKIE ASK http://w.y25.z/ Set-Cookie2: some_value3=value3; Version=1; Path="/"; Max-Age=3600
-## Check cookies with same name but different paths
-COOKIE ASK http://w.y26.z/Foo/ Set-Cookie2: some_value=value1; Version=1; Max-Age=3600
-COOKIE ASK http://w.y26.z/Bar/ Set-Cookie2: some_value=value2; Version=1; Max-Age=3600
-COOKIE ASK http://w.y26.z/ Set-Cookie2: some_value=value3; Version=1; Max-Age=3600
-## Check secure cookie handling
-COOKIE ASK https://secure.y26.z/ Set-Cookie2: some_value2=value2; Version=1; Path="/"; Max-Age=3600; Secure
-COOKIE ASK http://secure.y27.z/ Set-Cookie2: some_value3=value3; Version=1; Path="/"; Max-Age=3600; Secure
-## Check domain restrictions #1
-COOKIE ASK http://www.acme28.com/ Set-Cookie2: some_value=value1; Version=1; Domain=".acme28.com"; Max-Age=3600
-## Check domain restrictions #2
-COOKIE ASK http://novell29.com/ Set-Cookie2: some_value=value1; Version=1; Domain=".novell29.com"; Max-Age=3600
-## Check domain restrictions #3
-COOKIE ASK http://novell30.com/ Set-Cookie2: some_value=value1; Version=1; Max-Age=3600
-## Check domain restrictions #4
-COOKIE ASK http://novell31.com/ Set-Cookie2: some_value=value1; Version=1; Domain=".com"; Max-Age=3600
-# If the specified domain is too broad, we ignore the Domain
-# FIXME: RFC2965 says we should ignore the cookie completely
-## Check domain restrictions #5
-COOKIE ASK http://novell32.co.uk/ Set-Cookie2: some_value=value1; Version=1; Domain=".co.uk"; Max-Age=3600
-# If the specified domain is too broad, we default to host only
-# FIXME: RFC2965 says we should ignore the cookie completely
-COOKIE ASK http://x.y.z.foobar33.com/ Set-Cookie2: set_by=x.y.z.foobar.com; Version=1; Domain=".foobar33.com"; Max-Age=3600
-## Check domain restrictions #6
-COOKIE ASK http://x.y.z.frop34.com/ Set-Cookie2: set_by=x.y.z.frop.com; Version=1; Domain=".foobar.com"; Max-Age=3600
-COOKIE ASK http://x.y.z.frop34.com/ Set-Cookie2: set_by2=x.y.z.frop.com; Version=1; Domain=".com"; Max-Age=3600
-## Check domain restrictions #7
-COOKIE ASK http://frop35.com/ Set-Cookie2: set_by=x.y.z.frop.com; Version=1; Domain=".foobar.com"; Max-Age=3600
-COOKIE ASK http://frop35.com/ Set-Cookie2: set_by2=x.y.z.frop.com; Version=1; Domain=".com"; Max-Age=3600
-
-## Check results
-CHECK http://w.y.z/
-CHECK http://a.b.c/
-CHECK http://w.y1.z/ Cookie: some_value=value with spaces
-CHECK http://a.b1.c/ Cookie: some_other_value; some_value="quoted value"
-CHECK http://a.b2.c/ Cookie: some_value="quoted value
-CHECK http://w.y3.z/ Cookie: some_value2=foobar
-CHECK http://w.y4.z/
-CHECK http://w.y4.z/Foo Cookie: some_value=value1
-CHECK http://w.y4.z/Foo/ Cookie: some_value=value1
-CHECK http://w.y4.z/Foo/bar Cookie: some_value=value1
-CHECK http://w.y5.z/
-CHECK http://w.y5.z/Foo Cookie: some_value=value1
-CHECK http://w.y5.z/FooBar
-CHECK http://w.y5.z/Foo/ Cookie: some_value=value1
-CHECK http://w.y5.z/Foo/bar Cookie: some_value=value1
-CHECK http://w.y6.z/Foo/Bar Cookie: some_value2=value2; some_value=value1; some_value3=value3
-CHECK http://w.y7.z/Bar/Foo Cookie: some_value=value2; some_value=value3
-CHECK http://w.y7.z/Foo/Bar Cookie: some_value=value1; some_value=value3
-CHECK https://secure.y7.z/Foo/bar Cookie: some_value2=value2
-CHECK http://secure.y7.z/Foo/bar
-CHECK https://secure.y8.z/Foo/bar Cookie: some_value3=value3
-CHECK http://secure.y8.z/Foo/bar
-CHECK http://www.acme9.com/ Cookie: some_value=value1
-CHECK http://www.abc9.com/
-CHECK http://frop.acme9.com/ Cookie: some_value=value1
-CHECK http://novell10.com/ Cookie: some_value=value1
-CHECK http://www.novell10.com/ Cookie: some_value=value1
-CHECK http://novell11.com/ Cookie: some_value=value1
-CHECK http://www.novell11.com/ Cookie: some_value=value1
-CHECK http://novell12.com/ Cookie: some_value=value1
-CHECK http://www.novell12.com/
-CHECK http://novell13.com/ Cookie: some_value=value1
-CHECK http://www.novell13.com/
-CHECK http://com/
-CHECK http://sun13.com/
-CHECK http://novell14.co.uk/ Cookie: some_value=value1
-CHECK http://www.novell14.co.uk/
-CHECK http://co.uk/
-CHECK http://sun14.co.uk/
-CHECK http://x.y.z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://y.z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://www.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://x.y.z.foobar15.com/
-CHECK http://y.z.foobar15.com/
-CHECK http://z.foobar15.com/
-CHECK http://www.foobar15.com/
-CHECK http://foobar15.com/
-CHECK http://x.y.z.foobar16.com/
-CHECK http://y.z.foobar16.com/
-CHECK http://z.foobar16.com/
-CHECK http://www.foobar16.com/
-CHECK http://foobar16.com/
-## Check results for RFC cookies
-CHECK http://w.y20.z/ Cookie: $Version=1; some_value="value1"; $Path="/"
-CHECK http://a.b20.c/ Cookie: $Version=1; some_value="value2"; $Path="/"
-CHECK http://w.y21.z/ Cookie: $Version=1; some_value="extra space 2"
-CHECK http://a.b21.c/ Cookie: $Version=1; some_value="quoted value; and such"
-CHECK http://w.y22.z/ Cookie: $Version=1; some_value2=foobar; $Path="/"
-CHECK http://w.y23.z/
-CHECK http://w.y23.z/Foo Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y23.z/Foo/ Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y23.z/Foo/bar Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y24.z/
-CHECK http://w.y24.z/Foo Cookie: $Version=1; some_value=value1
-CHECK http://w.y24.z/FooBar
-CHECK http://w.y24.z/Foo/ Cookie: $Version=1; some_value=value1
-CHECK http://w.y24.z/Foo/bar Cookie: $Version=1; some_value=value1
-CHECK http://w.y25.z/Foo/Bar Cookie: $Version=1; some_value2=value2; $Path="/Foo/Bar"; some_value=value1; $Path="/Foo"; some_value3=value3; $Path="/"
-CHECK http://w.y26.z/Bar/Foo Cookie: $Version=1; some_value=value2; some_value=value3
-CHECK http://w.y26.z/Foo/Bar Cookie: $Version=1; some_value=value1; some_value=value3
-CHECK https://secure.y26.z/Foo/bar Cookie: $Version=1; some_value2=value2; $Path="/"
-CHECK http://secure.y26.z/Foo/bar
-CHECK https://secure.y27.z/Foo/bar Cookie: $Version=1; some_value3=value3; $Path="/"
-CHECK http://secure.y27.z/Foo/bar
-CHECK http://www.acme28.com/ Cookie: $Version=1; some_value=value1; $Domain=".acme28.com"
-CHECK http://www.abc28.com/
-CHECK http://frop.acme28.com/ Cookie: $Version=1; some_value=value1; $Domain=".acme28.com"
-CHECK http://novell29.com/ Cookie: $Version=1; some_value=value1; $Domain=".novell29.com"
-CHECK http://www.novell29.com/ Cookie: $Version=1; some_value=value1; $Domain=".novell29.com"
-CHECK http://novell30.com/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell30.com/
-CHECK http://novell31.com/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell31.com/
-CHECK http://com/
-CHECK http://sun31.com/
-CHECK http://novell32.co.uk/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell32.co.uk/
-CHECK http://co.uk/
-CHECK http://sun32.co.uk/
-CHECK http://x.y.z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://y.z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://www.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://x.y.z.foobar.com/
-CHECK http://y.z.foobar.com/
-CHECK http://z.foobar.com/
-CHECK http://www.foobar.com/
-CHECK http://foobar.com/
-
-
-SAVE
-## Check result after saving
-CHECK http://w.y.z/
-CHECK http://a.b.c/
-CHECK http://w.y1.z/ Cookie: some_value=value with spaces
-CHECK http://a.b1.c/ Cookie: some_other_value; some_value="quoted value"
-CHECK http://a.b2.c/ Cookie: some_value="quoted value
-CHECK http://w.y3.z/ Cookie: some_value2=foobar
-CHECK http://w.y4.z/
-CHECK http://w.y4.z/Foo Cookie: some_value=value1
-CHECK http://w.y4.z/Foo/ Cookie: some_value=value1
-CHECK http://w.y4.z/Foo/bar Cookie: some_value=value1
-CHECK http://w.y5.z/
-CHECK http://w.y5.z/Foo Cookie: some_value=value1
-CHECK http://w.y5.z/FooBar
-CHECK http://w.y5.z/Foo/ Cookie: some_value=value1
-CHECK http://w.y5.z/Foo/bar Cookie: some_value=value1
-CHECK http://w.y6.z/Foo/Bar Cookie: some_value2=value2; some_value=value1; some_value3=value3
-CHECK http://w.y7.z/Bar/Foo Cookie: some_value=value2; some_value=value3
-CHECK http://w.y7.z/Foo/Bar Cookie: some_value=value1; some_value=value3
-CHECK https://secure.y7.z/Foo/bar Cookie: some_value2=value2
-CHECK http://secure.y7.z/Foo/bar
-CHECK https://secure.y8.z/Foo/bar Cookie: some_value3=value3
-CHECK http://secure.y8.z/Foo/bar
-CHECK http://www.acme9.com/ Cookie: some_value=value1
-CHECK http://www.abc9.com/
-CHECK http://frop.acme9.com/ Cookie: some_value=value1
-CHECK http://novell10.com/ Cookie: some_value=value1
-CHECK http://www.novell10.com/ Cookie: some_value=value1
-CHECK http://novell11.com/ Cookie: some_value=value1
-CHECK http://www.novell11.com/ Cookie: some_value=value1
-CHECK http://novell12.com/ Cookie: some_value=value1
-CHECK http://www.novell12.com/
-CHECK http://novell13.com/ Cookie: some_value=value1
-CHECK http://www.novell13.com/
-CHECK http://com/
-CHECK http://sun13.com/
-CHECK http://novell14.co.uk/ Cookie: some_value=value1
-CHECK http://www.novell14.co.uk/
-CHECK http://co.uk/
-CHECK http://sun14.co.uk/
-CHECK http://x.y.z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://y.z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://www.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://x.y.z.foobar15.com/
-CHECK http://y.z.foobar15.com/
-CHECK http://z.foobar15.com/
-CHECK http://www.foobar15.com/
-CHECK http://foobar15.com/
-CHECK http://x.y.z.foobar16.com/
-CHECK http://y.z.foobar16.com/
-CHECK http://z.foobar16.com/
-CHECK http://www.foobar16.com/
-CHECK http://foobar16.com/
-## Check result for RFC cookies after saving
-CHECK http://w.y20.z/ Cookie: $Version=1; some_value="value1"; $Path="/"
-CHECK http://a.b20.c/ Cookie: $Version=1; some_value="value2"; $Path="/"
-CHECK http://w.y21.z/ Cookie: $Version=1; some_value="extra space 2"
-CHECK http://a.b21.c/ Cookie: $Version=1; some_value="quoted value; and such"
-CHECK http://w.y22.z/ Cookie: $Version=1; some_value2=foobar; $Path="/"
-CHECK http://w.y23.z/
-CHECK http://w.y23.z/Foo Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y23.z/Foo/ Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y23.z/Foo/bar Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y24.z/
-CHECK http://w.y24.z/Foo Cookie: $Version=1; some_value=value1
-CHECK http://w.y24.z/FooBar
-CHECK http://w.y24.z/Foo/ Cookie: $Version=1; some_value=value1
-CHECK http://w.y24.z/Foo/bar Cookie: $Version=1; some_value=value1
-CHECK http://w.y25.z/Foo/Bar Cookie: $Version=1; some_value2=value2; $Path="/Foo/Bar"; some_value=value1; $Path="/Foo"; some_value3=value3; $Path="/"
-CHECK http://w.y26.z/Bar/Foo Cookie: $Version=1; some_value=value2; some_value=value3
-CHECK http://w.y26.z/Foo/Bar Cookie: $Version=1; some_value=value1; some_value=value3
-CHECK https://secure.y26.z/Foo/bar Cookie: $Version=1; some_value2=value2; $Path="/"
-CHECK http://secure.y26.z/Foo/bar
-CHECK https://secure.y27.z/Foo/bar Cookie: $Version=1; some_value3=value3; $Path="/"
-CHECK http://secure.y27.z/Foo/bar
-CHECK http://www.acme28.com/ Cookie: $Version=1; some_value=value1; $Domain=".acme28.com"
-CHECK http://www.abc28.com/
-CHECK http://frop.acme28.com/ Cookie: $Version=1; some_value=value1; $Domain=".acme28.com"
-CHECK http://novell29.com/ Cookie: $Version=1; some_value=value1; $Domain=".novell29.com"
-CHECK http://www.novell29.com/ Cookie: $Version=1; some_value=value1; $Domain=".novell29.com"
-CHECK http://novell30.com/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell30.com/
-CHECK http://novell31.com/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell31.com/
-CHECK http://com/
-CHECK http://sun31.com/
-CHECK http://novell32.co.uk/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell32.co.uk/
-CHECK http://co.uk/
-CHECK http://sun32.co.uk/
-CHECK http://x.y.z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://y.z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://www.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://x.y.z.foobar.com/
-CHECK http://y.z.foobar.com/
-CHECK http://z.foobar.com/
-CHECK http://www.foobar.com/
-CHECK http://foobar.com/
-
-SAVE
-## Check result after saving a second time
-CHECK http://w.y.z/
-CHECK http://a.b.c/
-CHECK http://w.y1.z/ Cookie: some_value=value with spaces
-CHECK http://a.b1.c/ Cookie: some_other_value; some_value="quoted value"
-CHECK http://a.b2.c/ Cookie: some_value="quoted value
-CHECK http://w.y3.z/ Cookie: some_value2=foobar
-CHECK http://w.y4.z/
-CHECK http://w.y4.z/Foo Cookie: some_value=value1
-CHECK http://w.y4.z/Foo/ Cookie: some_value=value1
-CHECK http://w.y4.z/Foo/bar Cookie: some_value=value1
-CHECK http://w.y5.z/
-CHECK http://w.y5.z/Foo Cookie: some_value=value1
-CHECK http://w.y5.z/FooBar
-CHECK http://w.y5.z/Foo/ Cookie: some_value=value1
-CHECK http://w.y5.z/Foo/bar Cookie: some_value=value1
-CHECK http://w.y6.z/Foo/Bar Cookie: some_value2=value2; some_value=value1; some_value3=value3
-CHECK http://w.y7.z/Bar/Foo Cookie: some_value=value2; some_value=value3
-CHECK http://w.y7.z/Foo/Bar Cookie: some_value=value1; some_value=value3
-CHECK https://secure.y7.z/Foo/bar Cookie: some_value2=value2
-CHECK http://secure.y7.z/Foo/bar
-CHECK https://secure.y8.z/Foo/bar Cookie: some_value3=value3
-CHECK http://secure.y8.z/Foo/bar
-CHECK http://www.acme9.com/ Cookie: some_value=value1
-CHECK http://www.abc9.com/
-CHECK http://frop.acme9.com/ Cookie: some_value=value1
-CHECK http://novell10.com/ Cookie: some_value=value1
-CHECK http://www.novell10.com/ Cookie: some_value=value1
-CHECK http://novell11.com/ Cookie: some_value=value1
-CHECK http://www.novell11.com/ Cookie: some_value=value1
-CHECK http://novell12.com/ Cookie: some_value=value1
-CHECK http://www.novell12.com/
-CHECK http://novell13.com/ Cookie: some_value=value1
-CHECK http://www.novell13.com/
-CHECK http://com/
-CHECK http://sun13.com/
-CHECK http://novell14.co.uk/ Cookie: some_value=value1
-CHECK http://www.novell14.co.uk/
-CHECK http://co.uk/
-CHECK http://sun14.co.uk/
-CHECK http://x.y.z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://y.z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://z.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://www.foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://foobar14.com/ Cookie: set_by=x.y.z.foobar14.com
-CHECK http://x.y.z.foobar15.com/
-CHECK http://y.z.foobar15.com/
-CHECK http://z.foobar15.com/
-CHECK http://www.foobar15.com/
-CHECK http://foobar15.com/
-CHECK http://x.y.z.foobar16.com/
-CHECK http://y.z.foobar16.com/
-CHECK http://z.foobar16.com/
-CHECK http://www.foobar16.com/
-CHECK http://foobar16.com/
-## Check result for rfc cookies after saving a second time
-CHECK http://w.y20.z/ Cookie: $Version=1; some_value="value1"; $Path="/"
-CHECK http://a.b20.c/ Cookie: $Version=1; some_value="value2"; $Path="/"
-CHECK http://w.y21.z/ Cookie: $Version=1; some_value="extra space 2"
-CHECK http://a.b21.c/ Cookie: $Version=1; some_value="quoted value; and such"
-CHECK http://w.y22.z/ Cookie: $Version=1; some_value2=foobar; $Path="/"
-CHECK http://w.y23.z/
-CHECK http://w.y23.z/Foo Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y23.z/Foo/ Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y23.z/Foo/bar Cookie: $Version=1; some_value=value1; $Path="/Foo"
-CHECK http://w.y24.z/
-CHECK http://w.y24.z/Foo Cookie: $Version=1; some_value=value1
-CHECK http://w.y24.z/FooBar
-CHECK http://w.y24.z/Foo/ Cookie: $Version=1; some_value=value1
-CHECK http://w.y24.z/Foo/bar Cookie: $Version=1; some_value=value1
-CHECK http://w.y25.z/Foo/Bar Cookie: $Version=1; some_value2=value2; $Path="/Foo/Bar"; some_value=value1; $Path="/Foo"; some_value3=value3; $Path="/"
-CHECK http://w.y26.z/Bar/Foo Cookie: $Version=1; some_value=value2; some_value=value3
-CHECK http://w.y26.z/Foo/Bar Cookie: $Version=1; some_value=value1; some_value=value3
-CHECK https://secure.y26.z/Foo/bar Cookie: $Version=1; some_value2=value2; $Path="/"
-CHECK http://secure.y26.z/Foo/bar
-CHECK https://secure.y27.z/Foo/bar Cookie: $Version=1; some_value3=value3; $Path="/"
-CHECK http://secure.y27.z/Foo/bar
-CHECK http://www.acme28.com/ Cookie: $Version=1; some_value=value1; $Domain=".acme28.com"
-CHECK http://www.abc28.com/
-CHECK http://frop.acme28.com/ Cookie: $Version=1; some_value=value1; $Domain=".acme28.com"
-CHECK http://novell29.com/ Cookie: $Version=1; some_value=value1; $Domain=".novell29.com"
-CHECK http://www.novell29.com/ Cookie: $Version=1; some_value=value1; $Domain=".novell29.com"
-CHECK http://novell30.com/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell30.com/
-CHECK http://novell31.com/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell31.com/
-CHECK http://com/
-CHECK http://sun31.com/
-CHECK http://novell32.co.uk/ Cookie: $Version=1; some_value=value1
-CHECK http://www.novell32.co.uk/
-CHECK http://co.uk/
-CHECK http://sun32.co.uk/
-CHECK http://x.y.z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://y.z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://z.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://www.foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://foobar33.com/ Cookie: $Version=1; set_by=x.y.z.foobar.com; $Domain=".foobar33.com"
-CHECK http://x.y.z.foobar.com/
-CHECK http://y.z.foobar.com/
-CHECK http://z.foobar.com/
-CHECK http://www.foobar.com/
-CHECK http://foobar.com/
diff --git a/kioslave/http/kcookiejar/tests/cookie_settings.test b/kioslave/http/kcookiejar/tests/cookie_settings.test
deleted file mode 100644
index 7fc1a03a7..000000000
--- a/kioslave/http/kcookiejar/tests/cookie_settings.test
+++ /dev/null
@@ -1,116 +0,0 @@
-## Check CookieGlobalAdvice setting
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value1; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value2; Path="/"
-CONFIG CookieGlobalAdvice Reject
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value3; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value4; Path="/"
-CONFIG CookieGlobalAdvice Accept
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value5; Path="/"; expires=%NEXTYEAR%
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value6; Path="/"
-CONFIG CookieGlobalAdvice Ask
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value7; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value8; Path="/"
-CONFIG AcceptSessionCookies true
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-# FIXME: Shouldn't this be considered a session cookie?
-# COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="0"
-# COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%LASTYEAR%
-# FIXME: The 'Discard' attribute makes the cookie a session cookie
-# COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-## Treat all cookies as session cookies
-CONFIG IgnoreExpirationDate true
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-## Check host-based domain policies
-CONFIG IgnoreExpirationDate false
-CONFIG AcceptSessionCookies false
-CONFIG CookieDomainAdvice a.b.c:Reject
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE REJECT http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-COOKIE ASK http://d.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://d.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ASK http://d.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ASK http://d.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-## Check resetting of domain policies
-CONFIG CookieDomainAdvice
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ASK http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-COOKIE ASK http://d.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://d.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ASK http://d.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ASK http://d.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-## Check domain policies
-CONFIG CookieDomainAdvice .b.c:Reject
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE REJECT http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-COOKIE REJECT http://d.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://d.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE REJECT http://d.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE REJECT http://d.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-## Check overriding of domain policies #1
-CONFIG CookieDomainAdvice .b.c:Reject,a.b.c:Accept
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-COOKIE REJECT http://d.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://d.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE REJECT http://d.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE REJECT http://d.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-## Check overriding of domain policies #2
-CONFIG CookieDomainAdvice a.b.c:Reject,.b.c:Accept
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE REJECT http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-COOKIE ACCEPT http://d.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ACCEPT http://d.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ACCEPT http://d.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ACCEPT http://d.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-## Check resetting of domain policies
-CONFIG CookieDomainAdvice
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ASK http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ASK http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-COOKIE ASK http://d.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://d.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ASK http://d.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ASK http://d.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-## Check overriding of domain policies #3
-CONFIG CookieDomainAdvice b.c:Reject,.b.c:Accept
-COOKIE REJECT http://b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE REJECT http://b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE REJECT http://b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-## Check overriding of domain policies #4
-CONFIG CookieDomainAdvice .a.b.c.d:Reject,.b.c.d:Accept,.c.d:Ask
-COOKIE REJECT http://www.a.b.c.d/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ACCEPT http://www.b.c.d/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE ASK http://www.c.d/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-## Check interaction with session policy
-CONFIG AcceptSessionCookies true
-CONFIG CookieDomainAdvice .b.c:Reject
-COOKIE REJECT http://a.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://a.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ACCEPT http://a.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
-COOKIE REJECT http://d.b.c/ Set-Cookie: some_value=value9; Path="/"; expires=%NEXTYEAR%
-COOKIE REJECT http://d.b.c/ Set-Cookie2: some_value=value10; Version=1; Path="/"; max-age="600"
-COOKIE ACCEPT http://d.b.c/ Set-Cookie: some_value=value11; Path="/"
-COOKIE ACCEPT http://d.b.c/ Set-Cookie2: some_value=value12; Version=1; Path="/"
diff --git a/kioslave/http/kcookiejar/tests/kcookiejartest.cpp b/kioslave/http/kcookiejar/tests/kcookiejartest.cpp
deleted file mode 100644
index a150fc420..000000000
--- a/kioslave/http/kcookiejar/tests/kcookiejartest.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- This file is part of KDE
-
- Copyright (C) 2004 Waldo Bastian (bastian@kde.org)
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- version 2 as published by the Free Software Foundation.
-
- This software 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
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this library; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <tqdatetime.h>
-#include <tqstring.h>
-
-#include <kapplication.h>
-#include <kaboutdata.h>
-#include <kcmdlineargs.h>
-#include <kstandarddirs.h>
-
-#include "../kcookiejar.cpp"
-
-static const char *description = "KCookiejar regression test";
-
-static KCookieJar *jar;
-static TQCString *lastYear;
-static TQCString *nextYear;
-static KConfig *config = 0;
-
-
-static KCmdLineOptions options[] =
-{
- { "+testfile", "Regression test to run", 0},
- KCmdLineLastOption
-};
-
-static void FAIL(const TQString &msg)
-{
- tqWarning("%s", msg.local8Bit().data());
- exit(1);
-}
-
-static void popArg(TQCString &command, TQCString & line)
-{
- int i = line.find(' ');
- if (i != -1)
- {
- command = line.left(i);
- line = line.mid(i+1);
- }
- else
- {
- command = line;
- line = 0;
- }
-}
-
-
-static void popArg(TQString &command, TQCString & line)
-{
- int i = line.find(' ');
- if (i != -1)
- {
- command = TQString::fromLatin1(line.left(i));
- line = line.mid(i+1);
- }
- else
- {
- command = TQString::fromLatin1(line);
- line = 0;
- }
-}
-
-static void clearConfig()
-{
- delete config;
- TQString file = locateLocal("config", "kcookiejar-testconfig");
- TQFile::remove(file);
- config = new KConfig(file);
- config->setGroup("Cookie Policy");
- config->writeEntry("RejectCrossDomainCookies", false);
- config->writeEntry("AcceptSessionCookies", false);
- config->writeEntry("IgnoreExpirationDate", false);
- config->writeEntry("CookieGlobalAdvice", "Ask");
- jar->loadConfig(config, false);
-}
-
-static void clearCookies()
-{
- jar->eatAllCookies();
-}
-
-static void saveCookies()
-{
- TQString file = locateLocal("config", "kcookiejar-testcookies");
- TQFile::remove(file);
- jar->saveCookies(file);
- delete jar;
- jar = new KCookieJar();
- clearConfig();
- jar->loadCookies(file);
-}
-
-static void processCookie(TQCString &line)
-{
- TQString policy;
- popArg(policy, line);
- KCookieAdvice expectedAdvice = KCookieJar::strToAdvice(policy);
- if (expectedAdvice == KCookieDunno)
- FAIL(TQString("Unknown accept policy '%1'").arg(policy));
-
- TQString urlStr;
- popArg(urlStr, line);
- KURL url(urlStr);
- if (!url.isValid())
- FAIL(TQString("Invalid URL '%1'").arg(urlStr));
- if (url.isEmpty())
- FAIL(TQString("Missing URL"));
-
- line.replace("%LASTYEAR%", *lastYear);
- line.replace("%NEXTYEAR%", *nextYear);
-
- KHttpCookieList list = jar->makeCookies(urlStr, line, 0);
-
- if (list.isEmpty())
- FAIL(TQString("Failed to make cookies from: '%1'").arg(line));
-
- for(KHttpCookie *cookie = list.first();
- cookie; cookie = list.next())
- {
- KCookieAdvice cookieAdvice = jar->cookieAdvice(cookie);
- if (cookieAdvice != expectedAdvice)
- FAIL(urlStr+TQString("\n'%2'\nGot advice '%3' expected '%4'").arg(line)
- .arg(KCookieJar::adviceToStr(cookieAdvice))
- .arg(KCookieJar::adviceToStr(expectedAdvice)));
- jar->addCookie(cookie);
- }
-}
-
-static void processCheck(TQCString &line)
-{
- TQString urlStr;
- popArg(urlStr, line);
- KURL url(urlStr);
- if (!url.isValid())
- FAIL(TQString("Invalid URL '%1'").arg(urlStr));
- if (url.isEmpty())
- FAIL(TQString("Missing URL"));
-
- TQString expectedCookies = TQString::fromLatin1(line);
-
- TQString cookies = jar->findCookies(urlStr, false, 0, 0).stripWhiteSpace();
- if (cookies != expectedCookies)
- FAIL(urlStr+TQString("\nGot '%1' expected '%2'")
- .arg(cookies, expectedCookies));
-}
-
-static void processClear(TQCString &line)
-{
- if (line == "CONFIG")
- clearConfig();
- else if (line == "COOKIES")
- clearCookies();
- else
- FAIL(TQString("Unknown command 'CLEAR %1'").arg(line));
-}
-
-static void processConfig(TQCString &line)
-{
- TQCString key;
- popArg(key, line);
-
- if (key.isEmpty())
- FAIL(TQString("Missing Key"));
-
- config->setGroup("Cookie Policy");
- config->writeEntry(key.data(), line.data());
- jar->loadConfig(config, false);
-}
-
-static void processLine(TQCString line)
-{
- if (line.isEmpty())
- return;
-
- if (line[0] == '#')
- {
- if (line[1] == '#')
- tqWarning("%s", line.data());
- return;
- }
-
- TQCString command;
- popArg(command, line);
- if (command.isEmpty())
- return;
-
- if (command == "COOKIE")
- processCookie(line);
- else if (command == "CHECK")
- processCheck(line);
- else if (command == "CLEAR")
- processClear(line);
- else if (command == "CONFIG")
- processConfig(line);
- else if (command == "SAVE")
- saveCookies();
- else
- FAIL(TQString("Unknown command '%1'").arg(command));
-}
-
-static void runRegression(const TQString &filename)
-{
- FILE *file = fopen(filename.local8Bit(), "r");
- if (!file)
- FAIL(TQString("Can't open '%1'").arg(filename));
-
- char buf[4096];
- while (fgets(buf, sizeof(buf), file))
- {
- int l = strlen(buf);
- if (l)
- {
- l--;
- buf[l] = 0;
- }
- processLine(buf);
- }
- tqWarning("%s OK", filename.local8Bit().data());
-}
-
-int main(int argc, char *argv[])
-{
- TQString arg1;
- TQCString arg2;
- TQString result;
-
- lastYear = new TQCString(TQString("Fri, 04-May-%1 01:00:00 GMT").arg(TQDate::currentDate().year()-1).utf8());
- nextYear = new TQCString(TQString(" expires=Fri, 04-May-%1 01:00:00 GMT").arg(TQDate::currentDate().year()+1).utf8());
-
- KAboutData about("kcookietest", "kcookietest", "1.0", description, KAboutData::License_GPL, "(C) 2004 Waldo Bastian");
- KCmdLineArgs::init( argc, argv, &about);
-
- KCmdLineArgs::addCmdLineOptions( options );
-
- KInstance a("kcookietest");
-
- KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
- if (args->count() != 1)
- KCmdLineArgs::usage();
-
- jar = new KCookieJar;
-
- clearConfig();
-
- TQString file = args->url(0).path();
- runRegression(file);
- return 0;
-}
diff --git a/kioslave/http/rfc2518.txt b/kioslave/http/rfc2518.txt
deleted file mode 100644
index 34d2e942a..000000000
--- a/kioslave/http/rfc2518.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://www.ietf.org/rfc/rfc2518.txt
diff --git a/kioslave/http/rfc2616.txt b/kioslave/http/rfc2616.txt
deleted file mode 100644
index 7be662a97..000000000
--- a/kioslave/http/rfc2616.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://www.ietf.org/rfc/rfc2616.txt
diff --git a/kioslave/http/rfc2617.txt b/kioslave/http/rfc2617.txt
deleted file mode 100644
index da74cc63a..000000000
--- a/kioslave/http/rfc2617.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://www.ietf.org/rfc/rfc2617.txt
diff --git a/kioslave/http/rfc2817.txt b/kioslave/http/rfc2817.txt
deleted file mode 100644
index a29dfc44b..000000000
--- a/kioslave/http/rfc2817.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://www.ietf.org/rfc/rfc2817.txt
diff --git a/kioslave/http/rfc2818.txt b/kioslave/http/rfc2818.txt
deleted file mode 100644
index fff91b1a9..000000000
--- a/kioslave/http/rfc2818.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://www.ietf.org/rfc/rfc2818.txt
diff --git a/kioslave/http/rfc3229.txt b/kioslave/http/rfc3229.txt
deleted file mode 100644
index 54a19b685..000000000
--- a/kioslave/http/rfc3229.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://www.ietf.org/rfc/rfc3229.txt
diff --git a/kioslave/http/rfc3253.txt b/kioslave/http/rfc3253.txt
deleted file mode 100644
index 9968eea02..000000000
--- a/kioslave/http/rfc3253.txt
+++ /dev/null
@@ -1 +0,0 @@
-http://www.ietf.org/rfc/rfc3253.txt
diff --git a/kioslave/http/shoutcast-icecast.txt b/kioslave/http/shoutcast-icecast.txt
deleted file mode 100644
index f7bdcf1e7..000000000
--- a/kioslave/http/shoutcast-icecast.txt
+++ /dev/null
@@ -1,605 +0,0 @@
-
-Audio and Apache HTTPD
-ApacheCon 2001
-Santa Clara, US
-
-April 6th, 2001
-
-Sander van Zoest <sander@vanZoest.com>
-Covalent Technologies, Inc.
-<http://www.covalent.net/>
-
-Latest version can be found at:
- <http://www.vanZoest.com/sander/apachecon/2001/>
-
-Introduction:
-
-About this paper:
-
-Contents:
-
- 1. Why serve Audio on the Net?
-
- This is almost like asking, why are you reading this? it might be
- because of the excitement caused by the new media that has recently
- crazed upon the internet. People are looking to bring their lifes onto
- the net, one of the things that brings that closer to a reality is the
- ability to hear live broadcasts of the worlds news, favorite sport;
- hear music and to teleconference with others. Sometimes it is simply
- to enhance the mood to a web site or to provide audio feedback of
- actions performed by the visitor of the web site.
-
- 2. What makes delivering audio so different?
-
- The biggest reason to what makes audio different then traditional
- web media such as graphics, text and HTML is the fact that timing
- is very important. This caused by the significant increase in size
- of the media and the different quality levels that exist.
-
- There really are two kinds of goals behind audio streams.
- In one case there is a need for immediate response the moment
- playback is requested and this can sacrifice quality. While
- in the other case quality and a non-interrupted stream are much
- more important.
-
- This sort of timing is not really required of any other media,
- with the exception of video. In the case of HTML and images the
- files sizes are usually a lot smaller which causes the objects
- to load much quicker and usually are not very useful without
- having the entire file. In audio the middle of a stream can have
- useful information and still set a particular mood.
-
- 3. Different ways of delivery Audio on the Net.
- Embedding audio in your Web Page
-
- This used to be a lot more common in the past. Just like embedding
- an image in a web page, it is possible to add a sound clip or score
- to the web page.
-
- The linked in audio files are usually short and of low quality to
- avoid a long delay for downloading the rest of the web page and the
- audio format needs to be supported by the browser natively or with
- a browser plug-in to avoid annoying the visitor.
-
- This can be accomplished using the HTML 4.0 [HTML4] object element which
- works similar to how to specify an applet with the object element.
- In the past this could also be accomplished using the embed and bgsound
- browser specific additions to HTML.
-
- example:
- <object type="audio/x-midi" data="../media/sound.mid" width="200" height="26">
- <param name="src" value="../media/sound.mid">
- <param name="autostart" value="true">
- <param name="controls" value="ControlPanel">
- </object>
-
- Each param element is specific to each browser. Please check with each
- browser for specific information in regards to what param elements are
- available.
-
- In this method of delivering audio the audio file is served up via the
- web server. When using an Apache HTTPD server make sure that the appropriate
- mime type is configured for the audio file and that the audio file is
- named and referenced by the appropriate extension.
-
- Although the current HTML 4.01 [HTML4] says to use the object element
- many browsers out on the market today still look for the embed element.
- Below find a little snipbit that will work work in many browsers.
-
- <object type="audio/x-midi" data="../media/sound.mid" width="200" height="26">
- <param name="src" value="../media/sound.mid">
- <param name="autostart" value="true">
- <param name="controls" value="ControlPanel">
-
- <embed type="audio/x-midi" src="../media/sound.mid"
- width="200" height="26" autoplay="true" controls="ControlPanel">
- <noembed>Your browser does not support embedded WAV files.</noembed>
- </object>
-
- With the increasing installation base of the Flash browser plug-in by
- Macromedia most developers that are looking to provide this kind of
- functionality to a web page are creating flash elements that have their
- own way of adding audio that is discussed in Flash specific documents.
-
- Downloading via HTTP
-
- Using this method the visitor to the website will have to download the
- entire audio file and save it to the hard drive before it can be
- listened to. (1) This is very popular with people that want to listen
- to high quality streams of audio and have a below ISDN connection to
- the internet. In some cases where the demand for a stream is high or
- the internet is congested downloading the content even for high bandwidth
- users can be affective and useful.
-
- One of the advantages of downloading audio to the local computer hard
- drive is that it can be played back (once downloaded) any time as long
- as the audio file is accessable from the computer.
-
- There are a lot of sites on the internet that provide this functionality
- for music and other audio files. It is also one of the easiest ways to
- delivery high quality audio to visitors.
-
- (1) Microsoft Windows Media Player in conjunction with the Microsoft
- Internet Explorer Browser will automaticly start playing the
- audio stream after a sufficient amount of the file has been
- downloaded. This can be accomplished because of the tight
- integration of the Browser and Media Player. With most audio players
- you can listen to a file being downloaded, but you will have to
- envoke the action manually.
-
- . On-Demand streaming via HTTP
-
- The real difference between downloading and on-demand streaming is
- that in on-demand streaming the audio starts playing before the entire
- audio file has been downloaded. This is accomplished by a hand of off
- the browser to the audio player via an intermediate file format that
- has been configured by the browser to be handled by the audio player.
-
- Look in a further section entitled "Linking to Audio via Apache HTTPD"
- below for more information about the different intermediate file formats.
-
- This type of streaming is very popular among the open source crowd and
- is the most widely implemented using the MP3 file format. Apache,
- Shoutcast [SHOUTCAST] and Icecast [ICECAST] are the most common
- software components used to provide on-demand streaming via HTTP. Both
- Icecast and Shoutcast are not fully HTTP compliant, but Icecast is
- becoming closer. For more information about the Shoutcast and Icecast
- differences see the section below.
-
- Sites like Live365.com and MP3.com are huge sites that rely on this
- method of delivery of audio.
-
- . On-Demand Streaming via RTSP/RTP
-
- RTSP/RTP is a new set of streaming protocols that is getting more
- backing and becoming more popular by the second. The specification
- was developed by the Internet Engineering Task Force Working Groups
- AVT [IETFAVT] and MMUSIC [IETFMMUSIC]. RTP the Realtime Transfer
- Protocol has been around longer then RTSP and originally came out
- of the work towards a better teleconferencing, mbone, type system.
- RTSP is the Real-Time Streaming Protocol that is used as a control
- protocol and acts similarily to HTTP except that it maintains state
- and is bi-directional.
-
- Currently the latest Real Networks Streaming Servers support RTSP
- and RTP and Real Networks own proprietary transfer protocol RDT.
- Apple's Darwin Streaming server is also RTSP/RTP compliant.
-
- The RTSP/RTP protocol suite is very powerful and flexable in regards
- to your streaming needs. It has the ability to suport "server-push"
- style stream redirects and has the ability to throttle streams to
- ensure the stream can sustain the limited bandwidth over the network.
-
- For On-Demand streams the RTP protocol would usually stream over
- TCP and have a second TCP connection open for RTSP. Because of the
- rich features provided by the protocol suite, it is not very well
- suited to allow people to download the stream and therefore the
- download via HTTP method might still be preferred by some.
-
- . Live Broadcast Streaming via RTSP/RTP
-
- In the case of a live broadcast streaming RTSP/RTP shines. RTP allowing
- for UDP datagrams to be transmitted to clients allows for fast immediate
- delivery of content with the sacrifice of reliability. The RTP stream
- can be send over IP Multicast to minimize bandwidth on the network.
-
- Many Content Delivery Networks (CDNs) are starting to provide support for
- RTSP/RTP proxies that should provide a better quality streaming environment
- on the internet.
-
- Much work is also being done in the RTP space to provide transfers over
- telecommunication networks such as cellular phones. Although not directly
- related, per se, it does provide a positive feeling knowing that all the
- audio related transfer groups seem to be working towards a common standard
- such as RTP.
-
- . On-Demand or Live Broadcast streaming via MMS.
-
- This is the Microsoft Windows Media Technologies Streaming protocol. It
- is only supported by Microsoft Windows Media Player and currently only
- works on Microsoft Windows.
-
- 5. Configuring Mime Types
-
- One of the most hardest things in serving audio has been the wide variety
- of audio codecs and mime types available. The battle of mime types on the
- audio player side of things isn't over, but it seems to be a little more
- controlled.
-
- On the server side of things provide the appropriate mime type for the
- particular audio streams and/or files that are being served to the audio
- players. Although some clients and operating systems handle files fully
- based on the file extension. The mime type [RFC2045] is more specific
- and more defined.
-
- The registered mime types are maintained by IANA [IANA]. On their site
- they have a list of all the registered mime types and their name space.
-
- If you are planning on using a mime type that isn't registered by IANA
- then signal this in the name space by adding a "x-" before the subtype.
- Because this was not done very often in the audio space, there was a
- lot of confusion to what the real mime type should be.
-
- For example the MPEG 1.0 Layer 3 Audio (MP3) [ORAMP3BOOK] mime type
- was not specified for the longest time. Because of this the mime type
- was audio/x-mpeg. Although none of the audio players understood
- audio/x-mpeg, but understood audio/mpeg it was not a technically
- correct mime type. Later audio players recognized this and started
- using the audio/x-mpeg mime type. Which in the end caused a lot
- of hassles with clients needing to be configured differently depending
- on the website and client that was used. Last november we thanked
- Martin Nilsson of the ID3 tagging project for registering audo/mpeg
- with IANA. [RFC3003]
-
- Correct configuration of Mime Types is very important. Apache HTTPD
- ships with a fairly up to date copy of the mime.types file, so most
- of the default ones (including audio/mpeg) are there.
-
- But in case you run into some that are not defined use the mod_mime
- directives such as AddType to fix this.
-
- Examples:
- AddType audio/x-mpegurl .m3u
- AddType audio/x-scpls .pls
- AddType application/x-ogg .ogg
-
-
- 6. Common Audio File Formats
-
- There are many audio formats and metadata formats that exist. Many of
- them do not have registered mime types and are hardly documented.
- This section is an attempt at providing the most accurate mime type
- information for each format with a rough description of what the files
- are used for.
-
- . Real Audio
-
- Real Networks Proprietary audio format and meta formats. This is one
- of the more common streaming audio formats today. It comes in several
- sub flavors such as Real 5.0, Real G2 and Real 8.0 etc. The file size
- varies depending on the bitrates and what combination of bitrates are
- contained within the single file.
- The following mime types are used
- audio/x-pn-realaudio .ra, .ram, .rm
- audio/x-pn-realaudio-plugin .rpm
- application/x-pn-realmedia
-
- . MPEG 1.0 Layer 3 Audio (MP3)
-
- This is currently one of the most popular downloaded audio formats
- that was originally developed by the Motion Pictures Experts Group
- and has patents by the Fraunhofer IIS Institute and Thompson
- Multimedia. [ORAMP3BOOK] The file is a lossy compression that at
- a bitrate of 128kbps reduces the file size to roughly a MB/minute.
- The mime type is audio/mpeg with the extension of .mp3 [RFC3003]
-
- . Windows Media Audio
-
- Originally known as MS Audio was developed by Microsoft as the MP3
- killer. Still relatively a new format but heavily marketed by
- Microsoft and becoming more popular by the minute. It is a successor
- to the Microsoft Audio Streaming Format (ASF).
-
- . WAV
-
- Windows Audio Format is a pretty semi-complicated encapsulating
- format that in the most common case is PCM with a WAV header up front.
- It has the mime type audio/x-wav with the extension .wav.
-
- . Vorbis
-
- Ogg Vorbis [VORBIS] is still a relatively new format brought to
- life by CD Paranoia author Christopher Montgomery; known to the
- world as Monty. It is an open source audio format free of patents
- and gotchas. It is a codec/file format that is roughly as good as
- the MP3 format, if not much better. The mime type for Ogg Vorbis is
- application/x-ogg with the extension of .ogg.
-
- . MIDI
-
- The MIDI standard and file format [MIDISPEC] have been used by
- Musicians for a long time. It is a great format to add music to
- a website without the long download times and needing special players
- or plug-ins. The mime type is audio/x-midi and the extension is .mid
-
- . Shockwave Flash (ADPCM/MP3) [FLASH4AUDIO]
-
- Macromedia Flash [FLASH4AUDIO] uses its own internal audio format
- that is often used on Flash websites. It is based on Adaptive
- Differential Pulse Code Modulation (ADPCM) and the MP3 file format.
- Because it is usually used from within Flash it usually isn't served
- up seperatedly but it's extension is .swf
-
- There are many many many more audio codecs and file formats that exist.
- I have listed a few that won't be discussed but should be kept in mind.
- Formats such as PCM/Raw Audio (audio/basic), MOD, MIDI (audio/x-midi),
- QDesign (used by Quicktime), Beatnik, Sun's AU, Apple/SGI's AIFF, AAC
- by the MPEG Group, Liquid Audio and AT&T's a2b (AAC derivatives),
- Dolby AC-3, Yamaha's TwinVQ (originally by Nippon Telephone and Telegraph)
- and MPEG-4 audio.
-
- 7. Linking to Audio via Apache HTTPD
-
- There are many different ways to link to audio from the Apache HTTPD
- web server. It seems as if every codec has their own metafile format.
- The metafile format is provided to allow the browser to hand off the
- job of requesting the audio file to the audio player, because it is
- more familiar with the file format and how to handle streaming or how
- to actually connect to the audio server then the web browser is.
-
- This section will discuss the more common methods to provide streaming
- links to provide that gateway from the web to the audio world.
-
- Probably the one that is the most recognized file is the RAM file.
-
- . RAM
-
- Real Audio Metafile. It is a pretty straight forward way that Real
- Networks allowed their Real Player to take more control over their
- proprietary audio streams. The file format is simply a URL on each
- line that will be streamed in order by the client. The mime type
- is the same as other RealAudio files audio/x-pn-realaudio where
- the pn stands for Progressive Networks the old name of the company.
-
- . M3U
-
- This next one is the MPEG Layer 3 URL Metafile that has been around
- for a very long time as a playlist format for MP3 players. It supported
- URLs pretty early on by some players and got the mime type
- audio/x-mpegurl and is now used by Icecast and many destination sites
- such as MP3.com. The format is exactly the same as that of the RAM
- file, just a list of urls that are separated by line feeds.
-
- . PLS
-
- This is the playlist files used by Nullsoft's Winamp MP3 Player. Later
- on it got more widely used by Nullsoft's Shoutcast and has the mime
- type of audio/x-scpls with the extension .pls. Before shoutcast the
- mimetype was simply audio/x-pls. As you can see in the example below
- it looks very much like a standard windows INI file format.
-
- Example:
- [playlist]
- numberofentries=2
- File1=<uri>
- Title1=<title>
- Length1=<length or -1>
- File2=<uri>
- Title2=<title>
- Length2=<length or -1>
-
- . SDP
-
- This is the Session Description Protocol [RFC2327] which is heavily
- used within RTSP and is a standard way of describing how to subscribe
- to a particular RTP stream. The mime type is application/sdp with the
- extension .sdp .
-
- Sometimes you might see RTSL (Real-Time Streaming Language) floating
- around. This was an old Real Networks format that has been succeeded
- by SDP. It's mimetype was application/x-rtsl with the extension of .rtsl
-
- . ASX
-
- Is a Windows Media Metafile format [MSASX] that is based on early XML
- standards. It can be found with many extensions such as .wvx, .wax
- and .asx. I am not aware of a mime type for this format.
-
- . SMIL
-
- Is the Synchronized Multimedia Integration Language [SMIL20] that
- is now a W3C Recommendation [W3SYMM]. It was originally developed
- by Real Networks to provide an HTML-like language to their Real Player
- that was more focused on multimedia. The mime type is application/smil
- with the extensions of either .smil or .smi
-
- . MHEG
-
- Is a hypertext language developed by the ISO group. [MHEG1] [MHEG5]
- and [MHEG5COR]. It has been adopted by the Digital Audio Visual
- Council [DAVIC]. It is more used for teleconferencing, broadcasting
- and television, but close enough related that it receives a mention
- here. The mime type is application/x-mheg with the extension of
- .mheg
-
- 8. Configuring Apache HTTPD specificly to serve large Audio Files
-
- Some of the most common things that you will need to adjust to be
- able to serve many large audio files via the Apache HTTPD Server.
- Because of the difference in size between HTML files and Audio files,
- the MaxClients will need to be adjusted appropriatedly depending on
- the amount of time listeners end up tieing up a process. If you are
- serving high quality MP3 files at 128kbps for example you should
- expect more then 5 minute download times for most people.
-
- This will significantly impact your webserver since this means that
- that process is occupied for the entire time. Because of this you
- will also want to in crease the TimeOut Directive to a higher
- number. This is to ensure that connections do not get disconnected
- half way through a transfer and having that person hit "reload"
- and connect again.
-
- Because of the amount of time the downloads tie up the processes
- of the server, the smallest footprint of the server in memory would
- be recommended because that would mean you could run more processes
- on the machine.
-
- After that normal performance tweaks such as max file descriptor
- changes and longer tcp listen queues apply.
-
- 9. Icecast/Shoutcast Protocol.
-
- Both protocols are very tightly based on HTTP/1.0. The main difference
- is a group of new headers such as the icy headers by Shoutcast and the
- new x-audiocast headers provided by Icecast.
-
- A typical shoutcast request from the client.
-
- GET / HTTP/1.0
-
- ICY 200 OK
- icy-notice1:<BR>This stream requires <a href="http://www.winamp.com/">
- Winamp</a><BR>
- icy-notice2:SHOUTcast Distributed Network Audio Server/posix v1.0b<BR>
- icy-name: Great Songs
- icy-genre: Jazz
- icy-url: http://shout.serv.dom/
- icy-pub: 1
- icy-br: 24
-
- <data><songtitle><data>
-
- The icy headers display the song title and other formation including if
- this stream is public and what the bitrate is.
-
- A typical icecast request from the client.
-
- GET / HTTP/1.0
- Host: icecast.serv.dom
- x-audiocast-udpport: 6000
- Icy-MetaData: 0
- Accept: */*
-
- HTTP/1.0 200 OK
- Server: Icecast/VERSION
- Content-Type: audio/mpeg
- x-audiocast-name: Great Songs
- x-audiocast-genre: Jazz
- x-audiocast-url: http://icecast.serv.dom/
- x-audiocast-streamid:
- x-audiocast-public: 0
- x-audiocast-bitrate: 24
- x-audiocast-description: served by Icecast
-
- <data>
-
- NOTE: I am mixing the headers of the controlling client with those form
- a listening client. This might be better explained at a latter
- date.
-
- The CPAN Perl Package Apache::MP3 by Lincoln Stein implements a little of
- each which works because MP3 players tend to support both.
-
- One of the big differences in implementations between the listening clients
- is that Icecast uses an out of band UDP channel to update metadata
- while the Shoutcast server gets it meta data from the client embedded within
- the MP3 stream. The general meta data for the stream is set up via the
- icy and x-audiocast HTTP headers.
-
- Although the MP3 standard documents were written for interrupted communication
- it is not very specific on that. So although it doesn't state that there is
- anything wrong with embedding garbage between MPEG frames the players that
- do not understand it might make a noisy bleep and chirps because of it.
-
-References and Further Reading:
-
-[DAVIC]
- Digital Audio Visual Council
- <http://www.davic.org/>
-
-[FLASH4AUDIO]
- L. J. Lotus, "Flash 4: Audio Options", ZD, Inc. 2000.
- <http://www.zdnet.com/devhead/stories/articles/0,4413,2580376,00.html>
-
-[HTML4]
- D. Ragget, A. Le Hors, I. Jacobs, "HTML 4.01 Specification", W3C
- Recommendation, December, 1999.
- <http://www.w3.org/TR/html401/>
-
-[IANA]
- Internet Assigned Numbers Authority.
- <http:/www.iana.org/>
-
-[ICECAST]
- Icecast Open Source Streaming Audio System.
- <http://www.icecast.org/>
-
-[IETFAVT]
- Audio/Video Transport WG, Internet Engineering Task Force.
- <http://www.ietf.org/html.charters/avt-charter.html>
-
-[IETFMMUSIC]
- Multiparty Multimedia Session Control WG, Internet Engineering Task
- Force. <http://www.ietf.org/html.charters/mmusic-charter.html>
-
-[IETFSIP]
- Session Initiation Protocol WG, Internet Engineering Task Force.
- <http://www.ietf.org/html.charters/sip-charter.html>
-
-[IPMULTICAST]
- Transmit information to a group of recipients via a single transmission
- by the source, in contrast to unicast.
- IP Multicast Initiative
- <http://www.ipmulticast.com/>
-
-[MIDISPEC]
- The International MIDI Association,"MIDI File Format Spec 1.1",
- <http://www.vanZoest.com/sander/apachecon/2001/midispec.html>
-
-[MHEG1]
- ISO/IEC, "Information Technology - Coding of Multimedia and Hypermedia
- Information - Part 1: MHEG Object Representation, Base Notation (ASN.1)";
- Draft International Standard ISO 13522-1;1997;
- <http://www.ansi.org/>
- <http://www.iso.ch/cate/d22153.html>
-
-[MHEG5]
- ISO/IEC, "Information Technology - Coding of Multimedia and Hypermedia
- Information - Part 5: Support for Base-Level Interactive Applications";
- Draft International Standard ISO 13522-5:1997;
- <http://www.ansi.org/>
- <http://www.iso.ch/cate/d26876.html>
-
-[MHEG5COR]
- Information Technology - Coding of Multimedia and Hypermedia Information
- - Part 5: Support for base-level interactive applications -
- - Technical Corrigendum 1; ISO/IEC 13552-5:1997/Cor.1:1999(E)
- <http://www.ansi.org/>
- <http://www.iso.ch/cate/d31582.html>
-
-[MSASX]
- Microsoft Corp. "All About Windows Media Metafiles". October 2000.
- <http://msdn.microsoft.com/workshop/imedia/windowsmedia/
- crcontent/asx.asp>
-
-[ORAMP3]
- S. Hacker; MP3: The Definitive Guide; O'Reilly and Associates, Inc.
- March, 2000.
- <http://www.oreilly.com/catalog/mp3/>
-[RFC2045]
- N. Freed and N. Borenstein, "Multipurpose Internet Mail
- Extensions (MIME) Part One: Format of Internet Message Bodies",
- RFC 2045, November 1996. <http://www.ietf.org/rfc/2045.txt>
-
-[RFC2327]
- M. Handley and V. Jacobson, "SDP: Session Description Protocol",
- RFC 2327, April 1998. <http://www.ietf.org/rfc/rfc2327.txt>
-
-[RFC3003]
- M. Nilsson, "The audio/mpeg Media Type", RFC 3003, November 2000.
- <http://www.ietf.org/rfc/rfc3003.txt>
-
-[SHOUTCAST]
- Nullsoft Shoutcast MP3 Streaming Technology.
- <http://www.shoutcast.com/>
-
-[SMIL20]
- L. Rutledge, J. van Ossenbruggen, L. Hardman, D. Bulterman,
- "Anticipating SMIL 2.0: The Developing Cooperative Infrastructure
- for Multimedia on the Web"; 8th International WWW Conference,
- Proc. May, 1999.
- <http://www8.org/w8-papers/3c-hypermedia-video/anticipating/
- anticipating.html>
-
-[W39CIR]
- V. Krishnan and S. G. Chang, "Customized Internet Radio"; 9th
- International WWW Conference Proc. May 2000.
- <http://www9.org/w9cdrom/353/353.html>
-
-[VORBIS]
- Ogg Vorbis - Open Source Audio Codec
- <http://www.xiph.org/ogg/vorbis/>
-
-[W3SYMM]
- W3C Synchronized Multimedia Activity (SYMM Working Group);
- <http://www.w3.org/AudioVideo/>
diff --git a/kioslave/http/webdav.protocol b/kioslave/http/webdav.protocol
deleted file mode 100644
index f4f4df462..000000000
--- a/kioslave/http/webdav.protocol
+++ /dev/null
@@ -1,18 +0,0 @@
-[Protocol]
-exec=kio_http
-protocol=webdav
-input=none
-output=filesystem
-listing=Name,Type,Size,Date,AccessDate,Access
-reading=true
-writing=true
-makedir=true
-deleting=true
-moving=true
-deleteRecursive=true
-defaultMimetype=application/octet-stream
-determineMimetypeFromExtension=false
-Icon=www
-maxInstances=3
-DocPath=kioslave/webdav.html
-Class=:internet
diff --git a/kioslave/http/webdavs.protocol b/kioslave/http/webdavs.protocol
deleted file mode 100644
index c8b7cba3f..000000000
--- a/kioslave/http/webdavs.protocol
+++ /dev/null
@@ -1,18 +0,0 @@
-[Protocol]
-exec=kio_http
-protocol=webdavs
-input=none
-output=filesystem
-listing=Name,Type,Size,Date,AccessDate,Access
-reading=true
-writing=true
-makedir=true
-deleting=true
-moving=true
-deleteRecursive=true
-defaultMimetype=application/octet-stream
-determineMimetypeFromExtension=false
-Icon=www
-config=webdav
-DocPath=kioslave/webdavs.html
-Class=:internet
diff --git a/kioslave/iso/CMakeLists.txt b/kioslave/iso/CMakeLists.txt
deleted file mode 100644
index da6315b77..000000000
--- a/kioslave/iso/CMakeLists.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-add_subdirectory( libisofs )
-
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/kio
- ${CMAKE_SOURCE_DIR}/kio/kio
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES iso.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
-install( FILES isoservice.desktop DESTINATION ${DATA_INSTALL_DIR}/konqueror/servicemenus )
-install( FILES kio_isorc DESTINATION ${CONFIG_INSTALL_DIR} )
-install( FILES kio_iso.desktop DESTINATION ${APPS_INSTALL_DIR} )
-
-
-##### kio_iso ###################################
-
-set( target kio_iso )
-
-set( ${target}_SRCS
- kisodirectory.cpp kisofile.cpp qfilehack.cpp
- kiso.cpp iso.cpp
-)
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK isofs-static kio-shared
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/iso/Makefile.am b/kioslave/iso/Makefile.am
deleted file mode 100644
index f9c0bb754..000000000
--- a/kioslave/iso/Makefile.am
+++ /dev/null
@@ -1,67 +0,0 @@
-kde_module_LTLIBRARIES = kio_iso.la
-
-
-INCLUDES = $(all_includes)
-
-
-#LDFLAGS =
-
-kio_iso_la_METASOURCES=AUTO
-
-kio_iso_la_SOURCES = kisodirectory.cpp kisofile.cpp qfilehack.cpp kiso.cpp iso.cpp
-kio_iso_la_LIBADD = libisofs/libisofs.la $(LIB_QT) $(LIB_TDECORE) $(LIB_KIO)
-
-kio_iso_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
-
-
-SUBDIRS = libisofs
-
-noinst_HEADERS = iso.h kiso.h qfilehack.h kisofile.h kisodirectory.h
-EXTRA_DIST = iso.protocol isoservice.desktop kio_iso.desktop
-
-install-data-local:
- $(mkinstalldirs) $(DESTDIR)$(kde_servicesdir)/
- $(INSTALL_DATA) $(srcdir)/iso.protocol $(DESTDIR)$(kde_servicesdir)/iso.protocol
- $(mkinstalldirs) $(DESTDIR)$(kde_datadir)/konqueror/servicemenus/
- $(INSTALL_DATA) $(srcdir)/isoservice.desktop $(DESTDIR)$(kde_datadir)/konqueror/servicemenus/isoservice.desktop
- $(mkinstalldirs) $(DESTDIR)$(kde_confdir)/
- $(INSTALL_DATA) $(srcdir)/kio_isorc $(DESTDIR)$(kde_confdir)/kio_isorc
- $(mkinstalldirs) $(DESTDIR)$(kde_appsdir)/
- $(INSTALL_DATA) $(srcdir)/kio_iso.desktop $(DESTDIR)$(kde_appsdir)/kio_iso.desktop
-
-uninstall-local:
- -rm -f $(DESTDIR)$(kde_servicesdir)/iso.protocol
- -rm -f $(DESTDIR)$(kde_datadir)/konqueror/servicemenus/isoservice.desktop
- -rm -f $(DESTDIR)$(kde_confdir)/kio_isorc
- -rm -f $(DESTDIR)$(kde_appsdir)/kio_iso.desktop
-
-# These paths are KDE specific. Use them:
-# kde_appsdir Where your application's menu entry (.desktop) should go to.
-# kde_icondir Where your icon should go to - better use KDE_ICON.
-# kde_sounddir Where your sounds should go to.
-# kde_htmldir Where your docs should go to. (contains lang subdirs)
-# kde_datadir Where you install application data. (Use a subdir)
-# kde_locale Where translation files should go to. (contains lang subdirs)
-# kde_cgidir Where cgi-bin executables should go to.
-# kde_confdir Where config files should go to (system-wide ones with default values).
-# kde_mimedir Where mimetypes .desktop files should go to.
-# kde_servicesdir Where services .desktop files should go to.
-# kde_servicetypesdir Where servicetypes .desktop files should go to.
-# kde_toolbardir Where general toolbar icons should go to (deprecated, use KDE_ICON).
-# kde_wallpaperdir Where general wallpapers should go to.
-# kde_templatesdir Where templates for the "New" menu (Konqueror/KDesktop) should go to.
-# kde_bindir Where executables should go to. Use bin_PROGRAMS or bin_SCRIPTS.
-# kde_libdir Where shared libraries should go to. Use lib_LTLIBRARIES.
-# kde_moduledir Where modules (e.g. parts) should go to. Use kde_module_LTLIBRARIES.
-# kde_styledir Where Qt/KDE widget styles should go to (new in KDE 3).
-# kde_designerdir Where Qt Designer plugins should go to (new in KDE 3).
-
-
-# make messages.po. Move this one to ../po/ and "make merge" in po
-# the -x is for skipping messages already translated in tdelibs
-messages:
- LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \
- if test -n "$$LIST"; then \
- $(XGETTEXT) -C -ki18n -x $(kde_includes)/kde.pot $$LIST -o ../po/iso.pot; \
- fi
-
diff --git a/kioslave/iso/iso.cpp b/kioslave/iso/iso.cpp
deleted file mode 100644
index 4bd128e49..000000000
--- a/kioslave/iso/iso.cpp
+++ /dev/null
@@ -1,525 +0,0 @@
-/***************************************************************************
- iso.cpp
- -------------------
- begin : Oct 25 2002
- copyright : (C) 2002 by Szombathelyi Gy�gy
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
- /* This file is heavily based on tar.cc from tdebase
- * (c) David Faure <faure@kde.org>
- */
-
-#include <zlib.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <klargefile.h>
-#include <tqfile.h>
-#include <kurl.h>
-#include <kdebug.h>
-#include <kinstance.h>
-#include <kiso.h>
-#include <kmimemagic.h>
-
-#include <errno.h> // to be removed
-
-#include "libisofs/iso_fs.h"
-
-#include "kisofile.h"
-#include "kisodirectory.h"
-#include "iso.h"
-
-typedef struct {
- char magic[8];
- char uncompressed_len[4];
- unsigned char header_size;
- unsigned char block_size;
- char reserved[2]; /* Reserved for future use, MBZ */
-} compressed_file_header;
-
-static const unsigned char zisofs_magic[8] = {
- 0x37, 0xE4, 0x53, 0x96, 0xC9, 0xDB, 0xD6, 0x07
-};
-
-using namespace KIO;
-
-extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); }
-
-int kdemain( int argc, char **argv )
-{
- KInstance instance( "kio_iso" );
-
- kdDebug() << "Starting " << getpid() << endl;
-
- if (argc != 4)
- {
- fprintf(stderr, "Usage: kio_iso protocol domain-socket1 domain-socket2\n");
- exit(-1);
- }
-
- kio_isoProtocol slave(argv[2], argv[3]);
- slave.dispatchLoop();
-
- kdDebug() << "Done" << endl;
- return 0;
-}
-
-
-kio_isoProtocol::kio_isoProtocol( const TQCString &pool, const TQCString &app ) : SlaveBase( "iso", pool, app )
-{
- kdDebug() << "kio_isoProtocol::kio_isoProtocol" << endl;
- m_isoFile = 0L;
-}
-
-kio_isoProtocol::~kio_isoProtocol()
-{
- delete m_isoFile;
-}
-
-bool kio_isoProtocol::checkNewFile( TQString fullPath, TQString & path, int startsec )
-{
- kdDebug() << "kio_isoProtocol::checkNewFile " << fullPath << " startsec: " <<
- startsec << endl;
-
- // Are we already looking at that file ?
- if ( m_isoFile && startsec == m_isoFile->startSec() &&
- m_isoFile->fileName() == fullPath.left(m_isoFile->fileName().length()) )
- {
- // Has it changed ?
- struct stat statbuf;
- if ( ::stat( TQFile::encodeName( m_isoFile->fileName() ), &statbuf ) == 0 )
- {
- if ( m_mtime == statbuf.st_mtime )
- {
- path = fullPath.mid( m_isoFile->fileName().length() );
- kdDebug() << "kio_isoProtocol::checkNewFile returning " << path << endl;
- return true;
- }
- }
- }
- kdDebug() << "Need to open a new file" << endl;
-
- // Close previous file
- if ( m_isoFile )
- {
- m_isoFile->close();
- delete m_isoFile;
- m_isoFile = 0L;
- }
-
- // Find where the iso file is in the full path
- int pos = 0;
- TQString isoFile;
- path = TQString::null;
-
- int len = fullPath.length();
- if ( len != 0 && fullPath[ len - 1 ] != '/' )
- fullPath += '/';
-
- kdDebug() << "the full path is " << fullPath << endl;
- while ( (pos=fullPath.find( '/', pos+1 )) != -1 )
- {
- TQString tryPath = fullPath.left( pos );
- kdDebug() << fullPath << " trying " << tryPath << endl;
-
- KDE_struct_stat statbuf;
- if ( KDE_lstat( TQFile::encodeName(tryPath), &statbuf ) == 0 && !S_ISDIR(statbuf.st_mode) )
- {
- isoFile = tryPath;
- m_mtime = statbuf.st_mtime;
- m_mode = statbuf.st_mode;
- path = fullPath.mid( pos + 1 );
- kdDebug() << "fullPath=" << fullPath << " path=" << path << endl;
- len = path.length();
- if ( len > 1 )
- {
- if ( path[ len - 1 ] == '/' )
- path.truncate( len - 1 );
- }
- else
- path = TQString::fromLatin1("/");
- kdDebug() << "Found. isoFile=" << isoFile << " path=" << path << endl;
- break;
- }
- }
- if ( isoFile.isEmpty() )
- {
- kdDebug() << "kio_isoProtocol::checkNewFile: not found" << endl;
- return false;
- }
-
- // Open new file
- kdDebug() << "Opening KIso on " << isoFile << endl;
- m_isoFile = new KIso( isoFile );
- m_isoFile->setStartSec(startsec);
- if ( !m_isoFile->open( IO_ReadOnly ) )
- {
- kdDebug() << "Opening " << isoFile << " failed." << endl;
- delete m_isoFile;
- m_isoFile = 0L;
- return false;
- }
-
- return true;
-}
-
-
-void kio_isoProtocol::createUDSEntry( const KArchiveEntry * isoEntry, UDSEntry & entry )
-{
- UDSAtom atom;
-
- entry.clear();
- atom.m_uds = UDS_NAME;
- atom.m_str = isoEntry->name();
- entry.append(atom);
-
- atom.m_uds = UDS_FILE_TYPE;
- atom.m_long = isoEntry->permissions() & S_IFMT; // keep file type only
- entry.append( atom );
-
- atom.m_uds = UDS_ACCESS;
- atom.m_long = isoEntry->permissions() & 07777; // keep permissions only
- entry.append( atom );
-
- atom.m_uds = UDS_SIZE;
- if (isoEntry->isFile()) {
- atom.m_long = ((KIsoFile *)isoEntry)->realsize();
- if (!atom.m_long) atom.m_long = ((KIsoFile *)isoEntry)->size();
- } else {
- atom.m_long = 0L;
- }
- entry.append( atom );
-
- atom.m_uds = UDS_USER;
- atom.m_str = isoEntry->user();
- entry.append( atom );
-
- atom.m_uds = UDS_GROUP;
- atom.m_str = isoEntry->group();
- entry.append( atom );
-
- atom.m_uds = UDS_MODIFICATION_TIME;
- atom.m_long = isoEntry->date();
- entry.append( atom );
-
- atom.m_uds = UDS_ACCESS_TIME;
- atom.m_long = isoEntry->isFile() ? ((KIsoFile *)isoEntry)->adate() :
- ((KIsoDirectory *)isoEntry)->adate();
- entry.append( atom );
-
- atom.m_uds = UDS_CREATION_TIME;
- atom.m_long = isoEntry->isFile() ? ((KIsoFile *)isoEntry)->cdate() :
- ((KIsoDirectory *)isoEntry)->cdate();
- entry.append( atom );
-
- atom.m_uds = UDS_LINK_DEST;
- atom.m_str = isoEntry->symlink();
- entry.append( atom );
-}
-
-void kio_isoProtocol::listDir( const KURL & url )
-{
- kdDebug() << "kio_isoProtocol::listDir " << url.url() << endl;
-
- TQString path;
- if ( !checkNewFile( url.path(), path, url.hasRef() ? url.htmlRef().toInt() : -1 ) )
- {
- TQCString _path( TQFile::encodeName(url.path()));
- kdDebug() << "Checking (stat) on " << _path << endl;
- struct stat buff;
- if ( ::stat( _path.data(), &buff ) == -1 || !S_ISDIR( buff.st_mode ) ) {
- error( KIO::ERR_DOES_NOT_EXIST, url.path() );
- return;
- }
- // It's a real dir -> redirect
- KURL redir;
- redir.setPath( url.path() );
- if (url.hasRef()) redir.setRef(url.htmlRef());
- kdDebug() << "Ok, redirection to " << redir.url() << endl;
- redirection( redir );
- finished();
- // And let go of the iso file - for people who want to unmount a cdrom after that
- delete m_isoFile;
- m_isoFile = 0L;
- return;
- }
-
- if ( path.isEmpty() )
- {
- KURL redir( TQString::fromLatin1( "iso:/") );
- kdDebug() << "url.path()==" << url.path() << endl;
- if (url.hasRef()) redir.setRef(url.htmlRef());
- redir.setPath( url.path() + TQString::fromLatin1("/") );
- kdDebug() << "kio_isoProtocol::listDir: redirection " << redir.url() << endl;
- redirection( redir );
- finished();
- return;
- }
-
- kdDebug() << "checkNewFile done" << endl;
- const KArchiveDirectory* root = m_isoFile->directory();
- const KArchiveDirectory* dir;
- if (!path.isEmpty() && path != "/")
- {
- kdDebug() << TQString(TQString("Looking for entry %1").arg(path)) << endl;
- const KArchiveEntry* e = root->entry( path );
- if ( !e )
- {
- error( KIO::ERR_DOES_NOT_EXIST, path );
- return;
- }
- if ( ! e->isDirectory() )
- {
- error( KIO::ERR_IS_FILE, path );
- return;
- }
- dir = (KArchiveDirectory*)e;
- } else {
- dir = root;
- }
-
- TQStringList l = dir->entries();
- totalSize( l.count() );
-
- UDSEntry entry;
- TQStringList::Iterator it = l.begin();
- for( ; it != l.end(); ++it )
- {
- kdDebug() << (*it) << endl;
- const KArchiveEntry* isoEntry = dir->entry( (*it) );
-
- createUDSEntry( isoEntry, entry );
-
- listEntry( entry, false );
- }
-
- listEntry( entry, true ); // ready
-
- finished();
-
- kdDebug() << "kio_isoProtocol::listDir done" << endl;
-}
-
-void kio_isoProtocol::stat( const KURL & url )
-{
- TQString path;
- UDSEntry entry;
-
- kdDebug() << "kio_isoProtocol::stat " << url.url() << endl;
- if ( !checkNewFile( url.path(), path, url.hasRef() ? url.htmlRef().toInt() : -1 ) )
- {
- // We may be looking at a real directory - this happens
- // when pressing up after being in the root of an archive
- TQCString _path( TQFile::encodeName(url.path()));
- kdDebug() << "kio_isoProtocol::stat (stat) on " << _path << endl;
- struct stat buff;
- if ( ::stat( _path.data(), &buff ) == -1 || !S_ISDIR( buff.st_mode ) ) {
- kdDebug() << "isdir=" << S_ISDIR( buff.st_mode ) << " errno=" << strerror(errno) << endl;
- error( KIO::ERR_DOES_NOT_EXIST, url.path() );
- return;
- }
- // Real directory. Return just enough information for KRun to work
- UDSAtom atom;
- atom.m_uds = KIO::UDS_NAME;
- atom.m_str = url.fileName();
- entry.append( atom );
- kdDebug() << "kio_isoProtocol::stat returning name=" << url.fileName() << endl;
-
- atom.m_uds = KIO::UDS_FILE_TYPE;
- atom.m_long = buff.st_mode & S_IFMT;
- entry.append( atom );
-
- statEntry( entry );
-
- finished();
-
- // And let go of the iso file - for people who want to unmount a cdrom after that
- delete m_isoFile;
- m_isoFile = 0L;
- return;
- }
-
- const KArchiveDirectory* root = m_isoFile->directory();
- const KArchiveEntry* isoEntry;
- if ( path.isEmpty() )
- {
- path = TQString::fromLatin1( "/" );
- isoEntry = root;
- } else {
- isoEntry = root->entry( path );
- }
- if ( !isoEntry )
- {
- error( KIO::ERR_DOES_NOT_EXIST, path );
- return;
- }
- createUDSEntry( isoEntry, entry );
- statEntry( entry );
- finished();
-}
-
-void kio_isoProtocol::getFile( const KIsoFile *isoFileEntry, const TQString &path )
-{
- unsigned long long size, pos = 0;
- bool mime=false,zlib=false;
- TQByteArray fileData, pointer_block, inbuf, outbuf;
- char *pptr = 0;
- compressed_file_header *hdr;
- int block_shift;
- unsigned long nblocks;
- unsigned long fullsize = 0, block_size = 0, block_size2 = 0;
- size_t ptrblock_bytes;
- unsigned long cstart, cend, csize;
- uLong bytes;
-
- size = isoFileEntry->realsize();
- if (size >= sizeof(sizeof(compressed_file_header))) zlib=true;
- if (!size) size = isoFileEntry->size();
- totalSize( size );
- if (!size) mimeType("application/x-zerosize");
-
- if (size && !m_isoFile->device()->isOpen()) m_isoFile->device()->open(IO_ReadOnly);
-
- if (zlib) {
- fileData=isoFileEntry->data(0, sizeof(compressed_file_header));
- if ( fileData.size() == sizeof(compressed_file_header) &&
- !memcmp(fileData.data(), zisofs_magic, sizeof (zisofs_magic)) ) {
-
- hdr=(compressed_file_header*) fileData.data();
- block_shift = hdr->block_size;
- block_size = 1UL << block_shift;
- block_size2 = block_size << 1;
- fullsize = isonum_731(hdr->uncompressed_len);
- nblocks = (fullsize + block_size - 1) >> block_shift;
- ptrblock_bytes = (nblocks+1) * 4;
- pointer_block=isoFileEntry->data( hdr->header_size << 2, ptrblock_bytes );
- if (pointer_block.size() == ptrblock_bytes &&
- inbuf.resize(block_size2) &&
- outbuf.resize(block_size)) {
-
- pptr = pointer_block.data();
- } else {
- error(KIO::ERR_COULD_NOT_READ, path);
- return;
- }
- } else {
- zlib=false;
- }
- }
-
- while (pos<size) {
- if (zlib) {
- cstart = isonum_731(pptr);
- pptr += 4;
- cend = isonum_731(pptr);
-
- csize = cend-cstart;
-
- if ( csize == 0 ) {
- outbuf.fill(0, -1);
- } else {
- if ( csize > block_size2 ) {
- //err = EX_DATAERR;
- break;
- }
-
- inbuf=isoFileEntry->data(cstart, csize);
- if (inbuf.size() != csize) {
- break;
- }
-
- bytes = block_size; // Max output buffer size
- if ( (uncompress((Bytef*) outbuf.data(), &bytes, (Bytef*) inbuf.data(), csize)) != Z_OK ) {
- break;
- }
- }
-
- if ( ((fullsize > block_size) && (bytes != block_size))
- || ((fullsize <= block_size) && (bytes < fullsize)) ) {
-
- break;
- }
-
- if ( bytes > fullsize )
- bytes = fullsize;
- fileData.assign(outbuf);
- fileData.resize(bytes);
- fullsize -= bytes;
- } else {
- fileData=isoFileEntry->data(pos,65536);
- if (fileData.size()==0) break;
- }
- if (!mime) {
- KMimeMagicResult * result = KMimeMagic::self()->findBufferFileType( fileData, path );
- kdDebug() << "Emitting mimetype " << result->mimeType() << endl;
- mimeType( result->mimeType() );
- mime=true;
- }
- data(fileData);
- pos+=fileData.size();
- processedSize(pos);
- }
-
- if (pos!=size) {
- error(KIO::ERR_COULD_NOT_READ, path);
- return;
- }
-
- fileData.resize(0);
- data(fileData);
- processedSize(pos);
- finished();
-
-}
-
-void kio_isoProtocol::get( const KURL & url )
-{
- kdDebug() << "kio_isoProtocol::get" << url.url() << endl;
-
- TQString path;
- if ( !checkNewFile( url.path(), path, url.hasRef() ? url.htmlRef().toInt() : -1 ) )
- {
- error( KIO::ERR_DOES_NOT_EXIST, url.path() );
- return;
- }
-
- const KArchiveDirectory* root = m_isoFile->directory();
- const KArchiveEntry* isoEntry = root->entry( path );
-
- if ( !isoEntry )
- {
- error( KIO::ERR_DOES_NOT_EXIST, path );
- return;
- }
- if ( isoEntry->isDirectory() )
- {
- error( KIO::ERR_IS_DIRECTORY, path );
- return;
- }
-
- const KIsoFile* isoFileEntry = static_cast<const KIsoFile *>(isoEntry);
- if ( !isoEntry->symlink().isEmpty() )
- {
- kdDebug() << "Redirection to " << isoEntry->symlink() << endl;
- KURL realURL( url, isoEntry->symlink() );
- kdDebug() << "realURL= " << realURL.url() << endl;
- redirection( realURL.url() );
- finished();
- return;
- }
- getFile(isoFileEntry, path);
- if (m_isoFile->device()->isOpen()) m_isoFile->device()->close();
-}
diff --git a/kioslave/iso/iso.h b/kioslave/iso/iso.h
deleted file mode 100644
index 2a488bd9d..000000000
--- a/kioslave/iso/iso.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/***************************************************************************
- iso.h
- -------------------
- begin : Oct 25 2002
- copyright : (C) 2002 by Szombathelyi György
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
- /* This file is heavily based on tar.h from tdebase
- * (c) David Faure <faure@kde.org>
- */
-
-#ifndef _ISO_H
-#define _ISO_H
-
-#include <kio/slavebase.h>
-#include <sys/types.h>
-#include "kisofile.h"
-
-class KIso;
-
-class kio_isoProtocol : public KIO::SlaveBase
-{
-public:
- kio_isoProtocol( const TQCString &pool, const TQCString &app );
- virtual ~kio_isoProtocol();
-
- virtual void listDir( const KURL & url );
- virtual void stat( const KURL & url );
- virtual void get( const KURL & url );
-
-protected:
- void getFile( const KIsoFile *isoFileEntry, const TQString &path );
- void createUDSEntry( const KArchiveEntry * isoEntry, KIO::UDSEntry & entry );
- bool checkNewFile( TQString fullPath, TQString & path, int startsec );
-
- KIso * m_isoFile;
- time_t m_mtime;
- int m_mode;
-};
-
-#endif
diff --git a/kioslave/iso/iso.protocol b/kioslave/iso/iso.protocol
deleted file mode 100644
index 0e7d71b64..000000000
--- a/kioslave/iso/iso.protocol
+++ /dev/null
@@ -1,11 +0,0 @@
-[Protocol]
-exec=kio_iso
-protocol=iso
-listing=Name,Type,Size,Date,AccessDate,CreationDate,Access,Owner,Group,Link
-input=filesystem
-output=filesystem
-reading=true
-source=true
-Icon=cd
-Description=A kioslave for ISO9660 filesystems
-MimeType=application/x-iso
diff --git a/kioslave/iso/isoservice.desktop b/kioslave/iso/isoservice.desktop
deleted file mode 100644
index 00093709b..000000000
--- a/kioslave/iso/isoservice.desktop
+++ /dev/null
@@ -1,14 +0,0 @@
-[Desktop Entry]
-Encoding=UTF-8
-Actions=OpenISO
-ServiceTypes=inode/blockdevice,application/x-iso
-
-[Desktop Action OpenISO]
-Comment=ISO9660 View
-Comment[hu]=ISO9660 Nézet
-Comment[fr]=Lecteur ISO9660
-Icon=cd
-Name=ISO9660 View
-Name[hu]=ISO9660 Nézet
-Name[fr]=Lecteur ISO9660
-Exec=kfmclient exec iso:%f
diff --git a/kioslave/iso/kio_iso.desktop b/kioslave/iso/kio_iso.desktop
deleted file mode 100644
index 8578f44b4..000000000
--- a/kioslave/iso/kio_iso.desktop
+++ /dev/null
@@ -1,13 +0,0 @@
-[Desktop Entry]
-Type=Application
-Exec=konqueror iso:%f
-Icon=cd
-Terminal=false
-MimeType=application/x-iso;
-InitialPreference=10
-NoDisplay=true
-Name=ISO9660 Image Viewer
-Name[hu]=ISO9660 Nézet
-Name[fr]=Lecteur ISO9660
-X-DCOP-ServiceType=None
-Categories=Qt;TDE;System; \ No newline at end of file
diff --git a/kioslave/iso/kio_isorc b/kioslave/iso/kio_isorc
deleted file mode 100644
index 3a874172e..000000000
--- a/kioslave/iso/kio_isorc
+++ /dev/null
@@ -1,2 +0,0 @@
-showhidden=false
-showrr=true
diff --git a/kioslave/iso/kiso.cpp b/kioslave/iso/kiso.cpp
deleted file mode 100644
index 9ec1f1c3e..000000000
--- a/kioslave/iso/kiso.cpp
+++ /dev/null
@@ -1,460 +0,0 @@
-/***************************************************************************
- kiso.cpp
- -------------------
- begin : Oct 25 2002
- copyright : (C) 2002 by Szombathelyi Gy�gy
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
- /* This file is heavily based on ktar.cpp from tdelibs (c) David Faure */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-#include <grp.h>
-#include <pwd.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <tqcstring.h>
-#include <tqdir.h>
-#include <tqfile.h>
-#include <kdebug.h>
-#include <kurl.h>
-#include <kmimetype.h>
-#include <kconfig.h>
-#include <kfilterdev.h>
-#include <kfilterbase.h>
-
-#include "kiso.h"
-#include "libisofs/isofs.h"
-#include "qfilehack.h"
-
-
-#ifdef __linux__
-#undef __STRICT_ANSI__
-#include <linux/cdrom.h>
-#define __STRICT_ANSI__
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#endif
-
-////////////////////////////////////////////////////////////////////////
-/////////////////////////// KIso ///////////////////////////////////
-////////////////////////////////////////////////////////////////////////
-
-/**
- * puts the track layout of the device 'fname' into 'tracks'
- * tracks structure: start sector, track number, ...
- * tracks should be 100*2 entry long (this is the maximum in the CD-ROM standard)
- * currently it's linux only, porters are welcome
- */
-static int getTracks(const char *fname,int *tracks) {
- int ret=0;
- memset(tracks,0,200*sizeof(int));
-
-#ifdef __linux__
- int fd,i;
- struct cdrom_tochdr tochead;
- struct cdrom_tocentry tocentry;
-
- kdDebug() << "getTracks open:" << fname << endl;
- fd=open(fname, O_RDONLY | O_NONBLOCK);
- if (fd > 0) {
- if (ioctl(fd,CDROMREADTOCHDR,&tochead)!=-1) {
- kdDebug() << "getTracks first track:" << tochead.cdth_trk0
- << " last track " << tochead.cdth_trk1 << endl;
- for (i=tochead.cdth_trk0;i<=tochead.cdth_trk1;i++) {
- if (ret>99) break;
- memset(&tocentry,0,sizeof(struct cdrom_tocentry));
- tocentry.cdte_track=i;
- tocentry.cdte_format=CDROM_LBA;
- if (ioctl(fd,CDROMREADTOCENTRY,&tocentry)<0) break;
- kdDebug() << "getTracks got track " << i << " starting at: " <<
- tocentry.cdte_addr.lba << endl;
- if ((tocentry.cdte_ctrl & 0x4) == 0x4) {
- tracks[ret<<1]=tocentry.cdte_addr.lba;
- tracks[(ret<<1)+1]=i;
- ret++;
- }
- }
- }
- close(fd);
- }
-
-#endif
-
- return ret;
-}
-
-class KIso::KIsoPrivate
-{
-public:
- KIsoPrivate() {}
- TQStringList dirList;
-};
-
-KIso::KIso( const TQString& filename, const TQString & _mimetype )
- : KArchive( 0L )
-{
- m_startsec = -1;
- m_filename = filename;
- d = new KIsoPrivate;
- TQString mimetype( _mimetype );
- bool forced = true;
- if ( mimetype.isEmpty() )
- {
- mimetype = KMimeType::findByFileContent( filename )->name();
- kdDebug() << "KIso::KIso mimetype=" << mimetype << endl;
-
- // Don't move to prepareDevice - the other constructor theoretically allows ANY filter
- if ( mimetype == "application/x-tgz" || mimetype == "application/x-targz" || // the latter is deprecated but might still be around
- mimetype == "application/x-webarchive" )
- // that's a gzipped tar file, so ask for gzip filter
- mimetype = "application/x-gzip";
- else if ( mimetype == "application/x-tbz" ) // that's a bzipped2 tar file, so ask for bz2 filter
- mimetype = "application/x-bzip2";
- else
- {
- // Something else. Check if it's not really gzip though (e.g. for KOffice docs)
- TQFile file( filename );
- if ( file.open( IO_ReadOnly ) )
- {
- unsigned char firstByte = file.getch();
- unsigned char secondByte = file.getch();
- unsigned char thirdByte = file.getch();
- if ( firstByte == 0037 && secondByte == 0213 )
- mimetype = "application/x-gzip";
- else if ( firstByte == 'B' && secondByte == 'Z' && thirdByte == 'h' )
- mimetype = "application/x-bzip2";
- else if ( firstByte == 'P' && secondByte == 'K' && thirdByte == 3 )
- {
- unsigned char fourthByte = file.getch();
- if ( fourthByte == 4 )
- mimetype = "application/x-zip";
- }
- }
- }
- forced = false;
- }
-
- prepareDevice( filename, mimetype, forced );
-}
-
-void KIso::prepareDevice( const TQString & filename,
- const TQString & mimetype, bool forced )
-{
- /* 'hack' for Qt's false assumption that only S_ISREG is seekable */
- if( "inode/blockdevice" == mimetype )
- setDevice( TQT_TQIODEVICE(new QFileHack( filename )) );
- else
- {
- if( "application/x-gzip" == mimetype
- || "application/x-bzip2" == mimetype)
- forced = true;
-
- TQIODevice *dev = KFilterDev::deviceForFile( filename, mimetype, forced );
- if( dev )
- setDevice( dev );
- }
-
-}
-
-KIso::KIso( TQIODevice * dev )
- : KArchive( dev )
-{
- d = new KIsoPrivate;
-}
-
-KIso::~KIso()
-{
- // mjarrett: Closes to prevent ~KArchive from aborting w/o device
- if( isOpened() )
- close();
- if ( !m_filename.isEmpty() )
- delete device(); // we created it ourselves
- delete d;
-}
-
-/* callback function for libisofs */
-static int readf(char *buf, long long start, long long len,void *udata) {
-
- TQIODevice* dev = ( static_cast<KIso*> (udata) )->device();
-
- if (dev->at(start<<11)) {
- if ((dev->readBlock(buf, len<<11)) != -1) return (len);
- }
- kdDebug() << "KIso::ReadRequest failed start: " << start << " len: " << len << endl;
-
- return -1;
-}
-
-/* callback function for libisofs */
-static int mycallb(struct iso_directory_record *idr,void *udata) {
-
- KIso *iso = static_cast<KIso*> (udata);
- TQString path,user,group,symlink;
- int i;
- int access;
- int time,cdate,adate;
- rr_entry rr;
- bool special=false;
- KArchiveEntry *entry=NULL,*oldentry=NULL;
- char z_algo[2],z_params[2];
- long long z_size=0;
-
- if ((idr->flags[0] & 1) && !iso->showhidden) return 0;
- if (iso->level) {
- if (isonum_711(idr->name_len)==1) {
- switch (idr->name[0]) {
- case 0:
- path+=(".");
- special=true;
- break;
- case 1:
- path+=("..");
- special=true;
- break;
- }
- }
- if (iso->showrr && ParseRR(idr,&rr)>0) {
- if (!special) path=rr.name;
- symlink=rr.sl;
- access=rr.mode;
- time=rr.t_mtime;
- adate=rr.t_atime;
- cdate=rr.t_ctime;
- user.setNum(rr.uid);
- group.setNum(rr.gid);
- z_algo[0]=rr.z_algo[0];z_algo[1]=rr.z_algo[1];
- z_params[0]=rr.z_params[0];z_params[1]=rr.z_params[1];
- z_size=rr.z_size;
- } else {
- access=iso->dirent->permissions() & ~S_IFMT;
- adate=cdate=time=isodate_915(idr->date,0);
- user=iso->dirent->user();
- group=iso->dirent->group();
- if (idr->flags[0] & 2) access |= S_IFDIR; else access |= S_IFREG;
- if (!special) {
- if (iso->joliet) {
- for (i=0;i<(isonum_711(idr->name_len)-1);i+=2) {
- TQChar ch( be2me_16(*((ushort*)&(idr->name[i]))) );
- if (ch==';') break;
- path+=ch;
- }
- } else {
- for (i=0;i<isonum_711(idr->name_len);i++) {
- if (idr->name[i]==';') break;
- if (idr->name[i]) path+=(idr->name[i]);
- }
- }
- if (path.endsWith(".")) path.setLength(path.length()-1);
- }
- }
- if (iso->showrr) FreeRR(&rr);
- if (idr->flags[0] & 2) {
- entry = new KIsoDirectory( iso, path, access | S_IFDIR, time, adate, cdate,
- user, group, symlink );
- } else {
- entry = new KIsoFile( iso, path, access, time, adate, cdate,
- user, group, symlink, isonum_733(idr->extent)<<11,isonum_733(idr->size) );
- if (z_size) (static_cast <KIsoFile*> (entry))->setZF(z_algo,z_params,z_size);
-
- }
- iso->dirent->addEntry(entry);
- }
- if ( (idr->flags[0] & 2) && (iso->level==0 || !special) ) {
- if (iso->level) {
- oldentry=iso->dirent;
- iso->dirent=static_cast<KIsoDirectory*> (entry);
- }
- iso->level++;
- ProcessDir(&readf,isonum_733(idr->extent),isonum_733(idr->size),&mycallb,udata);
- iso->level--;
- if (iso->level) iso->dirent=static_cast<KIsoDirectory*> (oldentry);
- }
- return 0;
-}
-
-void KIso::addBoot(struct el_torito_boot_descriptor* bootdesc) {
-
- int i;
- long long size;
- boot_head boot;
- boot_entry *be;
- TQString path;
- KIsoFile *entry;
-
- entry=new KIsoFile( this, "Catalog", dirent->permissions() & ~S_IFDIR,
- dirent->date(), dirent->adate(), dirent->cdate(),
- dirent->user(), dirent->group(), TQString::null,
- isonum_731(bootdesc->boot_catalog)<<11, 2048 );
- dirent->addEntry(entry);
- if (!ReadBootTable(&readf,isonum_731(bootdesc->boot_catalog),&boot,this)) {
- i=1;
- be=boot.defentry;
- while (be) {
- size=BootImageSize( isonum_711((reinterpret_cast<struct default_entry*>(be->data))->media),
- isonum_721((reinterpret_cast<struct default_entry*>(be->data))->seccount));
- path="Default Image";
- if (i>1) path += " (" + TQString::number(i) + ")";
- entry=new KIsoFile( this, path, dirent->permissions() & ~S_IFDIR,
- dirent->date(), dirent->adate(), dirent->cdate(),
- dirent->user(), dirent->group(), TQString::null,
- isonum_731((reinterpret_cast<struct default_entry*>(be->data))->start)<<11, size<<9 );
- dirent->addEntry(entry);
- be=be->next;
- i++;
- }
-
- FreeBootTable(&boot);
- }
-}
-
-void KIso::readParams()
-{
- KConfig *config;
-
- config = new KConfig("kio_isorc");
-
- showhidden=config->readBoolEntry("showhidden",false);
- showrr=config->readBoolEntry("showrr",true);
- delete config;
-}
-
-bool KIso::openArchive( int mode )
-{
- iso_vol_desc *desc;
- TQString path,tmp,uid,gid;
- struct stat buf;
- int tracks[2*100],trackno=0,i,access,c_b,c_i,c_j;
- KArchiveDirectory *root;
- struct iso_directory_record* idr;
- struct el_torito_boot_descriptor* bootdesc;
-
- if ( mode == IO_WriteOnly )
- return false;
-
- readParams();
- d->dirList.clear();
-
- tracks[0]=0;
- if (m_startsec>0) tracks[0]=m_startsec;
- kdDebug() << " m_startsec: " << m_startsec << endl;
- /* We'll use the permission and user/group of the 'host' file except
- * in Rock Ridge, where the permissions are stored on the file system
- */
- if (::stat( m_filename.local8Bit(), &buf )<0) {
- /* defaults, if stat fails */
- memset(&buf,0,sizeof(struct stat));
- buf.st_mode=0777;
- } else {
- /* If it's a block device, try to query the track layout (for multisession) */
- if (m_startsec == -1 && S_ISBLK(buf.st_mode))
- trackno=getTracks(m_filename.latin1(),(int*) &tracks);
- }
- uid.setNum(buf.st_uid);
- gid.setNum(buf.st_gid);
- access = buf.st_mode & ~S_IFMT;
-
- kdDebug() << "KIso::openArchive number of tracks: " << trackno << endl;
-
- if (trackno==0) trackno=1;
- for (i=0;i<trackno;i++) {
-
- c_b=1;c_i=1;c_j=1;
- root=rootDir();
- if (trackno>1) {
- path=TQString::null;
- TQTextOStream(&path) << "Track " << tracks[(i<<1)+1];
- root = new KIsoDirectory( this, path, access | S_IFDIR,
- buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, TQString::null );
- rootDir()->addEntry(root);
- }
-
- desc=ReadISO9660(&readf,tracks[i<<1],this);
- if (!desc) {
- kdDebug() << "KIso::openArchive no volume descriptors" << endl;
- continue;
- }
-
- while (desc) {
- switch (isonum_711(desc->data.type)) {
- case ISO_VD_BOOT:
-
- bootdesc=(struct el_torito_boot_descriptor*) &(desc->data);
- if ( !memcmp(EL_TORITO_ID,bootdesc->system_id,ISODCL(8,39)) ) {
- path="El Torito Boot";
- if (c_b>1) path += " (" + TQString::number(c_b) + ")";
-
- dirent = new KIsoDirectory( this, path, access | S_IFDIR,
- buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, TQString::null );
- root->addEntry(dirent);
-
- addBoot(bootdesc);
- c_b++;
- }
- break;
-
- case ISO_VD_PRIMARY:
- case ISO_VD_SUPPLEMENTARY:
- idr=(struct iso_directory_record*) &( ((struct iso_primary_descriptor*) &desc->data)->root_directory_record);
- joliet = JolietLevel(&desc->data);
- if (joliet) {
- TQTextOStream(&path) << "Joliet level " << joliet;
- if (c_j>1) path += " (" + TQString::number(c_j) + ")";
- } else {
- path = "ISO9660";
- if (c_i>1) path += " (" + TQString::number(c_i) + ")";
- }
- dirent = new KIsoDirectory( this, path, access | S_IFDIR,
- buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, TQString::null );
- root->addEntry(dirent);
- level=0;
- mycallb(idr, this );
- if (joliet) c_j++; else c_i++;
- break;
- }
- desc=desc->next;
- }
- free(desc);
- }
- device()->close();
- return true;
-}
-
-bool KIso::closeArchive()
-{
- d->dirList.clear();
- return true;
-}
-
-bool KIso::writeDir( const TQString&, const TQString&, const TQString& )
-{
- return false;
-}
-
-bool KIso::prepareWriting( const TQString&, const TQString&, const TQString&, uint)
-{
- return false;
-}
-
-bool KIso::doneWriting( uint )
-{
- return false;
-}
-
-void KIso::virtual_hook( int id, void* data )
-{ KArchive::virtual_hook( id, data ); }
-
diff --git a/kioslave/iso/kiso.h b/kioslave/iso/kiso.h
deleted file mode 100644
index de0f06dca..000000000
--- a/kioslave/iso/kiso.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/***************************************************************************
- kiso.h
- -------------------
- begin : Oct 25 2002
- copyright : (C) 2002 by Szombathelyi Gy�gy
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
- /* This file is heavily based on ktar.h from tdelibs
- * (c) Torben Weis <weis@kde.org>, David Faure <faure@kde.org>
- */
-
-#ifndef KISO_H
-#define KISO_H
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <tqdatetime.h>
-#include <tqstring.h>
-#include <tqstringlist.h>
-#include <tqdict.h>
-
-#include "kisofile.h"
-#include "kisodirectory.h"
-
-/**
- * @short A class for reading (optionnally compressed) iso9660 files.
- * @author Gy�gy Szombathelyi <gyurco@users.sourceforge.net>,
- * Torben Weis <weis@kde.org>, David Faure <faure@kde.org>
- */
-class KIso : public KArchive
-{
-public:
- /**
- * Creates an instance that operates on the given filename.
- * using the compression filter associated to given mimetype.
- *
- * @param filename is a local path (e.g. "/home/weis/myfile.tgz")
- * @param mimetype "application/x-gzip" or "application/x-bzip2"
- * Do not use application/x-tgz or so. Only the compression layer !
- * If the mimetype is ommitted, it will be determined from the filename.
- */
- KIso( const TQString& filename, const TQString & mimetype = TQString::null );
-
- /**
- * Creates an instance that operates on the given device.
- * The device can be compressed (KFilterDev) or not (TQFile, etc.).
- * WARNING: don't assume that giving a TQFile here will decompress the file,
- * in case it's compressed!
- */
- KIso( TQIODevice * dev );
-
- /**
- * If the .iso is still opened, then it will be
- * closed automatically by the destructor.
- */
- virtual ~KIso();
-
- /**
- * The name of the os file, as passed to the constructor
- * Null if you used the TQIODevice constructor.
- */
- TQString fileName() { return m_filename; }
-
- bool writeDir( const TQString& , const TQString& , const TQString& );
- bool prepareWriting( const TQString& , const TQString& , const TQString& , uint );
- bool doneWriting( uint );
-
- void setStartSec(int startsec) { m_startsec = startsec; }
- int startSec() { return m_startsec; }
-
- bool showhidden,showrr;
- int level,joliet;
- KIsoDirectory *dirent;
-protected:
- /**
- * Opens the archive for reading.
- * Parses the directory listing of the archive
- * and creates the KArchiveDirectory/KArchiveFile entries.
- *
- */
- void readParams();
- virtual bool openArchive( int mode );
- virtual bool closeArchive();
-
-private:
- /**
- * @internal
- */
- void addBoot(struct el_torito_boot_descriptor* bootdesc);
- void prepareDevice( const TQString & filename, const TQString & mimetype, bool forced = false );
- int m_startsec;
-
- TQString m_filename;
-protected:
- virtual void virtual_hook( int id, void* data );
-private:
- class KIsoPrivate;
- KIsoPrivate * d;
-};
-
-#endif
diff --git a/kioslave/iso/kisodirectory.cpp b/kioslave/iso/kisodirectory.cpp
deleted file mode 100644
index 74987a232..000000000
--- a/kioslave/iso/kisodirectory.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/***************************************************************************
- kisodirectory.cpp - description
- -------------------
- begin : Wed Oct 30 2002
- copyright : (C) 2002 by Szombathelyi György
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "kisodirectory.h"
-
-KIsoDirectory::KIsoDirectory( KArchive* archive, const TQString& name, int access,
- int date, int adate, int cdate, const TQString& user, const TQString& group,
- const TQString& symlink) :
- KArchiveDirectory(archive, name, access, date, user, group, symlink) {
-
-
- m_adate=adate;
- m_cdate=cdate;
-}
-
-KIsoDirectory::~KIsoDirectory(){
-}
diff --git a/kioslave/iso/kisodirectory.h b/kioslave/iso/kisodirectory.h
deleted file mode 100644
index 74045ac75..000000000
--- a/kioslave/iso/kisodirectory.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/***************************************************************************
- kisodirectory.h - description
- -------------------
- begin : Wed Oct 30 2002
- copyright : (C) 2002 by Szombathelyi György
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef KISODIRECTORY_H
-#define KISODIRECTORY_H
-
-#include <tqstring.h>
-#include <karchive.h>
-
-/**
- *@author Szombathelyi György
- */
-
-class KIsoDirectory : public KArchiveDirectory {
-public:
- KIsoDirectory( KArchive* archive, const TQString& name, int access, int date,
- int adate,int cdate, const TQString& user, const TQString& group,
- const TQString& symlink);
- ~KIsoDirectory();
- int adate() const { return m_adate; }
- int cdate() const { return m_cdate; }
-private:
- int m_adate, m_cdate;
-};
-
-#endif
diff --git a/kioslave/iso/kisofile.cpp b/kioslave/iso/kisofile.cpp
deleted file mode 100644
index ffae0d3bc..000000000
--- a/kioslave/iso/kisofile.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/***************************************************************************
- kisofile.cpp - description
- -------------------
- begin : Wed Oct 30 2002
- copyright : (C) 2002 by Szombathelyi Gy�gy
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "kisofile.h"
-#include <kdebug.h>
-
-KIsoFile::KIsoFile( KArchive* archive, const TQString& name, int access,
- int date, int adate,int cdate, const TQString& user, const TQString& group,
- const TQString& symlink,long long pos, long long size) :
- KArchiveFile(archive, name, access, date, user, group, symlink, pos, size) {
-
-
- m_adate=adate;
- m_cdate=cdate;
- m_algo[0]=0;m_algo[1]=0;m_parms[0]=0;m_parms[1]=0;m_realsize=0;
-}
-
-KIsoFile::~KIsoFile(){
-}
-
-void KIsoFile::setZF(char algo[2],char parms[2],long long realsize) {
- m_algo[0]=algo[0];m_algo[1]=algo[1];
- m_parms[0]=parms[0];m_parms[1]=parms[1];
- m_realsize=realsize;
-}
-
-TQByteArray KIsoFile::data(long long pos, int count) const {
- TQByteArray r;
- int rlen;
-
- if ( archive()->device()->at(position()+pos) &&
- r.resize( ((pos+count) < size()) ? count : size()-pos) ) {
- rlen=archive()->device()->readBlock( r.data(), r.size() );
- if (rlen ==- 1) r.resize(0);
- else if (rlen != (int)r.size()) r.resize(rlen);
- }
-
- return r;
-}
diff --git a/kioslave/iso/kisofile.h b/kioslave/iso/kisofile.h
deleted file mode 100644
index 696a8c191..000000000
--- a/kioslave/iso/kisofile.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/***************************************************************************
- kisofile.h - description
- -------------------
- begin : Wed Oct 30 2002
- copyright : (C) 2002 by Szombathelyi Gy�gy
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef KISOFILE_H
-#define KISOFILE_H
-
-#include <tqstring.h>
-#include <karchive.h>
-
-/**
- *@author Szombathelyi Gy�gy
- */
-
-class KIsoFile : public KArchiveFile {
-public:
- KIsoFile( KArchive* archive, const TQString& name, int access, int date,
- int adate,int cdate, const TQString& user, const TQString& group,
- const TQString& symlink, long long pos, long long size);
- ~KIsoFile();
- void setZF(char algo[2],char parms[2],long long realsize);
- int adate() const { return m_adate; }
- int cdate() const { return m_cdate; }
- long long realsize() const { return m_realsize; }
-
- virtual TQByteArray data(long long pos, int count) const;
-private:
- /* hide this member function, it's broken by design, because the full
- data often requires too much memory */
- char m_algo[2],m_parms[2];
- long long m_realsize;
- int m_adate, m_cdate;
- long long m_curpos;
-};
-
-#endif
diff --git a/kioslave/iso/libisofs/CMakeLists.txt b/kioslave/iso/libisofs/CMakeLists.txt
deleted file mode 100644
index a9ef936a8..000000000
--- a/kioslave/iso/libisofs/CMakeLists.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${CMAKE_BINARY_DIR}
-)
-
-
-##### isofs-static ##############################
-
-set( target isofs )
-
-tde_add_library( ${target} STATIC_PIC
- SOURCES isofs.c
-)
diff --git a/kioslave/iso/libisofs/COPYING b/kioslave/iso/libisofs/COPYING
deleted file mode 100644
index c7aea1896..000000000
--- a/kioslave/iso/libisofs/COPYING
+++ /dev/null
@@ -1,280 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
diff --git a/kioslave/iso/libisofs/ChangeLog b/kioslave/iso/libisofs/ChangeLog
deleted file mode 100644
index fb46b8056..000000000
--- a/kioslave/iso/libisofs/ChangeLog
+++ /dev/null
@@ -1,6 +0,0 @@
-0.1 -> 0.2
-
-- Critical directory parsing bug fixed
-- Call backs only if some sanity checks on the directory entry succeeds
- (length checks to avoid buffer overrun if received corrupt data)
-- Preliminary El Torito boot specification support (No multiple boot entries yet)
diff --git a/kioslave/iso/libisofs/Makefile.am b/kioslave/iso/libisofs/Makefile.am
deleted file mode 100644
index a1278ff41..000000000
--- a/kioslave/iso/libisofs/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-noinst_LTLIBRARIES = libisofs.la
-
-
-INCLUDES = $(all_includes)
-
-
-#LDFLAGS =
-
-libisofs_la_METASOURCES=AUTO
-
-libisofs_la_SOURCES = isofs.c
-#libisofs_la_LIBADD = $(LIB_KIO)
-
-#libisofs_la_LDFLAGS = -module $(all_libraries) $(KDE_PLUGIN)
-
-
-
-noinst_HEADERS = bswap.h el_torito.h iso_fs.h isofs.h rock.h
diff --git a/kioslave/iso/libisofs/README b/kioslave/iso/libisofs/README
deleted file mode 100644
index 45d3bff04..000000000
--- a/kioslave/iso/libisofs/README
+++ /dev/null
@@ -1,24 +0,0 @@
-This is the 0.2 release of libisofs. For changes, see the ChangeLog.
-
-Libisofs implements the reading of the famous ISO-9660 (ECMA-119) file system,
-found on CD-ROM media. It also supports the Rock Ridge Interchange Protocol and
-Microsoft Joliet extensions. It allows user-mode programs to query the
-filesystem volume descriptors and traverse through the directory structure.
-Preliminary support for El-Torito boot CDs are added in version 0.2.
-
-To use it in your project, I recommend to copy bswap.h, isofs.h, iso_fs.h,
-el_torito.h rock.h and isofs.c to your sources, and include isofs.h in the
-appropriate places.
-
-Currently only the directory tables are parsed, the path tables are not.
-(The path tables contain redundant information.)
-
-Also a sample program can be compiled with the supplied Makefile. Simply
-execute 'make', it should create the executable file isofs.
-
-On big-endian systems, you need to define WORDS_BIGENDIAN (either in the
-compiler command-line, or if you defined HAVE_CONFIG_H, in config.h)
-
-
-György Szombathelyi <gyurco@users.sourceforge.net>
-http://libcdrom.sourceforge.net/libisofs.html
diff --git a/kioslave/iso/libisofs/bswap.h b/kioslave/iso/libisofs/bswap.h
deleted file mode 100644
index 95520c6ef..000000000
--- a/kioslave/iso/libisofs/bswap.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* From the mplayer project (www.mplayerhq.hu) */
-
-#ifndef __BSWAP_H__
-#define __BSWAP_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef HAVE_BYTESWAP_H
-#include <byteswap.h>
-#else
-
-#ifdef ARCH_X86
-inline static unsigned short ByteSwap16(unsigned short x)
-{
- __asm("xchgb %b0,%h0" :
- "=q" (x) :
- "0" (x));
- return x;
-}
-#define bswap_16(x) ByteSwap16(x)
-
-inline static unsigned int ByteSwap32(unsigned int x)
-{
-#if __CPU__ > 386
- __asm("bswap %0":
- "=r" (x) :
-#else
- __asm("xchgb %b0,%h0\n"
- " rorl $16,%0\n"
- " xchgb %b0,%h0":
- "=q" (x) :
-#endif
- "0" (x));
- return x;
-}
-#define bswap_32(x) ByteSwap32(x)
-
-inline static unsigned long long int ByteSwap64(unsigned long long int x)
-{
- register union { __extension__ unsigned long long int __ll;
- unsigned int __l[2]; } __x;
- asm("xchgl %0,%1":
- "=r"(__x.__l[0]),"=r"(__x.__l[1]):
- "0"(bswap_32((unsigned long)x)),"1"(bswap_32((unsigned long)(x>>32))));
- return __x.__ll;
-}
-#define bswap_64(x) ByteSwap64(x)
-
-#else
-
-#define bswap_16(x) (((x) & 0x00ff) << 8 | ((x) & 0xff00) >> 8)
-
-
-/* code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc. */
-#define bswap_32(x) \
- ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
- (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
-
-#define bswap_64(x) \
- (__extension__ \
- ({ union { __extension__ unsigned long long int __ll; \
- unsigned int __l[2]; } __w, __r; \
- __w.__ll = (x); \
- __r.__l[0] = bswap_32 (__w.__l[1]); \
- __r.__l[1] = bswap_32 (__w.__l[0]); \
- __r.__ll; }))
-#endif /* !ARCH_X86 */
-
-#endif /* !HAVE_BYTESWAP_H */
-
-/*
- be2me ... BigEndian to MachineEndian
- le2me ... LittleEndian to MachineEndian
-*/
-
-#ifdef WORDS_BIGENDIAN
-#define be2me_16(x) (x)
-#define be2me_32(x) (x)
-#define be2me_64(x) (x)
-#define le2me_16(x) bswap_16(x)
-#define le2me_32(x) bswap_32(x)
-#define le2me_64(x) bswap_64(x)
-#else
-#define be2me_16(x) bswap_16(x)
-#define be2me_32(x) bswap_32(x)
-#define be2me_64(x) bswap_64(x)
-#define le2me_16(x) (x)
-#define le2me_32(x) (x)
-#define le2me_64(x) (x)
-#endif
-
-#endif
diff --git a/kioslave/iso/libisofs/el_torito.h b/kioslave/iso/libisofs/el_torito.h
deleted file mode 100644
index cba83f785..000000000
--- a/kioslave/iso/libisofs/el_torito.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef ELTORITO_H
-#define ELTORITO_H 1
-
-#include "iso_fs.h"
-
-#define EL_TORITO_ID "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0"
-
-struct el_torito_boot_descriptor {
- char type [ISODCL ( 1, 1)]; /* 711 */
- char id [ISODCL ( 2, 6)];
- char version [ISODCL ( 7, 7)]; /* 711 */
- char system_id [ISODCL ( 8, 39)]; /* achars */
- char unused [ISODCL ( 40, 71)];
- char boot_catalog [ISODCL ( 72, 75)]; /* 731 */
-};
-
-struct validation_entry {
- char type [ISODCL ( 1, 1)]; /* 1 */
- char platform [ISODCL ( 2, 2)];
- char unused [ISODCL ( 3, 4)];
- char id [ISODCL ( 5, 28)];
- char cheksum [ISODCL ( 29, 30)];
- char key [ISODCL ( 31, 31)]; /* 0x55 */
- char key2 [ISODCL ( 32, 32)]; /* 0xaa */
-};
-
-struct default_entry {
- char bootid [ISODCL ( 1, 1)];
- char media [ISODCL ( 2, 2)];
- char loadseg [ISODCL ( 3, 4)];
- char systype [ISODCL ( 5, 5)];
- char unused [ISODCL ( 6, 6)];
- char seccount [ISODCL ( 7, 8)];
- char start [ISODCL ( 9, 12)];
- char unused2 [ISODCL ( 13, 32)];
-};
-
-struct section_header {
- char headerid [ISODCL ( 1, 1)];
- char platform [ISODCL ( 2, 2)];
- char entries [ISODCL ( 3, 4)];
- char id [ISODCL ( 5, 32)];
-};
-
-struct section_entry {
- char bootid [ISODCL ( 1, 1)];
- char media [ISODCL ( 2, 2)];
- char loadseg [ISODCL ( 3, 4)];
- char systype [ISODCL ( 5, 5)];
- char unused [ISODCL ( 6, 6)];
- char seccount [ISODCL ( 7, 8)];
- char start [ISODCL ( 9, 12)];
- char selcrit [ISODCL ( 13, 13)];
- char vendor_selcrit [ISODCL ( 14, 32)];
-};
-
-struct section_entry_ext {
- char extid [ISODCL ( 1, 1)];
- char extrec [ISODCL ( 2, 2)];
- char vendor_selcrit [ISODCL ( 3, 32)];
-};
-
-#endif
diff --git a/kioslave/iso/libisofs/iso_fs.h b/kioslave/iso/libisofs/iso_fs.h
deleted file mode 100644
index 43353b0d9..000000000
--- a/kioslave/iso/libisofs/iso_fs.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/* From the linux kernel */
-
-#ifndef _ISO_FS_H
-#define _ISO_FS_H 1
-
-#include "bswap.h"
-
-/*
- * The isofs filesystem constants/structures
- */
-
-/* This part borrowed from the bsd386 isofs */
-#define ISODCL(from, to) (to - from + 1)
-
-struct iso_volume_descriptor {
- char type[ISODCL(1,1)]; /* 711 */
- char id[ISODCL(2,6)];
- char version[ISODCL(7,7)];
- char data[ISODCL(8,2048)];
-};
-
-/* volume descriptor types */
-#define ISO_VD_BOOT 0
-#define ISO_VD_PRIMARY 1
-#define ISO_VD_SUPPLEMENTARY 2
-#define ISO_VD_END 255
-
-#define ISO_STANDARD_ID "CD001"
-
-struct iso_primary_descriptor {
- char type [ISODCL ( 1, 1)]; /* 711 */
- char id [ISODCL ( 2, 6)];
- char version [ISODCL ( 7, 7)]; /* 711 */
- char unused1 [ISODCL ( 8, 8)];
- char system_id [ISODCL ( 9, 40)]; /* achars */
- char volume_id [ISODCL ( 41, 72)]; /* dchars */
- char unused2 [ISODCL ( 73, 80)];
- char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
- char unused3 [ISODCL ( 89, 120)];
- char volume_set_size [ISODCL (121, 124)]; /* 723 */
- char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
- char logical_block_size [ISODCL (129, 132)]; /* 723 */
- char path_table_size [ISODCL (133, 140)]; /* 733 */
- char type_l_path_table [ISODCL (141, 144)]; /* 731 */
- char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
- char type_m_path_table [ISODCL (149, 152)]; /* 732 */
- char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
- char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
- char volume_set_id [ISODCL (191, 318)]; /* dchars */
- char publisher_id [ISODCL (319, 446)]; /* achars */
- char preparer_id [ISODCL (447, 574)]; /* achars */
- char application_id [ISODCL (575, 702)]; /* achars */
- char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
- char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
- char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
- char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
- char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
- char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
- char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
- char file_structure_version [ISODCL (882, 882)]; /* 711 */
- char unused4 [ISODCL (883, 883)];
- char application_data [ISODCL (884, 1395)];
- char unused5 [ISODCL (1396, 2048)];
-};
-
-/* Almost the same as the primary descriptor but two fields are specified */
-struct iso_supplementary_descriptor {
- char type [ISODCL ( 1, 1)]; /* 711 */
- char id [ISODCL ( 2, 6)];
- char version [ISODCL ( 7, 7)]; /* 711 */
- char flags [ISODCL ( 8, 8)]; /* 853 */
- char system_id [ISODCL ( 9, 40)]; /* achars */
- char volume_id [ISODCL ( 41, 72)]; /* dchars */
- char unused2 [ISODCL ( 73, 80)];
- char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
- char escape [ISODCL ( 89, 120)]; /* 856 */
- char volume_set_size [ISODCL (121, 124)]; /* 723 */
- char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
- char logical_block_size [ISODCL (129, 132)]; /* 723 */
- char path_table_size [ISODCL (133, 140)]; /* 733 */
- char type_l_path_table [ISODCL (141, 144)]; /* 731 */
- char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
- char type_m_path_table [ISODCL (149, 152)]; /* 732 */
- char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
- char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
- char volume_set_id [ISODCL (191, 318)]; /* dchars */
- char publisher_id [ISODCL (319, 446)]; /* achars */
- char preparer_id [ISODCL (447, 574)]; /* achars */
- char application_id [ISODCL (575, 702)]; /* achars */
- char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
- char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
- char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
- char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
- char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
- char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
- char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
- char file_structure_version [ISODCL (882, 882)]; /* 711 */
- char unused4 [ISODCL (883, 883)];
- char application_data [ISODCL (884, 1395)];
- char unused5 [ISODCL (1396, 2048)];
-};
-
-#define HS_STANDARD_ID "CDROM"
-
-struct hs_volume_descriptor {
- char foo [ISODCL ( 1, 8)]; /* 733 */
- char type [ISODCL ( 9, 9)]; /* 711 */
- char id [ISODCL ( 10, 14)];
- char version [ISODCL ( 15, 15)]; /* 711 */
- char data[ISODCL(16,2048)];
-};
-
-
-struct hs_primary_descriptor {
- char foo [ISODCL ( 1, 8)]; /* 733 */
- char type [ISODCL ( 9, 9)]; /* 711 */
- char id [ISODCL ( 10, 14)];
- char version [ISODCL ( 15, 15)]; /* 711 */
- char unused1 [ISODCL ( 16, 16)]; /* 711 */
- char system_id [ISODCL ( 17, 48)]; /* achars */
- char volume_id [ISODCL ( 49, 80)]; /* dchars */
- char unused2 [ISODCL ( 81, 88)]; /* 733 */
- char volume_space_size [ISODCL ( 89, 96)]; /* 733 */
- char unused3 [ISODCL ( 97, 128)]; /* 733 */
- char volume_set_size [ISODCL (129, 132)]; /* 723 */
- char volume_sequence_number [ISODCL (133, 136)]; /* 723 */
- char logical_block_size [ISODCL (137, 140)]; /* 723 */
- char path_table_size [ISODCL (141, 148)]; /* 733 */
- char type_l_path_table [ISODCL (149, 152)]; /* 731 */
- char unused4 [ISODCL (153, 180)]; /* 733 */
- char root_directory_record [ISODCL (181, 214)]; /* 9.1 */
-};
-
-/* We use this to help us look up the parent inode numbers. */
-
-struct iso_path_table{
- char name_len[1]; /* 711 */
- char ext_attr_length[1]; /* 711 */
- char extent[4]; /* 731 */
- char parent[2]; /* 721 */
- char name[1];
-};
-
-/* high sierra is identical to iso, except that the date is only 6 bytes, and
- there is an extra reserved byte after the flags */
-
-struct iso_directory_record {
- char length [ISODCL (1, 1)]; /* 711 */
- char ext_attr_length [ISODCL (2, 2)]; /* 711 */
- char extent [ISODCL (3, 10)]; /* 733 */
- char size [ISODCL (11, 18)]; /* 733 */
- char date [ISODCL (19, 25)]; /* 7 by 711 */
- char flags [ISODCL (26, 26)];
- char file_unit_size [ISODCL (27, 27)]; /* 711 */
- char interleave [ISODCL (28, 28)]; /* 711 */
- char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
- char name_len [ISODCL (33, 33)]; /* 711 */
- char name [1];
-};
-
-/* 8 bit numbers */
-__inline unsigned char isonum_711(char *p);
-__inline char isonum_712(char *p);
-
-/* 16 bit numbers */
-__inline unsigned short isonum_721(char *p);
-__inline unsigned short isonum_722(char *p);
-__inline unsigned short isonum_723(char *p);
-
-/* 32 bit numbers */
-__inline unsigned int isonum_731(char *p);
-__inline unsigned int isonum_732(char *p);
-__inline unsigned int isonum_733(char *p);
-
-
-/* 8 bit numbers */
-__inline unsigned char isonum_711(char *p)
-{
- return *(unsigned char *)p;
-}
-__inline char isonum_712(char *p)
-{
- return *p;
-}
-
-/* 16 bit numbers */
-__inline unsigned short isonum_721(char *p)
-{
- return le2me_16(*(unsigned short *)p);
-}
-__inline unsigned short isonum_722(char *p)
-{
- return be2me_16(*(unsigned short *)p);
-}
-__inline unsigned short isonum_723(char *p)
-{
- /* Ignore bigendian datum due to broken mastering programs */
- return le2me_16(*(unsigned short *)p);
-}
-
-/* 32 bit numbers */
-__inline unsigned int isonum_731(char *p)
-{
- return le2me_32(*(unsigned int *)p);
-}
-
-__inline unsigned int isonum_732(char *p)
-{
- return be2me_32(*(unsigned int *)p);
-}
-
-__inline unsigned int isonum_733(char *p)
-{
- /* Ignore bigendian datum due to broken mastering programs */
- return le2me_32(*(unsigned int *)p);
-}
-
-#endif /*_ISOFS_H*/
-
diff --git a/kioslave/iso/libisofs/isofs.c b/kioslave/iso/libisofs/isofs.c
deleted file mode 100644
index f1db4427c..000000000
--- a/kioslave/iso/libisofs/isofs.c
+++ /dev/null
@@ -1,876 +0,0 @@
-/***************************************************************************
- isofs.c - libisofs
- implementation
- -------------------
- begin : Oct 25 2002
- copyright : (C) 2002 by Szombathelyi Gy�gy
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "isofs.h"
-
-/**************************************************************/
-
-
-/* internal function from the linux kernel (isofs fs) */
-static time_t getisotime(int year,int month,int day,int hour,
- int minute,int second,int tz) {
-
- int days, i;
- time_t crtime;
-
- year-=1970;
-
- if (year < 0) {
- crtime = 0;
- } else {
- int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
-
- days = year * 365;
- if (year > 2)
- days += (year+1) / 4;
- for (i = 1; i < month; i++)
- days += monlen[i-1];
- if (((year+2) % 4) == 0 && month > 2)
- days++;
- days += day - 1;
- crtime = ((((days * 24) + hour) * 60 + minute) * 60)
- + second;
-
- /* sign extend */
- if (tz & 0x80)
- tz |= (-1 << 8);
-
- /*
- * The timezone offset is unreliable on some disks,
- * so we make a sanity check. In no case is it ever
- * more than 13 hours from GMT, which is 52*15min.
- * The time is always stored in localtime with the
- * timezone offset being what get added to GMT to
- * get to localtime. Thus we need to subtract the offset
- * to get to true GMT, which is what we store the time
- * as internally. On the local system, the user may set
- * their timezone any way they wish, of course, so GMT
- * gets converted back to localtime on the receiving
- * system.
- *
- * NOTE: mkisofs in versions prior to mkisofs-1.10 had
- * the sign wrong on the timezone offset. This has now
- * been corrected there too, but if you are getting screwy
- * results this may be the explanation. If enough people
- * complain, a user configuration option could be added
- * to add the timezone offset in with the wrong sign
- * for 'compatibility' with older discs, but I cannot see how
- * it will matter that much.
- *
- * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann)
- * for pointing out the sign error.
- */
- if (-52 <= tz && tz <= 52)
- crtime -= tz * 15 * 60;
- }
- return crtime;
-
-}
-
-/**
- * Returns the Unix from the ISO9660 9.1.5 time format
- */
-time_t isodate_915(char * p, int hs) {
-
- return getisotime(1900+p[0],p[1],p[2],p[3],p[4],p[5],hs==0 ? p[6] : 0);
-}
-
-/**
- * Returns the Unix from the ISO9660 8.4.26.1 time format
- * BUG: hundredth of seconds are ignored, because Unix time_t has one second
- * resolution (I think it's no problem at all)
- */
-time_t isodate_84261(char * p, int hs) {
- int year,month,day,hour,minute,second;
- year=(p[0]-'0')*1000 + (p[1]-'0')*100 + (p[2]-'0')*10 + p[3]-'0';
- month=(p[4]-'0')*10 + (p[5]-'0');
- day=(p[6]-'0')*10 + (p[7]-'0');
- hour=(p[8]-'0')*10 + (p[9]-'0');
- minute=(p[10]-'0')*10 + (p[11]-'0');
- second=(p[12]-'0')*10 + (p[13]-'0');
- return getisotime(year,month,day,hour,minute,second,hs==0 ? p[16] : 0);
-}
-
-void FreeBootTable(boot_head *boot) {
- boot_entry *be,*next;
-
- be=boot->defentry;
- while (be) {
- next=be->next;
- free(be);
- be=next;
- }
- boot->defentry=NULL;
-}
-
-int BootImageSize(int media,long long len) {
- long long ret;
-
- switch(media & 0xf) {
- case 0:
- ret=len; /* No emulation */
- break;
- case 1:
- ret=80*2*15; /* 1.2 MB */
- break;
- case 2:
- ret=80*2*18; /* 1.44 MB */
- break;
- case 3:
- ret=80*2*36; /* 2.88 MB */
- break;
- case 4:
- /* FIXME!!! */
- ret=len; /* Hard Disk */
- break;
- default:
- ret=len;
- }
- return ret;
-}
-
-static boot_entry *CreateBootEntry(char *be) {
- boot_entry *entry;
-
- entry = (boot_entry*) malloc(sizeof(boot_entry));
- if (!entry) return NULL;
- memset(entry, 0, sizeof(boot_entry));
- memcpy(entry->data,be,0x20);
- return entry;
-}
-
-int ReadBootTable(readfunc *read,long long sector, boot_head *head, void *udata) {
-
- char buf[2048], *c, *be;
- int i,end=0;
- unsigned short sum;
- boot_entry *defcur=NULL,*deflast=NULL;
- register struct validation_entry *ventry=NULL;
-
- head->sections=NULL;
- head->defentry=NULL;
- while (1) {
- be = (char*) &buf;
- if ( read(be, sector, 1, udata) != 1 ) goto err;
-
- /* first entry needs to be a validation entry */
- if (!ventry) {
- ventry=(struct validation_entry *) be;
- if ( isonum_711(ventry->type) !=1 ) goto err;
- sum=0;
- c = (char*) ventry;
- for (i=0;i<16;i++) { sum += isonum_721(c); c+=2; }
- if (sum) goto err;
- memcpy(&head->ventry,be,0x20);
- be += 0x20;
- }
-
- while (!end && (be < (char *)(&buf+1))) {
- switch (isonum_711(be)) {
- case 0x88:
- defcur=CreateBootEntry(be);
- if (!defcur) goto err;
- if (deflast)
- deflast->next=defcur;
- else
- head->defentry=defcur;
- defcur->prev=deflast;
- deflast=defcur;
- break;
- case 0x90:
- case 0x91:
- break;
- default:
- end=1;
- break;
- }
- be += 0x20;
- }
- if (end) break;
-
- sector ++;
- }
-
- return 0;
-
-err:
- FreeBootTable(head);
- return -1;
-}
-
-
-/**
- * Creates the linked list of the volume descriptors
- */
-iso_vol_desc *ReadISO9660(readfunc *read,long long sector,void *udata) {
-
- int i;
- struct iso_volume_descriptor buf;
- iso_vol_desc *first=NULL,*current=NULL,*prev=NULL;
-
- for (i=0;i<100;i++) {
- if (read( (char*) &buf, sector+i+16, 1, udata) != 1 ) {
- FreeISO9660(first);
- return NULL;
- }
- if (!memcmp(ISO_STANDARD_ID,&buf.id,5)) {
- switch ( isonum_711(&buf.type[0]) ) {
-
- case ISO_VD_BOOT:
- case ISO_VD_PRIMARY:
- case ISO_VD_SUPPLEMENTARY:
- current=(iso_vol_desc*) malloc(sizeof(iso_vol_desc));
- if (!current) {
- FreeISO9660(first);
- return NULL;
- }
- current->prev=prev;
- current->next=NULL;
- if (prev) prev->next=current;
- memcpy(&(current->data),&buf,2048);
- if (!first) first=current;
- prev=current;
- break;
-
- case ISO_VD_END:
- return first;
- break;
- }
- } else if (!memcmp(HS_STANDARD_ID,(struct hs_volume_descriptor*) &buf,5)) {
- /* High Sierra format not supported (yet) */
- }
- }
-
- return first;
-}
-
-/**
- * Frees the linked list of volume descriptors
- */
-void FreeISO9660(iso_vol_desc *data) {
-
- iso_vol_desc *current;
-
-
- while (data) {
- current=data;
- data=current->next;
- free(current);
- }
-}
-
-/**
- * Frees the strings in 'rrentry'
- */
-void FreeRR(rr_entry *rrentry) {
- if (rrentry->name) {
- free(rrentry->name);
- rrentry->name=NULL;
- }
- if (rrentry->sl) {
- free(rrentry->sl);
- rrentry->name=NULL;
- }
-}
-
-static int str_nappend(char **d,char *s,int n) {
- int i=0;
- char *c;
-
-/* i=strnlen(s,n)+1; */
- while (i<n && s[i]) i++;
- i++;
- if (*d) i+=(strlen(*d)+1);
- c=(char*) malloc(i);
- if (!c) return -ENOMEM;
- if (*d) {
- strcpy(c,*d);
- strncat(c,s,n);
-
- free(*d);
- } else
- strncpy(c,s,n);
- c[i-1]=0;
- *d=c;
- return 0;
-}
-
-static int str_append(char **d,char *s) {
- int i;
- char *c;
-
- i=strlen(s)+1;
- if (*d) i+=(strlen(*d)+1);
- c=(char*) malloc(i);
- if (!c) return -ENOMEM;
- if (*d) {
- strcpy(c,*d);
- strcat(c,s);
- free(*d);
- } else
- strcpy(c,s);
- c[i-1]=0;
- *d=c;
- return 0;
-}
-
-#define rrtlen(c) (((unsigned char) c & 0x80) ? 17 : 7)
-#define rrctime(f,c) ((unsigned char) f & 0x80) ? isodate_84261(c,0) : isodate_915(c,0)
-/**
- * Parses the System Use area and fills rr_entry with values
- */
-int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry) {
-
- int suspoffs,susplen,i,f,ret=0;
- char *r, *c;
- struct rock_ridge *rr;
-
- suspoffs=33+isonum_711(idr->name_len);
- if (!(isonum_711(idr->name_len) & 1)) suspoffs++;
- susplen=isonum_711(idr->length)-suspoffs;
- r= & (((char*) idr)[suspoffs]);
- rr = (struct rock_ridge*) r;
-
- memset(rrentry,0,sizeof(rr_entry));
- rrentry->len = sizeof(rr_entry);
-
- while (susplen > 0) {
- if (isonum_711(&rr->len) > susplen || rr->len == 0) break;
- if (rr->signature[0]=='N' && rr->signature[1]=='M') {
- if (!(rr->u.NM.flags & 0x26) && rr->len>5 && !rrentry->name) {
-
- if (str_nappend(&rrentry->name,rr->u.NM.name,isonum_711(&rr->len)-5)) {
- FreeRR(rrentry); return -ENOMEM;
- }
- ret++;
- }
- } else if (rr->signature[0]=='P' && rr->signature[1]=='X' &&
- (isonum_711(&rr->len)==44 || isonum_711(&rr->len)==36)) {
- rrentry->mode=isonum_733(rr->u.PX.mode);
- rrentry->nlink=isonum_733(rr->u.PX.n_links);
- rrentry->uid=isonum_733(rr->u.PX.uid);
- rrentry->gid=isonum_733(rr->u.PX.gid);
- if (isonum_711(&rr->len)==44) rrentry->serno=isonum_733(rr->u.PX.serno);
- ret++;
- } else if (rr->signature[0]=='P' && rr->signature[1]=='N' &&
- isonum_711(&rr->len)==20) {
- rrentry->dev_major=isonum_733(rr->u.PN.dev_high);
- rrentry->dev_minor=isonum_733(rr->u.PN.dev_low);
- ret++;
- } else if (rr->signature[0]=='P' && rr->signature[1]=='L' &&
- isonum_711(&rr->len)==12) {
- rrentry->pl=isonum_733(rr->u.PL.location);
- ret++;
- } else if (rr->signature[0]=='C' && rr->signature[1]=='L' &&
- isonum_711(&rr->len)==12) {
- rrentry->cl=isonum_733(rr->u.CL.location);
- ret++;
- } else if (rr->signature[0]=='R' && rr->signature[1]=='E' &&
- isonum_711(&rr->len)==4) {
- rrentry->re=1;
- ret++;
- } else if (rr->signature[0]=='S' && rr->signature[1]=='L' &&
- isonum_711(&rr->len)>7) {
- i = isonum_711(&rr->len)-5;
- c = (char*) rr;
- c += 5;
- while (i>0) {
- switch(c[0] & ~1) {
- case 0x2:
- if (str_append(&rrentry->sl,(char *)".")) {
- FreeRR(rrentry); return -ENOMEM;
- }
- break;
- case 0x4:
- if (str_append(&rrentry->sl,(char *)"..")) {
- FreeRR(rrentry); return -ENOMEM;
- }
- break;
- }
- if ( (c[0] & 0x08) == 0x08 || (c[1] && rrentry->sl &&
- strlen(rrentry->sl)>1) ) {
- if (str_append(&rrentry->sl,(char *)"/")) {
- FreeRR(rrentry); return -ENOMEM;
- }
- }
-
- if ((unsigned char)c[1]>0) {
- if (str_nappend(&rrentry->sl,c+2,(unsigned char)c[1])) {
- FreeRR(rrentry); return -ENOMEM;
- }
- }
- i -= ((unsigned char)c[1] + 2);
- c += ((unsigned char)c[1] + 2);
- }
- ret++;
- } else if (rr->signature[0]=='T' && rr->signature[1]=='F' &&
- isonum_711(&rr->len)>5) {
-
- i = isonum_711(&rr->len)-5;
- f = rr->u.TF.flags;
- c = (char*) rr;
- c += 5;
-
- while (i >= rrtlen(f)) {
- if (f & 1) {
- rrentry->t_creat=rrctime(f,c);
- f &= ~1;
- } else if (f & 2) {
- rrentry->t_mtime=rrctime(f,c);
- f &= ~2;
- } else if (f & 4) {
- rrentry->t_atime=rrctime(f,c);
- f &= ~4;
- } else if (f & 8) {
- rrentry->t_ctime=rrctime(f,c);
- f &= ~8;
- } else if (f & 16) {
- rrentry->t_backup=rrctime(f,c);
- f &= ~16;
- } else if (f & 32) {
- rrentry->t_expire=rrctime(f,c);
- f &= ~32;
- } else if (f & 64) {
- rrentry->t_effect=rrctime(f,c);
- f &= ~64;
- }
-
- i -= rrtlen(f);
- c += rrtlen(f);
- }
- ret++;
-
- } else if (rr->signature[0]=='Z' && rr->signature[1]=='F' &&
- isonum_711(&rr->len)==16) {
- /* Linux-specific extension: transparent decompression */
- rrentry->z_algo[0]=rr->u.ZF.algorithm[0];
- rrentry->z_algo[1]=rr->u.ZF.algorithm[1];
- rrentry->z_params[0]=rr->u.ZF.parms[0];
- rrentry->z_params[1]=rr->u.ZF.parms[1];
- rrentry->z_size=isonum_733(rr->u.ZF.real_size);
- ret++;
- } else {
-/* printf("SUSP sign: %c%c\n",rr->signature[0],rr->signature[1]); */
- }
-
- susplen -= isonum_711(&rr->len);
- r += isonum_711(&rr->len);
- rr = (struct rock_ridge*) r;
- }
-
- return ret;
-}
-
-/**
- * Iterates over the directory entries. The directory is in 'buf',
- * the size of the directory is 'size'. 'callback' is called for each
- * directory entry with the parameter 'udata'.
- */
-int ProcessDir(readfunc *read,int extent,int size,dircallback *callback,void *udata) {
-
- int pos=0,ret=0,siz;
- char *buf;
- struct iso_directory_record *idr;
-
- if (size & 2047) {
- siz=((size>>11)+1)<<11;
- } else {
- siz=size;
- }
-
- buf=(char*) malloc(siz);
- if (!buf) return -ENOMEM;
- if (read(buf,extent,siz>>11,udata)!=siz>>11) {
- free(buf);
- return -EIO;
- }
-
- while (size>0) {
- idr=(struct iso_directory_record*) &buf[pos];
- if (isonum_711(idr->length)==0) {
-
- size-=(2048 - (pos & 0x7ff));
- if (size<=2) break;
- pos+=0x800;
- pos&=0xfffff800;
- idr=(struct iso_directory_record*) &buf[pos];
- }
- pos+=isonum_711(idr->length);
- pos+=isonum_711(idr->ext_attr_length);
- size-=isonum_711(idr->length);
- size-=isonum_711(idr->ext_attr_length);
- if (size<0) break;
-
- if (isonum_711(idr->length)
-<33 ||
- isonum_711(idr->length)<33+isonum_711(idr->name_len)) {
- /* Invalid directory entry */
- continue;
- }
- if ((ret=callback(idr,udata))) break;
- }
-
- free(buf);
- return ret;
-}
-
-/**
- * returns the joliet level from the volume descriptor
- */
-int JolietLevel(struct iso_volume_descriptor *ivd) {
- int ret=0;
- register struct iso_supplementary_descriptor *isd;
-
- isd = (struct iso_supplementary_descriptor *) ivd;
-
- if (isonum_711(ivd->type)==ISO_VD_SUPPLEMENTARY) {
- if (isd->escape[0]==0x25 &&
- isd->escape[1]==0x2f) {
-
- switch (isd->escape[2]) {
- case 0x40:
- ret=1;
- break;
- case 0x43:
- ret=2;
- break;
- case 0x45:
- ret=3;
- break;
- }
- }
- }
- return ret;
-}
-
-/********************************************************************/
-#ifdef ISOFS_MAIN
-
-#include <time.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <iconv.h>
-
-int level=0,joliet=0,dirs,files;
-iconv_t iconv_d;
-int fd;
-
-int readf(char *buf, long long start, long long len,void *udata) {
- int ret;
-
- if ((ret=lseek64(fd, start << 11, SEEK_SET))<0) return ret;
- ret=read(fd, buf, len << 11);
- if (ret<0) return ret;
- return (ret >> 11);
-}
-
-void dumpchars(char *c,int len) {
- while (len>0) {
- printf("%c",*c);
- len--;
- c++;
- }
-}
-
-void sp(int num) {
- int i;
- for (i=0;i<num*5;i++) { printf(" "); };
-}
-
-void dumpflags(char flags) {
- if (flags & 1) printf("HIDDEN ");
- if (flags & 2) printf("DIR ");
- if (flags & 4) printf("ASF ");
-}
-
-void dumpjoliet(char *c,int len) {
-
- char outbuf[255];
- size_t out;
- int ret;
- char *outptr;
-
- outptr=(char*) &outbuf;
- out=255;
- if ((iconv(iconv_d,&c,&len,&outptr,&out))<0) {
- printf("conversion error=%d",errno);
- return;
- }
- ret=255-out;
- dumpchars((char*) &outbuf,ret);
-}
-
-void dumpchardesc(char *c,int len) {
-
- if (joliet)
- dumpjoliet(c,len);
- else {
- dumpchars(c,len);
- }
-}
-
-void dumpiso915time(char *t, int hs) {
-
- time_t time;
- char *c;
-
- time=isodate_915(t,hs);
- c=(char*) ctime(&time);
- if (c && c[strlen(c)-1]==0x0a) c[strlen(c)-1]=0;
- if (c) printf("%s",c);
-}
-
-void dumpiso84261time(char *t, int hs) {
-
- time_t time;
- char *c;
-
- time=isodate_84261(t,hs);
- c=(char*) ctime(&time);
- if (c && c[strlen(c)-1]==0x0a) c[strlen(c)-1]=0;
- if (c) printf("%s",c);
-}
-
-void dumpdirrec(struct iso_directory_record *dir) {
-
- if (isonum_711(dir->name_len)==1) {
- switch (dir->name[0]) {
- case 0:
- printf(".");
- break;
- case 1:
- printf("..");
- break;
- default:
- printf("%c",dir->name[0]);
- break;
- }
- }
- dumpchardesc(dir->name,isonum_711(dir->name_len));
- printf(" size=%d",isonum_733(dir->size));
- printf(" extent=%d ",isonum_733(dir->extent));
- dumpflags(isonum_711(dir->flags));
- dumpiso915time((char*) &(dir->date),0);
-}
-
-void dumprrentry(rr_entry *rr) {
- printf(" NM=[%s] uid=%d gid=%d nlink=%d mode=%o ",
- rr->name,rr->uid,rr->gid,rr->nlink,rr->mode);
- if (S_ISCHR(rr->mode) || S_ISBLK(rr->mode))
- printf("major=%d minor=%d ",rr->dev_major,rr->dev_minor);
- if (rr->mode & S_IFLNK && rr->sl) printf("slink=%s ",rr->sl);
-/*
- printf("\n");
- if (rr->t_creat) printf("t_creat: %s",ctime(&rr->t_creat));
- if (rr->st_mtime) printf("st_mtime: %s",ctime(&rr->st_mtime));
- if (rr->st_atime) printf("st_atime: %s",ctime(&rr->st_atime));
- if (rr->st_ctime) printf("st_ctime: %s",ctime(&rr->st_ctime));
- if (rr->t_backup) printf("t_backup: %s",ctime(&rr->t_backup));
- if (rr->t_expire) printf("t_expire: %s",ctime(&rr->t_expire));
- if (rr->t_effect) printf("t_effect: %s",ctime(&rr->t_effect));
-*/
-}
-
-void dumpsusp(char *c, int len) {
- dumpchars(c,len);
-}
-
-void dumpboot(struct el_torito_boot_descriptor *ebd) {
- printf("version: %d\n",isonum_711(ebd->version));
- printf("system id: ");dumpchars(ebd->system_id,ISODCL(8,39));printf("\n");
- printf("boot catalog start: %d\n",isonum_731(ebd->boot_catalog));
-}
-
-void dumpdefentry(struct default_entry *de) {
- printf("Default entry: \n");
- printf(" bootid=%x\n",isonum_711(de->bootid));
- printf(" media emulation=%d (",isonum_711(de->media));
- switch(isonum_711(de->media) & 0xf) {
- case 0:
- printf("No emulation");
- break;
- case 1:
- printf("1.2 Mb floppy");
- break;
- case 2:
- printf("1.44 Mb floppy");
- break;
- case 3:
- printf("2.88 Mb floppy");
- break;
- case 4:
- printf("Hard Disk");
- break;
- default:
- printf("Unknown/Invalid");
- break;
- }
- printf(")\n");
- printf(" loadseg=%d\n",isonum_721(de->loadseg));
- printf(" systype=%d\n",isonum_711(de->systype));
- printf(" start lba=%d count=%d\n",isonum_731(de->start),
- isonum_721(de->seccount));
-}
-
-void dumpbootcat(boot_head *bh) {
- boot_entry *be;
-
- printf("System id: ");dumpchars(bh->ventry.id,ISODCL(28,5));printf("\n");
- be=bh->defentry;
- while (be) {
- dumpdefentry(be->data);
- be=be->next;
- }
-}
-
-void dumpdesc(struct iso_primary_descriptor *ipd) {
-
- printf("system id: ");dumpchardesc(ipd->system_id,ISODCL(9,40));printf("\n");
- printf("volume id: ");dumpchardesc(ipd->volume_id,ISODCL(41,72));printf("\n");
- printf("volume space size: %d\n",isonum_733(ipd->volume_space_size));
- printf("volume set size: %d\n",isonum_723(ipd->volume_set_size));
- printf("volume seq num: %d\n",isonum_723(ipd->volume_set_size));
- printf("logical block size: %d\n",isonum_723(ipd->logical_block_size));
- printf("path table size: %d\n",isonum_733(ipd->path_table_size));
- printf("location of type_l path table: %d\n",isonum_731(ipd->type_l_path_table));
- printf("location of optional type_l path table: %d\n",isonum_731(ipd->opt_type_l_path_table));
- printf("location of type_m path table: %d\n",isonum_732(ipd->type_m_path_table));
- printf("location of optional type_m path table: %d\n",isonum_732(ipd->opt_type_m_path_table));
-/*
- printf("Root dir record:\n");dumpdirrec((struct iso_directory_record*) &ipd->root_directory_record);
-*/
- printf("Volume set id: ");dumpchardesc(ipd->volume_set_id,ISODCL(191,318));printf("\n");
- printf("Publisher id: ");dumpchardesc(ipd->publisher_id,ISODCL(319,446));printf("\n");
- printf("Preparer id: ");dumpchardesc(ipd->preparer_id,ISODCL(447,574));printf("\n");
- printf("Application id: ");dumpchardesc(ipd->application_id,ISODCL(575,702));printf("\n");
- printf("Copyright id: ");dumpchardesc(ipd->copyright_file_id,ISODCL(703,739));printf("\n");
- printf("Abstract file id: ");dumpchardesc(ipd->abstract_file_id,ISODCL(740,776));printf("\n");
- printf("Bibliographic file id: ");dumpchardesc(ipd->bibliographic_file_id,ISODCL(777,813));printf("\n");
- printf("Volume creation date: ");dumpiso84261time(ipd->creation_date,0);printf("\n");
- printf("Volume modification date: ");dumpiso84261time(ipd->modification_date,0);printf("\n");
- printf("Volume expiration date: ");dumpiso84261time(ipd->expiration_date,0);printf("\n");
- printf("Volume effective date: ");dumpiso84261time(ipd->effective_date,0);printf("\n");
- printf("File structure version: %d\n",isonum_711(ipd->file_structure_version));
-}
-
-int mycallb(struct iso_directory_record *idr,void *udata) {
- rr_entry rrentry;
-
- sp(level);dumpdirrec(idr);
- if (level==0) printf(" (Root directory) ");
- printf("\n");
-
- if (ParseRR(idr,&rrentry)>0) {
- sp(level);printf(" ");dumprrentry(&rrentry);printf("\n");
- }
- FreeRR(&rrentry);
- if ( !(idr->flags[0] & 2) ) files++;
- if ( (idr->flags[0] & 2) && (level==0 || isonum_711(idr->name_len)>1) ) {
- level++;
- dirs++;
- ProcessDir(&readf,isonum_733(idr->extent),isonum_733(idr->size),&mycallb,udata);
- level--;
- }
- return 0;
-}
-
-/************************************************/
-
-int main(int argc, char *argv[]) {
-
- int i=1,sector=0;
- iso_vol_desc *desc;
- boot_head boot;
-
- if (argc<2) {
- fprintf(stderr,"\nUsage: %s iso-file-name or device [starting sector]\n\n",argv[0]);
- return 0;
- }
- if (argc>=3) {
- sector=atoi(argv[2]);
- printf("Using starting sector number %d\n",sector);
- }
- fd=open(argv[1],O_RDONLY);
- if (fd<0) {
- fprintf(stderr,"open error\n");
- return -1;
- }
- iconv_d=iconv_open("ISO8859-2","UTF16BE");
- if (iconv_d==0) {
- fprintf(stderr,"iconv open error\n");
- return -1;
- }
-
- desc=ReadISO9660(&readf,sector,NULL);
- if (!desc) {
- printf("No volume descriptors\n");
- return -1;
- }
- while (desc) {
-
- printf("\n\n--------------- Volume descriptor (%d.) type %d: ---------------\n\n",
- i,isonum_711(desc->data.type));
- switch (isonum_711(desc->data.type)) {
- case ISO_VD_BOOT: {
-
- struct el_torito_boot_descriptor* bootdesc;
- bootdesc=&(desc->data);
- dumpboot(bootdesc);
- if ( !memcmp(EL_TORITO_ID,bootdesc->system_id,ISODCL(8,39)) ) {
-
- if (ReadBootTable(&readf,isonum_731(bootdesc->boot_catalog),&boot,NULL)) {
- printf("Boot Catalog Error\n");
- } else {
- dumpbootcat(&boot);
- FreeBootTable(&boot);
- }
- }
- }
- break;
-
- case ISO_VD_PRIMARY:
- case ISO_VD_SUPPLEMENTARY:
- joliet=0;
- joliet = JolietLevel(&desc->data);
- printf("Joliet level: %d\n",joliet);
- dumpdesc((struct iso_primary_descriptor*) &desc->data);
- printf("\n\n--------------- Directory structure: -------------------\n\n");
- dirs=0;files=0;
- mycallb( &( ((struct iso_primary_descriptor*) &desc->data)->root_directory_record), NULL );
- printf("\nnumber of directories: %d\n",dirs);
- printf("\nnumber of files: %d\n",files);
- break;
-
- }
- desc=desc->next;
- i++;
- }
- iconv_close(iconv_d);
- close(fd);
- FreeISO9660(desc);
- return 0;
-}
-
-#endif /* ISOFS_MAIN */
diff --git a/kioslave/iso/libisofs/isofs.h b/kioslave/iso/libisofs/isofs.h
deleted file mode 100644
index 1d17de4bb..000000000
--- a/kioslave/iso/libisofs/isofs.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/***************************************************************************
- isofs.h - include this file to use libisofs
- -------------------
- begin : Oct 25 2002
- copyright : (C) 2002 by Szombathelyi Gy�gy
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef ISOFS_H
-#define ISOFS_H
-
-#include <sys/time.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "iso_fs.h"
-#include "el_torito.h"
-#include "rock.h"
-
-typedef struct _rr_entry {
- int len; /* length of structure */
- char *name; /* Name from 'NM' */
- char *sl; /* symbolic link data */
- time_t t_creat;
- time_t t_mtime;
- time_t t_atime;
- time_t t_ctime;
- time_t t_backup;
- time_t t_expire;
- time_t t_effect;
- int mode; /* POSIX file modes */
- int nlink;
- int uid;
- int gid;
- int serno;
- int dev_major;
- int dev_minor;
- int pl; /* parent location */
- int cl; /* child location */
- int re; /* relocated */
- char z_algo[2]; /* zizofs algorithm */
- char z_params[2]; /* zizofs parameters */
- long long z_size; /* zizofs real_size */
-} rr_entry;
-
-typedef struct _iso_vol_desc {
- struct _iso_vol_desc *next;
- struct _iso_vol_desc *prev;
- struct iso_volume_descriptor data;
-} iso_vol_desc;
-
-typedef struct _boot_entry {
- struct _boot_entry *next;
- struct _boot_entry *prev;
- struct _boot_entry *parent;
- struct _boot_entry *child;
- char data[32];
-}
- boot_entry;
-
-typedef struct _boot_head {
- struct validation_entry ventry;
- struct _boot_entry *defentry;
- struct _boot_entry *sections;
-}
- boot_head;
-
-/**
- * this callback function needs to read 'len' sectors from 'start' into 'buf'
- */
-typedef int readfunc(char *buf,long long start, long long len,void *);
-
-/**
- * ProcessDir uses this callback
- */
-typedef int dircallback(struct iso_directory_record *,void *);
-
-/**
- * Returns the Unix from the ISO9660 9.1.5 (7 bytes) time format
- * This function is from the linux kernel.
- * Set 'hs' to non-zero if it's a HighSierra volume
- */
-time_t isodate_915(char * p, int hs);
-
-/**
- * Returns the Unix time from the ISO9660 8.4.26.1 (17 bytes) time format
- * BUG: hundredth of seconds are ignored, because time_t has one second
- * resolution (I think it's no problem at all)
- * Set 'hs' to non-zero if it's a HighSierra volume
- */
-time_t isodate_84261(char * p, int hs);
-
-/**
- * Creates the linked list of the volume descriptors
- * 'sector' is the starting sector number of where the filesystem start
- * (starting sector of a session on a CD-ROM)
- * If the function fails, returns NULL
- * Don't forget to call FreeISO9660 after using the volume descriptor list!
- */
-iso_vol_desc *ReadISO9660(readfunc *read,long long sector,void *udata);
-
-/**
- * Frees the linked list of volume descriptors
-.
- */
-void FreeISO9660(iso_vol_desc *data);
-
-/**
- * Iterates over the directory entries. The directory is in 'buf',
- * the size of the directory is 'size'. 'callback' is called for each
- * directory entry with the parameter 'udata'.
- */
-int ProcessDir(readfunc *read,int extent,int size,dircallback *callback,void *udata);
-
-/**
- * Parses the System Use area and fills rr_entry with values
- */
-int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry);
-
-/**
- * Frees the strings in 'rrentry'
- */
-void FreeRR(rr_entry *rrentry);
-
-/**
- * returns the joliet level from the volume descriptor
- */
-int JolietLevel(struct iso_volume_descriptor *ivd);
-
-/**
- * Returns the size of the boot image (in 512 byte sectors)
- */
-int BootImageSize(int media,long long len);
-
-/**
- * Frees the boot catalog entries in 'boot'. If you ever called ReadBootTable,
- * then don't forget to call FreeBootTable!
- */
-void FreeBootTable(boot_head *boot);
-
-/**
- * Reads the boot catalog into 'head'. Don't forget to call FreeBootTable!
- */
-int ReadBootTable(readfunc *read,long long sector, boot_head *head, void *udata);
-
-#ifdef __cplusplus
-} //extern "C"
-#endif
-
-#endif
-
diff --git a/kioslave/iso/libisofs/rock.h b/kioslave/iso/libisofs/rock.h
deleted file mode 100644
index e85919261..000000000
--- a/kioslave/iso/libisofs/rock.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* this header is from the linux kernel */
-
-#ifndef ROCK_H
-#define ROCK_H 1
-
-/* These structs are used by the system-use-sharing protocol, in which the
- Rock Ridge extensions are embedded. It is quite possible that other
- extensions are present on the disk, and this is fine as long as they
- all use SUSP */
-
-struct SU_SP{
- unsigned char magic[2];
- unsigned char skip;
-};
-
-struct SU_CE{
- char extent[8];
- char offset[8];
- char size[8];
-};
-
-struct SU_ER{
- unsigned char len_id;
- unsigned char len_des;
- unsigned char len_src;
- unsigned char ext_ver;
- char data[1];
-};
-
-struct RR_RR{
- char flags[1];
-};
-
-struct RR_PX{
- char mode[8];
- char n_links[8];
- char uid[8];
- char gid[8];
- char serno[8];
-};
-
-struct RR_PN{
- char dev_high[8];
- char dev_low[8];
-};
-
-
-struct SL_component{
- unsigned char flags;
- unsigned char len;
- char text[1];
-};
-
-struct RR_SL{
- unsigned char flags;
- struct SL_component link;
-};
-
-struct RR_NM{
- unsigned char flags;
- char name[1];
-};
-
-struct RR_CL{
- char location[8];
-};
-
-struct RR_PL{
- char location[8];
-};
-
-struct stamp{
- char time[7];
-};
-
-struct RR_TF{
- char flags;
- struct stamp times[1]; /* Variable number of these beasts */
-};
-
-/* Linux-specific extension for transparent decompression */
-struct RR_ZF{
- char algorithm[2];
- char parms[2];
- char real_size[8];
-};
-
-/* These are the bits and their meanings for flags in the TF structure. */
-#define TF_CREATE 1
-#define TF_MODIFY 2
-#define TF_ACCESS 4
-#define TF_ATTRIBUTES 8
-#define TF_BACKUP 16
-#define TF_EXPIRATION 32
-#define TF_EFFECTIVE 64
-#define TF_LONG_FORM 128
-
-struct rock_ridge{
- char signature[2];
- char len; /* 711 */
- char version; /* 711 */
- union{
- struct SU_SP SP;
- struct SU_CE CE;
- struct SU_ER ER;
- struct RR_RR RR;
- struct RR_PX PX;
- struct RR_PN PN;
- struct RR_SL SL;
- struct RR_NM NM;
- struct RR_CL CL;
- struct RR_PL PL;
- struct RR_TF TF;
- struct RR_ZF ZF;
- } u;
-};
-
-#define RR_PX 1 /* POSIX attributes */
-#define RR_PN 2 /* POSIX devices */
-#define RR_SL 4 /* Symbolic link */
-#define RR_NM 8 /* Alternate Name */
-#define RR_CL 16 /* Child link */
-#define RR_PL 32 /* Parent link */
-#define RR_RE 64 /* Relocation directory */
-#define RR_TF 128 /* Timestamps */
-
-#endif /* ROCK_H */
diff --git a/kioslave/iso/qfilehack.cpp b/kioslave/iso/qfilehack.cpp
deleted file mode 100644
index f4f788f25..000000000
--- a/kioslave/iso/qfilehack.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/***************************************************************************
- qfilehack.cpp - description
- -------------------
- begin : Tue Oct 29 2002
- copyright : (C) 2002 by Szombathelyi György
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#include "qfilehack.h"
-
-QFileHack::QFileHack(){
-}
-
-QFileHack::QFileHack( const TQString & name ) : TQFile(name) {
-}
-
-QFileHack::~QFileHack(){
-}
-
-bool QFileHack::open ( int m ) {
- bool ret;
-
-#ifdef __linux__
- m |= IO_Async; //On linux, set O_NONBLOCK, opens CD-ROMs faster
-#endif
- ret=TQFile::open(m);
- if (ret && isSequentialAccess() ) {
- setType(IO_Direct);
- }
- return ret;
-}
diff --git a/kioslave/iso/qfilehack.h b/kioslave/iso/qfilehack.h
deleted file mode 100644
index 3f0b1f6a6..000000000
--- a/kioslave/iso/qfilehack.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/***************************************************************************
- qfilehack.h - description
- -------------------
- begin : Tue Oct 29 2002
- copyright : (C) 2002 by Szombathelyi György
- email : gyurco@users.sourceforge.net
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-
-#ifndef QFILEHACK_H
-#define QFILEHACK_H
-
-#include <tqfile.h>
-#include <tqstring.h>
-
-/**
- *@author Szombathelyi György
- * Qt thinks if a file is not S_IFREG, you cannot seek in it. It's false (what about
- * block devices for example?
- */
-
-class QFileHack : public TQFile {
-public:
- QFileHack();
- QFileHack( const TQString & name );
- ~QFileHack();
- virtual bool open ( int m );
-};
-
-#endif
diff --git a/kioslave/metainfo/CMakeLists.txt b/kioslave/metainfo/CMakeLists.txt
deleted file mode 100644
index 9c5fcdf20..000000000
--- a/kioslave/metainfo/CMakeLists.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/dcop
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/kio
- ${CMAKE_SOURCE_DIR}/kio/kio
-)
-
-link_directories(
- ${TQT_LIBRARY_DIRS}
-)
-
-
-##### other data ################################
-
-install( FILES metainfo.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
-
-
-##### kio_metainfo ##############################
-
-set( target kio_metainfo )
-
-set( ${target}_SRCS
- metainfo.cpp
-)
-
-tde_add_kpart( ${target} AUTOMOC
- SOURCES ${${target}_SRCS}
- LINK kio-shared
- DESTINATION ${PLUGIN_INSTALL_DIR}
-)
diff --git a/kioslave/metainfo/Makefile.am b/kioslave/metainfo/Makefile.am
deleted file mode 100644
index e2de616c6..000000000
--- a/kioslave/metainfo/Makefile.am
+++ /dev/null
@@ -1,24 +0,0 @@
-## $Id$
-## Makefile.am of tdebase/kioslave/metainfo
-
-INCLUDES = $(all_includes)
-AM_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -lktexteditor
-METASOURCES = AUTO
-
-kde_module_LTLIBRARIES = kio_metainfo.la
-
-kio_metainfo_la_SOURCES = metainfo.cpp
-kio_metainfo_la_LIBADD = $(LIB_KIO) $(LIB_QT) $(LIB_TDECORE)
-kio_metainfo_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
-
-noinst_HEADERS = metainfo.h
-
-kdelnk_DATA = metainfo.protocol
-kdelnkdir = $(kde_servicesdir)
-
-#servicetypes_DATA = thumbcreator.desktop
-#servicetypesdir = $(kde_servicetypesdir)
-
-#services_DATA = imagethumbnail.desktop textthumbnail.desktop
-# htmlthumbnail.desktop gsthumbnail.desktop
-#servicesdir = $(kde_servicesdir)
diff --git a/kioslave/metainfo/metainfo.cpp b/kioslave/metainfo/metainfo.cpp
deleted file mode 100644
index 21e24e428..000000000
--- a/kioslave/metainfo/metainfo.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (C) 2002 Rolf Magnus <ramagnus@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 version 2.0
-
- 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.
-*/
-
-// $Id$
-
-#include <kdatastream.h> // Do not remove, needed for correct bool serialization
-#include <kurl.h>
-#include <kapplication.h>
-#include <kmimetype.h>
-#include <kdebug.h>
-#include <kfilemetainfo.h>
-#include <klocale.h>
-#include <stdlib.h>
-
-#include "metainfo.h"
-
-// Recognized metadata entries:
-// mimeType - the mime type of the file, so we need not extra determine it
-// what - what to load
-
-using namespace KIO;
-
-extern "C"
-{
- KDE_EXPORT int kdemain(int argc, char **argv);
-}
-
-int kdemain(int argc, char **argv)
-{
- KApplication app(argc, argv, "kio_metainfo", false, true);
-
- if (argc != 4)
- {
- kdError() << "Usage: kio_metainfo protocol domain-socket1 domain-socket2" << endl;
- exit(-1);
- }
-
- MetaInfoProtocol slave(argv[2], argv[3]);
- slave.dispatchLoop();
-
- return 0;
-}
-
-MetaInfoProtocol::MetaInfoProtocol(const TQCString &pool, const TQCString &app)
- : SlaveBase("metainfo", pool, app)
-{
-}
-
-MetaInfoProtocol::~MetaInfoProtocol()
-{
-}
-
-void MetaInfoProtocol::get(const KURL &url)
-{
- TQString mimeType = metaData("mimeType");
- KFileMetaInfo info(url.path(), mimeType);
-
- TQByteArray arr;
- TQDataStream stream(arr, IO_WriteOnly);
-
- stream << info;
-
- data(arr);
- finished();
-}
-
-void MetaInfoProtocol::put(const KURL& url, int, bool, bool)
-{
- TQString mimeType = metaData("mimeType");
- KFileMetaInfo info;
-
- TQByteArray arr;
- readData(arr);
- TQDataStream stream(arr, IO_ReadOnly);
-
- stream >> info;
-
- if (info.isValid())
- {
- info.applyChanges();
- }
- else
- {
- error(ERR_NO_CONTENT, i18n("No metainfo for %1").arg(url.path()));
- return;
- }
- finished();
-}
diff --git a/kioslave/metainfo/metainfo.h b/kioslave/metainfo/metainfo.h
deleted file mode 100644
index 491da62eb..000000000
--- a/kioslave/metainfo/metainfo.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* This file is part of the KDE libraries
- Copyright (C) 2002 Rolf Magnus <ramagnus@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 version 2.0
-
- 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.
-*/
-
-// $Id$
-
-#ifndef _METAINFO_H_
-#define _METAINFO_H_
-
-#include <kio/slavebase.h>
-
-class MetaInfoProtocol : public KIO::SlaveBase
-{
-public:
- MetaInfoProtocol(const TQCString &pool, const TQCString &app);
- virtual ~MetaInfoProtocol();
-
- virtual void get(const KURL &url);
- virtual void put(const KURL& url, int permissions,
- bool overwrite, bool resume);
-
-};
-
-#endif
diff --git a/kioslave/metainfo/metainfo.protocol b/kioslave/metainfo/metainfo.protocol
deleted file mode 100644
index f1fa9adac..000000000
--- a/kioslave/metainfo/metainfo.protocol
+++ /dev/null
@@ -1,9 +0,0 @@
-[Protocol]
-exec=kio_metainfo
-protocol=metainfo
-input=stream
-output=stream
-reading=true
-writing=true
-source=false
-Icon=help