[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    [LONG PATCH] Fix for bug #56197: enable charset selection for FTP
From:       Thiago Macieira <thiago.macieira () kdemail ! net>
Date:       2003-11-24 14:39:17
[Download RAW message or body]

[Attachment #2 (multipart/mixed)]


I have come up with a patch fixing bug #56197, but I think it is too intrusive 
to be added to CVS at this time. In any event, I am posting it for review.

Rough edges:
- introduces one new message, but that could be changed to reuse an existing 
one
- reloading the site when changing the encoding seems not to work

What I did for kio_ftp has to be done for other T_FILESYSTEM ioslaves as well 
(kio_fish, for instance).

I'd also like to recommend this Charset feature for determining encoding in 
other situations as well -- kate/kwrite for instance would benefit from it.
-- 
  Thiago Macieira  -  Registered Linux user #65028
   thiagom@mail.com           
    ICQ UIN: 1967141   PGP/GPG: 0x6EF45358; fingerprint:
    E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

["kio.patch" (text/x-diff)]

Index: slavebase.cpp
===================================================================
RCS file: /home/kde/kdelibs/kio/kio/slavebase.cpp,v
retrieving revision 1.155
diff -u -3 -p -r1.155 slavebase.cpp
--- slavebase.cpp	14 Nov 2003 20:56:04 -0000	1.155
+++ slavebase.cpp	24 Nov 2003 14:31:24 -0000
@@ -51,6 +51,7 @@
 #include <ksocks.h>
 
 #include "slavebase.h"
+#include "kremotefilename.h"
 
 #include "kio/slavebase.h"
 #include "kio/connection.h"
@@ -123,6 +124,7 @@ public:
     KIO::filesize_t totalSize;
     KIO::filesize_t sentListEntries;
     DCOPClient *dcopClient;
+    KRemoteFilename *remotefile;
     time_t timeout;
     QByteArray timeoutData;
 };
@@ -223,6 +225,7 @@ SlaveBase::SlaveBase( const QCString &pr
     connectSlave(mAppSocket);
 
     d->dcopClient = 0;
+    d->remotefile = 0;
 }
 
 SlaveBase::~SlaveBase()
@@ -366,6 +369,13 @@ void SlaveBase::sendMetaData()
    mOutgoingMetaData.clear(); // Clear
 }
 
