diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2013-01-27 01:04:16 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2013-01-27 01:04:16 -0600 |
commit | 5159cd2beb2e87806a5b54e9991b7895285c9d3e (patch) | |
tree | 9b70e8be47a390f8f4d56ead812ab0c9dad88709 /kioslave | |
parent | c17cb900dcf52b8bd6dc300d4f103392900ec2b4 (diff) | |
download | tdelibs-5159cd2beb2e87806a5b54e9991b7895285c9d3e.tar.gz tdelibs-5159cd2beb2e87806a5b54e9991b7895285c9d3e.zip |
Rename a number of libraries and executables to avoid conflicts with KDE4
Diffstat (limited to 'kioslave')
102 files changed, 0 insertions, 25892 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 73a037b91..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 TDEIO; - -#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"); - TDEInstance instance( "kio_file" ); - ( void ) TDEGlobal::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( TDEIO::ERR_ACCESS_DENIED, url.path() ); - break; - case ENOTSUP: - error( TDEIO::ERR_UNSUPPORTED_ACTION, url.path() ); - break; - case ENOSPC: - error( TDEIO::ERR_DISK_FULL, url.path() ); - break; - default: - error( TDEIO::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( TDEIO::ERR_ACCESS_DENIED, url.path() ); - return; - } else if ( errno == ENOSPC ) { - error( TDEIO::ERR_DISK_FULL, url.path() ); - return; - } else { - error( TDEIO::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( TDEIO::ERR_DIR_ALREADY_EXIST, url.path() ); - return; - } - error( TDEIO::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( TDEIO::ERR_ACCESS_DENIED, url.path() ); - else - error( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); - return; - } - - if ( S_ISDIR( buff.st_mode ) ) { - error( TDEIO::ERR_IS_DIRECTORY, url.path() ); - return; - } - if ( !S_ISREG( buff.st_mode ) ) { - error( TDEIO::ERR_CANNOT_OPEN_FOR_READING, url.path() ); - return; - } - - int fd = KDE_open( _path.data(), O_RDONLY); - if ( fd < 0 ) { - error( TDEIO::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() ); - - TDEIO::filesize_t processed_size = 0; - - TQString resumeOffset = metaData("resume"); - if ( !resumeOffset.isEmpty() ) - { - bool ok; - TDEIO::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: " << TDEIO::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( TDEIO::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: " << TDEIO::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 " - << TDEIO::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( TDEIO::ERR_DIR_ALREADY_EXIST, dest_orig ); - else - error( TDEIO::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( TDEIO::ERR_WRITE_ACCESS_DENIED, dest ); - else - error( TDEIO::ERR_CANNOT_OPEN_FOR_WRITING, dest ); - return; - } - } - - if (write_all( fd, buffer.data(), buffer.size())) - { - if ( errno == ENOSPC ) // disk full - { - error( TDEIO::ERR_DISK_FULL, dest_orig); - result = -2; // means: remove dest file - } - else - { - kdWarning(7101) << "Couldn't write. Error:" << strerror(errno) << endl; - error( TDEIO::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( TDEIO::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( TDEIO::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 ( TDEIO::testFileSystemFlag( _dest_orig, TDEIO::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( TDEIO::ERR_ACCESS_DENIED, src.path() ); - else - error( TDEIO::ERR_DOES_NOT_EXIST, src.path() ); - return; - } - - if ( S_ISDIR( buff_src.st_mode ) ) { - error( TDEIO::ERR_IS_DIRECTORY, src.path() ); - return; - } - if ( S_ISFIFO( buff_src.st_mode ) || S_ISSOCK ( buff_src.st_mode ) ) { - error( TDEIO::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( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); - return; - } - - if ( same_inode( buff_dest, buff_src) ) - { - error( TDEIO::ERR_IDENTICAL_FILES, dest.path() ); - return; - } - - if (!_overwrite) - { - error( TDEIO::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( TDEIO::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( TDEIO::ERR_WRITE_ACCESS_DENIED, dest.path() ); - } else { - error( TDEIO::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 ); - - TDEIO::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( TDEIO::ERR_DISK_FULL, dest.path()); - remove( _dest.data() ); - } - else { - error( TDEIO::ERR_SLAVE_DEFINED, - i18n("Cannot copy file from %1 to %2. (Errno: %3)") - .arg( src.path() ).arg( dest.path() ).arg( errno ) ); - } - } else -#endif - error( TDEIO::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( TDEIO::ERR_DISK_FULL, dest.path()); - remove( _dest.data() ); - } - else - { - kdWarning(7101) << "Couldn't write[2]. Error:" << strerror(errno) << endl; - error( TDEIO::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( TDEIO::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 ( TDEIO::testFileSystemFlag( _dest, TDEIO::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( TDEIO::ERR_ACCESS_DENIED, src.path() ); - else - error( TDEIO::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( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); - return; - } - - if ( same_inode( buff_dest, buff_src) ) - { - error( TDEIO::ERR_IDENTICAL_FILES, dest.path() ); - return; - } - - if (!_overwrite) - { - error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.path() ); - return; - } - } - - if ( ::rename( _src.data(), _dest.data())) - { - if (( errno == EACCES ) || (errno == EPERM)) { - error( TDEIO::ERR_ACCESS_DENIED, dest.path() ); - } - else if (errno == EXDEV) { - error( TDEIO::ERR_UNSUPPORTED_ACTION, TQString::fromLatin1("rename")); - } - else if (errno == EROFS) { // The file is on a read-only filesystem - error( TDEIO::ERR_CANNOT_DELETE, src.path() ); - } - else { - error( TDEIO::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( TDEIO::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( TDEIO::ERR_DIR_ALREADY_EXIST, dest.path() ); - else - error( TDEIO::ERR_FILE_ALREADY_EXIST, dest.path() ); - return; - } - } - else - { - // Some error occurred while we tried to symlink - error( TDEIO::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( TDEIO::ERR_ACCESS_DENIED, url.path()); - else if (errno == EISDIR) - error( TDEIO::ERR_IS_DIRECTORY, url.path()); - else - error( TDEIO::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( TDEIO::ERR_ACCESS_DENIED, url.path()); - else { - kdDebug( 7101 ) << "could not rmdir " << perror << endl; - error( TDEIO::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 = TDEIO::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 = TDEIO::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 = TDEIO::UDS_FILE_TYPE; - atom.m_long = type; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = access; - entry.append( atom ); - - atom.m_uds = TDEIO::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 = TDEIO::UDS_FILE_TYPE; - atom.m_long = type; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = access; - entry.append( atom ); - - atom.m_uds = TDEIO::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 = TDEIO::UDS_MODIFICATION_TIME; - atom.m_long = buff.st_mtime; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_USER; - atom.m_str = getUserName( buff.st_uid ); - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_GROUP; - atom.m_str = getGroupName( buff.st_gid ); - entry.append( atom ); - - atom.m_uds = TDEIO::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( TDEIO::ERR_DOES_NOT_EXIST, url.path(-1) ); - return; - } -#if 0 -///////// debug code - TDEIO::UDSEntry::ConstIterator it = entry.begin(); - for( ; it != entry.end(); it++ ) { - switch ((*it).m_uds) { - case TDEIO::UDS_FILE_TYPE: - kdDebug(7101) << "File Type : " << (mode_t)((*it).m_long) << endl; - break; - case TDEIO::UDS_ACCESS: - kdDebug(7101) << "Access permissions : " << (mode_t)((*it).m_long) << endl; - break; - case TDEIO::UDS_USER: - kdDebug(7101) << "User : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_GROUP: - kdDebug(7101) << "Group : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_NAME: - kdDebug(7101) << "Name : " << ((*it).m_str.ascii() ) << endl; - //m_strText = decodeFileName( (*it).m_str ); - break; - case TDEIO::UDS_URL: - kdDebug(7101) << "URL : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_MIME_TYPE: - kdDebug(7101) << "MimeType : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::UDS_LINK_DEST: - kdDebug(7101) << "LinkDest : " << ((*it).m_str.ascii() ) << endl; - break; - case TDEIO::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( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); - return; - } - - if ( !S_ISDIR( buff.st_mode ) ) { - error( TDEIO::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( TDEIO::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( TDEIO::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( TDEIO::filesize_t ) ), - this, TQT_SLOT( slotProcessedSize( TDEIO::filesize_t ) ) ); - connect( &shred, TQT_SIGNAL( infoMessage( const TQString & ) ), - this, TQT_SLOT( slotInfoMessage( const TQString & ) ) ); - if (!shred.shred()) - error( TDEIO::ERR_CANNOT_DELETE, filename ); - else - finished(); - break; - } - default: - break; - } -} - -// Connected to KShred -void FileProtocol::slotProcessedSize( TDEIO::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( TDEIO::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( TDEIO::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( TDEProcess::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( TDEProcess::quote( uuidName ) ); - } - else - dev = TQFile::encodeName( TDEProcess::quote(_dev) ); // get those ready to be given to a shell - - TQCString point = TQFile::encodeName( TDEProcess::quote(_point) ); - bool fstype_empty = !_fstype || !*_fstype; - TQCString fstype = TDEProcess::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 = TDEGlobal::dirs()->findExe("mount", path); - if (mountProg.isEmpty()){ - error( TDEIO::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 = TDEIO::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( TDEIO::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( TDEIO::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( TDEIO::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(TDEProcess::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( TDEIO::ERR_COULD_NOT_UNMOUNT, err ); - return; - } -#else - TQString epath = getenv("PATH"); - TQString path = TQString::fromLatin1("/sbin:/bin"); - if (!epath.isEmpty()) - path += ":" + epath; - TQString umountProg = TDEGlobal::dirs()->findExe("umount", path); - - if (umountProg.isEmpty()) { - error( TDEIO::ERR_COULD_NOT_UNMOUNT, i18n("Could not find program \"umount\"")); - return; - } - buffer.sprintf( "%s %s 2>%s", umountProg.latin1(), TQFile::encodeName(TDEProcess::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( TDEIO::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 = TDEGlobal::dirs()->findExe("pmount", path); - - if (pmountProg.isEmpty()) - return false; - - TQCString buffer; - buffer.sprintf( "%s %s", TQFile::encodeName(pmountProg).data(), - TQFile::encodeName(TDEProcess::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 = TDEGlobal::dirs()->findExe("pumount", path); - - if (pumountProg.isEmpty()) - return false; - - TQCString buffer; - buffer.sprintf( "%s %s", TQFile::encodeName(pumountProg).data(), - TQFile::encodeName(TDEProcess::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 = TDEIO::UDS_EXTENDED_ACL; - atom.m_long = 1; - entry.append( atom ); - } - if ( withACL ) { - if ( acl ) { - atom.m_uds = TDEIO::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 = TDEIO::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 9f9d98995..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 TDEIO::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( TDEIO::filesize_t _bytes ); - void slotInfoMessage( const TQString & msg ); - -protected: - - bool createUDSEntry( const TQString & filename, const TQCString & path, TDEIO::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 3d29e2b65..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 TDEIO { - 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; - } -} - -TDEIO::filesize_t Ftp::UnknownSize = (TDEIO::filesize_t)-1; - -using namespace TDEIO; - -extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); } - -int kdemain( int argc, char **argv ) -{ - KLocale::setMainCatalogue("tdelibs"); - TDEInstance instance( "kio_ftp" ); - ( void ) TDEGlobal::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 TDESocketAddress *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 TDESocketAddress *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, TDEIO::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 = TDEIO::UDS_NAME; - atom.m_str = filename; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = isDir ? S_IFDIR : S_IFREG; - entry.append( atom ); - - atom.m_uds = TDEIO::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 = TDEIO::UDS_NAME; - atom.m_str = TQString::null; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = S_IFDIR; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_USER; - atom.m_str = "root"; - entry.append( atom ); - atom.m_uds = TDEIO::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 = TDEIO::UDS_NAME; - atom.m_str = filename; - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = S_IFDIR; - entry.append( atom ); - - atom.m_uds = TDEIO::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( ¤tTime ); - 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, TDEIO::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; - } - - TDEIO::filesize_t bytesLeft = 0; - if ( m_size != UnknownSize ) - bytesLeft = m_size - llOffset; - - kdDebug(7102) << "ftpGet: starting with offset=" << llOffset << endl; - TDEIO::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, TDEIO::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; - - TDEIO::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; - TDEIO::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 ... - TDEIO::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 8a847e6da..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; - - TDEIO::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 TDEIO::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, TDEIO::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, TDEIO::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, TDEIO::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; - - TDEIO::filesize_t m_size; - static TDEIO::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 0ec2e03c9..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) -ltdetexteditor -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 c093df483..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 tdentlm-shared kio-shared - DESTINATION ${PLUGIN_INSTALL_DIR} -) diff --git a/kioslave/http/Makefile.am b/kioslave/http/Makefile.am deleted file mode 100644 index 5946fc9f8..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/tdentlm/libtdentlm.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 9dbf60a3e..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 tdehtml 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 e1eefa595..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/tdentlm/tdentlm.h> - -using namespace TDEIO; - -extern "C" { - KDE_EXPORT int kdemain(int argc, char **argv); -} - -int kdemain( int argc, char **argv ) -{ - KLocale::setMainCatalogue("tdelibs"); - TDEInstance instance( "kio_http" ); - ( void ) TDEGlobal::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 ((TDEIO::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( TDEIO::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 = TDEIO::UDS_NAME; - atom.m_str = url.fileName(); - entry.append( atom ); - - atom.m_uds = TDEIO::UDS_FILE_TYPE; - atom.m_long = S_IFREG; // a file - entry.append( atom ); - - atom.m_uds = TDEIO::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 = TDEIO::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, TDEIO::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 = TDEIO::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 = TDEIO::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 = TDEIO::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 = TDEIO::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 = TDEIO::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 = TDEIO::UDS_ACCESS; - atom.m_long = 0700; - entry.append(atom); - } - else - { - atom.m_uds = TDEIO::UDS_ACCESS; - atom.m_long = 0600; - entry.append(atom); - } - - if ( !isDirectory && !mimeType.isEmpty() ) - { - atom.m_uds = TDEIO::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; - TDEIO::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; - TDEIO::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 TDEIOJob::put() or TDEIOJob::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 == TDEIO::CC_CacheOnly); - bool bOffline = isOffline(m_request.doProxy ? m_proxyURL : m_request.url); - if (bOffline && (m_request.cache != TDEIO::CC_Reload)) - m_request.cache = TDEIO::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 == TDEIO::CC_CacheOnly) || (m_request.cache == TDEIO::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(TDEIO::number(m_request.offset)); - kdDebug(7103) << "kio_http : Range = " << TDEIO::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 - // tdehtml. - 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, (TDEIO::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 TDEIOJob::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. - TDEIO::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(TDEIO::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. " - << TDEIO::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 = "<< TDEIO::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 "<< TDEIO::number(m_iBytesLeft) - << " bytes left! can't close cache entry!\n"; - } - - if (sz <= 1) - { - /* kdDebug(7113) << "(" << m_pid << ") readBody: sz = " << TDEIO::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); - TDEApplication::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 (TDEGlobal::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 = TDEApplication::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 ccbb60ce6..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 TDEIO { - class AuthInfo; -} - -class HTTPProtocol : public TQObject, public TDEIO::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 = TDEIO::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; - TDEIO::HTTP_METHOD method; - TDEIO::CacheControl cache; - TDEIO::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, TDEIO::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, TDEIO::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( TDEIO::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 - TDEIO::filesize_t m_iSize; // Expected size of message - TDEIO::filesize_t m_iBytesLeft; // # of bytes left to receive in this message. - TDEIO::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 554d221d5..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"); - TDECmdLineArgs::init( argc, argv, appName, - I18N_NOOP("TDE HTTP cache maintenance tool"), - description, version, true); - - TDECmdLineArgs::addCmdLineOptions( options ); - - TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); - - bool deleteAll = args->isSet("clear-all"); - - TDEInstance 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 = TDEGlobal::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 289daa4f0..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}/tdehtml ) - - -##### 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 431502c12..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)/tdehtml - 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 12d92a8df..000000000 --- a/kioslave/http/kcookiejar/kcookiejar.cpp +++ /dev/null @@ -1,1559 +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), - mCrossDomain(false), - 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; - - TDEConfig cfg("tdehtml/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(TDEConfig *_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(TDEConfig *_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 bb16d75d3..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 TDEConfig; -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(TDEConfig *_config); - - /** - * Load the cookie configuration - */ - void loadConfig(TDEConfig *_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 94df40b63..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 TDEConfig("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 2cbb9ccf1..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 TDEConfig; - -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; - TDEConfig *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 57a22f62c..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( TDEGlobal::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 e24112888..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"); - TDECmdLineArgs::init(argc, argv, "kcookiejar", I18N_NOOP("HTTP cookie daemon"), - description, version); - - TDECmdLineArgs::addCmdLineOptions( options ); - - TDEInstance a("kcookiejar"); - - kapp->dcopClient()->attach(); - - TDECmdLineArgs *args = TDECmdLineArgs::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> | <A -HREF="http://home.netscape.com/misc/nav_redir/site_map.html" TARGET="_top">Site Map</A> | <A -HREF="http://home.netscape.com/misc/nav_redir/howtoget.html" TARGET="_top">How to Get Netscape Products</A> | <A HREF="http://home.netscape.com/misc/nav_redir/ad.html" TARGET="_top">Advertise With Us</A> | <A HREF="http://home.netscape.com/misc/nav_redir/addsite.html" TARGET="_top">Add Site</A> | <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> | <A -HREF="http://home.netscape.com/misc/nav_redir/channels/business.html" TARGET="_top">Business</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/computers_internet.html" TARGET="_top">Computing & Internet</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/entertainment.html" TARGET="_top">Entertainment</A> | <A -HREF="http://home.netscape.com/misc/nav_redir/channels/kids_family.html" TARGET="_top">Family</A> | <A -HREF="http://home.netscape.com/misc/nav_redir/channels/games.html" TARGET="_top">Games</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/health.html" TARGET="_top">Health</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/lifestyles.html" TARGET="_top">Lifestyles</A> | <A -HREF="http://home.netscape.com/misc/nav_redir/channels/local.html" TARGET="_top">Local</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/netscape.html" TARGET="_top">Netscape</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/open_directory.html">Netscape Open Directory</A> | <A -HREF="http://home.netscape.com/misc/nav_redir/channels/news.html" TARGET="_top">News</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/personalize_finance.html" TARGET="_top">Personal Finance</A> | <A -HREF="http://home.netscape.com/misc/nav_redir/channels/real_estate.html" TARGET="_top">Real Estate</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/education.html" TARGET="_top">Research & Learn</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/shopping.html" TARGET="_top">Shopping</A> | <A HREF="http://home.netscape.com/misc/nav_redir/channels/smallbiz.html" TARGET="_top">Small Business</A> | <A -HREF="http://home.netscape.com/misc/nav_redir/channels/sports.html" TARGET="_top">Sports</A> | <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> -© 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 4059cdcd1..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) -ltdetexteditor - -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 236e2406b..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 TDEConfig *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 TDEConfig(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()); - - TDEAboutData about("kcookietest", "kcookietest", "1.0", description, TDEAboutData::License_GPL, "(C) 2004 Waldo Bastian"); - TDECmdLineArgs::init( argc, argv, &about); - - TDECmdLineArgs::addCmdLineOptions( options ); - - TDEInstance a("kcookietest"); - - TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); - if (args->count() != 1) - TDECmdLineArgs::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 59f5f781e..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 TDEIO; - -extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); } - -int kdemain( int argc, char **argv ) -{ - TDEInstance 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( TDEIO::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( TDEIO::ERR_DOES_NOT_EXIST, path ); - return; - } - if ( ! e->isDirectory() ) - { - error( TDEIO::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( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); - return; - } - // Real directory. Return just enough information for KRun to work - UDSAtom atom; - atom.m_uds = TDEIO::UDS_NAME; - atom.m_str = url.fileName(); - entry.append( atom ); - kdDebug() << "kio_isoProtocol::stat returning name=" << url.fileName() << endl; - - atom.m_uds = TDEIO::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( TDEIO::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(TDEIO::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(TDEIO::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( TDEIO::ERR_DOES_NOT_EXIST, url.path() ); - return; - } - - const KArchiveDirectory* root = m_isoFile->directory(); - const KArchiveEntry* isoEntry = root->entry( path ); - - if ( !isoEntry ) - { - error( TDEIO::ERR_DOES_NOT_EXIST, path ); - return; - } - if ( isoEntry->isDirectory() ) - { - error( TDEIO::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 136c32736..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 TDEIO::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, TDEIO::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 b19ec589b..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() -{ - TDEConfig *config; - - config = new TDEConfig("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 c1d1d295e..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) -ltdetexteditor -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 66e5357f9..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 TDEIO; - -extern "C" -{ - KDE_EXPORT int kdemain(int argc, char **argv); -} - -int kdemain(int argc, char **argv) -{ - TDEApplication 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 a77647180..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 TDEIO::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 |