• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

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

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeio/tdeio by doxygen 1.7.1
This website is maintained by Timothy Pearson.