+KRemoteFilename *SlaveBase::remoteEncoding()
+{
+   if (d->remotefile != 0)
+      return d->remotefile;
+
+   return d->remotefile = new KRemoteFilename(metaData("Charset").latin1());
+}
 
 void SlaveBase::data( const QByteArray &data )
 {
@@ -964,6 +974,8 @@ void SlaveBase::dispatch( int command, c
     case CMD_CONFIG:
         stream >> d->configData;
         KSocks::setConfig(d->config);
+	delete d->remotefile;
+	d->remotefile = 0;
         break;
     case CMD_GET:
     {
Index: slavebase.h
===================================================================
RCS file: /home/kde/kdelibs/kio/kio/slavebase.h,v
retrieving revision 1.103
diff -u -3 -p -r1.103 slavebase.h
--- slavebase.h	28 Oct 2003 17:04:49 -0000	1.103
+++ slavebase.h	24 Nov 2003 14:31:24 -0000
@@ -26,6 +26,7 @@
 #include <kio/authinfo.h>
 
 class DCOPClient;
+class KRemoteFilename;
 
 namespace KIO {
 
@@ -290,6 +291,15 @@ public:
      */
     KConfigBase* config();
 
+    /**
+     * Returns an object that can translate remote filenames into proper
+     * Unicode forms. This encoding can be set by the user.
+     *
+     * @since 3.2
+     */
+    KRemoteFilename* remoteEncoding();
+    
+
     ///////////
     // Commands sent by the job, the slave has to
     // override what it wants to implement
--- /dev/null	1969-12-31 21:00:00.000000000 -0300
+++ kremotefilename.h	2003-11-23 13:30:26.000000000 -0200
@@ -0,0 +1,121 @@
+/* This file is part of the KDE libraries
+   Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net>
+
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+#ifndef KREMOTEFILENAME_H
+#define KREMOTEFILENAME_H
+
+#include <kurl.h>
+#include <qstring.h>
+#include <qcstring.h>
+#include <qtextcodec.h>
+
+class KRemoteFilenamePrivate;
+/**
+ * Allows encoding and decoding properly remote filenames into Unicode.
+ *
+ * Certain protocols do not specify an appropriate encoding for decoding
+ * their 8-bit data into proper Unicode forms. Therefore, ioslaves should
+ * use this class in order to convert those forms into QStrings before
+ * creating the respective @ref UDSEntry. The same is true for decoding
+ * URLs to its components.
+ * 
+ * Each @ref SlaveBase has one object of this kind, even if it is not necessary.
+ * It can be accessed through @ref SlaveBase::remoteEncoding.
+ *
+ * @short A class for handling remote filenames
+ * @author Thiago Macieira <thiago.macieira@kdemail.net>
+ * @since 3.2
+ */
+class KRemoteFilename
+{
+public:
+  /**
+   * Constructor.
+   *
+   * Constructs this object to use the given encoding name.
+   * If @p name is a null pointer, the standard encoding will be used.
+   */
+  explicit KRemoteFilename(const char *name = 0L);
+
+  /**
+   * Destructor
+   */
+  virtual ~KRemoteFilename();
+
+  /**
+   * Converts the given full pathname or filename to Unicode.
+   * This function is supposed to work for dirnames, filenames
+   * or a full pathname.
+   */
+  QString decode(const QCString& name);
+
+  /**
+   * Converts the given name from Unicode.
+   * This function is supposed to work for dirnames, filenames
+   * or a full pathname.
+   */
+  QCString encode(const QString& name);
+
+  /**
+   * Converts the given URL into its 8-bit components
+   */
+  QCString encode(const KURL& url);
+
+  /**
+   * Converts the given URL into 8-bit form and separate the
+   * dirname from the filename. This is useful for slave functions
+   * like stat or get.
+   *
+   * The dirname is returned with the final slash always stripped
+   */
+  QCString directory(const KURL& url, bool ignore_trailing_slash = true);
+
+  /**
+   * Converts the given URL into 8-bit form and retrieve the filename.
+   */
+  QCString fileName(const KURL& url);
+
+  /**
+   * Returns the encoding being used.
+   */
+  inline const char *encoding()
+  { return codec->name(); }
+
+  /**
+   * Sets the encoding being used.
+   * This function does not change the global configuration.
+   *
+   * Pass a null pointer in @p name to revert to the standard
+   * encoding.
+   */
+  void setEncoding(const char* name);
+
+protected:
+  QTextCodec *codec;
+
+  virtual void virtual_hook(int id, void* data);
+
+private:
+  // copy constructor
+  KRemoteFilename(const KRemoteFilename&);
+
+
+  KRemoteFilenamePrivate *d;
+};
+
+#endif
--- /dev/null	1969-12-31 21:00:00.000000000 -0300
+++ kremotefilename.cpp	2003-11-24 00:57:12.000000000 -0200
@@ -0,0 +1,93 @@
+/* This file is part of the KDE libraries
+   Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net>
+
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <kdebug.h>
+#include <kstringhandler.h>
+#include "kremotefilename.h"
+
+KRemoteFilename::KRemoteFilename(const char *name)
+  : codec(0L), d(0L)
+{
+  setEncoding(name);
+}
+
+KRemoteFilename::~KRemoteFilename()
+{
+  // delete d;		// not necessary yet
+}
+
+QString KRemoteFilename::decode(const QCString& name)
+{
+#ifdef CHECK_UTF8
+  if (codec->mibEnum() == 106 && !KStringHandler::isUtf8(name))
+    return QString::fromLatin1(name);
+#endif
+
+  QString result = codec->toUnicode(name);
+  if (codec->fromUnicode(result) != name)
+    // fallback in case of decoding failure
+    return QString::fromLatin1(name);
+
+  return result;
+}
+
+QCString KRemoteFilename::encode(const QString& name)
+{
+  QCString result = codec->fromUnicode(name);
+  if (codec->toUnicode(result) != name)
+    return name.latin1();
+ 
+  return result;
+}
+
+QCString KRemoteFilename::encode(const KURL& url)
+{
+  return encode(url.path());
+}
+
+QCString KRemoteFilename::directory(const KURL& url, bool ignore_trailing_slash)
+{
+  QString dir = url.directory(true, ignore_trailing_slash);
+
+  return encode(dir);
+}
+
+QCString KRemoteFilename::fileName(const KURL& url)
+{
+  return encode(url.fileName());
+}
+
+void KRemoteFilename::setEncoding(const char *name)
+{
+  // don't delete codecs
+
+  if (name)
+    codec = QTextCodec::codecForName(name);
+
+  if (codec == 0L)
+    codec = QTextCodec::codecForMib(1);
+
+  kdDebug() << k_funcinfo << "setting encoding " << codec->name() 
+	    << " for name=" << name << endl;
+}
+
+void KRemoteFilename::virtual_hook(int, void*)
+{
+}

["kio_ftp.patch" (text/x-diff)]

Index: ftp.cc
===================================================================
RCS file: /home/kde/kdelibs/kioslave/ftp/ftp.cc,v
retrieving revision 1.192
diff -u -3 -p -r1.192 ftp.cc
--- ftp.cc	24 Nov 2003 08:14:09 -0000	1.192
+++ ftp.cc	24 Nov 2003 14:33:20 -0000
@@ -59,6 +59,7 @@
 #include <ksocks.h>
 #include <kio/ioslave_defaults.h>
 #include <kio/slaveconfig.h>
+#include <kremotefilename.h>
 
 #define FTP_LOGIN   QString::fromLatin1("anonymous")
 #define FTP_PASSWD  QString::fromLatin1("anonymous@")
@@ -1085,7 +1086,7 @@ bool Ftp::ftpOpenCommand( const char *_c
 
   if ( !_path.isEmpty() ) {
     tmp += " ";
-    tmp += _path.ascii();
+    tmp += remoteEncoding()->encode(_path);
   }
 
   if ( !ftpSendCmd( tmp ) || rspbuf[0] != '1' ) {
@@ -1145,7 +1146,7 @@ bool Ftp::ftpCloseCommand()
 
 void Ftp::mkdir( const KURL & url, int permissions )
 {
-  QString path = url.path();
+  QString path = remoteEncoding()->encode(url);
   if (!m_bLoggedOn)
   {
       openConnection();
@@ -1159,7 +1160,7 @@ void Ftp::mkdir( const KURL & url, int p
   assert( m_bLoggedOn );
 
   QCString buf = "mkd ";
-  buf += path.latin1();
+  buf += remoteEncoding()->encode(path);
 
   if ( !ftpSendCmd( buf ) || rspbuf[0] != '2' )
   {
@@ -1200,7 +1201,7 @@ bool Ftp::ftpRename( const QString & src
   // TODO honor overwrite
   assert( m_bLoggedOn );
 
-  QCString filepath = src.ascii();
+  QCString filepath = remoteEncoding()->encode(src);
   int pos = filepath.findRev("/");
 
   QCString cwd_cmd = "CWD ";
@@ -1210,7 +1211,7 @@ bool Ftp::ftpRename( const QString & src
   from_cmd += filepath.mid(pos+1);
 
   QCString to_cmd = "RNTO ";
-  to_cmd += dst.ascii();
+  to_cmd += remoteEncoding()->encode(dst);
 
   if ( !ftpSendCmd( cwd_cmd ) || rspbuf[0] != '2')
       return false;
@@ -1226,7 +1227,6 @@ bool Ftp::ftpRename( const QString & src
 
 void Ftp::del( const KURL& url, bool isfile )
 {
-  QString path = url.path();
   if (!m_bLoggedOn)
   {
       openConnection();
@@ -1244,17 +1244,17 @@ void Ftp::del( const KURL& url, bool isf
     // When deleting a directory, we must exit from it first
     // The last command probably went into it (to stat it)
     QCString tmp = "cwd ";
-    tmp += url.directory().ascii();
+    tmp += remoteEncoding()->directory(url);
 
     (void) ftpSendCmd( tmp );
     // ignore errors
   }
 
   QCString cmd = isfile ? "DELE " : "RMD ";
-  cmd += path.ascii();
+  cmd += remoteEncoding()->encode(url);
 
   if ( !ftpSendCmd( cmd ) || rspbuf[0] != '2' )
-    error( ERR_CANNOT_DELETE, path );
+    error( ERR_CANNOT_DELETE, url.path() );
   else
     finished();
 }
@@ -1271,7 +1271,7 @@ bool Ftp::ftpChmod( const QString & path
   sprintf(buf, "%o ", permissions & 511 );
 
   cmd += buf;
-  cmd += path.ascii();
+  cmd += remoteEncoding()->encode(path);
 
   return ftpSendCmd( cmd ) && rspbuf[0] == '2';
 }
@@ -1463,7 +1463,7 @@ void Ftp::stat( const KURL &url)
   // 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)  QCString tmp = "cwd ";
-  tmp += path.latin1();
+  tmp += remoteEncoding()->encode(path);
   if ( !ftpSendCmd( tmp ) )
   {
     kdDebug(7102) << "stat: ftpSendCmd returned false" << endl;
@@ -1536,7 +1536,7 @@ void Ftp::stat( const KURL &url)
 
   // Now cwd the parent dir, to prepare for listing
   tmp = "cwd ";
-  tmp += parentDir.latin1();
+  tmp += remoteEncoding()->encode(parentDir);
   if ( !ftpSendCmd( tmp ) )
     // error already emitted
     return;
@@ -1721,7 +1721,7 @@ bool Ftp::ftpOpenDir( const QString & pa
   // We try to change to this directory first to see whether it really is a \
directory.  // (And also to follow symlinks)
   QCString tmp = "cwd ";
-  tmp += ( !path.isEmpty() ) ? path.latin1() : "/";
+  tmp += ( !path.isEmpty() ) ? remoteEncoding()->encode(path) : "/";
 
   if ( !ftpSendCmd( tmp ) || rspbuf[0] != '2' )
   {
@@ -1811,23 +1811,28 @@ FtpEntry* Ftp::ftpParseDir( char* buffer
                 if ((p_date_3 = strtok(NULL," ")) != 0)
                   if ((p_name = strtok(NULL,"\r\n")) != 0)
                   {
-                    if ( p_access[0] == 'l' )
-                    {
-                      tmp = p_name;
-                      int i = tmp.findRev( QString::fromLatin1(" -> ") );
-                      if ( i != -1 ) {
-                        de.link = p_name + i + 4;
-                        tmp.truncate( i );
-                        p_name = tmp.ascii();
-                      }
-                      else
-                        de.link = QString::null;
-                    }
-                    else
-                      de.link = QString::null;
 
-                    if (strchr(p_name, '/'))
-                       return 0L; // Don't trick us!
+		    {
+		       QCString 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 = QString::null;
+		       }
+		       else
+			 de.link = QString::null;
+
+		       if (tmp.find('/') != -1)
+			 return 0L; // 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.access = 0;
                     de.type = S_IFREG;
@@ -1880,13 +1885,9 @@ FtpEntry* Ftp::ftpParseDir( char* buffer
                     // maybe fromLocal8Bit would be better in some cases,
                     // but what proves that the ftp server is in the same encoding
                     // than the user ??
-                    de.owner    = QString::fromLatin1(p_owner);
-                    de.group    = QString::fromLatin1(p_group);
+                    de.owner    = remoteEncoding()->decode(p_owner);
+                    de.group    = remoteEncoding()->decode(p_group);
                     de.size     = STRTOLL(p_size, 0, 10);
-                    QCString tmp( p_name );
-                    // Some sites put more than one space between the date and the \
                name
-                    // e.g. ftp://ftp.uni-marburg.de/mirror/
-                    de.name     = QString::fromLatin1(tmp.stripWhiteSpace());
 
                     // Parsing the date is somewhat tricky
                     // Examples : "Oct  6 22:49", "May 13  1999"
@@ -1991,7 +1992,7 @@ void Ftp::get( const KURL & url )
   {
       // Not a file, or doesn't exist. We need to find out.
       QCString tmp = "cwd ";
-      tmp += url.path().latin1();
+      tmp += remoteEncoding()->encode(url);
       if ( ftpSendCmd( tmp ) && rspbuf[0] == '2' )
       {
           // Ok it's a dir in fact
@@ -2198,7 +2199,7 @@ void Ftp::put( const KURL& dest_url, int
   {
     if ( m_size == 0 ) {  // delete files with zero size
       QCString cmd = "DELE ";
-      cmd += dest_orig.ascii();
+      cmd += remoteEncoding()->encode(dest_orig);
       if ( !ftpSendCmd( cmd ) || rspbuf[0] != '2' )
       {
         error( ERR_CANNOT_DELETE_PARTIAL, dest_orig );
@@ -2220,7 +2221,7 @@ void Ftp::put( const KURL& dest_url, int
   } else if ( bMarkPartial && ftpSize( dest_part, 'I' ) ) { // file with extension \
.part exists  if ( m_size == 0 ) {  // delete files with zero size
       QCString cmd = "DELE ";
-      cmd += dest_part.ascii();
+      cmd += remoteEncoding()->encode(dest_part);
       if ( !ftpSendCmd( cmd ) || rspbuf[0] != '2' )
       {
         error( ERR_CANNOT_DELETE_PARTIAL, dest_orig );
@@ -2284,7 +2285,7 @@ void Ftp::put( const KURL& dest_url, int
            ( m_size < (unsigned long) config()->readNumEntry("MinimumKeepSize", \
DEFAULT_MINIMUM_KEEP_SIZE) ) )  {
         QCString cmd = "DELE ";
-        cmd += dest.ascii();
+        cmd += remoteEncoding()->encode(dest);
         (void) ftpSendCmd( cmd );
       }
     }
@@ -2337,7 +2338,7 @@ bool Ftp::ftpSize( const QString & path,
   }
 
   buf="SIZE ";
-  buf+=path.ascii();
+  buf+=remoteEncoding()->encode(path);
   if ( !ftpSendCmd( buf ) || rspbuf[0] !='2' ) {
     m_size = UnknownSize;
     return false;


["remoteencodingplugin.patch" (text/x-diff)]

--- /dev/null	1969-12-31 21:00:00.000000000 -0300
+++ remoteencodingplugin/Makefile.am	2003-11-24 00:08:11.000000000 -0200
@@ -0,0 +1,13 @@
+INCLUDES= -I$(top_srcdir)/libkonq $(all_includes)
+METASOURCES=AUTO
+
+kde_module_LTLIBRARIES = konq_remoteencoding.la
+konq_remoteencoding_la_SOURCES = kremoteencodingplugin.cpp
+konq_remoteencoding_la_LIBADD = $(top_builddir)/libkonq/libkonq.la
+konq_remoteencoding_la_LDFLAGS = -module $(KDE_PLUGIN)
+
+iconviewdir = $(kde_datadir)/konqiconview/kpartplugins
+iconview_DATA = kremoteencodingplugin.rc
+
+listviewdir = $(kde_datadir)/konqlistview/kpartplugins
+listview_DATA = kremoteencodingplugin.rc
--- /dev/null	1969-12-31 21:00:00.000000000 -0300
+++ remoteencodingplugin/kremoteencodingplugin.rc	2003-11-23 22:16:01.000000000 -0200
@@ -0,0 +1,8 @@
+<!DOCTYPE kpartplugin>
+<kpartplugin library="konq_remoteencoding">
+<MenuBar>
+ <Menu name="tools"><text>&amp;Tools</text>
+  <Action name="changeremoteencoding"/>
+ </Menu>
+</MenuBar>
+</kpartplugin>
--- /dev/null	1969-12-31 21:00:00.000000000 -0300
+++ remoteencodingplugin/kremoteencodingplugin.h	2003-11-24 11:47:23.000000000 -0200
@@ -0,0 +1,63 @@
+/*
+    Copyright (c) 2003 Thiago Macieira <thiago.macieira@kdemail.net>
+
+    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., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#ifndef REMOTEENCODING_PLUGIN_H
+#define REMOTEENCODING_PLUGIN_H
+
+#include <qstringlist.h>
+#include <kurl.h>
+#include <klibloader.h>
+#include <kparts/plugin.h>
+
+class KActionMenu;
+class KConfig;
+class KonqDirPart;
+
+class KRemoteEncodingPlugin: public KParts::Plugin
+{
+  Q_OBJECT
+public:
+  KRemoteEncodingPlugin(QObject * parent, const char *name,
+			const QStringList &);
+  ~KRemoteEncodingPlugin();
+
+protected slots:
+  void slotAboutToOpenURL();
+  void slotAboutToShow();
+  void slotItemSelected(int);
+  void slotReload();
+  void slotDefault();
+
+private:
+  void updateBrowser();
+  void loadSettings();
+  void fillMenu();
+  void updateMenu();
+
+  KonqDirPart *m_part;
+  KActionMenu *m_menu;
+  QStringList m_encodingDescriptions;
+  KURL m_currentURL;
+
+  bool m_loaded;
+  int m_idDefault;
+};
+
+#endif
--- /dev/null	1969-12-31 21:00:00.000000000 -0300
+++ remoteencodingplugin/kremoteencodingplugin.cpp	2003-11-24 11:49:49.000000000 -0200
@@ -0,0 +1,251 @@
+/*
+    Copyright (c) 2003 Thiago Macieira <thiago.macieira@kdemail.net>
+
+    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., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kcharsets.h>
+#include <kpopupmenu.h>
+#include <dcopclient.h>
+#include <kgenericfactory.h>
+#include <kprotocolmanager.h>
+#include <kprotocolinfo.h>
+#include <kio/slaveconfig.h>
+#include <konq_dirpart.h>
+#include <kparts/browserextension.h>
+
+#include "kremoteencodingplugin.h"
+
+#define DATA_KEY	QString::fromLatin1("Charset")
+
+KRemoteEncodingPlugin::KRemoteEncodingPlugin(QObject * parent,
+					     const char *name,
+					     const QStringList &)
+  : KParts::Plugin(parent, name), m_loaded(false), m_idDefault(0)
+{
+  m_menu = new KActionMenu(i18n("Select remote charset"), "charset",
+			   actionCollection(), "changeremoteencoding");
+  connect(m_menu->popupMenu(), SIGNAL(aboutToShow()),
+	  this, SLOT(slotAboutToShow()));
+  m_menu->setEnabled(false);
+  m_menu->setDelayed(false);
+
+  m_part = dynamic_cast<KonqDirPart*>(parent);
+  if (m_part)
+    // if parent is not a KonqDirPart, our menu will never show
+    QObject::connect(m_part, SIGNAL(aboutToOpenURL()), 
+		     this, SLOT(slotAboutToOpenURL()));
+}
+
+KRemoteEncodingPlugin::~KRemoteEncodingPlugin()
+{
+}
+
+void
+KRemoteEncodingPlugin::slotReload()
+{
+  loadSettings();
+}
+
+void
+KRemoteEncodingPlugin::loadSettings()
+{
+  m_loaded = true;
+
+  m_encodingDescriptions = KGlobal::charsets()->descriptiveEncodingNames();
+
+  fillMenu();
+}
+
+void
+KRemoteEncodingPlugin::slotAboutToOpenURL()
+{
+  KURL oldURL = m_currentURL;
+  m_currentURL = m_part->url();
+
+  if (m_currentURL.protocol() != oldURL.protocol())
+    {
+      // This plugin works on ftp, fish, etc.
+      // everything whose type is T_FILESYSTEM except for local files
+      if (!m_currentURL.isLocalFile() &&
+	  KProtocolInfo::outputType(m_currentURL) == KProtocolInfo::T_FILESYSTEM)
+	{
+	  m_menu->setEnabled(true);
+	  loadSettings();
+	}
+      else
+	m_menu->setEnabled(false);
+
+      return;
+    }
+
+  if (m_currentURL.host() != oldURL.host())
+    updateMenu();
+}
+
+void
+KRemoteEncodingPlugin::fillMenu()
+{
+  KPopupMenu *menu = m_menu->popupMenu();
+  menu->clear();
+
+  QStringList::ConstIterator it;
+  int count = 0;
+  for (it = m_encodingDescriptions.begin(); it != m_encodingDescriptions.end(); ++it)
+    menu->insertItem(*it, this, SLOT(slotItemSelected(int)), 0, ++count);
+  menu->insertSeparator();
+
+  menu->insertItem(i18n("Reload"), this, SLOT(slotReload()), 0, ++count);
+  menu->insertItem(i18n("Default"), this, SLOT(slotDefault()), 0, ++count);
+  m_idDefault = count;
+}
+
+void
+KRemoteEncodingPlugin::updateMenu()
+{
+  if (!m_loaded)
+    loadSettings();
+
+  // uncheck everything
+  for (unsigned i =  0; i < m_menu->popupMenu()->count(); i++)
+    m_menu->popupMenu()->setItemChecked(m_menu->popupMenu()->idAt(i), false);
+
+  QString charset = KIO::SlaveConfig::self()->configData(m_currentURL.protocol(), m_currentURL.host(),
+							 DATA_KEY);
+  if (!charset.isEmpty())
+    {
+      int id = 1;
+      QStringList::Iterator it;
+      for (it = m_encodingDescriptions.begin(); it != m_encodingDescriptions.end(); ++it, ++id)
+	if ((*it).find(charset) != -1)
+	  break;
+
+      kdDebug() << k_funcinfo << "URL=" << m_currentURL << " charset=" << charset << endl;
+
+      if (it == m_encodingDescriptions.end())
+	kdWarning() << k_funcinfo << "could not find entry for charset=" << charset << endl;
+      else
+	m_menu->popupMenu()->setItemChecked(id, true);
+    }
+  else
+    m_menu->popupMenu()->setItemChecked(m_idDefault, true);
+}
+
+void
+KRemoteEncodingPlugin::slotAboutToShow()
+{
+  if (!m_loaded)
+    loadSettings();
+  updateMenu();
+}
+
+void
+KRemoteEncodingPlugin::slotItemSelected(int id)
+{
+  KConfig config(("kio_" + m_currentURL.protocol() + "rc").latin1());
+  QString host = m_currentURL.host();
+
+  if (!m_menu->popupMenu()->isItemChecked(id))
+    {
+      QString charset = KGlobal::charsets()->encodingForName(m_encodingDescriptions[id - 1]);
+      
+      config.setGroup(host);
+      config.writeEntry(DATA_KEY, charset);
+      config.sync();
+
+      // Update the io-slaves...
+      updateBrowser();
+    }
+}
+
+void
+KRemoteEncodingPlugin::slotDefault()
+{
+  // We have no choice but delete all higher domain level
+  // settings here since it affects what will be matched.
+  KConfig config(("kio_" + m_currentURL.protocol() + "rc").latin1());
+
+  QStringList partList = QStringList::split('.', m_currentURL.host(), false);
+  if (!partList.isEmpty())
+    {
+      partList.remove(partList.begin());
+
+      QStringList domains;
+      // Remove the exact name match...
+      domains << m_currentURL.host();
+
+      while (partList.count())
+	{
+	  if (partList.count() == 2)
+	    if (partList[0].length() <= 2 && partList[1].length() == 2)
+	      break;
+
+	  if (partList.count() == 1)
+	    break;
+
+	  domains << partList.join(".");
+	  partList.remove(partList.begin());
+	}
+
+      for (QStringList::Iterator it = domains.begin(); it != domains.end();
+	   it++)
+	{
+	  kdDebug() << k_funcinfo << "Domain to remove: " << *it << endl;
+	  if (config.hasGroup(*it))
+	    config.deleteGroup(*it);
+	  else if (config.hasKey(*it))
+	    config.deleteEntry(*it);
+	}
+    }
+  config.sync();
+
+  // Update the io-slaves.
+  updateBrowser();
+}
+
+void
+KRemoteEncodingPlugin::updateBrowser()
+{
+  // Inform running io-slaves about the change...
+  DCOPClient *client = new DCOPClient();
+
+  if (!client->attach())
+    kdDebug() << "Can't connect with DCOP server." << endl;
+
+  QByteArray data;
+  QDataStream stream(data, IO_WriteOnly);
+  stream << QString::null;
+  client->send("*", "KIO::Scheduler", "reparseSlaveConfiguration(QString)",
+	       data);
+  delete client;
+
+  // Reload the page with the new charset
+  KParts::URLArgs args = m_part->extension()->urlArgs();
+  args.reload = true;
+  m_part->extension()->setURLArgs(args);
+  m_part->openURL(m_currentURL);
+}
+
+typedef KGenericFactory < KRemoteEncodingPlugin > KRemoteEncodingPluginFactory;
+K_EXPORT_COMPONENT_FACTORY(konq_remoteencoding,
+			   KRemoteEncodingPluginFactory("kremoteencodingplugin"))
+#include "kremoteencodingplugin.moc"

[Attachment #8 (application/pgp-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic