kio Library API Documentation

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., 59 Temple Place - Suite 330,
00016    Boston, MA 02111-1307, 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::convertSize( KIO::filesize_t size )
00046 {
00047     double fsize = size;
00048     QString s;
00049     // Giga-byte
00050     if ( size >= 1073741824 )
00051     {
00052         fsize /= 1073741824.0;
00053         if ( fsize > 1024 ) // Tera-byte
00054             s = i18n( "%1 TB" ).arg( KGlobal::locale()->formatNumber(fsize / 1024.0, 1));
00055         else
00056             s = i18n( "%1 GB" ).arg( KGlobal::locale()->formatNumber(fsize, 1));
00057     }
00058     // Mega-byte
00059     else if ( size >= 1048576 )
00060     {
00061         fsize /= 1048576.0;
00062         s = i18n( "%1 MB" ).arg( KGlobal::locale()->formatNumber(fsize, 1));
00063     }
00064     // Kilo-byte
00065     else if ( size >= 1024 )
00066     {
00067         fsize /= 1024.0;
00068         s = i18n( "%1 KB" ).arg( KGlobal::locale()->formatNumber(fsize, 1));
00069     }
00070     // Just byte
00071     else
00072     {
00073         s = i18n( "%1 B" ).arg( KGlobal::locale()->formatNumber(fsize, 0));
00074     }
00075     return s;
00076 }
00077 
00078 KIO_EXPORT QString KIO::convertSizeFromKB( KIO::filesize_t kbSize )
00079 {
00080     return convertSize(kbSize * 1024);
00081 }
00082 
00083 KIO_EXPORT QString KIO::number( KIO::filesize_t size )
00084 {
00085     char charbuf[256];
00086     sprintf(charbuf, "%lld", size);
00087     return QString::fromLatin1(charbuf);
00088 }
00089 
00090 KIO_EXPORT unsigned int KIO::calculateRemainingSeconds( KIO::filesize_t totalSize,
00091                                                         KIO::filesize_t processedSize, KIO::filesize_t speed )
00092 {
00093   if ( (speed != 0) && (totalSize != 0) )
00094     return ( totalSize - processedSize ) / speed;
00095   else
00096     return 0;
00097 }
00098 
00099 KIO_EXPORT QString KIO::convertSeconds( unsigned int seconds )
00100 {
00101   unsigned int days  = seconds / 86400;
00102   unsigned int hours = (seconds - (days * 86400)) / 3600;
00103   unsigned int mins  = (seconds - (days * 86400) - (hours * 3600)) / 60;
00104   seconds            = (seconds - (days * 86400) - (hours * 3600) - (mins * 60));
00105 
00106   const QTime time(hours, mins, seconds);
00107   const QString timeStr( KGlobal::locale()->formatTime(time, true /*with seconds*/, true /*duration*/) );
00108   if ( days > 0 )
00109     return i18n("1 day %1", "%n days %1", days).arg(timeStr);
00110   else
00111     return timeStr;
00112 }
00113 
00114 KIO_EXPORT QTime KIO::calculateRemaining( KIO::filesize_t totalSize, KIO::filesize_t processedSize, KIO::filesize_t speed )
00115 {
00116   QTime remainingTime;
00117 
00118   if ( speed != 0 ) {
00119     KIO::filesize_t secs;
00120     if ( totalSize == 0 ) {
00121       secs = 0;
00122     } else {
00123       secs = ( totalSize - processedSize ) / speed;
00124     }
00125     if (secs >= (24*60*60)) // Limit to 23:59:59
00126        secs = (24*60*60)-1;
00127     int hr = secs / ( 60 * 60 );
00128     int mn = ( secs - hr * 60 * 60 ) / 60;
00129     int sc = ( secs - hr * 60 * 60 - mn * 60 );
00130 
00131     remainingTime.setHMS( hr, mn, sc );
00132   }
00133 
00134   return remainingTime;
00135 }
00136 
00137 KIO_EXPORT QString KIO::itemsSummaryString(uint items, uint files, uint dirs, KIO::filesize_t size, bool showSize)
00138 {
00139     QString text = items == 0 ? i18n( "No Items" ) : i18n( "One Item", "%n Items", items );
00140     text += " - ";
00141     text += files == 0 ? i18n( "No Files" ) : i18n( "One File", "%n Files", files );
00142     if ( showSize && files > 0 )
00143     {
00144         text += " ";
00145         text += i18n("(%1 Total)").arg(KIO::convertSize( size ) );
00146     }
00147     text += " - ";
00148     text += dirs == 0 ? i18n( "No Folders" ) : i18n("One Folder", "%n Folders", dirs);
00149     return text;
00150 }
00151 
00152 KIO_EXPORT QString KIO::encodeFileName( const QString & _str )
00153 {
00154   QString str( _str );
00155 
00156   int i = 0;
00157   while ( ( i = str.find( "%", i ) ) != -1 )
00158   {
00159     str.replace( i, 1, "%%");
00160     i += 2;
00161   }
00162   while ( ( i = str.find( "/" ) ) != -1 )
00163       str.replace( i, 1, "%2f");
00164   return str;
00165 }
00166 
00167 KIO_EXPORT QString KIO::decodeFileName( const QString & _str )
00168 {
00169   QString str;
00170 
00171   unsigned int i = 0;
00172   for ( ; i < _str.length() ; ++i )
00173   {
00174     if ( _str[i]=='%' )
00175     {
00176       if ( _str[i+1]=='%' ) // %% -> %
00177       {
00178         str.append('%');
00179         ++i;
00180       }
00181       else if ( _str[i+1]=='2' && (i+2<_str.length()) && _str[i+2].lower()=='f' ) // %2f -> /
00182       {
00183         str.append('/');
00184         i += 2;
00185       }
00186       else
00187         str.append('%');
00188     } else
00189       str.append(_str[i]);
00190   }
00191 
00192   return str;
00193 }
00194 
00195 KIO_EXPORT QString KIO::Job::errorString() const
00196 {
00197   return KIO::buildErrorString(m_error, m_errorText);
00198 }
00199 
00200 KIO_EXPORT QString KIO::buildErrorString(int errorCode, const QString &errorText)
00201 {
00202   QString result;
00203 
00204   switch( errorCode )
00205     {
00206     case  KIO::ERR_CANNOT_OPEN_FOR_READING:
00207       result = i18n( "Could not read %1." ).arg( errorText );
00208       break;
00209     case  KIO::ERR_CANNOT_OPEN_FOR_WRITING:
00210       result = i18n( "Could not write to %1." ).arg( errorText );
00211       break;
00212     case  KIO::ERR_CANNOT_LAUNCH_PROCESS:
00213       result = i18n( "Could not start process %1." ).arg( errorText );
00214       break;
00215     case  KIO::ERR_INTERNAL:
00216       result = i18n( "Internal Error\nPlease send a full bug report at http://bugs.kde.org\n%1" ).arg( errorText );
00217       break;
00218     case  KIO::ERR_MALFORMED_URL:
00219       result = i18n( "Malformed URL %1." ).arg( errorText );
00220       break;
00221     case  KIO::ERR_UNSUPPORTED_PROTOCOL:
00222       result = i18n( "The protocol %1 is not supported." ).arg( errorText );
00223       break;
00224     case  KIO::ERR_NO_SOURCE_PROTOCOL:
00225       result = i18n( "The protocol %1 is only a filter protocol.").arg( errorText );
00226       break;
00227     case  KIO::ERR_UNSUPPORTED_ACTION:
00228       result = errorText;
00229 //       result = i18n( "Unsupported action %1" ).arg( errorText );
00230       break;
00231     case  KIO::ERR_IS_DIRECTORY:
00232       result = i18n( "%1 is a folder, but a file was expected." ).arg( errorText );
00233       break;
00234     case  KIO::ERR_IS_FILE:
00235       result = i18n( "%1 is a file, but a folder was expected." ).arg( errorText );
00236       break;
00237     case  KIO::ERR_DOES_NOT_EXIST:
00238       result = i18n( "The file or folder %1 does not exist." ).arg( errorText );
00239       break;
00240     case  KIO::ERR_FILE_ALREADY_EXIST:
00241       result = i18n( "A file named %1 already exists." ).arg( errorText );
00242       break;
00243     case  KIO::ERR_DIR_ALREADY_EXIST:
00244       result = i18n( "A folder named %1 already exists." ).arg( errorText );
00245       break;
00246     case  KIO::ERR_UNKNOWN_HOST:
00247       result = errorText.isEmpty() ? i18n( "No hostname specified." ) : i18n( "Unknown host %1" ).arg( errorText );
00248       break;
00249     case  KIO::ERR_ACCESS_DENIED:
00250       result = i18n( "Access denied to %1." ).arg( errorText );
00251       break;
00252     case  KIO::ERR_WRITE_ACCESS_DENIED:
00253       result = i18n( "Access denied.\nCould not write to %1." ).arg( errorText );
00254       break;
00255     case  KIO::ERR_CANNOT_ENTER_DIRECTORY:
00256       result = i18n( "Could not enter folder %1." ).arg( errorText );
00257       break;
00258     case  KIO::ERR_PROTOCOL_IS_NOT_A_FILESYSTEM:
00259       result = i18n( "The protocol %1 does not implement a folder service." ).arg( errorText );
00260       break;
00261     case  KIO::ERR_CYCLIC_LINK:
00262       result = i18n( "Found a cyclic link in %1." ).arg( errorText );
00263       break;
00264     case  KIO::ERR_USER_CANCELED:
00265       // Do nothing in this case. The user doesn't need to be told what he just did.
00266       break;
00267     case  KIO::ERR_CYCLIC_COPY:
00268       result = i18n( "Found a cyclic link while copying %1." ).arg( errorText );
00269       break;
00270     case  KIO::ERR_COULD_NOT_CREATE_SOCKET:
00271       result = i18n( "Could not create socket for accessing %1." ).arg( errorText );
00272       break;
00273     case  KIO::ERR_COULD_NOT_CONNECT:
00274       result = i18n( "Could not connect to host %1." ).arg( errorText.isEmpty() ? QString::fromLatin1("localhost") : errorText );
00275       break;
00276     case  KIO::ERR_CONNECTION_BROKEN:
00277       result = i18n( "Connection to host %1 is broken." ).arg( errorText );
00278       break;
00279     case  KIO::ERR_NOT_FILTER_PROTOCOL:
00280       result = i18n( "The protocol %1 is not a filter protocol." ).arg( errorText );
00281       break;
00282     case  KIO::ERR_COULD_NOT_MOUNT:
00283       result = i18n( "Could not mount device.\nThe reported error was:\n%1" ).arg( errorText );
00284       break;
00285     case  KIO::ERR_COULD_NOT_UNMOUNT:
00286       result = i18n( "Could not unmount device.\nThe reported error was:\n%1" ).arg( errorText );
00287       break;
00288     case  KIO::ERR_COULD_NOT_READ:
00289       result = i18n( "Could not read file %1." ).arg( errorText );
00290       break;
00291     case  KIO::ERR_COULD_NOT_WRITE:
00292       result = i18n( "Could not write to file %1." ).arg( errorText );
00293       break;
00294     case  KIO::ERR_COULD_NOT_BIND:
00295       result = i18n( "Could not bind %1." ).arg( errorText );
00296       break;
00297     case  KIO::ERR_COULD_NOT_LISTEN:
00298       result = i18n( "Could not listen %1." ).arg( errorText );
00299       break;
00300     case  KIO::ERR_COULD_NOT_ACCEPT:
00301       result = i18n( "Could not accept %1." ).arg( errorText );
00302       break;
00303     case  KIO::ERR_COULD_NOT_LOGIN:
00304       result = errorText;
00305       break;
00306     case  KIO::ERR_COULD_NOT_STAT:
00307       result = i18n( "Could not access %1." ).arg( errorText );
00308       break;
00309     case  KIO::ERR_COULD_NOT_CLOSEDIR:
00310       result = i18n( "Could not terminate listing %1." ).arg( errorText );
00311       break;
00312     case  KIO::ERR_COULD_NOT_MKDIR:
00313       result = i18n( "Could not make folder %1." ).arg( errorText );
00314       break;
00315     case  KIO::ERR_COULD_NOT_RMDIR:
00316       result = i18n( "Could not remove folder %1." ).arg( errorText );
00317       break;
00318     case  KIO::ERR_CANNOT_RESUME:
00319       result = i18n( "Could not resume file %1." ).arg( errorText );
00320       break;
00321     case  KIO::ERR_CANNOT_RENAME:
00322       result = i18n( "Could not rename file %1." ).arg( errorText );
00323       break;
00324     case  KIO::ERR_CANNOT_CHMOD:
00325       result = i18n( "Could not change permissions for %1." ).arg( errorText );
00326       break;
00327     case  KIO::ERR_CANNOT_DELETE:
00328       result = i18n( "Could not delete file %1." ).arg( errorText );
00329       break;
00330     case  KIO::ERR_SLAVE_DIED:
00331       result = i18n( "The process for the %1 protocol died unexpectedly." ).arg( errorText );
00332       break;
00333     case  KIO::ERR_OUT_OF_MEMORY:
00334       result = i18n( "Error. Out of memory.\n%1" ).arg( errorText );
00335       break;
00336     case  KIO::ERR_UNKNOWN_PROXY_HOST:
00337       result = i18n( "Unknown proxy host\n%1" ).arg( errorText );
00338       break;
00339     case  KIO::ERR_COULD_NOT_AUTHENTICATE:
00340       result = i18n( "Authorization failed, %1 authentication not supported" ).arg( errorText );
00341       break;
00342     case  KIO::ERR_ABORTED:
00343       result = i18n( "User canceled action\n%1" ).arg( errorText );
00344       break;
00345     case  KIO::ERR_INTERNAL_SERVER:
00346       result = i18n( "Internal error in server\n%1" ).arg( errorText );
00347       break;
00348     case  KIO::ERR_SERVER_TIMEOUT:
00349       result = i18n( "Timeout on server\n%1" ).arg( errorText );
00350       break;
00351     case  KIO::ERR_UNKNOWN:
00352       result = i18n( "Unknown error\n%1" ).arg( errorText );
00353       break;
00354     case  KIO::ERR_UNKNOWN_INTERRUPT:
00355       result = i18n( "Unknown interrupt\n%1" ).arg( errorText );
00356       break;
00357 /*
00358     case  KIO::ERR_CHECKSUM_MISMATCH:
00359       if (errorText)
00360         result = i18n( "Warning: MD5 Checksum for %1 does not match checksum returned from server" ).arg(errorText);
00361       else
00362         result = i18n( "Warning: MD5 Checksum for %1 does not match checksum returned from server" ).arg("document");
00363       break;
00364 */
00365     case KIO::ERR_CANNOT_DELETE_ORIGINAL:
00366       result = i18n( "Could not delete original file %1.\nPlease check permissions." ).arg( errorText );
00367       break;
00368     case KIO::ERR_CANNOT_DELETE_PARTIAL:
00369       result = i18n( "Could not delete partial file %1.\nPlease check permissions." ).arg( errorText );
00370       break;
00371     case KIO::ERR_CANNOT_RENAME_ORIGINAL:
00372       result = i18n( "Could not rename original file %1.\nPlease check permissions." ).arg( errorText );
00373       break;
00374     case KIO::ERR_CANNOT_RENAME_PARTIAL:
00375       result = i18n( "Could not rename partial file %1.\nPlease check permissions." ).arg( errorText );
00376       break;
00377     case KIO::ERR_CANNOT_SYMLINK:
00378       result = i18n( "Could not create symlink %1.\nPlease check permissions." ).arg( errorText );
00379       break;
00380     case KIO::ERR_NO_CONTENT:
00381       result = errorText;
00382       break;
00383     case KIO::ERR_DISK_FULL:
00384       result = i18n( "Could not write file %1.\nDisk full." ).arg( errorText );
00385       break;
00386     case KIO::ERR_IDENTICAL_FILES:
00387       result = i18n( "The source and destination are the same file.\n%1" ).arg( errorText );
00388       break;
00389     case KIO::ERR_SLAVE_DEFINED:
00390       result = errorText;
00391       break;
00392     case KIO::ERR_UPGRADE_REQUIRED:
00393       result = i18n( "%1 is required by the server, but is not available." ).arg(errorText);
00394     case KIO::ERR_POST_DENIED:
00395       result = i18n( "Access to restricted port in POST denied.");
00396       break;
00397     default:
00398       result = i18n( "Unknown error code %1\n%2\nPlease send a full bug report at http://bugs.kde.org." ).arg( errorCode ).arg( errorText );
00399       break;
00400     }
00401 
00402   return result;
00403 }
00404 
00405 KIO_EXPORT QString KIO::unsupportedActionErrorString(const QString &protocol, int cmd) {
00406   switch (cmd) {
00407     case CMD_CONNECT:
00408       return i18n("Opening connections is not supported with the protocol %1." ).arg(protocol);
00409     case CMD_DISCONNECT:
00410       return i18n("Closing connections is not supported with the protocol %1." ).arg(protocol);
00411     case CMD_STAT:
00412       return i18n("Accessing files is not supported with the protocol %1.").arg(protocol);
00413     case CMD_PUT:
00414       return i18n("Writing to %1 is not supported.").arg(protocol);
00415     case CMD_SPECIAL:
00416       return i18n("There are no special actions available for protocol %1.").arg(protocol);
00417     case CMD_LISTDIR:
00418       return i18n("Listing folders is not supported for protocol %1.").arg(protocol);
00419     case CMD_GET:
00420       return i18n("Retrieving data from %1 is not supported.").arg(protocol);
00421     case CMD_MIMETYPE:
00422       return i18n("Retrieving mime type information from %1 is not supported.").arg(protocol);
00423     case CMD_RENAME:
00424       return i18n("Renaming or moving files within %1 is not supported.").arg(protocol);
00425     case CMD_SYMLINK:
00426       return i18n("Creating symlinks is not supported with protocol %1.").arg(protocol);
00427     case CMD_COPY:
00428       return i18n("Copying files within %1 is not supported.").arg(protocol);
00429     case CMD_DEL:
00430       return i18n("Deleting files from %1 is not supported.").arg(protocol);
00431     case CMD_MKDIR:
00432       return i18n("Creating folders is not supported with protocol %1.").arg(protocol);
00433     case CMD_CHMOD:
00434       return i18n("Changing the attributes of files is not supported with protocol %1.").arg(protocol);
00435     case CMD_SUBURL:
00436       return i18n("Using sub-URLs with %1 is not supported.").arg(protocol);
00437     case CMD_MULTI_GET:
00438       return i18n("Multiple get is not supported with protocol %1.").arg(protocol);
00439     default:
00440       return i18n("Protocol %1 does not support action %2.").arg(protocol).arg(cmd);
00441   }/*end switch*/
00442 }
00443 
00444 KIO_EXPORT QStringList KIO::Job::detailedErrorStrings( const KURL *reqUrl /*= 0L*/,
00445                                             int method /*= -1*/ ) const
00446 {
00447   QString errorName, techName, description, ret2;
00448   QStringList causes, solutions, ret;
00449 
00450   QByteArray raw = rawErrorDetail( m_error, m_errorText, reqUrl, method );
00451   QDataStream stream(raw, IO_ReadOnly);
00452 
00453   stream >> errorName >> techName >> description >> causes >> solutions;
00454 
00455   QString url, protocol, datetime;
00456   if ( reqUrl ) {
00457     url = reqUrl->htmlURL();
00458     protocol = reqUrl->protocol();
00459   } else {
00460     url = i18n( "(unknown)" );
00461   }
00462 
00463   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
00464                                                 false );
00465 
00466   ret << errorName;
00467   ret << QString::fromLatin1( "<qt><p><b>" ) + errorName +
00468          QString::fromLatin1( "</b></p><p>" ) + description +
00469          QString::fromLatin1( "</p>" );
00470   ret2 = QString::fromLatin1( "<qt><p>" );
00471   if ( !techName.isNull() )
00472     ret2 += i18n( "<b>Technical reason</b>: " ) + techName + QString::fromLatin1( "</p>" );
00473   ret2 += i18n( "</p><p><b>Details of the request</b>:" );
00474   ret2 += i18n( "</p><ul><li>URL: %1</li>" ).arg( url );
00475   if ( !protocol.isNull() ) {
00476     ret2 += i18n( "<li>Protocol: %1</li>" ).arg( protocol );
00477   }
00478   ret2 += i18n( "<li>Date and time: %1</li>" ).arg( datetime );
00479   ret2 += i18n( "<li>Additional information: %1</li></ul>" ).arg( m_errorText );
00480   if ( causes.count() ) {
00481     ret2 += i18n( "<p><b>Possible causes</b>:</p><ul><li>" );
00482     ret2 += causes.join( "</li><li>" );
00483     ret2 += QString::fromLatin1( "</li></ul>" );
00484   }
00485   if ( solutions.count() ) {
00486     ret2 += i18n( "<p><b>Possible solutions</b>:</p><ul><li>" );
00487     ret2 += solutions.join( "</li><li>" );
00488     ret2 += QString::fromLatin1( "</li></ul>" );
00489   }
00490   ret << ret2;
00491   return ret;
00492 }
00493 
00494 KIO_EXPORT QByteArray KIO::rawErrorDetail(int errorCode, const QString &errorText,
00495                                const KURL *reqUrl /*= 0L*/, int /*method = -1*/ )
00496 {
00497   QString url, host, protocol, datetime, domain, path, dir, filename;
00498   bool isSlaveNetwork = false;
00499   if ( reqUrl ) {
00500     url = reqUrl->prettyURL();
00501     host = reqUrl->host();
00502     protocol = reqUrl->protocol();
00503 
00504     if ( host.left(4) == "www." )
00505       domain = host.mid(4);
00506     else
00507       domain = host;
00508 
00509     path = reqUrl->path(1);
00510     filename = reqUrl->fileName();
00511     dir =  path + filename;
00512 
00513     // detect if protocol is a network protocol...
00514     // add your hacks here...
00515     if ( protocol == "http" ||
00516          protocol == "https" ||
00517          protocol == "ftp" ||
00518          protocol == "sftp" ||
00519          protocol == "webdav" ||
00520          protocol == "webdavs" ||
00521          protocol == "finger" ||
00522          protocol == "fish" ||
00523          protocol == "gopher" ||
00524          protocol == "imap" ||
00525          protocol == "imaps" ||
00526          protocol == "lan" ||
00527          protocol == "ldap" ||
00528          protocol == "mailto" ||
00529          protocol == "news" ||
00530          protocol == "nntp" ||
00531          protocol == "pop3" ||
00532          protocol == "pop3s" ||
00533          protocol == "smtp" ||
00534          protocol == "smtps" ||
00535          protocol == "telnet"
00536         ) {
00537       isSlaveNetwork = false;
00538     }
00539   } else {
00540     // assume that the errorText has the location we are interested in
00541     url = host = domain = path = filename = dir = errorText;
00542     protocol = i18n( "(unknown)" );
00543   }
00544 
00545   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
00546                                                 false );
00547 
00548   QString errorName, techName, description;
00549   QStringList causes, solutions;
00550 
00551   // c == cause, s == solution
00552   QString sSysadmin = i18n( "Contact your appropriate computer support system, "
00553     "whether the system administrator, or technical support group for further "
00554     "assistance." );
00555   QString sServeradmin = i18n( "Contact the administrator of the server "
00556     "for further assistance." );
00557   // FIXME active link to permissions dialog
00558   QString sAccess = i18n( "Check your access permissions on this resource." );
00559   QString cAccess = i18n( "Your access permissions may be inadequate to "
00560     "perform the requested operation on this resource." );
00561   QString cLocked = i18n( "The file may be in use (and thus locked) by "
00562     "another user or application." );
00563   QString sQuerylock = i18n( "Check to make sure that no other "
00564     "application or user is using the file or has locked the file." );
00565   QString cHardware = i18n( "Although unlikely, a hardware error may have "
00566     "occurred." );
00567   QString cBug = i18n( "You may have encountered a bug in the program." );
00568   QString cBuglikely = i18n( "This is most likely to be caused by a bug in the "
00569     "program. Please consider submitting a full bug report as detailed below." );
00570   QString sUpdate = i18n( "Update your software to the latest version. "
00571     "Your distribution should provide tools to update your software." );
00572   QString sBugreport = i18n( "When all else fails, please consider helping the "
00573     "KDE team or the third party maintainer of this software by submitting a "
00574     "high quality bug report. If the software is provided by a third party, "
00575     "please contact them directly. Otherwise, first look to see if "
00576     "the same bug has been submitted by someone else by searching at the "
00577     "<a href=\"http://bugs.kde.org/\">KDE bug reporting website</a>. If not, take "
00578     "note of the details given above, and include them in your bug report, along "
00579     "with as many other details as you think might help." );
00580   QString cNetwork = i18n( "There may have been a problem with your network "
00581     "connection." );
00582   // FIXME netconf kcontrol link
00583   QString cNetconf = i18n( "There may have been a problem with your network "
00584     "configuration. If you have been accessing the Internet with no problems "
00585     "recently, this is unlikely." );
00586   QString cNetpath = i18n( "There may have been a problem at some point along "
00587     "the network path between the server and this computer." );
00588   QString sTryagain = i18n( "Try again, either now or at a later time." );
00589   QString cProtocol = i18n( "A protocol error or incompatibility may have occurred." );
00590   QString sExists = i18n( "Ensure that the resource exists, and try again." );
00591   QString cExists = i18n( "The specified resource may not exist." );
00592   QString cTypo = i18n( "You may have incorrectly typed the location." );
00593   QString sTypo = i18n( "Double-check that you have entered the correct location "
00594     "and try again." );
00595   QString sNetwork = i18n( "Check your network connection status." );
00596 
00597   switch( errorCode ) {
00598     case  KIO::ERR_CANNOT_OPEN_FOR_READING:
00599       errorName = i18n( "Cannot Open Resource For Reading" );
00600       description = i18n( "This means that the contents of the requested file "
00601         "or folder <strong>%1</strong> could not be retrieved, as read "
00602         "access could not be obtained." ).arg( dir );
00603       causes << i18n( "You may not have permissions to read the file or open "
00604         "the folder.") << cLocked << cHardware;
00605       solutions << sAccess << sQuerylock << sSysadmin;
00606       break;
00607 
00608     case  KIO::ERR_CANNOT_OPEN_FOR_WRITING:
00609       errorName = i18n( "Cannot Open Resource For Writing" );
00610       description = i18n( "This means that the file, <strong>%1</strong>, could "
00611         "not be written to as requested, because access with permission to "
00612         "write could not be obtained." ).arg( filename );
00613       causes << cAccess << cLocked << cHardware;
00614       solutions << sAccess << sQuerylock << sSysadmin;
00615       break;
00616 
00617     case  KIO::ERR_CANNOT_LAUNCH_PROCESS:
00618       errorName = i18n( "Cannot Initiate the %1 Protocol" ).arg( protocol );
00619       techName = i18n( "Unable to Launch Process" );
00620       description = i18n( "The program on your computer which provides access "
00621         "to the <strong>%1</strong> protocol could not be started. This is "
00622         "usually due to technical reasons." ).arg( protocol );
00623       causes << i18n( "The program which provides compatibility with this "
00624         "protocol may not have been updated with your last update of KDE. "
00625         "This can cause the program to be incompatible with the current version "
00626         "and thus not start." ) << cBug;
00627       solutions << sUpdate << sSysadmin;
00628       break;
00629 
00630     case  KIO::ERR_INTERNAL:
00631       errorName = i18n( "Internal Error" );
00632       description = i18n( "The program on your computer which provides access "
00633         "to the <strong>%1</strong> protocol has reported an internal error." )
00634         .arg( protocol );
00635       causes << cBuglikely;
00636       solutions << sUpdate << sBugreport;
00637       break;
00638 
00639     case  KIO::ERR_MALFORMED_URL:
00640       errorName = i18n( "Improperly Formatted URL" );
00641       description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource "
00642         "<strong>L</strong>ocator (URL) that you entered was not properly "
00643         "formatted. The format of a URL is generally as follows:"
00644         "<blockquote><strong>protocol://user:password@www.example.org:port/folder/"
00645         "filename.extension?query=value</strong></blockquote>" );
00646       solutions << sTypo;
00647       break;
00648 
00649     case  KIO::ERR_UNSUPPORTED_PROTOCOL:
00650       errorName = i18n( "Unsupported Protocol %1" ).arg( protocol );
00651       description = i18n( "The protocol <strong>%1</strong> is not supported "
00652         "by the KDE programs currently installed on this computer." )
00653         .arg( protocol );
00654       causes << i18n( "The requested protocol may not be supported." )
00655         << i18n( "The versions of the %1 protocol supported by this computer and "
00656         "the server may be incompatible." ).arg( protocol );
00657       solutions << i18n( "You may perform a search on the Internet for a KDE "
00658         "program (called a kioslave or ioslave) which supports this protocol. "
00659         "Places to search include <a href=\"http://kde-apps.org/\">"
00660         "http://kde-apps.org/</a> and <a href=\"http://freshmeat.net/\">"
00661         "http://freshmeat.net/</a>." )
00662         << sUpdate << sSysadmin;
00663       break;
00664 
00665     case  KIO::ERR_NO_SOURCE_PROTOCOL:
00666       errorName = i18n( "URL Does Not Refer to a Resource." );
00667       techName = i18n( "Protocol is a Filter Protocol" );
00668       description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource "
00669         "<strong>L</strong>ocator (URL) that you entered did not refer to a "
00670         "specific resource." );
00671       causes << i18n( "KDE is able to communicate through a protocol within a "
00672         "protocol; the protocol specified is only for use in such situations, "
00673         "however this is not one of these situations. This is a rare event, and "
00674         "is likely to indicate a programming error." );
00675       solutions << sTypo;
00676       break;
00677 
00678     case  KIO::ERR_UNSUPPORTED_ACTION:
00679       errorName = i18n( "Unsupported Action: %1" ).arg( errorText );
00680       description = i18n( "The requested action is not supported by the KDE "
00681         "program which is implementing the <strong>%1</strong> protocol." )
00682         .arg( protocol );
00683       causes << i18n( "This error is very much dependent on the KDE program. The "
00684         "additional information should give you more information than is available "
00685         "to the KDE input/output architecture." );
00686       solutions << i18n( "Attempt to find another way to accomplish the same "
00687         "outcome." );
00688       break;
00689 
00690     case  KIO::ERR_IS_DIRECTORY:
00691       errorName = i18n( "File Expected" );
00692       description = i18n( "The request expected a file, however the "
00693         "folder <strong>%1</strong> was found instead." ).arg( dir );
00694       causes << i18n( "This may be an error on the server side." ) << cBug;
00695       solutions << sUpdate << sSysadmin;
00696       break;
00697 
00698     case  KIO::ERR_IS_FILE:
00699       errorName = i18n( "Folder Expected" );
00700       description = i18n( "The request expected a folder, however "
00701         "the file <strong>%1</strong> was found instead." ).arg( filename );
00702       causes << cBug;
00703       solutions << sUpdate << sSysadmin;
00704       break;
00705 
00706     case  KIO::ERR_DOES_NOT_EXIST:
00707       errorName = i18n( "File or Folder Does Not Exist" );
00708       description = i18n( "The specified file or folder <strong>%1</strong> "
00709         "does not exist." ).arg( dir );
00710       causes << cBug;
00711       solutions << sUpdate << sSysadmin;
00712       break;
00713 
00714     case  KIO::ERR_FILE_ALREADY_EXIST:
00715       errorName = i18n( "File Already Exists" );
00716       description = i18n( "The requested file could not be created because a "
00717         "file with the same name already exists." );
00718       solutions << i18n ( "Try moving the current file out of the way first, "
00719         "and then try again." )
00720         << i18n ( "Delete the current file and try again." )
00721         << i18n( "Choose an alternate filename for the new file." );
00722       break;
00723 
00724     case  KIO::ERR_DIR_ALREADY_EXIST:
00725       errorName = i18n( "Folder Already Exists" );
00726       description = i18n( "The requested folder could not be created because "
00727         "a folder with the same name already exists." );
00728       solutions << i18n( "Try moving the current folder out of the way first, "
00729         "and then try again." )
00730         << i18n( "Delete the current folder and try again." )
00731         << i18n( "Choose an alternate name for the new folder." );
00732       break;
00733 
00734     case  KIO::ERR_UNKNOWN_HOST:
00735       errorName = i18n( "Unknown Host" );
00736       description = i18n( "An unknown host error indicates that the server with "
00737         "the requested name, <strong>%1</strong>, could not be "
00738         "located on the Internet." ).arg( host );
00739       causes << i18n( "The name that you typed, %1, may not exist: it may be "
00740         "incorrectly typed." ).arg( host )
00741         << cNetwork << cNetconf;
00742       solutions << sNetwork << sSysadmin;
00743       break;
00744 
00745     case  KIO::ERR_ACCESS_DENIED:
00746       errorName = i18n( "Access Denied" );
00747       description = i18n( "Access was denied to the specified resource, "
00748         "<strong>%1</strong>." ).arg( url );
00749       causes << i18n( "You may have supplied incorrect authentication details or "
00750         "none at all." )
00751         << i18n( "Your account may not have permission to access the "
00752         "specified resource." );
00753       solutions << i18n( "Retry the request and ensure your authentication details "
00754         "are entered correctly." ) << sSysadmin;
00755       if ( !isSlaveNetwork ) solutions << sServeradmin;
00756       break;
00757 
00758     case  KIO::ERR_WRITE_ACCESS_DENIED:
00759       errorName = i18n( "Write Access Denied" );
00760       description = i18n( "This means that an attempt to write to the file "
00761         "<strong>%1</strong> was rejected." ).arg( filename );
00762       causes << cAccess << cLocked << cHardware;
00763       solutions << sAccess << sQuerylock << sSysadmin;
00764       break;
00765 
00766     case  KIO::ERR_CANNOT_ENTER_DIRECTORY:
00767       errorName = i18n( "Unable to Enter Folder" );
00768       description = i18n( "This means that an attempt to enter (in other words, "
00769         "to open) the requested folder <strong>%1</strong> was rejected." )
00770         .arg( dir );
00771       causes << cAccess << cLocked;
00772       solutions << sAccess << sQuerylock << sSysadmin;
00773       break;
00774 
00775     case  KIO::ERR_PROTOCOL_IS_NOT_A_FILESYSTEM:
00776       errorName = i18n( "Folder Listing Unavailable" );
00777       techName = i18n( "Protocol %1 is not a Filesystem" ).arg( protocol );
00778       description = i18n( "This means that a request was made which requires "
00779         "determining the contents of the folder, and the KDE program supporting "
00780         "this protocol is unable to do so." );
00781       causes << cBug;
00782       solutions << sUpdate << sBugreport;
00783       break;
00784 
00785     case  KIO::ERR_CYCLIC_LINK:
00786       errorName = i18n( "Cyclic Link Detected" );
00787       description = i18n( "UNIX environments are commonly able to link a file or "
00788         "folder to a separate name and/or location. KDE detected a link or "
00789         "series of links that results in an infinite loop - i.e. the file was "
00790         "(perhaps in a roundabout way) linked to itself." );
00791       solutions << i18n( "Delete one part of the loop in order that it does not "
00792         "cause an infinite loop, and try again." ) << sSysadmin;
00793       break;
00794 
00795     case  KIO::ERR_USER_CANCELED:
00796       // Do nothing in this case. The user doesn't need to be told what he just did.
00797       // rodda: However, if we have been called, an application is about to display
00798       // this information anyway. If we don't return sensible information, the
00799       // user sees a blank dialog (I have seen this myself)
00800       errorName = i18n( "Request Aborted By User" );
00801       description = i18n( "The request was not completed because it was "
00802         "aborted." );
00803       solutions << i18n( "Retry the request." );
00804       break;
00805 
00806     case  KIO::ERR_CYCLIC_COPY:
00807       errorName = i18n( "Cyclic Link Detected During Copy" );
00808       description = i18n( "UNIX environments are commonly able to link a file or "
00809         "folder to a separate name and/or location. During the requested copy "
00810         "operation, KDE detected a link or series of links that results in an "
00811         "infinite loop - i.e. the file was (perhaps in a roundabout way) linked "
00812         "to itself." );
00813       solutions << i18n( "Delete one part of the loop in order that it does not "
00814         "cause an infinite loop, and try again." ) << sSysadmin;
00815       break;
00816 
00817     case  KIO::ERR_COULD_NOT_CREATE_SOCKET:
00818       errorName = i18n( "Could Not Create Network Connection" );
00819       techName = i18n( "Could Not Create Socket" );
00820       description = i18n( "This is a fairly technical error in which a required "
00821         "device for network communications (a socket) could not be created." );
00822       causes << i18n( "The network connection may be incorrectly configured, or "
00823         "the network interface may not be enabled." );
00824       solutions << sNetwork << sSysadmin;
00825       break;
00826 
00827     case  KIO::ERR_COULD_NOT_CONNECT:
00828       errorName = i18n( "Connection to Server Refused" );
00829       description = i18n( "The server <strong>%1</strong> refused to allow this "
00830         "computer to make a connection." ).arg( host );
00831       causes << i18n( "The server, while currently connected to the Internet, "
00832         "may not be configured to allow requests." )
00833         << i18n( "The server, while currently connected to the Internet, "
00834         "may not be running the requested service (%1)." ).arg( protocol )
00835         << i18n( "A network firewall (a device which restricts Internet "
00836         "requests), either protecting your network or the network of the server, "
00837         "may have intervened, preventing this request." );
00838       solutions << sTryagain << sServeradmin << sSysadmin;
00839       break;
00840 
00841     case  KIO::ERR_CONNECTION_BROKEN:
00842       errorName = i18n( "Connection to Server Closed Unexpectedly" );
00843       description = i18n( "Although a connection was established to "
00844         "<strong>%1</strong>, the connection was closed at an unexpected point "
00845         "in the communication." ).arg( host );
00846       causes << cNetwork << cNetpath << i18n( "A protocol error may have occurred, "
00847         "causing the server to close the connection as a response to the error." );
00848       solutions << sTryagain << sServeradmin << sSysadmin;
00849       break;
00850 
00851     case  KIO::ERR_NOT_FILTER_PROTOCOL:
00852       errorName = i18n( "URL Resource Invalid" );
00853       techName = i18n( "Protocol %1 is not a Filter Protocol" ).arg( protocol );
00854       description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource "
00855         "<strong>L</strong>ocator (URL) that you entered did not refer to "
00856         "a valid mechanism of accessing the specific resource, "
00857         "<strong>%1%2</strong>." )
00858         .arg( !host.isNull() ? host + '/' : QString::null ).arg( dir );
00859       causes << i18n( "KDE is able to communicate through a protocol within a "
00860         "protocol. This request specified a protocol be used as such, however "
00861         "this protocol is not capable of such an action. This is a rare event, "
00862         "and is likely to indicate a programming error." );
00863       solutions << sTypo << sSysadmin;
00864       break;
00865 
00866     case  KIO::ERR_COULD_NOT_MOUNT:
00867       errorName = i18n( "Unable to Initialize Input/Output Device" );
00868       techName = i18n( "Could Not Mount Device" );
00869       description = i18n( "The requested device could not be initialized "
00870         "(\"mounted\"). The reported error was: <strong>%1</strong>" )
00871         .arg( errorText );
00872       causes << i18n( "The device may not be ready, for example there may be "
00873         "no media in a removable media device (i.e. no CD-ROM in a CD drive), "
00874         "or in the case of a peripheral/portable device, the device may not "
00875         "be correctly connected." )
00876         << i18n( "You may not have permissions to initialize (\"mount\") the "
00877         "device. On UNIX systems, often system administrator privileges are "
00878         "required to initialize a device." )
00879         << cHardware;
00880       solutions << i18n( "Check that the device is ready; removable drives "
00881         "must contain media, and portable devices must be connected and powered "
00882         "on.; and try again." ) << sAccess << sSysadmin;
00883       break;
00884 
00885     case  KIO::ERR_COULD_NOT_UNMOUNT:
00886       errorName = i18n( "Unable to Uninitialize Input/Output Device" );
00887       techName = i18n( "Could Not Unmount Device" );
00888       description = i18n( "The requested device could not be uninitialized "
00889         "(\"unmounted\"). The reported error was: <strong>%1</strong>" )
00890         .arg( errorText );
00891       causes << i18n( "The device may be busy, that is, still in use by "
00892         "another application or user. Even such things as having an open "
00893         "browser window on a location on this device may cause the device to "
00894         "remain in use." )
00895         << i18n( "You may not have permissions to uninitialize (\"unmount\") "
00896         "the device. On UNIX systems, system administrator privileges are "
00897         "often required to uninitialize a device." )
00898         << cHardware;
00899       solutions << i18n( "Check that no applications are accessing the device, "
00900         "and try again." ) << sAccess << sSysadmin;
00901       break;
00902 
00903     case  KIO::ERR_COULD_NOT_READ:
00904       errorName = i18n( "Cannot Read From Resource" );
00905       description = i18n( "This means that although the resource, "
00906         "<strong>%1</strong>, was able to be opened, an error occurred while "
00907         "reading the contents of the resource." ).arg( url );
00908       causes << i18n( "You may not have permissions to read from the resource." );
00909       if ( !isSlaveNetwork ) causes << cNetwork;
00910       causes << cHardware;
00911       solutions << sAccess;
00912       if ( !isSlaveNetwork ) solutions << sNetwork;
00913       solutions << sSysadmin;
00914       break;
00915 
00916     case  KIO::ERR_COULD_NOT_WRITE:
00917       errorName = i18n( "Cannot Write to Resource" );
00918       description = i18n( "This means that although the resource, <strong>%1</strong>"
00919         ", was able to be opened, an error occurred while writing to the resource." )
00920         .arg( url );
00921       causes << i18n( "You may not have permissions to write to the resource." );
00922       if ( !isSlaveNetwork ) causes << cNetwork;
00923       causes << cHardware;
00924       solutions << sAccess;
00925       if ( !isSlaveNetwork ) solutions << sNetwork;
00926       solutions << sSysadmin;
00927       break;
00928 
00929     case  KIO::ERR_COULD_NOT_BIND:
00930       errorName = i18n( "Could Not Listen for Network Connections" );
00931       techName = i18n( "Could Not Bind" );
00932       description = i18n( "This is a fairly technical error in which a required "
00933         "device for network communications (a socket) could not be established "
00934         "to listen for incoming network connections." );
00935       causes << i18n( "The network connection may be incorrectly configured, or "
00936         "the network interface may not be enabled." );
00937       solutions << sNetwork << sSysadmin;
00938       break;
00939 
00940     case  KIO::ERR_COULD_NOT_LISTEN:
00941       errorName = i18n( "Could Not Listen for Network Connections" );
00942       techName = i18n( "Could Not Listen" );
00943       description = i18n( "This is a fairly technical error in which a required "
00944         "device for network communications (a socket) could not be established "
00945         "to listen for incoming network connections." );
00946       causes << i18n( "The network connection may be incorrectly configured, or "
00947         "the network interface may not be enabled." );
00948       solutions << sNetwork << sSysadmin;
00949       break;
00950 
00951     case  KIO::ERR_COULD_NOT_ACCEPT:
00952       errorName = i18n( "Could Not Accept Network Connection" );
00953       description = i18n( "This is a fairly technical error in which an error "
00954         "occurred while attempting to accept an incoming network connection." );
00955       causes << i18n( "The network connection may be incorrectly configured, or "
00956         "the network interface may not be enabled." )
00957         << i18n( "You may not have permissions to accept the connection." );
00958       solutions << sNetwork << sSysadmin;
00959       break;
00960 
00961     case  KIO::ERR_COULD_NOT_LOGIN:
00962       errorName = i18n( "Could Not Login: %1" ).arg( errorText );
00963       description = i18n( "An attempt to login to perform the requested "
00964         "operation was unsuccessful." );
00965       causes << i18n( "You may have supplied incorrect authentication details or "
00966         "none at all." )
00967         << i18n( "Your account may not have permission to access the "
00968         "specified resource." ) << cProtocol;
00969       solutions << i18n( "Retry the request and ensure your authentication details "
00970         "are entered correctly." ) << sServeradmin << sSysadmin;
00971       break;
00972 
00973     case  KIO::ERR_COULD_NOT_STAT:
00974       errorName = i18n( "Could Not Determine Resource Status" );
00975       techName = i18n( "Could Not Stat Resource" );
00976       description = i18n( "An attempt to determine information about the status "
00977         "of the resource <strong>%1</strong>, such as the resource name, type, "
00978         "size, etc., was unsuccessful." ).arg( url );
00979       causes << i18n( "The specified resource may not have existed or may "
00980         "not be accessible." ) << cProtocol << cHardware;
00981       solutions << i18n( "Retry the request and ensure your authentication details "
00982         "are entered correctly." ) << sSysadmin;
00983       break;
00984 
00985     case  KIO::ERR_COULD_NOT_CLOSEDIR:
00986       //result = i18n( "Could not terminate listing %1" ).arg( errorText );
00987       errorName = i18n( "Could Not Cancel Listing" );
00988       techName = i18n( "FIXME: Document this" );
00989       break;
00990 
00991     case  KIO::ERR_COULD_NOT_MKDIR:
00992       errorName = i18n( "Could Not Create Folder" );
00993       description = i18n( "An attempt to create the requested folder failed." );
00994       causes << cAccess << i18n( "The location where the folder was to be created "
00995         "may not exist." );
00996       if ( !isSlaveNetwork ) causes << cProtocol;
00997       solutions << i18n( "Retry the request." ) << sAccess;
00998       break;
00999 
01000     case  KIO::ERR_COULD_NOT_RMDIR:
01001       errorName = i18n( "Could Not Remove Folder" );
01002       description = i18n( "An attempt to remove the specified folder, "
01003         "<strong>%1</strong>, failed." ).arg( dir );
01004       causes << i18n( "The specified folder may not exist." )
01005         << i18n( "The specified folder may not be empty." )
01006         << cAccess;
01007       if ( !isSlaveNetwork ) causes << cProtocol;
01008       solutions << i18n( "Ensure that the folder exists and is empty, and try "
01009         "again." ) << sAccess;
01010       break;
01011 
01012     case  KIO::ERR_CANNOT_RESUME:
01013       errorName = i18n( "Could Not Resume File Transfer" );
01014       description = i18n( "The specified request asked that the transfer of "
01015         "file <strong>%1</strong> be resumed at a certain point of the "
01016         "transfer. This was not possible." ).arg( filename );
01017       causes << i18n( "The protocol, or the server, may not support file "
01018         "resuming." );
01019       solutions << i18n( "Retry the request without attempting to resume "
01020         "transfer." );
01021       break;
01022 
01023     case  KIO::ERR_CANNOT_RENAME:
01024       errorName = i18n( "Could Not Rename Resource" );
01025       description = i18n( "An attempt to rename the specified resource "
01026         "<strong>%1</strong> failed." ).arg( url );
01027       causes << cAccess << cExists;
01028       if ( !isSlaveNetwork ) causes << cProtocol;
01029       solutions << sAccess << sExists;
01030       break;
01031 
01032     case  KIO::ERR_CANNOT_CHMOD:
01033       errorName = i18n( "Could Not Alter Permissions of Resource" );
01034       description = i18n( "An attempt to alter the permissions on the specified "
01035         "resource <strong>%1</strong> failed." ).arg( url );
01036       causes << cAccess << cExists;
01037       solutions << sAccess << sExists;
01038       break;
01039 
01040     case  KIO::ERR_CANNOT_DELETE:
01041       errorName = i18n( "Could Not Delete Resource" );
01042       description = i18n( "An attempt to delete the specified resource "
01043         "<strong>%1</strong> failed." ).arg( url );
01044       causes << cAccess << cExists;
01045       solutions << sAccess << sExists;
01046       break;
01047 
01048     case  KIO::ERR_SLAVE_DIED:
01049       errorName = i18n( "Unexpected Program Termination" );
01050       description = i18n( "The program on your computer which provides access "
01051         "to the <strong>%1</strong> protocol has unexpectedly terminated." )
01052         .arg( url );
01053       causes << cBuglikely;
01054       solutions << sUpdate << sBugreport;
01055       break;
01056 
01057     case  KIO::ERR_OUT_OF_MEMORY:
01058       errorName = i18n( "Out of Memory" );
01059       description = i18n( "The program on your computer which provides access "
01060         "to the <strong>%1</strong> protocol could not obtain the memory "
01061         "required to continue." ).arg( protocol );
01062       causes << cBuglikely;
01063       solutions << sUpdate << sBugreport;
01064       break;
01065 
01066     case  KIO::ERR_UNKNOWN_PROXY_HOST:
01067       errorName = i18n( "Unknown Proxy Host" );
01068       description = i18n( "While retrieving information about the specified "
01069         "proxy host, <strong>%1</strong>, an Unknown Host error was encountered. "
01070         "An unknown host error indicates that the requested name could not be "
01071         "located on the Internet." ).arg( errorText );
01072       causes << i18n( "There may have been a problem with your network "
01073         "configuration, specifically your proxy's hostname. If you have been "
01074         "accessing the Internet with no problems recently, this is unlikely." )
01075         << cNetwork;
01076       solutions << i18n( "Double-check your proxy settings and try again." )
01077         << sSysadmin;
01078       break;
01079 
01080     case  KIO::ERR_COULD_NOT_AUTHENTICATE:
01081       errorName = i18n( "Authentication Failed: Method %1 Not Supported" )
01082          .arg( errorText );
01083       description = i18n( "Although you may have supplied the correct "
01084         "authentication details, the authentication failed because the "
01085         "method that the server is using is not supported by the KDE "
01086         "program implementing the protocol %1." ).arg( protocol );
01087       solutions << i18n( "Please file a bug at <a href=\"http://bugs.kde.org/\">"
01088         "http://bugs.kde.org/</a> to inform the KDE team of the unsupported "
01089         "authentication method." ) << sSysadmin;
01090       break;
01091 
01092     case  KIO::ERR_ABORTED:
01093       errorName = i18n( "Request Aborted" );
01094       description = i18n( "The request was not completed because it was "
01095         "aborted." );
01096       solutions << i18n( "Retry the request." );
01097       break;
01098 
01099     case  KIO::ERR_INTERNAL_SERVER:
01100       errorName = i18n( "Internal Error in Server" );
01101       description = i18n( "The program on the server which provides access "
01102         "to the <strong>%1</strong> protocol has reported an internal error: "
01103         "%0." ).arg( protocol );
01104       causes << i18n( "This is most likely to be caused by a bug in the "
01105         "server program. Please consider submitting a full bug report as "
01106         "detailed below." );
01107       solutions << i18n( "Contact the administrator of the server "
01108         "to advise them of the problem." )
01109         << i18n( "If you know who the authors of the server software are, "
01110         "submit the bug report directly to them." );
01111       break;
01112 
01113     case  KIO::ERR_SERVER_TIMEOUT:
01114       errorName = i18n( "Timeout Error" );
01115       description = i18n( "Although contact was made with the server, a "
01116         "response was not received within the amount of time allocated for "
01117         "the request as follows:<ul>"
01118         "<li>Timeout for establishing a connection: %1 seconds</li>"
01119         "<li>Timeout for receiving a response: %2 seconds</li>"
01120         "<li>Timeout for accessing proxy servers: %3 seconds</li></ul>"
01121         "Please note that you can alter these timeout settings in the KDE "
01122         "Control Center, by selecting Network -> Preferences." )
01123         .arg( KProtocolManager::connectTimeout() )
01124         .arg( KProtocolManager::responseTimeout() )
01125         .arg( KProtocolManager::proxyConnectTimeout() );
01126       causes << cNetpath << i18n( "The server was too busy responding to other "
01127         "requests to respond." );
01128       solutions << sTryagain << sServeradmin;
01129       break;
01130 
01131     case  KIO::ERR_UNKNOWN:
01132       errorName = i18n( "Unknown Error" );
01133       description = i18n( "The program on your computer which provides access "
01134         "to the <strong>%1</strong> protocol has reported an unknown error: "
01135         "%2." ).arg( protocol ).arg( errorText );
01136       causes << cBug;
01137       solutions << sUpdate << sBugreport;
01138       break;
01139 
01140     case  KIO::ERR_UNKNOWN_INTERRUPT:
01141       errorName = i18n( "Unknown Interruption" );
01142       description = i18n( "The program on your computer which provides access "
01143         "to the <strong>%1</strong> protocol has reported an interruption of "
01144         "an unknown type: %2." ).arg( protocol ).arg( errorText );
01145       causes << cBug;
01146       solutions << sUpdate << sBugreport;
01147       break;
01148 
01149     case KIO::ERR_CANNOT_DELETE_ORIGINAL:
01150       errorName = i18n( "Could Not Delete Original File" );
01151       description = i18n( "The requested operation required the deleting of "
01152         "the original file, most likely at the end of a file move operation. "
01153         "The original file <strong>%1</strong> could not be deleted." )
01154         .arg( errorText );
01155       causes << cAccess;
01156       solutions << sAccess;
01157       break;
01158 
01159     case KIO::ERR_CANNOT_DELETE_PARTIAL:
01160       errorName = i18n( "Could Not Delete Temporary File" );
01161       description = i18n( "The requested operation required the creation of "
01162         "a temporary file in which to save the new file while being "
01163         "downloaded. This temporary file <strong>%1</strong> could not be "
01164         "deleted." ).arg( errorText );
01165       causes << cAccess;
01166       solutions << sAccess;
01167       break;
01168 
01169     case KIO::ERR_CANNOT_RENAME_ORIGINAL:
01170       errorName = i18n( "Could Not Rename Original File" );
01171       description = i18n( "The requested operation required the renaming of "
01172         "the original file <strong>%1</strong>, however it could not be "
01173         "renamed." ).arg( errorText );
01174       causes << cAccess;
01175       solutions << sAccess;
01176       break;
01177 
01178     case KIO::ERR_CANNOT_RENAME_PARTIAL:
01179       errorName = i18n( "Could Not Rename Temporary File" );
01180       description = i18n( "The requested operation required the creation of "
01181         "a temporary file <strong>%1</strong>, however it could not be "
01182         "created." ).arg( errorText );
01183       causes << cAccess;
01184       solutions << sAccess;
01185       break;
01186 
01187     case KIO::ERR_CANNOT_SYMLINK:
01188       errorName = i18n( "Could Not Create Link" );
01189       techName = i18n( "Could Not Create Symbolic Link" );
01190       description = i18n( "The requested symbolic link %1 could not be created." )
01191         .arg( errorText );
01192       causes << cAccess;
01193       solutions << sAccess;
01194       break;
01195 
01196     case KIO::ERR_NO_CONTENT:
01197       errorName = i18n( "No Content" );
01198       description = errorText;
01199       break;
01200 
01201     case KIO::ERR_DISK_FULL:
01202       errorName = i18n( "Disk Full" );
01203       description = i18n( "The requested file <strong>%1</strong> could not be "
01204         "written to as there is inadequate disk space." ).arg( errorText );
01205       solutions << i18n( "Free up enough disk space by 1) deleting unwanted and "
01206         "temporary files; 2) archiving files to removable media storage such as "
01207         "CD-Recordable discs; or 3) obtain more storage capacity." )
01208         << sSysadmin;
01209       break;
01210 
01211     case KIO::ERR_IDENTICAL_FILES:
01212       errorName = i18n( "Source and Destination Files Identical" );
01213       description = i18n( "The operation could not be completed because the "
01214         "source and destination files are the same file." );
01215       solutions << i18n( "Choose a different filename for the destination file." );
01216       break;
01217 
01218     // We assume that the slave has all the details
01219     case KIO::ERR_SLAVE_DEFINED:
01220       errorName = QString::null;
01221       description = errorText;
01222       break;
01223 
01224     default:
01225       // fall back to the plain error...
01226       errorName = i18n( "Undocumented Error" );
01227       description = buildErrorString( errorCode, errorText );
01228   }
01229 
01230   QByteArray ret;
01231   QDataStream stream(ret, IO_WriteOnly);
01232   stream << errorName << techName << description << causes << solutions;
01233   return ret;
01234 }
01235 
01236 #ifdef Q_OS_UNIX
01237 
01238 #include <limits.h>
01239 #include <stdlib.h>
01240 #include <stdio.h>
01241 #include <qfile.h>
01242 
01243 #include <config.h>
01244 
01245 #ifdef HAVE_PATHS_H
01246 #include <paths.h>
01247 #endif
01248 #ifdef HAVE_SYS_STAT_H
01249 #include <sys/stat.h>
01250 #endif
01251 #include <sys/param.h>
01252 #ifdef HAVE_LIMITS_H
01253 #include <limits.h>
01254 #endif
01255 #ifdef HAVE_SYS_MNTTAB_H
01256 #include <sys/mnttab.h>
01257 #endif
01258 #ifdef HAVE_MNTENT_H
01259 #include <mntent.h>
01260 #elif defined(HAVE_SYS_MNTENT_H)
01261 #include <sys/mntent.h>
01262 #endif
01263 #ifdef HAVE_SYS_UCRED_H
01264 #include <sys/ucred.h>
01265 #endif
01266 #ifdef HAVE_SYS_MOUNT_H
01267 #include <sys/mount.h>
01268 #endif
01269 #ifdef HAVE_FSTAB_H
01270 #include <fstab.h>
01271 #endif
01272 #if defined(_AIX)
01273 #include <sys/mntctl.h>
01274 #include <sys/vmount.h>
01275 #include <sys/vfs.h>
01276 
01277 /* AIX does not prototype mntctl anywhere that I can find */
01278 #ifndef mntctl
01279 extern "C" {
01280 int mntctl(int command, int size, void* buffer);
01281 }
01282 #endif
01283 extern "C" struct vfs_ent *getvfsbytype(int vfsType);
01284 extern "C" void endvfsent( );
01285 #endif
01286 
01287 /***************************************************************
01288  *
01289  * Utility functions
01290  *
01291  ***************************************************************/
01292 
01293 #ifndef HAVE_GETMNTINFO
01294 
01295 #ifdef _PATH_MOUNTED
01296 // On some Linux, MNTTAB points to /etc/fstab !
01297 # undef MNTTAB
01298 # define MNTTAB _PATH_MOUNTED
01299 #else
01300 # ifndef MNTTAB
01301 #  ifdef MTAB_FILE
01302 #   define MNTTAB MTAB_FILE
01303 #  else
01304 #   define MNTTAB "/etc/mnttab"
01305 #  endif
01306 # endif
01307 #endif
01308 
01309 #ifndef FSTAB
01310 # ifdef _PATH_FSTAB
01311 #  define FSTAB _PATH_FSTAB
01312 # else
01313 #  define FSTAB "/etc/fstab"
01314 # endif
01315 #endif
01316 
01317 // There are (at least) four kind of APIs:
01318 // setmntent + getmntent + struct mntent (linux...)
01319 //             getmntent + struct mnttab
01320 // mntctl                + struct vmount (AIX)
01321 // getmntinfo + struct statfs&flags (BSD 4.4 and friends)
01322 // getfsent + char* (BSD 4.3 and friends)
01323 
01324 #ifdef HAVE_SETMNTENT
01325 #define SETMNTENT setmntent
01326 #define ENDMNTENT endmntent
01327 #define STRUCT_MNTENT struct mntent *
01328 #define STRUCT_SETMNTENT FILE *
01329 #define GETMNTENT(file, var) ((var = getmntent(file)) != 0)
01330 #define MOUNTPOINT(var) var->mnt_dir
01331 #define MOUNTTYPE(var) var->mnt_type
01332 #define HASMNTOPT(var, opt) hasmntopt(var, opt)
01333 #define FSNAME(var) var->mnt_fsname
01334 #elif defined(_AIX)
01335 /* we don't need this stuff */
01336 #else
01337 #define SETMNTENT fopen
01338 #define ENDMNTENT fclose
01339 #define STRUCT_MNTENT struct mnttab
01340 #define STRUCT_SETMNTENT FILE *
01341 #define GETMNTENT(file, var) (getmntent(file, &var) == 0)
01342 #define MOUNTPOINT(var) var.mnt_mountp
01343 #define MOUNTTYPE(var) var.mnt_fstype
01344 #define HASMNTOPT(var, opt) hasmntopt(&var, opt)
01345 #define FSNAME(var) var.mnt_special
01346 #endif
01347 
01348 #endif /* HAVE_GETMNTINFO */
01349 
01350 QString KIO::findDeviceMountPoint( const QString& filename )
01351 {
01352     QString result;
01353 
01354 #ifdef HAVE_VOLMGT
01355     /*
01356      *  support for Solaris volume management
01357      */
01358     const char *volpath;
01359     FILE *mnttab;
01360     struct mnttab mnt;
01361     int len;
01362     QCString devname;
01363 
01364     if( (volpath = volmgt_root()) == NULL ) {
01365         kdDebug( 7007 ) << "findDeviceMountPoint: "
01366             << "VOLMGT: can't find volmgt root dir" << endl;
01367         return QString::null;
01368     }
01369 
01370     if( (mnttab = fopen( MNTTAB, "r" )) == NULL ) {
01371         kdDebug( 7007 ) << "findDeviceMountPoint: "
01372             << "VOLMGT: can't open mnttab" << endl;
01373         return QString::null;
01374     }
01375 
01376     devname = volpath;
01377     devname += QFile::encodeName( filename );
01378     devname += '/';
01379     len = devname.length();
01380 //  kdDebug( 7007 ) << "findDeviceMountPoint: "
01381 //      << "VOLMGT: searching mountpoint for \"" << devname << "\""
01382 //      << endl;
01383 
01384     /*
01385      *  find the mountpoint
01386      *  floppies:
01387      *  /dev/disketteN    => <volpath>/dev/disketteN
01388      *  CDROM, ZIP, and other media:
01389      *  /dev/dsk/cXtYdZs2 => <volpath>/dev/dsk/cXtYdZ  (without slice#)
01390      */
01391     rewind( mnttab );
01392     result = QString::null;
01393     while( getmntent( mnttab, &mnt ) == 0 ) {
01394         /*
01395          *  either match the exact device name (floppies),
01396          *  or the device name without the slice#
01397          */
01398         if( strncmp( devname.data(), mnt.mnt_special, len ) == 0
01399             || (strncmp( devname.data(), mnt.mnt_special, len - 3 ) == 0
01400                 && mnt.mnt_special[len - 3] == '/' )
01401             || (strcmp(QFile::encodeName(filename).data()
01402                     , mnt.mnt_special)==0)) {
01403             result = mnt.mnt_mountp;
01404             break;
01405         }
01406     }
01407     fclose( mnttab );
01408 #else
01409 
01410     char    realpath_buffer[MAXPATHLEN];
01411     QCString realname;
01412 
01413     realname = QFile::encodeName(filename);
01414     /* If the path contains symlinks, get the real name */
01415     if (realpath(realname, realpath_buffer) != 0)
01416       // succes, use result from realpath
01417       realname = realpath_buffer;
01418 
01419     //kdDebug(7007) << "findDeviceMountPoint realname=" << realname << endl;
01420 
01421 #ifdef HAVE_GETMNTINFO
01422 
01423     struct statfs *mounted;
01424 
01425     int num_fs = getmntinfo(&mounted, MNT_NOWAIT);
01426 
01427     for (int i=0;i<num_fs;i++) {
01428 
01429         QCString device_name = mounted[i].f_mntfromname;
01430 
01431         // If the path contains symlinks, get
01432         // the real name
01433         if (realpath(device_name, realpath_buffer) != 0)
01434             // succes, use result from realpath
01435             device_name = realpath_buffer;
01436 
01437         if (realname == device_name) {
01438             result = mounted[i].f_mntonname;
01439             break;
01440         }
01441     }
01442 
01443 #elif defined(_AIX)
01444 
01445     struct vmount *mntctl_buffer;
01446     struct vmount *vm;
01447     char *mountedfrom;
01448     char *mountedto;
01449     int fsname_len, num;
01450     int buf_sz = 4096;
01451 
01452     /* mntctl can be used to query mounted file systems.
01453      * mntctl takes only the command MCTL_QUERY so far.
01454      * The buffer is filled with an array of vmount structures, but these
01455      * vmount structures have variable size.
01456      * mntctl return values:
01457      * -1 error
01458      *  0 look in first word of buffer for required bytes, 4096 may be
01459      *    a good starting size, but if tables grow too large, look here.
01460      * >0 number of vmount structures
01461      */
01462     mntctl_buffer = (struct vmount*)malloc(buf_sz);
01463     num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
01464     if (num == 0)
01465     {
01466     buf_sz = *(int*)mntctl_buffer;
01467     free(mntctl_buffer);
01468     mntctl_buffer = (struct vmount*)malloc(buf_sz);
01469     num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
01470     }
01471 
01472     if (num > 0)
01473     {
01474         /* iterate through items in the vmount structure: */
01475         vm = mntctl_buffer;
01476         for ( ; num > 0; num-- )
01477         {
01478             /* get the name of the mounted file systems: */
01479             fsname_len = vmt2datasize(vm, VMT_STUB);
01480             mountedto     = (char*)malloc(fsname_len + 1);
01481         mountedto[fsname_len] = '\0';
01482             strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len);
01483 
01484             /* get the mount-from information: */
01485             fsname_len = vmt2datasize(vm, VMT_OBJECT);
01486             mountedfrom     = (char*)malloc(fsname_len + 1);
01487         mountedfrom[fsname_len] = '\0';
01488             strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len);
01489 
01490             QCString device_name = mountedfrom;
01491 
01492             if (realpath(device_name, realpath_buffer) != 0)
01493                 // success, use result from realpath
01494                 device_name = realpath_buffer;
01495 
01496             free(mountedfrom);
01497 
01498             if (realname == device_name) {
01499                 result = mountedto;
01500                 free(mountedto);
01501                 break;
01502             }
01503 
01504             free(mountedto);
01505 
01506             /* goto the next vmount structure: */
01507             vm = (struct vmount *)((char *)vm + vm->vmt_length);
01508         }
01509     }
01510 
01511     free( mntctl_buffer );
01512 
01513 #else
01514 
01515     STRUCT_SETMNTENT mtab;
01516 
01517     /* Get the list of mounted file systems */
01518 
01519     if ((mtab = SETMNTENT(MNTTAB, "r")) == 0) {
01520         perror("setmntent");
01521         return QString::null;
01522     }
01523 
01524     /* Loop over all file systems and see if we can find our
01525      * mount point.
01526      * Note that this is the mount point with the longest match.
01527      * XXX: Fails if me->mnt_dir is not a realpath but goes
01528      * through a symlink, e.g. /foo/bar where /foo is a symlink
01529      * pointing to /local/foo.
01530      *
01531      * How kinky can you get with a filesystem?
01532      */
01533 
01534     STRUCT_MNTENT me;
01535 
01536     while (GETMNTENT(mtab, me))
01537     {
01538       // There may be symbolic links into the /etc/mnttab
01539       // So we have to find the real device name here as well!
01540       QCString device_name = FSNAME(me);
01541       if (device_name.isEmpty() || (device_name == "none"))
01542          continue;
01543 
01544       //kdDebug( 7007 ) << "device_name=" << device_name << endl;
01545 
01546       // If the path contains symlinks, get
01547       // the real name
01548       if (realpath(device_name, realpath_buffer) != 0)
01549           // succes, use result from realpath
01550          device_name = realpath_buffer;
01551 
01552       //kdDebug( 7007 ) << "device_name after realpath =" << device_name << endl;
01553 
01554       if (realname == device_name)
01555       {
01556           result = MOUNTPOINT(me);
01557           break;
01558       }
01559     }
01560 
01561     ENDMNTENT(mtab);
01562 
01563 #endif /* GET_MNTINFO */
01564 #endif /* HAVE_VOLMGT */
01565 
01566     //kdDebug( 7007 ) << "Returning result " << result << endl;
01567     return result;
01568 }
01569 
01570 // Don't just trust the return value, keep iterating to check for a better match (bigger max)
01571 static bool is_my_mountpoint( const char *mountpoint, const char *realname, int &max )
01572 {
01573     int length = strlen(mountpoint);
01574 
01575     if (!strncmp(mountpoint, realname, length)
01576         && length > max) {
01577         max = length;
01578         if (length == 1 || realname[length] == '/' || realname[length] == '\0')
01579             return true;
01580     }
01581     return false;
01582 }
01583 
01584 typedef enum { Unseen, Right, Wrong } MountState;
01585 
01589 static void check_mount_point(const char *mounttype,
01590                               const char *fsname,
01591                               MountState &isslow, MountState &isautofs)
01592 {
01593     bool nfs = !strcmp(mounttype, "nfs");
01594     bool autofs = !strcmp(mounttype, "autofs") || !strcmp(mounttype,"subfs");
01595     bool pid = (strstr(fsname, ":(pid") != 0);
01596 
01597     if (nfs && !pid)
01598         isslow = Right;
01599     else if (isslow == Right)
01600         isslow = Wrong;
01601 
01602     /* Does this look like automounted? */
01603     if (autofs || (nfs && pid)) {
01604         isautofs = Right;
01605         isslow = Right;
01606     }
01607 }
01608 
01609 // returns the mount point, checks the mount state.
01610 // if ismanual == Wrong this function does not check the manual mount state
01611 static QString get_mount_info(const QString& filename,
01612     MountState& isautofs, MountState& isslow, MountState& ismanual,
01613     QString& fstype)
01614 {
01615     static bool gotRoot = false;
01616     static dev_t rootDevice;
01617 
01618     struct cachedDevice_t
01619     {
01620        dev_t device;
01621        QString mountPoint;
01622        MountState isautofs;
01623        MountState isslow;
01624        MountState ismanual;
01625        QString fstype;
01626     };
01627     static struct cachedDevice_t *cachedDevice = 0;
01628 
01629     if (!gotRoot)
01630     {
01631        KDE_struct_stat stat_buf;
01632        KDE_stat("/", &stat_buf);
01633        gotRoot = true;
01634        rootDevice = stat_buf.st_dev;
01635     }
01636 
01637     bool gotDevice = false;
01638     KDE_struct_stat stat_buf;
01639     if (KDE_stat(QFile::encodeName(filename), &stat_buf) == 0)
01640     {
01641        gotDevice = true;
01642        if (stat_buf.st_dev == rootDevice)
01643        {
01644           static const QString &root = KGlobal::staticQString("/");
01645           isautofs = Wrong;
01646           isslow = Wrong;
01647           ismanual = Wrong;
01648           fstype = QString::null; // ### do we need it?
01649           return root;
01650        }
01651        if (cachedDevice && (stat_buf.st_dev == cachedDevice->device))
01652        {
01653           bool interestedInIsManual = ismanual != Wrong;
01654           isautofs = cachedDevice->isautofs;
01655           isslow = cachedDevice->isslow;
01656           ismanual = cachedDevice->ismanual;
01657           fstype = cachedDevice->fstype;
01658           // Don't use the cache if it doesn't have the information we're looking for
01659           if ( !interestedInIsManual || ismanual != Unseen )
01660               return cachedDevice->mountPoint;
01661        }
01662     }
01663 
01664     char realname[MAXPATHLEN];
01665 
01666     memset(realname, 0, MAXPATHLEN);
01667 
01668     /* If the path contains symlinks, get the real name */
01669     if (realpath(QFile::encodeName(filename), realname) == 0) {
01670         if( strlcpy(realname, QFile::encodeName(filename), MAXPATHLEN)>=MAXPATHLEN)
01671             return QString::null;
01672     }
01673 
01674     int max = 0;
01675     QString mountPoint;
01676 
01677     /* Loop over all file systems and see if we can find our
01678      * mount point.
01679      * Note that this is the mount point with the longest match.
01680      * XXX: Fails if me->mnt_dir is not a realpath but goes
01681      * through a symlink, e.g. /foo/bar where /foo is a symlink
01682      * pointing to /local/foo.
01683      *
01684      * How kinky can you get with a filesystem?
01685      */
01686 
01687 #ifdef HAVE_GETMNTINFO
01688 
01689     struct statfs *mounted;
01690     char    realpath_buffer[MAXPATHLEN];
01691 
01692     int num_fs = getmntinfo(&mounted, MNT_NOWAIT);
01693 
01694     for (int i=0;i<num_fs;i++) {
01695 
01696         QCString device_name = mounted[i].f_mntfromname;
01697 
01698         // If the path contains symlinks, get
01699         // the real name
01700         if (realpath(device_name, realpath_buffer) != 0)
01701             // succes, use result from realpath
01702             device_name = realpath_buffer;
01703 #ifdef __osf__
01704         char * mounttype = mnt_names[mounted[i].f_type];
01705 #else
01706         char * mounttype = mounted[i].f_fstypename;
01707 #endif
01708         if ( is_my_mountpoint( mounted[i].f_mntonname, realname, max ) )
01709         {
01710             mountPoint = QFile::decodeName(mounted[i].f_mntonname);
01711             fstype = QString::fromLatin1(mounttype);
01712             check_mount_point( mounttype, mounted[i].f_mntfromname,
01713                                isautofs, isslow );
01714             // keep going, looking for a potentially better one
01715 
01716             if (ismanual == Unseen)
01717             {
01718                 struct fstab *ft = getfsfile(mounted[i].f_mntonname);
01719                 if (!ft || strstr(ft->fs_mntops, "noauto"))
01720                   ismanual = Right;
01721             }
01722         }
01723     }
01724 
01725 #elif defined(_AIX)
01726 
01727     struct vmount *mntctl_buffer;
01728     struct vmount *vm;
01729     char *mountedfrom;
01730     char *mountedto;
01731     int fsname_len, num;
01732     char realpath_buffer[MAXPATHLEN];
01733     int buf_sz = 4096;
01734 
01735     mntctl_buffer = (struct vmount*)malloc(buf_sz);
01736     num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
01737     if (num == 0)
01738     {
01739     buf_sz = *(int*)mntctl_buffer;
01740     free(mntctl_buffer);
01741     mntctl_buffer = (struct vmount*)malloc(buf_sz);
01742     num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
01743     }
01744 
01745     if (num > 0)
01746     {
01747         /* iterate through items in the vmount structure: */
01748         vm = (struct vmount *)mntctl_buffer;
01749         for ( ; num > 0; num-- )
01750         {
01751             /* get the name of the mounted file systems: */
01752             fsname_len = vmt2datasize(vm, VMT_STUB);
01753             mountedto     = (char*)malloc(fsname_len + 1);
01754         mountedto[fsname_len] = '\0';
01755             strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len);
01756 
01757             fsname_len = vmt2datasize(vm, VMT_OBJECT);
01758             mountedfrom     = (char*)malloc(fsname_len + 1);
01759         mountedfrom[fsname_len] = '\0';
01760             strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len);
01761 
01762             /* get the mount-from information: */
01763             QCString device_name = mountedfrom;
01764 
01765             if (realpath(device_name, realpath_buffer) != 0)
01766                 // success, use result from realpath
01767                 device_name = realpath_buffer;
01768 
01769         /* Look up the string for the file system type,
01770              * as listed in /etc/vfs.
01771              * ex.: nfs,jfs,afs,cdrfs,sfs,cachefs,nfs3,autofs
01772              */
01773             struct vfs_ent* ent = getvfsbytype(vm->vmt_gfstype);
01774 
01775             if ( is_my_mountpoint( mountedto, realname, max ) )
01776             {
01777                 mountPoint = QFile::decodeName(mountedto);
01778                 fstype = QString::fromLatin1(ent->vfsent_name);
01779                 check_mount_point(ent->vfsent_name, device_name, isautofs, isslow);
01780 
01781                 if (ismanual == Unseen)
01782                 {
01783                     // TODO: add check for ismanual, I couldn't find any way
01784                     // how to get the mount attribute from /etc/filesystems
01785                     ismanual == Wrong;
01786                 }
01787             }
01788 
01789             free(mountedfrom);
01790             free(mountedto);
01791 
01792             /* goto the next vmount structure: */
01793             vm = (struct vmount *)((char *)vm + vm->vmt_length);
01794         }
01795 
01796     endvfsent( );
01797     }
01798 
01799     free( mntctl_buffer );
01800 
01801 #else
01802 
01803     STRUCT_SETMNTENT mtab;
01804     /* Get the list of mounted file systems */
01805 
01806     if ((mtab = SETMNTENT(MNTTAB, "r")) == 0) {
01807         perror("setmntent");
01808         return QString::null;
01809     }
01810 
01811     STRUCT_MNTENT me;
01812 
01813     while (true) {
01814         if (!GETMNTENT(mtab, me))
01815             break;
01816 
01817         if ( is_my_mountpoint( MOUNTPOINT(me), realname, max ) )
01818         {
01819             mountPoint = QFile::decodeName( MOUNTPOINT(me) );
01820             fstype = MOUNTTYPE(me);
01821             check_mount_point(MOUNTTYPE(me), FSNAME(me), isautofs, isslow);
01822             // we don't check if ismanual is Right, if /a/b is manually
01823             // mounted /a/b/c can't be automounted. At least IMO.
01824             if (ismanual == Unseen)
01825             {
01826                 // The next GETMNTENT call may destroy 'me'
01827                 // Copy out the info that we need
01828                 QCString fsname_me = FSNAME(me);
01829                 QCString mounttype_me = MOUNTTYPE(me);
01830 
01831                 STRUCT_SETMNTENT fstab;
01832                 if ((fstab = SETMNTENT(FSTAB, "r")) == 0) {
01833                     continue;
01834                 }
01835 
01836                 bool found = false;
01837                 STRUCT_MNTENT fe;
01838                 while (GETMNTENT(fstab, fe))
01839                 {
01840                     if (fsname_me == FSNAME(fe))
01841                     {
01842                         found = true;
01843                         if (HASMNTOPT(fe, "noauto") ||
01844                             !strcmp(MOUNTTYPE(fe), "subfs") ||
01845                             !strcmp(MOUNTTYPE(fe), "supermount"))
01846                             ismanual = Right;
01847                         break;
01848                     }
01849                 }
01850                 if (!found || (mounttype_me == "subfs") || (mounttype_me == "supermount"))
01851                   ismanual = Right;
01852 
01853                 ENDMNTENT(fstab);
01854             }
01855         }
01856     }
01857 
01858     ENDMNTENT(mtab);
01859 
01860 #endif
01861 
01862     if (isautofs == Right && isslow == Unseen)
01863         isslow = Right;
01864 
01865     if (gotDevice)
01866     {
01867        if (!cachedDevice)
01868           cachedDevice = new cachedDevice_t;
01869 
01870        cachedDevice->device = stat_buf.st_dev;
01871        cachedDevice->mountPoint = mountPoint;
01872        cachedDevice->isautofs = isautofs;
01873        cachedDevice->isslow = isslow;
01874        cachedDevice->ismanual = ismanual;
01875        cachedDevice->fstype = fstype;
01876     }
01877 
01878     return mountPoint;
01879 }
01880 
01881 #else 
01882 //dummy
01883 QString KIO::findDeviceMountPoint( const QString& filename )
01884 {
01885     return QString::null;
01886 }
01887 #endif
01888 
01889 QString KIO::findPathMountPoint(const QString& filename)
01890 {
01891 #ifdef Q_OS_UNIX
01892   MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong;
01893   QString fstype;
01894   return get_mount_info(filename, isautofs, isslow, ismanual, fstype);
01895 #else 
01896   return QString::null;
01897 #endif 
01898 }
01899 
01900 bool KIO::manually_mounted(const QString& filename)
01901 {
01902 #ifdef Q_OS_UNIX
01903   MountState isautofs = Unseen, isslow = Unseen, ismanual = Unseen;
01904   QString fstype;
01905   QString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype);
01906   return !mountPoint.isNull() && (ismanual == Right);
01907 #else 
01908   return false;
01909 #endif 
01910 }
01911 
01912 bool KIO::probably_slow_mounted(const QString& filename)
01913 {
01914 #ifdef Q_OS_UNIX
01915   MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong;
01916   QString fstype;
01917   QString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype);
01918   return !mountPoint.isNull() && (isslow == Right);
01919 #else 
01920   return false;
01921 #endif 
01922 }
01923 
01924 bool KIO::testFileSystemFlag(const QString& filename, FileSystemFlag flag)
01925 {
01926 #ifdef Q_OS_UNIX
01927   MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong;
01928   QString fstype;
01929   QString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype);
01930     kdDebug() << "testFileSystemFlag: fstype=" << fstype << endl;
01931   if (mountPoint.isNull())
01932       return false;
01933   bool isMsDos = ( fstype == "msdos" || fstype == "fat" || fstype == "vfat" );
01934   switch (flag)  {
01935   case SupportsChmod:
01936   case SupportsChown:
01937   case SupportsUTime:
01938   case SupportsSymlinks:
01939       return !isMsDos; // it's amazing the number of things FAT doesn't support :)
01940   case CaseInsensitive:
01941       return isMsDos;
01942   }
01943 #endif 
01944   return false;
01945 }
01946 
01947 KIO::CacheControl KIO::parseCacheControl(const QString &cacheControl)
01948 {
01949   QString tmp = cacheControl.lower();
01950 
01951   if (tmp == "cacheonly")
01952      return KIO::CC_CacheOnly;
01953   if (tmp == "cache")
01954      return KIO::CC_Cache;
01955   if (tmp == "verify")
01956      return KIO::CC_Verify;
01957   if (tmp == "refresh")
01958      return KIO::CC_Refresh;
01959   if (tmp == "reload")
01960      return KIO::CC_Reload;
01961 
01962   kdDebug() << "unrecognized Cache control option:"<<cacheControl<<endl;
01963   return KIO::CC_Verify;
01964 }
01965 
01966 QString KIO::getCacheControlString(KIO::CacheControl cacheControl)
01967 {
01968     if (cacheControl == KIO::CC_CacheOnly)
01969     return "CacheOnly";
01970     if (cacheControl == KIO::CC_Cache)
01971     return "Cache";
01972     if (cacheControl == KIO::CC_Verify)
01973     return "Verify";
01974     if (cacheControl == KIO::CC_Refresh)
01975     return "Refresh";
01976     if (cacheControl == KIO::CC_Reload)
01977     return "Reload";
01978     kdDebug() << "unrecognized Cache control enum value:"<<cacheControl<<endl;
01979     return QString::null;
01980 }
KDE Logo
This file is part of the documentation for kio Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Jan 23 19:33:28 2006 by doxygen 1.4.3 written by Dimitri van Heesch, © 1997-2003