global.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2000 David Faure <faure@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include <config.h>
00020 
00021 #include <sys/types.h>
00022 #include <sys/wait.h>
00023 #include <sys/uio.h>
00024 
00025 #include <assert.h>
00026 #include <signal.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <stdio.h>
00031 
00032 #include "kio/global.h"
00033 #include "kio/job.h"
00034 
00035 #include <kdebug.h>
00036 #include <klocale.h>
00037 #include <kglobal.h>
00038 #include <kprotocolmanager.h>
00039 #include <kde_file.h>
00040 
00041 #ifdef HAVE_VOLMGT
00042 #include <volmgt.h>
00043 #endif
00044 
00045 KIO_EXPORT QString KIO::convertSizeWithBytes( KIO::filesize_t size )
00046 {
00047     if ( size >= 1024 )
00048         return convertSize( size ) + " (" + i18n( "%1 B" ).arg( KGlobal::locale()->formatNumber(size, 0) ) + ")";
00049     else
00050     return convertSize( size );
00051 }
00052 
00053 KIO_EXPORT QString KIO::convertSize( KIO::filesize_t size )
00054 {
00055     double fsize = size;
00056     QString s;
00057     // Giga-byte
00058     if ( size >= 1073741824 )
00059     {
00060         fsize /= 1073741824.0;
00061         if ( fsize > 1024 ) // Tera-byte
00062             s = i18n( "%1 TB" ).arg( KGlobal::locale()->formatNumber(fsize / 1024.0, 1));
00063         else
00064             s = i18n( "%1 GB" ).arg( KGlobal::locale()->formatNumber(fsize, 1));
00065     }
00066     // Mega-byte
00067     else if ( size >= 1048576 )
00068     {
00069         fsize /= 1048576.0;
00070         s = i18n( "%1 MB" ).arg( KGlobal::locale()->formatNumber(fsize, 1));
00071     }
00072     // Kilo-byte
00073     else if ( size >= 1024 )
00074     {
00075         fsize /= 1024.0;
00076         s = i18n( "%1 KB" ).arg( KGlobal::locale()->formatNumber(fsize, 1));
00077     }
00078     // Just byte
00079     else if ( size > 0 )
00080     {
00081         s = i18n( "%1 B" ).arg( KGlobal::locale()->formatNumber(fsize, 0));
00082     }
00083     // Nothing
00084     else
00085     {
00086         s = i18n( "0 B" );
00087     }
00088     return s;
00089 }
00090 
00091 KIO_EXPORT QString KIO::convertSizeFromKB( KIO::filesize_t kbSize )
00092 {
00093     return convertSize(kbSize * 1024);
00094 }
00095 
00096 KIO_EXPORT QString KIO::number( KIO::filesize_t size )
00097 {
00098     char charbuf[256];
00099     sprintf(charbuf, "%lld", size);
00100     return QString::fromLatin1(charbuf);
00101 }
00102 
00103 KIO_EXPORT unsigned int KIO::calculateRemainingSeconds( KIO::filesize_t totalSize,
00104                                                         KIO::filesize_t processedSize, KIO::filesize_t speed )
00105 {
00106   if ( (speed != 0) && (totalSize != 0) )
00107     return ( totalSize - processedSize ) / speed;
00108   else
00109     return 0;
00110 }
00111 
00112 KIO_EXPORT QString KIO::convertSeconds( unsigned int seconds )
00113 {
00114   unsigned int days  = seconds / 86400;
00115   unsigned int hours = (seconds - (days * 86400)) / 3600;
00116   unsigned int mins  = (seconds - (days * 86400) - (hours * 3600)) / 60;
00117   seconds            = (seconds - (days * 86400) - (hours * 3600) - (mins * 60));
00118 
00119   const QTime time(hours, mins, seconds);
00120   const QString timeStr( KGlobal::locale()->formatTime(time, true /*with seconds*/, true /*duration*/) );
00121   if ( days > 0 )
00122     return i18n("1 day %1", "%n days %1", days).arg(timeStr);
00123   else
00124     return timeStr;
00125 }
00126 
00127 KIO_EXPORT QTime KIO::calculateRemaining( KIO::filesize_t totalSize, KIO::filesize_t processedSize, KIO::filesize_t speed )
00128 {
00129   QTime remainingTime;
00130 
00131   if ( speed != 0 ) {
00132     KIO::filesize_t secs;
00133     if ( totalSize == 0 ) {
00134       secs = 0;
00135     } else {
00136       secs = ( totalSize - processedSize ) / speed;
00137     }
00138     if (secs >= (24*60*60)) // Limit to 23:59:59
00139        secs = (24*60*60)-1;
00140     int hr = secs / ( 60 * 60 );
00141     int mn = ( secs - hr * 60 * 60 ) / 60;
00142     int sc = ( secs - hr * 60 * 60 - mn * 60 );
00143 
00144     remainingTime.setHMS( hr, mn, sc );
00145   }
00146 
00147   return remainingTime;
00148 }
00149 
00150 KIO_EXPORT QString KIO::itemsSummaryString(uint items, uint files, uint dirs, KIO::filesize_t size, bool showSize)
00151 {
00152     QString text = items == 0 ? i18n( "No Items" ) : i18n( "One Item", "%n Items", items );
00153     text += " - ";
00154     text += files == 0 ? i18n( "No Files" ) : i18n( "One File", "%n Files", files );
00155     if ( showSize && files > 0 )
00156     {
00157         text += " ";
00158         text += i18n("(%1 Total)").arg(KIO::convertSize( size ) );
00159     }
00160     text += " - ";
00161     text += dirs == 0 ? i18n( "No Folders" ) : i18n("One Folder", "%n Folders", dirs);
00162     return text;
00163 }
00164 
00165 KIO_EXPORT QString KIO::encodeFileName( const QString & _str )
00166 {
00167   QString str( _str );
00168 
00169   int i = 0;
00170   while ( ( i = str.find( "%", i ) ) != -1 )
00171   {
00172     str.replace( i, 1, "%%");
00173     i += 2;
00174   }
00175   while ( ( i = str.find( "/" ) ) != -1 )
00176       str.replace( i, 1, "%2f");
00177   return str;
00178 }
00179 
00180 KIO_EXPORT QString KIO::decodeFileName( const QString & _str )
00181 {
00182   QString str;
00183 
00184   unsigned int i = 0;
00185   for ( ; i < _str.length() ; ++i )
00186   {
00187     if ( _str[i]=='%' )
00188     {
00189       if ( _str[i+1]=='%' ) // %% -> %
00190       {
00191         str.append('%');
00192         ++i;
00193       }
00194       else if ( _str[i+1]=='2' && (i+2<_str.length()) && _str[i+2].lower()=='f' ) // %2f -> /
00195       {
00196         str.append('/');
00197         i += 2;
00198       }
00199       else
00200         str.append('%');
00201     } else
00202       str.append(_str[i]);
00203   }
00204 
00205   return str;
00206 }
00207 
00208 KIO_EXPORT QString KIO::Job::errorString() const
00209 {
00210   return KIO::buildErrorString(m_error, m_errorText);
00211 }
00212 
00213 KIO_EXPORT QString KIO::buildErrorString(int errorCode, const QString &errorText)
00214 {
00215   QString result;
00216 
00217   switch( errorCode )
00218     {
00219     case  KIO::ERR_CANNOT_OPEN_FOR_READING:
00220       result = i18n( "Could not read %1." ).arg( errorText );
00221       break;
00222     case  KIO::ERR_CANNOT_OPEN_FOR_WRITING:
00223       result = i18n( "Could not write to %1." ).arg( errorText );
00224       break;
00225     case  KIO::ERR_CANNOT_LAUNCH_PROCESS:
00226       result = i18n( "Could not start process %1." ).arg( errorText );
00227       break;
00228     case  KIO::ERR_INTERNAL:
00229       result = i18n( "Internal Error\nPlease send a full bug report at http://bugs.kde.org\n%1" ).arg( errorText );
00230       break;
00231     case  KIO::ERR_MALFORMED_URL:
00232       result = i18n( "Malformed URL %1." ).arg( errorText );
00233       break;
00234     case  KIO::ERR_UNSUPPORTED_PROTOCOL:
00235       result = i18n( "The protocol %1 is not supported." ).arg( errorText );
00236       break;
00237     case  KIO::ERR_NO_SOURCE_PROTOCOL:
00238       result = i18n( "The protocol %1 is only a filter protocol.").arg( errorText );
00239       break;
00240     case  KIO::ERR_UNSUPPORTED_ACTION:
00241       result = errorText;
00242 //       result = i18n( "Unsupported action %1" ).arg( errorText );
00243       break;
00244     case  KIO::ERR_IS_DIRECTORY:
00245       result = i18n( "%1 is a folder, but a file was expected." ).arg( errorText );
00246       break;
00247     case  KIO::ERR_IS_FILE:
00248       result = i18n( "%1 is a file, but a folder was expected." ).arg( errorText );
00249       break;
00250     case  KIO::ERR_DOES_NOT_EXIST:
00251       result = i18n( "The file or folder %1 does not exist." ).arg( errorText );
00252       break;
00253     case  KIO::ERR_FILE_ALREADY_EXIST:
00254       result = i18n( "A file named %1 already exists." ).arg( errorText );
00255       break;
00256     case  KIO::ERR_DIR_ALREADY_EXIST:
00257       result = i18n( "A folder named %1 already exists." ).arg( errorText );
00258       break;
00259     case  KIO::ERR_UNKNOWN_HOST:
00260       result = errorText.isEmpty() ? i18n( "No hostname specified." ) : i18n( "Unknown host %1" ).arg( errorText );
00261       break;
00262     case  KIO::ERR_ACCESS_DENIED:
00263       result = i18n( "Access denied to %1." ).arg( errorText );
00264       break;
00265     case  KIO::ERR_WRITE_ACCESS_DENIED:
00266       result = i18n( "Access denied.\nCould not write to %1." ).arg( errorText );
00267       break;
00268     case  KIO::ERR_CANNOT_ENTER_DIRECTORY:
00269       result = i18n( "Could not enter folder %1." ).arg( errorText );
00270       break;
00271     case  KIO::ERR_PROTOCOL_IS_NOT_A_FILESYSTEM:
00272       result = i18n( "The protocol %1 does not implement a folder service." ).arg( errorText );
00273       break;
00274     case  KIO::ERR_CYCLIC_LINK:
00275       result = i18n( "Found a cyclic link in %1." ).arg( errorText );
00276       break;
00277     case  KIO::ERR_USER_CANCELED:
00278       // Do nothing in this case. The user doesn't need to be told what he just did.
00279       break;
00280     case  KIO::ERR_CYCLIC_COPY:
00281       result = i18n( "Found a cyclic link while copying %1." ).arg( errorText );
00282       break;
00283     case  KIO::ERR_COULD_NOT_CREATE_SOCKET:
00284       result = i18n( "Could not create socket for accessing %1." ).arg( errorText );
00285       break;
00286     case  KIO::ERR_COULD_NOT_CONNECT:
00287       result = i18n( "Could not connect to host %1." ).arg( errorText.isEmpty() ? QString::fromLatin1("localhost") : errorText );
00288       break;
00289     case  KIO::ERR_CONNECTION_BROKEN:
00290       result = i18n( "Connection to host %1 is broken." ).arg( errorText );
00291       break;
00292     case  KIO::ERR_NOT_FILTER_PROTOCOL:
00293       result = i18n( "The protocol %1 is not a filter protocol." ).arg( errorText );
00294       break;
00295     case  KIO::ERR_COULD_NOT_MOUNT:
00296       result = i18n( "Could not mount device.\nThe reported error was:\n%1" ).arg( errorText );
00297       break;
00298     case  KIO::ERR_COULD_NOT_UNMOUNT:
00299       result = i18n( "Could not unmount device.\nThe reported error was:\n%1" ).arg( errorText );
00300       break;
00301     case  KIO::ERR_COULD_NOT_READ:
00302       result = i18n( "Could not read file %1." ).arg( errorText );
00303       break;
00304     case  KIO::ERR_COULD_NOT_WRITE:
00305       result = i18n( "Could not write to file %1." ).arg( errorText );
00306       break;
00307     case  KIO::ERR_COULD_NOT_BIND:
00308       result = i18n( "Could not bind %1." ).arg( errorText );
00309       break;
00310     case  KIO::ERR_COULD_NOT_LISTEN:
00311       result = i18n( "Could not listen %1." ).arg( errorText );
00312       break;
00313     case  KIO::ERR_COULD_NOT_ACCEPT:
00314       result = i18n( "Could not accept %1." ).arg( errorText );
00315       break;
00316     case  KIO::ERR_COULD_NOT_LOGIN:
00317       result = errorText;
00318       break;
00319     case  KIO::ERR_COULD_NOT_STAT:
00320       result = i18n( "Could not access %1." ).arg( errorText );
00321       break;
00322     case  KIO::ERR_COULD_NOT_CLOSEDIR:
00323       result = i18n( "Could not terminate listing %1." ).arg( errorText );
00324       break;
00325     case  KIO::ERR_COULD_NOT_MKDIR:
00326       result = i18n( "Could not make folder %1." ).arg( errorText );
00327       break;
00328     case  KIO::ERR_COULD_NOT_RMDIR:
00329       result = i18n( "Could not remove folder %1." ).arg( errorText );
00330       break;
00331     case  KIO::ERR_CANNOT_RESUME:
00332       result = i18n( "Could not resume file %1." ).arg( errorText );
00333       break;
00334     case  KIO::ERR_CANNOT_RENAME:
00335       result = i18n( "Could not rename file %1." ).arg( errorText );
00336       break;
00337     case  KIO::ERR_CANNOT_CHMOD:
00338       result = i18n( "Could not change permissions for %1." ).arg( errorText );
00339       break;
00340     case  KIO::ERR_CANNOT_DELETE:
00341       result = i18n( "Could not delete file %1." ).arg( errorText );
00342       break;
00343     case  KIO::ERR_SLAVE_DIED:
00344       result = i18n( "The process for the %1 protocol died unexpectedly." ).arg( errorText );
00345       break;
00346     case  KIO::ERR_OUT_OF_MEMORY:
00347       result = i18n( "Error. Out of memory.\n%1" ).arg( errorText );
00348       break;
00349     case  KIO::ERR_UNKNOWN_PROXY_HOST:
00350       result = i18n( "Unknown proxy host\n%1" ).arg( errorText );
00351       break;
00352     case  KIO::ERR_COULD_NOT_AUTHENTICATE:
00353       result = i18n( "Authorization failed, %1 authentication not supported" ).arg( errorText );
00354       break;
00355     case  KIO::ERR_ABORTED:
00356       result = i18n( "User canceled action\n%1" ).arg( errorText );
00357       break;
00358     case  KIO::ERR_INTERNAL_SERVER:
00359       result = i18n( "Internal error in server\n%1" ).arg( errorText );
00360       break;
00361     case  KIO::ERR_SERVER_TIMEOUT:
00362       result = i18n( "Timeout on server\n%1" ).arg( errorText );
00363       break;
00364     case  KIO::ERR_UNKNOWN:
00365       result = i18n( "Unknown error\n%1" ).arg( errorText );
00366       break;
00367     case  KIO::ERR_UNKNOWN_INTERRUPT:
00368       result = i18n( "Unknown interrupt\n%1" ).arg( errorText );
00369       break;
00370 /*
00371     case  KIO::ERR_CHECKSUM_MISMATCH:
00372       if (errorText)
00373         result = i18n( "Warning: MD5 Checksum for %1 does not match checksum returned from server" ).arg(errorText);
00374       else
00375         result = i18n( "Warning: MD5 Checksum for %1 does not match checksum returned from server" ).arg("document");
00376       break;
00377 */
00378     case KIO::ERR_CANNOT_DELETE_ORIGINAL:
00379       result = i18n( "Could not delete original file %1.\nPlease check permissions." ).arg( errorText );
00380       break;
00381     case KIO::ERR_CANNOT_DELETE_PARTIAL:
00382       result = i18n( "Could not delete partial file %1.\nPlease check permissions." ).arg( errorText );
00383       break;
00384     case KIO::ERR_CANNOT_RENAME_ORIGINAL:
00385       result = i18n( "Could not rename original file %1.\nPlease check permissions." ).arg( errorText );
00386       break;
00387     case KIO::ERR_CANNOT_RENAME_PARTIAL:
00388       result = i18n( "Could not rename partial file %1.\nPlease check permissions." ).arg( errorText );
00389       break;
00390     case KIO::ERR_CANNOT_SYMLINK:
00391       result = i18n( "Could not create symlink %1.\nPlease check permissions." ).arg( errorText );
00392       break;
00393     case KIO::ERR_NO_CONTENT:
00394       result = errorText;
00395       break;
00396     case KIO::ERR_DISK_FULL:
00397       result = i18n( "Could not write file %1.\nDisk full." ).arg( errorText );
00398       break;
00399     case KIO::ERR_IDENTICAL_FILES:
00400       result = i18n( "The source and destination are the same file.\n%1" ).arg( errorText );
00401       break;
00402     case KIO::ERR_SLAVE_DEFINED:
00403       result = errorText;
00404       break;
00405     case KIO::ERR_UPGRADE_REQUIRED:
00406       result = i18n( "%1 is required by the server, but is not available." ).arg(errorText);
00407       break;
00408     case KIO::ERR_POST_DENIED:
00409       result = i18n( "Access to restricted port in POST denied.");
00410       break;
00411     default:
00412       result = i18n( "Unknown error code %1\n%2\nPlease send a full bug report at http://bugs.kde.org." ).arg( errorCode ).arg( errorText );
00413       break;
00414     }
00415 
00416   return result;
00417 }
00418 
00419 KIO_EXPORT QString KIO::unsupportedActionErrorString(const QString &protocol, int cmd) {
00420   switch (cmd) {
00421     case CMD_CONNECT:
00422       return i18n("Opening connections is not supported with the protocol %1." ).arg(protocol);
00423     case CMD_DISCONNECT:
00424       return i18n("Closing connections is not supported with the protocol %1." ).arg(protocol);
00425     case CMD_STAT:
00426       return i18n("Accessing files is not supported with the protocol %1.").arg(protocol);
00427     case CMD_PUT:
00428       return i18n("Writing to %1 is not supported.").arg(protocol);
00429     case CMD_SPECIAL:
00430       return i18n("There are no special actions available for protocol %1.").arg(protocol);
00431     case CMD_LISTDIR:
00432       return i18n("Listing folders is not supported for protocol %1.").arg(protocol);
00433     case CMD_GET:
00434       return i18n("Retrieving data from %1 is not supported.").arg(protocol);
00435     case CMD_MIMETYPE:
00436       return i18n("Retrieving mime type information from %1 is not supported.").arg(protocol);
00437     case CMD_RENAME:
00438       return i18n("Renaming or moving files within %1 is not supported.").arg(protocol);
00439     case CMD_SYMLINK:
00440       return i18n("Creating symlinks is not supported with protocol %1.").arg(protocol);
00441     case CMD_COPY:
00442       return i18n("Copying files within %1 is not supported.").arg(protocol);
00443     case CMD_DEL:
00444       return i18n("Deleting files from %1 is not supported.").arg(protocol);
00445     case CMD_MKDIR:
00446       return i18n("Creating folders is not supported with protocol %1.").arg(protocol);
00447     case CMD_CHMOD:
00448       return i18n("Changing the attributes of files is not supported with protocol %1.").arg(protocol);
00449     case CMD_SUBURL:
00450       return i18n("Using sub-URLs with %1 is not supported.").arg(protocol);
00451     case CMD_MULTI_GET:
00452       return i18n("Multiple get is not supported with protocol %1.").arg(protocol);
00453     default:
00454       return i18n("Protocol %1 does not support action %2.").arg(protocol).arg(cmd);
00455   }/*end switch*/
00456 }
00457 
00458 KIO_EXPORT QStringList KIO::Job::detailedErrorStrings( const KURL *reqUrl /*= 0L*/,
00459                                             int method /*= -1*/ ) const
00460 {
00461   QString errorName, techName, description, ret2;
00462   QStringList causes, solutions, ret;
00463 
00464   QByteArray raw = rawErrorDetail( m_error, m_errorText, reqUrl, method );
00465   QDataStream stream(raw, IO_ReadOnly);
00466 
00467   stream >> errorName >> techName >> description >> causes >> solutions;
00468 
00469   QString url, protocol, datetime;
00470   if ( reqUrl ) {
00471     url = reqUrl->htmlURL();
00472     protocol = reqUrl->protocol();
00473   } else {
00474     url = i18n( "(unknown)" );
00475   }
00476 
00477   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
00478                                                 false );
00479 
00480   ret << errorName;
00481   ret << QString::fromLatin1( "<qt><p><b>" ) + errorName +
00482          QString::fromLatin1( "</b></p><p>" ) + description +
00483          QString::fromLatin1( "</p>" );
00484   ret2 = QString::fromLatin1( "<qt><p>" );
00485   if ( !techName.isEmpty() )
00486     ret2 += i18n( "<b>Technical reason</b>: " ) + techName + QString::fromLatin1( "</p>" );
00487   ret2 += i18n( "</p><p><b>Details of the request</b>:" );
00488   ret2 += i18n( "</p><ul><li>URL: %1</li>" ).arg( url );
00489   if ( !protocol.isEmpty() ) {
00490     ret2 += i18n( "<li>Protocol: %1</li>" ).arg( protocol );
00491   }
00492   ret2 += i18n( "<li>Date and time: %1</li>" ).arg( datetime );
00493   ret2 += i18n( "<li>Additional information: %1</li></ul>" ).arg( m_errorText );
00494   if ( !causes.isEmpty() ) {
00495     ret2 += i18n( "<p><b>Possible causes</b>:</p><ul><li>" );
00496     ret2 += causes.join( "</li><li>" );
00497     ret2 += QString::fromLatin1( "</li></ul>" );
00498   }
00499   if ( !solutions.isEmpty() ) {
00500     ret2 += i18n( "<p><b>Possible solutions</b>:</p><ul><li>" );
00501     ret2 += solutions.join( "</li><li>" );
00502     ret2 += QString::fromLatin1( "</li></ul>" );
00503   }
00504   ret << ret2;
00505   return ret;
00506 }
00507 
00508 KIO_EXPORT QByteArray KIO::rawErrorDetail(int errorCode, const QString &errorText,
00509                                const KURL *reqUrl /*= 0L*/, int /*method = -1*/ )
00510 {
00511   QString url, host, protocol, datetime, domain, path, dir, filename;
00512   bool isSlaveNetwork = false;
00513   if ( reqUrl ) {
00514     url = reqUrl->prettyURL();
00515     host = reqUrl->host();
00516     protocol = reqUrl->protocol();
00517 
00518     if ( host.left(4) == "www." )
00519       domain = host.mid(4);
00520     else
00521       domain = host;
00522 
00523     path = reqUrl->path(1);
00524     filename = reqUrl->fileName();
00525     dir =  path + filename;
00526 
00527     // detect if protocol is a network protocol...
00528     // add your hacks here...
00529     if ( protocol == "http" ||
00530          protocol == "https" ||
00531          protocol == "ftp" ||
00532          protocol == "sftp" ||
00533          protocol == "webdav" ||
00534          protocol == "webdavs" ||
00535          protocol == "finger" ||
00536          protocol == "fish" ||
00537          protocol == "gopher" ||
00538          protocol == "imap" ||
00539          protocol == "imaps" ||
00540          protocol == "lan" ||
00541          protocol == "ldap" ||
00542          protocol == "mailto" ||
00543          protocol == "news" ||
00544          protocol == "nntp" ||
00545          protocol == "pop3" ||
00546          protocol == "pop3s" ||
00547          protocol == "smtp" ||
00548          protocol == "smtps" ||
00549          protocol == "telnet"
00550         ) {
00551       isSlaveNetwork = false;
00552     }
00553   } else {
00554     // assume that the errorText has the location we are interested in
00555     url = host = domain = path = filename = dir = errorText;
00556     protocol = i18n( "(unknown)" );
00557   }
00558 
00559   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
00560                                                 false );
00561 
00562   QString errorName, techName, description;
00563   QStringList causes, solutions;
00564 
00565   // c == cause, s == solution
00566   QString sSysadmin = i18n( "Contact your appropriate computer support system, "
00567     "whether the system administrator, or technical support group for further "
00568     "assistance." );
00569   QString sServeradmin = i18n( "Contact the administrator of the server "
00570     "for further assistance." );
00571   // FIXME active link to permissions dialog
00572   QString sAccess = i18n( "Check your access permissions on this resource." );
00573   QString cAccess = i18n( "Your access permissions may be inadequate to "
00574     "perform the requested operation on this resource." );
00575   QString cLocked = i18n( "The file may be in use (and thus locked) by "
00576     "another user or application." );
00577   QString sQuerylock = i18n( "Check to make sure that no other "
00578     "application or user is using the file or has locked the file." );
00579   QString cHardware = i18n( "Although unlikely, a hardware error may have "
00580     "occurred." );
00581   QString cBug = i18n( "You may have encountered a bug in the program." );
00582   QString cBuglikely = i18n( "This is most likely to be caused by a bug in the "
00583     "program. Please consider submitting a full bug report as detailed below." );
00584   QString sUpdate = i18n( "Update your software to the latest version. "
00585     "Your distribution should provide tools to update your software." );
00586   QString sBugreport = i18n( "When all else fails, please consider helping the "
00587     "KDE team or the third party maintainer of this software by submitting a "
00588     "high quality bug report. If the software is provided by a third party, "
00589     "please contact them directly. Otherwise, first look to see if "
00590     "the same bug has been submitted by someone else by searching at the "
00591     "<a href=\"http://bugs.kde.org/\">KDE bug reporting website</a>. If not, take "
00592     "note of the details given above, and include them in your bug report, along "
00593     "with as many other details as you think might help." );
00594   QString cNetwork = i18n( "There may have been a problem with your network "
00595     "connection." );
00596   // FIXME netconf kcontrol link
00597   QString cNetconf = i18n( "There may have been a problem with your network "
00598     "configuration. If you have been accessing the Internet with no problems "
00599     "recently, this is unlikely." );
00600   QString cNetpath = i18n( "There may have been a problem at some point along "
00601     "the network path between the server and this computer." );
00602   QString sTryagain = i18n( "Try again, either now or at a later time." );
00603   QString cProtocol = i18n( "A protocol error or incompatibility may have occurred." );
00604   QString sExists = i18n( "Ensure that the resource exists, and try again." );
00605   QString cExists = i18n( "The specified resource may not exist." );
00606   QString cTypo = i18n( "You may have incorrectly typed the location." );
00607   QString sTypo = i18n( "Double-check that you have entered the correct location "
00608     "and try again." );
00609   QString sNetwork = i18n( "Check your network connection status." );
00610 
00611   switch( errorCode ) {
00612     case  KIO::ERR_CANNOT_OPEN_FOR_READING:
00613       errorName = i18n( "Cannot Open Resource For Reading" );
00614       description = i18n( "This means that the contents of the requested file "
00615         "or folder <strong>%1</strong> could not be retrieved, as read "
00616         "access could not be obtained." ).arg( dir );
00617       causes << i18n( "You may not have permissions to read the file or open "
00618         "the folder.") << cLocked << cHardware;
00619       solutions << sAccess << sQuerylock << sSysadmin;
00620       break;
00621 
00622     case  KIO::ERR_CANNOT_OPEN_FOR_WRITING:
00623       errorName = i18n( "Cannot Open Resource For Writing" );
00624       description = i18n( "This means that the file, <strong>%1</strong>, could "
00625         "not be written to as requested, because access with permission to "
00626         "write could not be obtained." ).arg( filename );
00627       causes << cAccess << cLocked << cHardware;
00628       solutions << sAccess << sQuerylock << sSysadmin;
00629       break;
00630 
00631     case  KIO::ERR_CANNOT_LAUNCH_PROCESS:
00632       errorName = i18n( "Cannot Initiate the %1 Protocol" ).arg( protocol );
00633       techName = i18n( "Unable to Launch Process" );
00634       description = i18n( "The program on your computer which provides access "
00635         "to the <strong>%1</strong> protocol could not be started. This is "
00636         "usually due to technical reasons." ).arg( protocol );
00637       causes << i18n( "The program which provides compatibility with this "
00638         "protocol may not have been updated with your last update of KDE. "
00639         "This can cause the program to be incompatible with the current version "
00640         "and thus not start." ) << cBug;
00641       solutions << sUpdate << sSysadmin;
00642       break;
00643 
00644     case  KIO::ERR_INTERNAL:
00645       errorName = i18n( "Internal Error" );
00646       description = i18n( "The program on your computer which provides access "
00647         "to the <strong>%1</strong> protocol has reported an internal error." )
00648         .arg( protocol );
00649       causes << cBuglikely;
00650       solutions << sUpdate << sBugreport;
00651       break;
00652 
00653     case  KIO::ERR_MALFORMED_URL:
00654       errorName = i18n( "Improperly Formatted URL" );
00655       description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource "
00656         "<strong>L</strong>ocator (URL) that you entered was not properly "
00657         "formatted. The format of a URL is generally as follows:"
00658         "<blockquote><strong>protocol://user:password@www.example.org:port/folder/"
00659         "filename.extension?query=value</strong></blockquote>" );
00660       solutions << sTypo;
00661       break;
00662 
00663     case  KIO::ERR_UNSUPPORTED_PROTOCOL:
00664       errorName = i18n( "Unsupported Protocol %1" ).arg( protocol );
00665       description = i18n( "The protocol <strong>%1</strong> is not supported "
00666         "by the KDE programs currently installed on this computer." )
00667         .arg( protocol );
00668       causes << i18n( "The requested protocol may not be supported." )
00669         << i18n( "The versions of the %1 protocol supported by this computer and "
00670         "the server may be incompatible." ).arg( protocol );
00671       solutions << i18n( "You may perform a search on the Internet for a KDE "
00672         "program (called a kioslave or ioslave) which supports this protocol. "
00673         "Places to search include <a href=\"http://kde-apps.org/\">"
00674         "http://kde-apps.org/</a> and <a href=\"http://freshmeat.net/\">"
00675         "http://freshmeat.net/</a>." )
00676         << sUpdate << sSysadmin;
00677       break;
00678 
00679     case  KIO::ERR_NO_SOURCE_PROTOCOL:
00680       errorName = i18n( "URL Does Not Refer to a Resource." );
00681       techName = i18n( "Protocol is a Filter Protocol" );
00682       description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource "
00683         "<strong>L</strong>ocator (URL) that you entered did not refer to a "
00684         "specific resource." );
00685       causes << i18n( "KDE is able to communicate through a protocol within a "
00686         "protocol; the protocol specified is only for use in such situations, "
00687         "however this is not one of these situations. This is a rare event, and "
00688         "is likely to indicate a programming error." );
00689       solutions << sTypo;
00690       break;
00691 
00692     case  KIO::ERR_UNSUPPORTED_ACTION:
00693       errorName = i18n( "Unsupported Action: %1" ).arg( errorText );
00694       description = i18n( "The requested action is not supported by the KDE "
00695         "program which is implementing the <strong>%1</strong> protocol." )
00696         .arg( protocol );
00697       causes << i18n( "This error is very much dependent on the KDE program. The "
00698         "additional information should give you more information than is available "
00699         "to the KDE input/output architecture." );
00700       solutions << i18n( "Attempt to find another way to accomplish the same "
00701         "outcome." );
00702       break;
00703 
00704     case  KIO::ERR_IS_DIRECTORY:
00705       errorName = i18n( "File Expected" );
00706       description = i18n( "The request expected a file, however the "
00707         "folder <strong>%1</strong> was found instead." ).arg( dir );
00708       causes << i18n( "This may be an error on the server side." ) << cBug;
00709       solutions << sUpdate << sSysadmin;
00710       break;
00711 
00712     case  KIO::ERR_IS_FILE:
00713       errorName = i18n( "Folder Expected" );
00714       description = i18n( "The request expected a folder, however "
00715         "the file <strong>%1</strong> was found instead." ).arg( filename );
00716       causes << cBug;
00717       solutions << sUpdate << sSysadmin;
00718       break;
00719 
00720     case  KIO::ERR_DOES_NOT_EXIST:
00721       errorName = i18n( "File or Folder Does Not Exist" );
00722       description = i18n( "The specified file or folder <strong>%1</strong> "
00723         "does not exist." ).arg( dir );
00724       causes << cBug;
00725       solutions << sUpdate << sSysadmin;
00726       break;
00727 
00728     case  KIO::ERR_FILE_ALREADY_EXIST:
00729       errorName = i18n( "File Already Exists" );
00730       description = i18n( "The requested file could not be created because a "
00731         "file with the same name already exists." );
00732       solutions << i18n ( "Try moving the current file out of the way first, "
00733         "and then try again." )
00734         << i18n ( "Delete the current file and try again." )
00735         << i18n( "Choose an alternate filename for the new file." );
00736       break;
00737 
00738     case  KIO::ERR_DIR_ALREADY_EXIST:
00739       errorName = i18n( "Folder Already Exists" );
00740       description = i18n( "The requested folder could not be created because "
00741         "a folder with the same name already exists." );
00742       solutions << i18n( "Try moving the current folder out of the way first, "
00743         "and then try again." )
00744         << i18n( "Delete the current folder and try again." )
00745         << i18n( "Choose an alternate name for the new folder." );
00746       break;
00747 
00748     case  KIO::ERR_UNKNOWN_HOST:
00749       errorName = i18n( "Unknown Host" );
00750       description = i18n( "An unknown host error indicates that the server with "
00751         "the requested name, <strong>%1</strong>, could not be "
00752         "located on the Internet." ).arg( host );
00753       causes << i18n( "The name that you typed, %1, may not exist: it may be "
00754         "incorrectly typed." ).arg( host )
00755         << cNetwork << cNetconf;
00756       solutions << sNetwork << sSysadmin;
00757       break;
00758 
00759     case  KIO::ERR_ACCESS_DENIED:
00760       errorName = i18n( "Access Denied" );
00761       description = i18n( "Access was denied to the specified resource, "
00762         "<strong>%1</strong>." ).arg( url );
00763       causes << i18n( "You may have supplied incorrect authentication details or "
00764         "none at all." )
00765         << i18n( "Your account may not have permission to access the "
00766         "specified resource." );
00767       solutions << i18n( "Retry the request and ensure your authentication details "
00768         "are entered correctly." ) << sSysadmin;
00769       if ( !isSlaveNetwork ) solutions << sServeradmin;
00770       break;
00771 
00772     case  KIO::ERR_WRITE_ACCESS_DENIED:
00773       errorName = i18n( "Write Access Denied" );
00774       description = i18n( "This means that an attempt to write to the file "
00775         "<strong>%1</strong> was rejected." ).arg( filename );
00776       causes << cAccess << cLocked << cHardware;
00777       solutions << sAccess << sQuerylock << sSysadmin;
00778       break;
00779 
00780     case  KIO::ERR_CANNOT_ENTER_DIRECTORY:
00781       errorName = i18n( "Unable to Enter Folder" );
00782       description = i18n( "This means that an attempt to enter (in other words, "
00783         "to open) the requested folder <strong>%1</strong> was rejected." )
00784         .arg( dir );
00785       causes << cAccess << cLocked;
00786       solutions << sAccess << sQuerylock << sSysadmin;
00787       break;
00788 
00789     case  KIO::ERR_PROTOCOL_IS_NOT_A_FILESYSTEM:
00790       errorName = i18n( "Folder Listing Unavailable" );
00791       techName = i18n( "Protocol %1 is not a Filesystem" ).arg( protocol );
00792       description = i18n( "This means that a request was made which requires "
00793         "determining the contents of the folder, and the KDE program supporting "
00794         "this protocol is unable to do so." );
00795       causes << cBug;
00796       solutions << sUpdate << sBugreport;
00797       break;
00798 
00799     case  KIO::ERR_CYCLIC_LINK:
00800       errorName = i18n( "Cyclic Link Detected" );
00801       description = i18n( "UNIX environments are commonly able to link a file or "
00802         "folder to a separate name and/or location. KDE detected a link or "
00803         "series of links that results in an infinite loop - i.e. the file was "
00804         "(perhaps in a roundabout way) linked to itself." );
00805       solutions << i18n( "Delete one part of the loop in order that it does not "
00806         "cause an infinite loop, and try again." ) << sSysadmin;
00807       break;
00808 
00809     case  KIO::ERR_USER_CANCELED:
00810       // Do nothing in this case. The user doesn't need to be told what he just did.
00811       // rodda: However, if we have been called, an application is about to display
00812       // this information anyway. If we don't return sensible information, the
00813       // user sees a blank dialog (I have seen this myself)
00814       errorName = i18n( "Request Aborted By User" );
00815       description = i18n( "The request was not completed because it was "
00816         "aborted." );
00817       solutions << i18n( "Retry the request." );
00818       break;
00819 
00820     case  KIO::ERR_CYCLIC_COPY:
00821       errorName = i18n( "Cyclic Link Detected During Copy" );
00822       description = i18n( "UNIX environments are commonly able to link a file or "
00823         "folder to a separate name and/or location. During the requested copy "
00824         "operation, KDE detected a link or series of links that results in an "
00825         "infinite loop - i.e. the file was (perhaps in a roundabout way) linked "
00826         "to itself." );
00827       solutions << i18n( "Delete one part of the loop in order that it does not "
00828         "cause an infinite loop, and try again." ) << sSysadmin;
00829       break;
00830 
00831     case  KIO::ERR_COULD_NOT_CREATE_SOCKET:
00832       errorName = i18n( "Could Not Create Network Connection" );
00833       techName = i18n( "Could Not Create Socket" );
00834       description = i18n( "This is a fairly technical error in which a required "
00835         "device for network communications (a socket) could not be created." );
00836       causes << i18n( "The network connection may be incorrectly configured, or "
00837         "the network interface may not be enabled." );
00838       solutions << sNetwork << sSysadmin;
00839       break;
00840 
00841     case  KIO::ERR_COULD_NOT_CONNECT:
00842       errorName = i18n( "Connection to Server Refused" );
00843       description = i18n( "The server <strong>%1</strong> refused to allow this "
00844         "computer to make a connection." ).arg( host );
00845       causes << i18n( "The server, while currently connected to the Internet, "
00846         "may not be configured to allow requests." )
00847         << i18n( "The server, while currently connected to the Internet, "
00848         "may not be running the requested service (%1)." ).arg( protocol )
00849         << i18n( "A network firewall (a device which restricts Internet "
00850         "requests), either protecting your network or the network of the server, "
00851         "may have intervened, preventing this request." );
00852       solutions << sTryagain << sServeradmin << sSysadmin;
00853       break;
00854 
00855     case  KIO::ERR_CONNECTION_BROKEN:
00856       errorName = i18n( "Connection to Server Closed Unexpectedly" );
00857       description = i18n( "Although a connection was established to "
00858         "<strong>%1</strong>, the connection was closed at an unexpected point "
00859         "in the communication." ).arg( host );
00860       causes << cNetwork << cNetpath << i18n( "A protocol error may have occurred, "
00861         "causing the server to close the connection as a response to the error." );
00862       solutions << sTryagain << sServeradmin << sSysadmin;
00863       break;
00864 
00865     case  KIO::ERR_NOT_FILTER_PROTOCOL:
00866       errorName = i18n( "URL Resource Invalid" );
00867       techName = i18n( "Protocol %1 is not a Filter Protocol" ).arg( protocol );
00868       description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource "
00869         "<strong>L</strong>ocator (URL) that you entered did not refer to "
00870         "a valid mechanism of accessing the specific resource, "
00871         "<strong>%1%2</strong>." )
00872         .arg( !host.isNull() ? host + '/' : QString::null ).arg( dir );
00873       causes << i18n( "KDE is able to communicate through a protocol within a "
00874         "protocol. This request specified a protocol be used as such, however "
00875         "this protocol is not capable of such an action. This is a rare event, "
00876         "and is likely to indicate a programming error." );
00877       solutions << sTypo << sSysadmin;
00878       break;
00879 
00880     case  KIO::ERR_COULD_NOT_MOUNT:
00881       errorName = i18n( "Unable to Initialize Input/Output Device" );
00882       techName = i18n( "Could Not Mount Device" );
00883       description = i18n( "The requested device could not be initialized "
00884         "(\"mounted\"). The reported error was: <strong>%1</strong>" )
00885         .arg( errorText );
00886       causes << i18n( "The device may not be ready, for example there may be "
00887         "no media in a removable media device (i.e. no CD-ROM in a CD drive), "
00888         "or in the case of a peripheral/portable device, the device may not "
00889         "be correctly connected." )
00890         << i18n( "You may not have permissions to initialize (\"mount\") the "
00891         "device. On UNIX systems, often system administrator privileges are "
00892         "required to initialize a device." )
00893         << cHardware;
00894       solutions << i18n( "Check that the device is ready; removable drives "
00895         "must contain media, and portable devices must be connected and powered "
00896         "on.; and try again." ) << sAccess << sSysadmin;
00897       break;
00898 
00899     case  KIO::ERR_COULD_NOT_UNMOUNT:
00900       errorName = i18n( "Unable to Uninitialize Input/Output Device" );
00901       techName = i18n( "Could Not Unmount Device" );
00902       description = i18n( "The requested device could not be uninitialized "
00903         "(\"unmounted\"). The reported error was: <strong>%1</strong>" )
00904         .arg( errorText );
00905       causes << i18n( "The device may be busy, that is, still in use by "
00906         "another application or user. Even such things as having an open "
00907         "browser window on a location on this device may cause the device to "
00908         "remain in use." )
00909         << i18n( "You may not have permissions to uninitialize (\"unmount\") "
00910         "the device. On UNIX systems, system administrator privileges are "
00911         "often required to uninitialize a device." )
00912         << cHardware;
00913       solutions << i18n( "Check that no applications are accessing the device, "
00914         "and try again." ) << sAccess << sSysadmin;
00915       break;
00916 
00917     case  KIO::ERR_COULD_NOT_READ:
00918       errorName = i18n( "Cannot Read From Resource" );
00919       description = i18n( "This means that although the resource, "
00920         "<strong>%1</strong>, was able to be opened, an error occurred while "
00921         "reading the contents of the resource." ).arg( url );
00922       causes << i18n( "You may not have permissions to read from the resource." );
00923       if ( !isSlaveNetwork ) causes << cNetwork;
00924       causes << cHardware;
00925       solutions << sAccess;
00926       if ( !isSlaveNetwork ) solutions << sNetwork;
00927       solutions << sSysadmin;
00928       break;
00929 
00930     case  KIO::ERR_COULD_NOT_WRITE:
00931       errorName = i18n( "Cannot Write to Resource" );
00932       description = i18n( "This means that although the resource, <strong>%1</strong>"
00933         ", was able to be opened, an error occurred while writing to the resource." )
00934         .arg( url );
00935       causes << i18n( "You may not have permissions to write to the resource." );
00936       if ( !isSlaveNetwork ) causes << cNetwork;
00937       causes << cHardware;
00938       solutions << sAccess;
00939       if ( !isSlaveNetwork ) solutions << sNetwork;
00940       solutions << sSysadmin;
00941       break;
00942 
00943     case  KIO::ERR_COULD_NOT_BIND:
00944       errorName = i18n( "Could Not Listen for Network Connections" );
00945       techName = i18n( "Could Not Bind" );
00946       description = i18n( "This is a fairly technical error in which a required "
00947         "device for network communications (a socket) could not be established "
00948         "to listen for incoming network connections." );
00949       causes << i18n( "The network connection may be incorrectly configured, or "
00950         "the network interface may not be enabled." );
00951       solutions << sNetwork << sSysadmin;
00952       break;
00953 
00954     case  KIO::ERR_COULD_NOT_LISTEN:
00955       errorName = i18n( "Could Not Listen for Network Connections" );
00956       techName = i18n( "Could Not Listen" );
00957       description = i18n( "This is a fairly technical error in which a required "
00958         "device for network communications (a socket) could not be established "
00959         "to listen for incoming network connections." );
00960       causes << i18n( "The network connection may be incorrectly configured, or "
00961         "the network interface may not be enabled." );
00962       solutions << sNetwork << sSysadmin;
00963       break;
00964 
00965     case  KIO::ERR_COULD_NOT_ACCEPT:
00966       errorName = i18n( "Could Not Accept Network Connection" );
00967       description = i18n( "This is a fairly technical error in which an error "
00968         "occurred while attempting to accept an incoming network connection." );
00969       causes << i18n( "The network connection may be incorrectly configured, or "
00970         "the network interface may not be enabled." )
00971         << i18n( "You may not have permissions to accept the connection." );
00972       solutions << sNetwork << sSysadmin;
00973       break;
00974 
00975     case  KIO::ERR_COULD_NOT_LOGIN:
00976       errorName = i18n( "Could Not Login: %1" ).arg( errorText );
00977       description = i18n( "An attempt to login to perform the requested "
00978         "operation was unsuccessful." );
00979       causes << i18n( "You may have supplied incorrect authentication details or "
00980         "none at all." )
00981         << i18n( "Your account may not have permission to access the "
00982         "specified resource." ) << cProtocol;
00983       solutions << i18n( "Retry the request and ensure your authentication details "
00984         "are entered correctly." ) << sServeradmin << sSysadmin;
00985       break;
00986 
00987     case  KIO::ERR_COULD_NOT_STAT:
00988       errorName = i18n( "Could Not Determine Resource Status" );
00989       techName = i18n( "Could Not Stat Resource" );
00990       description = i18n( "An attempt to determine information about the status "
00991         "of the resource <strong>%1</strong>, such as the resource name, type, "
00992         "size, etc., was unsuccessful." ).arg( url );
00993       causes << i18n( "The specified resource may not have existed or may "
00994         "not be accessible." ) << cProtocol << cHardware;
00995       solutions << i18n( "Retry the request and ensure your authentication details "
00996         "are entered correctly." ) << sSysadmin;
00997       break;
00998 
00999     case  KIO::ERR_COULD_NOT_CLOSEDIR:
01000       //result = i18n( "Could not terminate listing %1" ).arg( errorText );
01001       errorName = i18n( "Could Not Cancel Listing" );
01002       techName = i18n( "FIXME: Document this" );
01003       break;
01004 
01005     case  KIO::ERR_COULD_NOT_MKDIR:
01006       errorName = i18n( "Could Not Create Folder" );
01007       description = i18n( "An attempt to create the requested folder failed." );
01008       causes << cAccess << i18n( "The location where the folder was to be created "
01009         "may not exist." );
01010       if ( !isSlaveNetwork ) causes << cProtocol;
01011       solutions << i18n( "Retry the request." ) << sAccess;
01012       break;
01013 
01014     case  KIO::ERR_COULD_NOT_RMDIR:
01015       errorName = i18n( "Could Not Remove Folder" );
01016       description = i18n( "An attempt to remove the specified folder, "
01017         "<strong>%1</strong>, failed." ).arg( dir );
01018       causes << i18n( "The specified folder may not exist." )
01019         << i18n( "The specified folder may not be empty." )
01020         << cAccess;
01021       if ( !isSlaveNetwork ) causes << cProtocol;
01022       solutions << i18n( "Ensure that the folder exists and is empty, and try "
01023         "again." ) << sAccess;
01024       break;
01025 
01026     case  KIO::ERR_CANNOT_RESUME:
01027       errorName = i18n( "Could Not Resume File Transfer" );
01028