• 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 Trinity website for a TDE "
00692         "program (called a tdeioslave, ioslave or tdeio) which supports this protocol. "
00693         "Places to search include <a href=\"https://mirror.git.trinitydesktop.org/cgit/\">"
00694         "https://mirror.git.trinitydesktop.org/cgit/</a> or the repos for your distribution." )
00695         << sUpdate << sSysadmin;
00696       break;
00697 
00698     case  TDEIO::ERR_NO_SOURCE_PROTOCOL:
00699       errorName = i18n( "URL Does Not Refer to a Resource." );
00700       techName = i18n( "Protocol is a Filter Protocol" );
00701       description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource "
00702         "<strong>L</strong>ocator (URL) that you entered did not refer to a "
00703         "specific resource." );
00704       causes << i18n( "TDE is able to communicate through a protocol within a "
00705         "protocol; the protocol specified is only for use in such situations, "
00706         "however this is not one of these situations. This is a rare event, and "
00707         "is likely to indicate a programming error." );
00708       solutions << sTypo;
00709       break;
00710 
00711     case  TDEIO::ERR_UNSUPPORTED_ACTION:
00712       errorName = i18n( "Unsupported Action: %1" ).arg( errorText );
00713       description = i18n( "The requested action is not supported by the TDE "
00714         "program which is implementing the <strong>%1</strong> protocol." )
00715         .arg( protocol );
00716       causes << i18n( "This error is very much dependent on the TDE program. The "
00717         "additional information should give you more information than is available "
00718         "to the TDE input/output architecture." );
00719       solutions << i18n( "Attempt to find another way to accomplish the same "
00720         "outcome." );
00721       break;
00722 
00723     case  TDEIO::ERR_IS_DIRECTORY:
00724       errorName = i18n( "File Expected" );
00725       description = i18n( "The request expected a file, however the "
00726         "folder <strong>%1</strong> was found instead." ).arg( dir );
00727       causes << i18n( "This may be an error on the server side." ) << cBug;
00728       solutions << sUpdate << sSysadmin;
00729       break;
00730 
00731     case  TDEIO::ERR_IS_FILE:
00732       errorName = i18n( "Folder Expected" );
00733       description = i18n( "The request expected a folder, however "
00734         "the file <strong>%1</strong> was found instead." ).arg( filename );
00735       causes << cBug;
00736       solutions << sUpdate << sSysadmin;
00737       break;
00738 
00739     case  TDEIO::ERR_DOES_NOT_EXIST:
00740       errorName = i18n( "File or Folder Does Not Exist" );
00741       description = i18n( "The specified file or folder <strong>%1</strong> "
00742         "does not exist." ).arg( dir );
00743       causes << cBug;
00744       solutions << sUpdate << sSysadmin;
00745       break;
00746 
00747     case  TDEIO::ERR_FILE_ALREADY_EXIST:
00748       errorName = i18n( "File Already Exists" );
00749       description = i18n( "The requested file could not be created because a "
00750         "file with the same name already exists." );
00751       solutions << i18n ( "Try moving the current file out of the way first, "
00752         "and then try again." )
00753         << i18n ( "Delete the current file and try again." )
00754         << i18n( "Choose an alternate filename for the new file." );
00755       break;
00756 
00757     case  TDEIO::ERR_DIR_ALREADY_EXIST:
00758       errorName = i18n( "Folder Already Exists" );
00759       description = i18n( "The requested folder could not be created because "
00760         "a folder with the same name already exists." );
00761       solutions << i18n( "Try moving the current folder out of the way first, "
00762         "and then try again." )
00763         << i18n( "Delete the current folder and try again." )
00764         << i18n( "Choose an alternate name for the new folder." );
00765       break;
00766 
00767     case  TDEIO::ERR_UNKNOWN_HOST:
00768       errorName = i18n( "Unknown Host" );
00769       description = i18n( "An unknown host error indicates that the server with "
00770         "the requested name, <strong>%1</strong>, could not be "
00771         "located on the Internet." ).arg( host );
00772       causes << i18n( "The name that you typed, %1, may not exist: it may be "
00773         "incorrectly typed." ).arg( host )
00774         << cNetwork << cNetconf;
00775       solutions << sNetwork << sSysadmin;
00776       break;
00777 
00778     case  TDEIO::ERR_ACCESS_DENIED:
00779       errorName = i18n( "Access Denied" );
00780       description = i18n( "Access was denied to the specified resource, "
00781         "<strong>%1</strong>." ).arg( url );
00782       causes << i18n( "You may have supplied incorrect authentication details or "
00783         "none at all." )
00784         << i18n( "Your account may not have permission to access the "
00785         "specified resource." );
00786       solutions << i18n( "Retry the request and ensure your authentication details "
00787         "are entered correctly." ) << sSysadmin;
00788       if ( !isSlaveNetwork ) solutions << sServeradmin;
00789       break;
00790 
00791     case  TDEIO::ERR_WRITE_ACCESS_DENIED:
00792       errorName = i18n( "Write Access Denied" );
00793       description = i18n( "This means that an attempt to write to the file "
00794         "<strong>%1</strong> was rejected." ).arg( filename );
00795       causes << cAccess << cLocked << cHardware;
00796       solutions << sAccess << sQuerylock << sSysadmin;
00797       break;
00798 
00799     case  TDEIO::ERR_CANNOT_ENTER_DIRECTORY:
00800       errorName = i18n( "Unable to Enter Folder" );
00801       description = i18n( "This means that an attempt to enter (in other words, "
00802         "to open) the requested folder <strong>%1</strong> was rejected." )
00803         .arg( dir );
00804       causes << cAccess << cLocked;
00805       solutions << sAccess << sQuerylock << sSysadmin;
00806       break;
00807 
00808     case  TDEIO::ERR_PROTOCOL_IS_NOT_A_FILESYSTEM:
00809       errorName = i18n( "Folder Listing Unavailable" );
00810       techName = i18n( "Protocol %1 is not a Filesystem" ).arg( protocol );
00811       description = i18n( "This means that a request was made which requires "
00812         "determining the contents of the folder, and the TDE program supporting "
00813         "this protocol is unable to do so." );
00814       causes << cBug;
00815       solutions << sUpdate << sBugreport;
00816       break;
00817 
00818     case  TDEIO::ERR_CYCLIC_LINK:
00819       errorName = i18n( "Cyclic Link Detected" );
00820       description = i18n( "UNIX environments are commonly able to link a file or "
00821         "folder to a separate name and/or location. TDE detected a link or "
00822         "series of links that results in an infinite loop - i.e. the file was "
00823         "(perhaps in a roundabout way) linked to itself." );
00824       solutions << i18n( "Delete one part of the loop in order that it does not "
00825         "cause an infinite loop, and try again." ) << sSysadmin;
00826       break;
00827 
00828     case  TDEIO::ERR_USER_CANCELED:
00829       // Do nothing in this case. The user doesn't need to be told what he just did.
00830       // rodda: However, if we have been called, an application is about to display
00831       // this information anyway. If we don't return sensible information, the
00832       // user sees a blank dialog (I have seen this myself)
00833       errorName = i18n( "Request Aborted By User" );
00834       description = i18n( "The request was not completed because it was "
00835         "aborted." );
00836       solutions << i18n( "Retry the request." );
00837       break;
00838 
00839     case  TDEIO::ERR_CYCLIC_COPY:
00840       errorName = i18n( "Cyclic Link Detected During Copy" );
00841       description = i18n( "UNIX environments are commonly able to link a file or "
00842         "folder to a separate name and/or location. During the requested copy "
00843         "operation, TDE detected a link or series of links that results in an "
00844         "infinite loop - i.e. the file was (perhaps in a roundabout way) linked "
00845         "to itself." );
00846       solutions << i18n( "Delete one part of the loop in order that it does not "
00847         "cause an infinite loop, and try again." ) << sSysadmin;
00848       break;
00849 
00850     case  TDEIO::ERR_COULD_NOT_CREATE_SOCKET:
00851       errorName = i18n( "Could Not Create Network Connection" );
00852       techName = i18n( "Could Not Create Socket" );
00853       description = i18n( "This is a fairly technical error in which a required "
00854         "device for network communications (a socket) could not be created." );
00855       causes << i18n( "The network connection may be incorrectly configured, or "
00856         "the network interface may not be enabled." );
00857       solutions << sNetwork << sSysadmin;
00858       break;
00859 
00860     case  TDEIO::ERR_COULD_NOT_CONNECT:
00861       errorName = i18n( "Connection to Server Refused" );
00862       description = i18n( "The server <strong>%1</strong> refused to allow this "
00863         "computer to make a connection." ).arg( host );
00864       causes << i18n( "The server, while currently connected to the Internet, "
00865         "may not be configured to allow requests." )
00866         << i18n( "The server, while currently connected to the Internet, "
00867         "may not be running the requested service (%1)." ).arg( protocol )
00868         << i18n( "A network firewall (a device which restricts Internet "
00869         "requests), either protecting your network or the network of the server, "
00870         "may have intervened, preventing this request." );
00871       solutions << sTryagain << sServeradmin << sSysadmin;
00872       break;
00873 
00874     case  TDEIO::ERR_CONNECTION_BROKEN:
00875       errorName = i18n( "Connection to Server Closed Unexpectedly" );
00876       description = i18n( "Although a connection was established to "
00877         "<strong>%1</strong>, the connection was closed at an unexpected point "
00878         "in the communication." ).arg( host );
00879       causes << cNetwork << cNetpath << i18n( "A protocol error may have occurred, "
00880         "causing the server to close the connection as a response to the error." );
00881       solutions << sTryagain << sServeradmin << sSysadmin;
00882       break;
00883 
00884     case  TDEIO::ERR_NOT_FILTER_PROTOCOL:
00885       errorName = i18n( "URL Resource Invalid" );
00886       techName = i18n( "Protocol %1 is not a Filter Protocol" ).arg( protocol );
00887       description = i18n( "The <strong>U</strong>niform <strong>R</strong>esource "
00888         "<strong>L</strong>ocator (URL) that you entered did not refer to "
00889         "a valid mechanism of accessing the specific resource, "
00890         "<strong>%1%2</strong>." )
00891         .arg( !host.isNull() ? host + '/' : TQString::null ).arg( dir );
00892       causes << i18n( "TDE is able to communicate through a protocol within a "
00893         "protocol. This request specified a protocol be used as such, however "
00894         "this protocol is not capable of such an action. This is a rare event, "
00895         "and is likely to indicate a programming error." );
00896       solutions << sTypo << sSysadmin;
00897       break;
00898 
00899     case  TDEIO::ERR_COULD_NOT_MOUNT:
00900       errorName = i18n( "Unable to Initialize Input/Output Device" );
00901       techName = i18n( "Could Not Mount Device" );
00902       description = i18n( "The requested device could not be initialized "
00903         "(\"mounted\"). The reported error was: <strong>%1</strong>" )
00904         .arg( errorText );
00905       causes << i18n( "The device may not be ready, for example there may be "
00906         "no media in a removable media device (i.e. no CD-ROM in a CD drive), "
00907         "or in the case of a peripheral/portable device, the device may not "
00908         "be correctly connected." )
00909         << i18n( "You may not have permissions to initialize (\"mount\") the "
00910         "device. On UNIX systems, often system administrator privileges are "
00911         "required to initialize a device." )
00912         << cHardware;
00913       solutions << i18n( "Check that the device is ready; removable drives "
00914         "must contain media, and portable devices must be connected and powered "
00915         "on.; and try again." ) << sAccess << sSysadmin;
00916       break;
00917 
00918     case  TDEIO::ERR_COULD_NOT_UNMOUNT:
00919       errorName = i18n( "Unable to Uninitialize Input/Output Device" );
00920       techName = i18n( "Could Not Unmount Device" );
00921       description = i18n( "The requested device could not be uninitialized "
00922         "(\"unmounted\"). The reported error was: <strong>%1</strong>" )
00923         .arg( errorText );
00924       causes << i18n( "The device may be busy, that is, still in use by "
00925         "another application or user. Even such things as having an open "
00926         "browser window on a location on this device may cause the device to "
00927         "remain in use." )
00928         << i18n( "You may not have permissions to uninitialize (\"unmount\") "
00929         "the device. On UNIX systems, system administrator privileges are "
00930         "often required to uninitialize a device." )
00931         << cHardware;
00932       solutions << i18n( "Check that no applications are accessing the device, "
00933         "and try again." ) << sAccess << sSysadmin;
00934       break;
00935 
00936     case  TDEIO::ERR_COULD_NOT_READ:
00937       errorName = i18n( "Cannot Read From Resource" );
00938       description = i18n( "This means that although the resource, "
00939         "<strong>%1</strong>, was able to be opened, an error occurred while "
00940         "reading the contents of the resource." ).arg( url );
00941       causes << i18n( "You may not have permissions to read from the resource." );
00942       if ( !isSlaveNetwork ) causes << cNetwork;
00943       causes << cHardware;
00944       solutions << sAccess;
00945       if ( !isSlaveNetwork ) solutions << sNetwork;
00946       solutions << sSysadmin;
00947       break;
00948 
00949     case  TDEIO::ERR_COULD_NOT_WRITE:
00950       errorName = i18n( "Cannot Write to Resource" );
00951       description = i18n( "This means that although the resource, <strong>%1</strong>"
00952         ", was able to be opened, an error occurred while writing to the resource." )
00953         .arg( url );
00954       causes << i18n( "You may not have permissions to write to the resource." );
00955       if ( !isSlaveNetwork ) causes << cNetwork;
00956       causes << cHardware;
00957       solutions << sAccess;
00958       if ( !isSlaveNetwork ) solutions << sNetwork;
00959       solutions << sSysadmin;
00960       break;
00961 
00962     case  TDEIO::ERR_COULD_NOT_BIND:
00963       errorName = i18n( "Could Not Listen for Network Connections" );
00964       techName = i18n( "Could Not Bind" );
00965       description = i18n( "This is a fairly technical error in which a required "
00966         "device for network communications (a socket) could not be established "
00967         "to listen for incoming network connections." );
00968       causes << i18n( "The network connection may be incorrectly configured, or "
00969         "the network interface may not be enabled." );
00970       solutions << sNetwork << sSysadmin;
00971       break;
00972 
00973     case  TDEIO::ERR_COULD_NOT_LISTEN:
00974       errorName = i18n( "Could Not Listen for Network Connections" );
00975       techName = i18n( "Could Not Listen" );
00976       description = i18n( "This is a fairly technical error in which a required "
00977         "device for network communications (a socket) could not be established "
00978         "to listen for incoming network connections." );
00979       causes << i18n( "The network connection may be incorrectly configured, or "
00980         "the network interface may not be enabled." );
00981       solutions << sNetwork << sSysadmin;
00982       break;
00983 
00984     case  TDEIO::ERR_COULD_NOT_ACCEPT:
00985       errorName = i18n( "Could Not Accept Network Connection" );
00986       description = i18n( "This is a fairly technical error in which an error "
00987         "occurred while attempting to accept an incoming network connection." );
00988       causes << i18n( "The network connection may be incorrectly configured, or "
00989         "the network interface may not be enabled." )
00990         << i18n( "You may not have permissions to accept the connection." );
00991       solutions << sNetwork << sSysadmin;
00992       break;
00993 
00994     case  TDEIO::ERR_COULD_NOT_LOGIN:
00995       errorName = i18n( "Could Not Login: %1" ).arg( errorText );
00996       description = i18n( "An attempt to login to perform the requested "
00997         "operation was unsuccessful." );
00998       causes << i18n( "You may have supplied incorrect authentication details or "
00999         "none at all." )
01000         << i18n( "Your account may not have permission to access the "
01001         "specified resource." ) << cProtocol;
01002       solutions << i18n( "Retry the request and ensure your authentication details "
01003         "are entered correctly." ) << sServeradmin << sSysadmin;
01004       break;
01005 
01006     case  TDEIO::ERR_COULD_NOT_STAT:
01007       errorName = i18n( "Could Not Determine Resource Status" );
01008       techName = i18n( "Could Not Stat Resource" );
01009       description = i18n( "An attempt to determine information about the status "
01010         "of the resource <strong>%1</strong>, such as the resource name, type, "
01011         "size, etc., was unsuccessful." ).arg( url );
01012       causes << i18n( "The specified resource may not have existed or may "
01013         "not be accessible." ) << cProtocol << cHardware;
01014       solutions << i18n( "Retry the request and ensure your authentication details "
01015         "are entered correctly." ) << sSysadmin;
01016       break;
01017 
01018     case  TDEIO::ERR_COULD_NOT_CLOSEDIR:
01019       //result = i18n( "Could not terminate listing %1" ).arg( errorText );
01020       errorName = i18n( "Could Not Cancel Listing" );
01021       techName = i18n( "FIXME: Document this" );
01022       break;
01023 
01024     case  TDEIO::ERR_COULD_NOT_MKDIR:
01025       errorName = i18n( "Could Not Create Folder" );
01026       description = i18n( "An attempt to create the requested folder failed." );
01027       causes << cAccess << i18n( "The location where the folder was to be created "
01028         "may not exist." );
01029       if ( !isSlaveNetwork ) causes << cProtocol;
01030       solutions << i18n( "Retry the request." ) << sAccess;
01031       break;
01032 
01033     case  TDEIO::ERR_COULD_NOT_RMDIR:
01034       errorName = i18n( "Could Not Remove Folder" );
01035       description = i18n( "An attempt to remove the specified folder, "
01036         "<strong>%1</strong>, failed." ).arg( dir );
01037       causes << i18n( "The specified folder may not exist." )
01038         << i18n( "The specified folder may not be empty." )
01039         << cAccess;
01040       if ( !isSlaveNetwork ) causes << cProtocol;
01041       solutions << i18n( "Ensure that the folder exists and is empty, and try "
01042         "again." ) << sAccess;
01043       break;
01044 
01045     case  TDEIO::ERR_CANNOT_RESUME:
01046       errorName = i18n( "Could Not Resume File Transfer" );
01047       description = i18n( "The specified request asked that the transfer of "
01048         "file <strong>%1</strong> be resumed at a certain point of the "
01049         "transfer. This was not possible." ).arg( filename );
01050       causes << i18n( "The protocol, or the server, may not support file "
01051         "resuming." );
01052       solutions << i18n( "Retry the request without attempting to resume "
01053         "transfer." );
01054       break;
01055 
01056     case  TDEIO::ERR_CANNOT_RENAME:
01057       errorName = i18n( "Could Not Rename Resource" );
01058       description = i18n( "An attempt to rename the specified resource "
01059         "<strong>%1</strong> failed." ).arg( url );
01060       causes << cAccess << cExists;
01061       if ( !isSlaveNetwork ) causes << cProtocol;
01062       solutions << sAccess << sExists;
01063       break;
01064 
01065     case  TDEIO::ERR_CANNOT_CHMOD:
01066       errorName = i18n( "Could Not Alter Permissions of Resource" );
01067       description = i18n( "An attempt to alter the permissions on the specified "
01068         "resource <strong>%1</strong> failed." ).arg( url );
01069       causes << cAccess << cExists;
01070       solutions << sAccess << sExists;
01071       break;
01072 
01073     case  TDEIO::ERR_CANNOT_DELETE:
01074       errorName = i18n( "Could Not Delete Resource" );
01075       description = i18n( "An attempt to delete the specified resource "
01076         "<strong>%1</strong> failed." ).arg( url );
01077       causes << cAccess << cExists;
01078       solutions << sAccess << sExists;
01079       break;
01080 
01081     case  TDEIO::ERR_SLAVE_DIED:
01082       errorName = i18n( "Unexpected Program Termination" );
01083       description = i18n( "The program on your computer which provides access "
01084         "to the <strong>%1</strong> protocol has unexpectedly terminated." )
01085         .arg( url );
01086       causes << cBuglikely;
01087       solutions << sUpdate << sBugreport;
01088       break;
01089 
01090     case  TDEIO::ERR_OUT_OF_MEMORY:
01091       errorName = i18n( "Out of Memory" );
01092       description = i18n( "The program on your computer which provides access "
01093         "to the <strong>%1</strong> protocol could not obtain the memory "
01094         "required to continue." ).arg( protocol );
01095       causes << cBuglikely;
01096       solutions << sUpdate << sBugreport;
01097       break;
01098 
01099     case  TDEIO::ERR_UNKNOWN_PROXY_HOST:
01100       errorName = i18n( "Unknown Proxy Host" );
01101       description = i18n( "While retrieving information about the specified "
01102         "proxy host, <strong>%1</strong>, an Unknown Host error was encountered. "
01103         "An unknown host error indicates that the requested name could not be "
01104         "located on the Internet." ).arg( errorText );
01105       causes << i18n( "There may have been a problem with your network "
01106         "configuration, specifically your proxy's hostname. If you have been "
01107         "accessing the Internet with no problems recently, this is unlikely." )
01108         << cNetwork;
01109       solutions << i18n( "Double-check your proxy settings and try again." )
01110         << sSysadmin;
01111       break;
01112 
01113     case  TDEIO::ERR_COULD_NOT_AUTHENTICATE:
01114       errorName = i18n( "Authentication Failed: Method %1 Not Supported" )
01115          .arg( errorText );
01116       description = i18n( "Although you may have supplied the correct "
01117         "authentication details, the authentication failed because the "
01118         "method that the server is using is not supported by the TDE "
01119         "program implementing the protocol %1." ).arg( protocol );
01120       solutions << i18n( "Please file a bug at <a href=\"http://bugs.trinitydesktop.org/\">"
01121         "http://bugs.trinitydesktop.org/</a> to inform the TDE team of the unsupported "
01122         "authentication method." ) << sSysadmin;
01123       break;
01124 
01125     case  TDEIO::ERR_ABORTED:
01126       errorName = i18n( "Request Aborted" );
01127       description = i18n( "The request was not completed because it was "
01128         "aborted." );
01129       solutions << i18n( "Retry the request." );
01130       break;
01131 
01132     case  TDEIO::ERR_INTERNAL_SERVER:
01133       errorName = i18n( "Internal Error in Server" );
01134       description = i18n( "The program on the server which provides access "
01135         "to the <strong>%1</strong> protocol has reported an internal error: "
01136         "%0." ).arg( protocol );
01137       causes << i18n( "This is most likely to be caused by a bug in the "
01138         "server program. Please consider submitting a full bug report as "
01139         "detailed below." );
01140       solutions << i18n( "Contact the administrator of the server "
01141         "to advise them of the problem." )
01142         << i18n( "If you know who the authors of the server software are, "
01143         "submit the bug report directly to them." );
01144       break;
01145 
01146     case  TDEIO::ERR_SERVER_TIMEOUT:
01147       errorName = i18n( "Timeout Error" );
01148       description = i18n( "Although contact was made with the server, a "
01149         "response was not received within the amount of time allocated for "
01150         "the request as follows:<ul>"
01151         "<li>Timeout for establishing a connection: %1 seconds</li>"
01152         "<li>Timeout for receiving a response: %2 seconds</li>"
01153         "<li>Timeout for accessing proxy servers: %3 seconds</li></ul>"
01154         "Please note that you can alter these timeout settings in the TDE "
01155         "Control Center, by selecting Network -> Preferences." )
01156         .arg( KProtocolManager::connectTimeout() )
01157         .arg( KProtocolManager::responseTimeout() )
01158         .arg( KProtocolManager::proxyConnectTimeout() );
01159       causes << cNetpath << i18n( "The server was too busy responding to other "
01160         "requests to respond." );
01161       solutions << sTryagain << sServeradmin;
01162       break;
01163 
01164     case  TDEIO::ERR_UNKNOWN:
01165       errorName = i18n( "Unknown Error" );
01166       description = i18n( "The program on your computer which provides access "
01167         "to the <strong>%1</strong> protocol has reported an unknown error: "
01168         "%2." ).arg( protocol ).arg( errorText );
01169       causes << cBug;
01170       solutions << sUpdate << sBugreport;
01171       break;
01172 
01173     case  TDEIO::ERR_UNKNOWN_INTERRUPT:
01174       errorName = i18n( "Unknown Interruption" );
01175       description = i18n( "The program on your computer which provides access "
01176         "to the <strong>%1</strong> protocol has reported an interruption of "
01177         "an unknown type: %2." ).arg( protocol ).arg( errorText );
01178       causes << cBug;
01179       solutions << sUpdate << sBugreport;
01180       break;
01181 
01182     case TDEIO::ERR_CANNOT_DELETE_ORIGINAL:
01183       errorName = i18n( "Could Not Delete Original File" );
01184       description = i18n( "The requested operation required the deleting of "
01185         "the original file, most likely at the end of a file move operation. "
01186         "The original file <strong>%1</strong> could not be deleted." )
01187         .arg( errorText );
01188       causes << cAccess;
01189       solutions << sAccess;
01190       break;
01191 
01192     case TDEIO::ERR_CANNOT_DELETE_PARTIAL:
01193       errorName = i18n( "Could Not Delete Temporary File" );
01194       description = i18n( "The requested operation required the creation of "
01195         "a temporary file in which to save the new file while being "
01196         "downloaded. This temporary file <strong>%1</strong> could not be "
01197         "deleted." ).arg( errorText );
01198       causes << cAccess;
01199       solutions << sAccess;
01200       break;
01201 
01202     case TDEIO::ERR_CANNOT_RENAME_ORIGINAL:
01203       errorName = i18n( "Could Not Rename Original File" );
01204       description = i18n( "The requested operation required the renaming of "
01205         "the original file <strong>%1</strong>, however it could not be "
01206         "renamed." ).arg( errorText );
01207       causes << cAccess;
01208       solutions << sAccess;
01209       break;
01210 
01211     case TDEIO::ERR_CANNOT_RENAME_PARTIAL:
01212       errorName = i18n( "Could Not Rename Temporary File" );
01213       description = i18n( "The requested operation required the creation of "
01214         "a temporary file <strong>%1</strong>, however it could not be "
01215         "created." ).arg( errorText );
01216       causes << cAccess;
01217       solutions << sAccess;
01218       break;
01219 
01220     case TDEIO::ERR_CANNOT_SYMLINK:
01221       errorName = i18n( "Could Not Create Link" );
01222       techName = i18n( "Could Not Create Symbolic Link" );
01223       description = i18n( "The requested symbolic link %1 could not be created." )
01224         .arg( errorText );
01225       causes << cAccess;
01226       solutions << sAccess;
01227       break;
01228 
01229     case TDEIO::ERR_NO_CONTENT:
01230       errorName = i18n( "No Content" );
01231       description = errorText;
01232       break;
01233 
01234     case TDEIO::ERR_DISK_FULL:
01235       errorName = i18n( "Disk Full" );
01236       description = i18n( "The requested file <strong>%1</strong> could not be "
01237         "written to as there is inadequate disk space." ).arg( errorText );
01238       solutions << i18n( "Free up enough disk space by 1) deleting unwanted and "
01239         "temporary files; 2) archiving files to removable media storage such as "
01240         "CD-Recordable discs; or 3) obtain more storage capacity." )
01241         << sSysadmin;
01242       break;
01243 
01244     case TDEIO::ERR_IDENTICAL_FILES:
01245       errorName = i18n( "Source and Destination Files Identical" );
01246       description = i18n( "The operation could not be completed because the "
01247         "source and destination files are the same file." );
01248       solutions << i18n( "Choose a different filename for the destination file." );
01249       break;
01250 
01251     // We assume that the slave has all the details
01252     case TDEIO::ERR_SLAVE_DEFINED:
01253       errorName = TQString::null;
01254       description = errorText;
01255       break;
01256 
01257     default:
01258       // fall back to the plain error...
01259       errorName = i18n( "Undocumented Error" );
01260       description = buildErrorString( errorCode, errorText );
01261   }
01262 
01263   TQByteArray ret;
01264   TQDataStream stream(ret, IO_WriteOnly);
01265   stream << errorName << techName << description << causes << solutions;
01266   return ret;
01267 }
01268 
01269 #ifdef Q_OS_UNIX
01270 
01271 #include <limits.h>
01272 #include <stdlib.h>
01273 #include <stdio.h>
01274 #include <tqfile.h>
01275 
01276 #include <config.h>
01277 
01278 #ifdef HAVE_PATHS_H
01279 #include <paths.h>
01280 #endif
01281 #ifdef HAVE_SYS_STAT_H
01282 #include <sys/stat.h>
01283 #endif
01284 #include <sys/param.h>
01285 #ifdef HAVE_LIMITS_H
01286 #include <limits.h>
01287 #endif
01288 #ifdef HAVE_SYS_MNTTAB_H
01289 #include <sys/mnttab.h>
01290 #endif
01291 #ifdef HAVE_MNTENT_H
01292 #include <mntent.h>
01293 #elif defined(HAVE_SYS_MNTENT_H)
01294 #include <sys/mntent.h>
01295 #endif
01296 #ifdef HAVE_SYS_UCRED_H
01297 #include <sys/ucred.h>
01298 #endif
01299 #ifdef HAVE_SYS_MOUNT_H
01300 #include <sys/mount.h>
01301 #endif
01302 #ifdef HAVE_FSTAB_H
01303 #include <fstab.h>
01304 #endif
01305 #if defined(_AIX)
01306 #include <sys/mntctl.h>
01307 #include <sys/vmount.h>
01308 #include <sys/vfs.h>
01309 
01310 /* AIX does not prototype mntctl anywhere that I can find */
01311 #ifndef mntctl
01312 extern "C" {
01313 int mntctl(int command, int size, void* buffer);
01314 }
01315 #endif
01316 extern "C" struct vfs_ent *getvfsbytype(int vfsType);
01317 extern "C" void endvfsent( );
01318 #endif
01319 
01320 /***************************************************************
01321  *
01322  * Utility functions
01323  *
01324  ***************************************************************/
01325 
01326 #ifndef HAVE_GETMNTINFO
01327 
01328 #ifdef _PATH_MOUNTED
01329 // On some Linux, MNTTAB points to /etc/fstab !
01330 # undef MNTTAB
01331 # define MNTTAB _PATH_MOUNTED
01332 #else
01333 # ifndef MNTTAB
01334 #  ifdef MTAB_FILE
01335 #   define MNTTAB MTAB_FILE
01336 #  else
01337 #   define MNTTAB "/etc/mnttab"
01338 #  endif
01339 # endif
01340 #endif
01341 
01342 #ifndef FSTAB
01343 # ifdef _PATH_FSTAB
01344 #  define FSTAB _PATH_FSTAB
01345 # else
01346 #  define FSTAB "/etc/fstab"
01347 # endif
01348 #endif
01349 
01350 #ifdef __CYGWIN__                
01351 #define hasmntopt(var,opt) (0)   
01352 #endif                           
01353                                  
01354 // There are (at least) four kind of APIs:
01355 // setmntent + getmntent + struct mntent (linux...)
01356 //             getmntent + struct mnttab
01357 // mntctl                + struct vmount (AIX)
01358 // getmntinfo + struct statfs&flags (BSD 4.4 and friends)
01359 // getfsent + char* (BSD 4.3 and friends)
01360 
01361 #ifdef HAVE_SETMNTENT
01362 #define SETMNTENT setmntent
01363 #define ENDMNTENT endmntent
01364 #define STRUCT_MNTENT struct mntent *
01365 #define STRUCT_SETMNTENT FILE *
01366 #define GETMNTENT(file, var) ((var = getmntent(file)) != 0)
01367 #define MOUNTPOINT(var) var->mnt_dir
01368 #define MOUNTTYPE(var) var->mnt_type
01369 #define HASMNTOPT(var, opt) hasmntopt(var, opt)
01370 #define FSNAME(var) var->mnt_fsname
01371 #elif defined(_AIX)
01372 /* we don't need this stuff */
01373 #else
01374 #define SETMNTENT fopen
01375 #define ENDMNTENT fclose
01376 #define STRUCT_MNTENT struct mnttab
01377 #define STRUCT_SETMNTENT FILE *
01378 #define GETMNTENT(file, var) (getmntent(file, &var) == 0)
01379 #define MOUNTPOINT(var) var.mnt_mountp
01380 #define MOUNTTYPE(var) var.mnt_fstype
01381 #define HASMNTOPT(var, opt) hasmntopt(&var, opt)
01382 #define FSNAME(var) var.mnt_special
01383 #endif
01384 
01385 #endif /* HAVE_GETMNTINFO */
01386 
01387 TQString TDEIO::findDeviceMountPoint( const TQString& filename )
01388 {
01389     TQString result;
01390 
01391 #ifdef HAVE_VOLMGT
01392     /*
01393      *  support for Solaris volume management
01394      */
01395     const char *volpath;
01396     FILE *mnttab;
01397     struct mnttab mnt;
01398     int len;
01399     TQCString devname;
01400 
01401     if( (volpath = volmgt_root()) == NULL ) {
01402         kdDebug( 7007 ) << "findDeviceMountPoint: "
01403             << "VOLMGT: can't find volmgt root dir" << endl;
01404         return TQString::null;
01405     }
01406 
01407     if( (mnttab = fopen( MNTTAB, "r" )) == NULL ) {
01408         kdDebug( 7007 ) << "findDeviceMountPoint: "
01409             << "VOLMGT: can't open mnttab" << endl;
01410         return TQString::null;
01411     }
01412 
01413     devname = volpath;
01414     devname += TQFile::encodeName( filename );
01415     devname += '/';
01416     len = devname.length();
01417 //  kdDebug( 7007 ) << "findDeviceMountPoint: "
01418 //      << "VOLMGT: searching mountpoint for \"" << devname << "\""
01419 //      << endl;
01420 
01421     /*
01422      *  find the mountpoint
01423      *  floppies:
01424      *  /dev/disketteN    => <volpath>/dev/disketteN
01425      *  CDROM, ZIP, and other media:
01426      *  /dev/dsk/cXtYdZs2 => <volpath>/dev/dsk/cXtYdZ  (without slice#)
01427      */
01428     rewind( mnttab );
01429     result = TQString::null;
01430     while( getmntent( mnttab, &mnt ) == 0 ) {
01431         /*
01432          *  either match the exact device name (floppies),
01433          *  or the device name without the slice#
01434          */
01435         if( strncmp( devname.data(), mnt.mnt_special, len ) == 0
01436             || (strncmp( devname.data(), mnt.mnt_special, len - 3 ) == 0
01437                 && mnt.mnt_special[len - 3] == '/' )
01438             || (strcmp(TQFile::encodeName(filename).data()
01439                     , mnt.mnt_special)==0)) {
01440             result = mnt.mnt_mountp;
01441             break;
01442         }
01443     }
01444     fclose( mnttab );
01445 #else
01446 
01447     char    realpath_buffer[MAXPATHLEN];
01448     TQCString realname;
01449 
01450     realname = TQFile::encodeName(filename);
01451     /* If the path contains symlinks, get the real name */
01452     if (realpath(realname, realpath_buffer) != 0)
01453       // succes, use result from realpath
01454       realname = realpath_buffer;
01455 
01456     //kdDebug(7007) << "findDeviceMountPoint realname=" << realname << endl;
01457 
01458 #ifdef HAVE_GETMNTINFO
01459 
01460 #ifdef GETMNTINFO_USES_STATVFS
01461     struct statvfs *mounted;
01462 #else
01463     struct statfs *mounted;
01464 #endif
01465 
01466     int num_fs = getmntinfo(&mounted, MNT_NOWAIT);
01467 
01468     for (int i=0;i<num_fs;i++) {
01469 
01470         TQCString device_name = mounted[i].f_mntfromname;
01471 
01472         // If the path contains symlinks, get
01473         // the real name
01474         if (realpath(device_name, realpath_buffer) != 0)
01475             // succes, use result from realpath
01476             device_name = realpath_buffer;
01477 
01478         if (realname == device_name) {
01479             result = mounted[i].f_mntonname;
01480             break;
01481         }
01482     }
01483 
01484 #elif defined(_AIX)
01485 
01486     struct vmount *mntctl_buffer;
01487     struct vmount *vm;
01488     char *mountedfrom;
01489     char *mountedto;
01490     int fsname_len, num;
01491     int buf_sz = 4096;
01492 
01493     /* mntctl can be used to query mounted file systems.
01494      * mntctl takes only the command MCTL_QUERY so far.
01495      * The buffer is filled with an array of vmount structures, but these
01496      * vmount structures have variable size.
01497      * mntctl return values:
01498      * -1 error
01499      *  0 look in first word of buffer for required bytes, 4096 may be
01500      *    a good starting size, but if tables grow too large, look here.
01501      * >0 number of vmount structures
01502      */
01503     mntctl_buffer = (struct vmount*)malloc(buf_sz);
01504     num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
01505     if (num == 0)
01506     {
01507     buf_sz = *(int*)mntctl_buffer;
01508     free(mntctl_buffer);
01509     mntctl_buffer = (struct vmount*)malloc(buf_sz);
01510     num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
01511     }
01512 
01513     if (num > 0)
01514     {
01515         /* iterate through items in the vmount structure: */
01516         vm = mntctl_buffer;
01517         for ( ; num > 0; num-- )
01518         {
01519             /* get the name of the mounted file systems: */
01520             fsname_len = vmt2datasize(vm, VMT_STUB);
01521             mountedto     = (char*)malloc(fsname_len + 1);
01522         mountedto[fsname_len] = '\0';
01523             strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len);
01524 
01525             /* get the mount-from information: */
01526             fsname_len = vmt2datasize(vm, VMT_OBJECT);
01527             mountedfrom     = (char*)malloc(fsname_len + 1);
01528         mountedfrom[fsname_len] = '\0';
01529             strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len);
01530 
01531             TQCString device_name = mountedfrom;
01532 
01533             if (realpath(device_name, realpath_buffer) != 0)
01534                 // success, use result from realpath
01535                 device_name = realpath_buffer;
01536 
01537             free(mountedfrom);
01538 
01539             if (realname == device_name) {
01540                 result = mountedto;
01541                 free(mountedto);
01542                 break;
01543             }
01544 
01545             free(mountedto);
01546 
01547             /* goto the next vmount structure: */
01548             vm = (struct vmount *)((char *)vm + vm->vmt_length);
01549         }
01550     }
01551 
01552     free( mntctl_buffer );
01553 
01554 #else
01555 
01556     STRUCT_SETMNTENT mtab;
01557 
01558     /* Get the list of mounted file systems */
01559 
01560     if ((mtab = SETMNTENT(MNTTAB, "r")) == 0) {
01561         perror("setmntent");
01562         return TQString::null;
01563     }
01564 
01565     /* Loop over all file systems and see if we can find our
01566      * mount point.
01567      * Note that this is the mount point with the longest match.
01568      * XXX: Fails if me->mnt_dir is not a realpath but goes
01569      * through a symlink, e.g. /foo/bar where /foo is a symlink
01570      * pointing to /local/foo.
01571      *
01572      * How kinky can you get with a filesystem?
01573      */
01574 
01575     STRUCT_MNTENT me;
01576 
01577     while (GETMNTENT(mtab, me))
01578     {
01579       // There may be symbolic links into the /etc/mnttab
01580       // So we have to find the real device name here as well!
01581       TQCString device_name = FSNAME(me);
01582       if (device_name.isEmpty() || (device_name == "none"))
01583          continue;
01584 
01585       //kdDebug( 7007 ) << "device_name=" << device_name << endl;
01586 
01587       // If the path contains symlinks, get
01588       // the real name
01589       if (realpath(device_name, realpath_buffer) != 0)
01590           // succes, use result from realpath
01591          device_name = realpath_buffer;
01592 
01593       //kdDebug( 7007 ) << "device_name after realpath =" << device_name << endl;
01594 
01595       if (realname == device_name)
01596       {
01597           result = MOUNTPOINT(me);
01598           break;
01599       }
01600     }
01601 
01602     ENDMNTENT(mtab);
01603 
01604 #endif /* GET_MNTINFO */
01605 #endif /* HAVE_VOLMGT */
01606 
01607     //kdDebug( 7007 ) << "Returning result " << result << endl;
01608     return result;
01609 }
01610 
01611 // Don't just trust the return value, keep iterating to check for a better match (bigger max)
01612 static bool is_my_mountpoint( const char *mountpoint, const char *realname, int &max )
01613 {
01614     int length = strlen(mountpoint);
01615 
01616     if (!strncmp(mountpoint, realname, length)
01617         && length > max) {
01618         max = length;
01619         if (length == 1 || realname[length] == '/' || realname[length] == '\0')
01620             return true;
01621     }
01622     return false;
01623 }
01624 
01625 typedef enum { Unseen, Right, Wrong } MountState;
01626 
01630 static void check_mount_point(const char *mounttype,
01631                               const char *fsname,
01632                               MountState &isslow, MountState &isautofs)
01633 {
01634     bool nfs = !strcmp(mounttype, "nfs");
01635     bool autofs = !strcmp(mounttype, "autofs") || !strcmp(mounttype,"subfs");
01636     bool pid = (strstr(fsname, ":(pid") != 0);
01637 
01638     if (nfs && !pid)
01639         isslow = Right;
01640     else if (isslow == Right)
01641         isslow = Wrong;
01642 
01643     /* Does this look like automounted? */
01644     if (autofs || (nfs && pid)) {
01645         isautofs = Right;
01646         isslow = Right;
01647     }
01648 }
01649 
01650 // returns the mount point, checks the mount state.
01651 // if ismanual == Wrong this function does not check the manual mount state
01652 static TQString get_mount_info(const TQString& filename,
01653     MountState& isautofs, MountState& isslow, MountState& ismanual,
01654     TQString& fstype)
01655 {
01656     static bool gotRoot = false;
01657     static dev_t rootDevice;
01658 
01659     struct cachedDevice_t
01660     {
01661        dev_t device;
01662        TQString mountPoint;
01663        MountState isautofs;
01664        MountState isslow;
01665        MountState ismanual;
01666        TQString fstype;
01667     };
01668     static struct cachedDevice_t *cachedDevice = 0;
01669 
01670     if (!gotRoot)
01671     {
01672        KDE_struct_stat stat_buf;
01673        KDE_stat("/", &stat_buf);
01674        gotRoot = true;
01675        rootDevice = stat_buf.st_dev;
01676     }
01677 
01678     bool gotDevice = false;
01679     KDE_struct_stat stat_buf;
01680     if (KDE_stat(TQFile::encodeName(filename), &stat_buf) == 0)
01681     {
01682        gotDevice = true;
01683        if (stat_buf.st_dev == rootDevice)
01684        {
01685           static const TQString &root = TDEGlobal::staticQString("/");
01686           isautofs = Wrong;
01687           isslow = Wrong;
01688           ismanual = Wrong;
01689           fstype = TQString::null; // ### do we need it?
01690           return root;
01691        }
01692        if (cachedDevice && (stat_buf.st_dev == cachedDevice->device))
01693        {
01694           bool interestedInIsManual = ismanual != Wrong;
01695           isautofs = cachedDevice->isautofs;
01696           isslow = cachedDevice->isslow;
01697           ismanual = cachedDevice->ismanual;
01698           fstype = cachedDevice->fstype;
01699           // Don't use the cache if it doesn't have the information we're looking for
01700           if ( !interestedInIsManual || ismanual != Unseen )
01701               return cachedDevice->mountPoint;
01702        }
01703     }
01704 
01705     char realname[MAXPATHLEN];
01706 
01707     memset(realname, 0, MAXPATHLEN);
01708 
01709     /* If the path contains symlinks, get the real name */
01710     if (realpath(TQFile::encodeName(filename), realname) == 0) {
01711         if( strlcpy(realname, TQFile::encodeName(filename), MAXPATHLEN)>=MAXPATHLEN)
01712             return TQString::null;
01713     }
01714 
01715     int max = 0;
01716     TQString mountPoint;
01717 
01718     /* Loop over all file systems and see if we can find our
01719      * mount point.
01720      * Note that this is the mount point with the longest match.
01721      * XXX: Fails if me->mnt_dir is not a realpath but goes
01722      * through a symlink, e.g. /foo/bar where /foo is a symlink
01723      * pointing to /local/foo.
01724      *
01725      * How kinky can you get with a filesystem?
01726      */
01727 
01728 #ifdef HAVE_GETMNTINFO
01729 
01730 #ifdef GETMNTINFO_USES_STATVFS
01731     struct statvfs *mounted;
01732 #else
01733     struct statfs *mounted;
01734 #endif
01735 
01736     char    realpath_buffer[MAXPATHLEN];
01737 
01738     int num_fs = getmntinfo(&mounted, MNT_NOWAIT);
01739 
01740     for (int i=0;i<num_fs;i++) {
01741 
01742         TQCString device_name = mounted[i].f_mntfromname;
01743 
01744         // If the path contains symlinks, get
01745         // the real name
01746         if (realpath(device_name, realpath_buffer) != 0)
01747             // succes, use result from realpath
01748             device_name = realpath_buffer;
01749 #ifdef __osf__
01750         char * mounttype = mnt_names[mounted[i].f_type];
01751 #else
01752         char * mounttype = mounted[i].f_fstypename;
01753 #endif
01754         if ( is_my_mountpoint( mounted[i].f_mntonname, realname, max ) )
01755         {
01756             mountPoint = TQFile::decodeName(mounted[i].f_mntonname);
01757             fstype = TQString::fromLatin1(mounttype);
01758             check_mount_point( mounttype, mounted[i].f_mntfromname,
01759                                isautofs, isslow );
01760             // keep going, looking for a potentially better one
01761 
01762             if (ismanual == Unseen)
01763             {
01764                 struct fstab *ft = getfsfile(mounted[i].f_mntonname);
01765                 if (!ft || strstr(ft->fs_mntops, "noauto"))
01766                   ismanual = Right;
01767             }
01768         }
01769     }
01770 
01771 #elif defined(_AIX)
01772 
01773     struct vmount *mntctl_buffer;
01774     struct vmount *vm;
01775     char *mountedfrom;
01776     char *mountedto;
01777     int fsname_len, num;
01778     char realpath_buffer[MAXPATHLEN];
01779     int buf_sz = 4096;
01780 
01781     mntctl_buffer = (struct vmount*)malloc(buf_sz);
01782     num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
01783     if (num == 0)
01784     {
01785     buf_sz = *(int*)mntctl_buffer;
01786     free(mntctl_buffer);
01787     mntctl_buffer = (struct vmount*)malloc(buf_sz);
01788     num = mntctl(MCTL_QUERY, buf_sz, mntctl_buffer);
01789     }
01790 
01791     if (num > 0)
01792     {
01793         /* iterate through items in the vmount structure: */
01794         vm = (struct vmount *)mntctl_buffer;
01795         for ( ; num > 0; num-- )
01796         {
01797             /* get the name of the mounted file systems: */
01798             fsname_len = vmt2datasize(vm, VMT_STUB);
01799             mountedto     = (char*)malloc(fsname_len + 1);
01800         mountedto[fsname_len] = '\0';
01801             strncpy(mountedto, (char *)vmt2dataptr(vm, VMT_STUB), fsname_len);
01802 
01803             fsname_len = vmt2datasize(vm, VMT_OBJECT);
01804             mountedfrom     = (char*)malloc(fsname_len + 1);
01805         mountedfrom[fsname_len] = '\0';
01806             strncpy(mountedfrom, (char *)vmt2dataptr(vm, VMT_OBJECT), fsname_len);
01807 
01808             /* get the mount-from information: */
01809             TQCString device_name = mountedfrom;
01810 
01811             if (realpath(device_name, realpath_buffer) != 0)
01812                 // success, use result from realpath
01813                 device_name = realpath_buffer;
01814 
01815         /* Look up the string for the file system type,
01816              * as listed in /etc/vfs.
01817              * ex.: nfs,jfs,afs,cdrfs,sfs,cachefs,nfs3,autofs
01818              */
01819             struct vfs_ent* ent = getvfsbytype(vm->vmt_gfstype);
01820 
01821             if ( is_my_mountpoint( mountedto, realname, max ) )
01822             {
01823                 mountPoint = TQFile::decodeName(mountedto);
01824                 fstype = TQString::fromLatin1(ent->vfsent_name);
01825                 check_mount_point(ent->vfsent_name, device_name, isautofs, isslow);
01826 
01827                 if (ismanual == Unseen)
01828                 {
01829                     // TODO: add check for ismanual, I couldn't find any way
01830                     // how to get the mount attribute from /etc/filesystems
01831                     ismanual == Wrong;
01832                 }
01833             }
01834 
01835             free(mountedfrom);
01836             free(mountedto);
01837 
01838             /* goto the next vmount structure: */
01839             vm = (struct vmount *)((char *)vm + vm->vmt_length);
01840         }
01841 
01842     endvfsent( );
01843     }
01844 
01845     free( mntctl_buffer );
01846 
01847 #else
01848 
01849     STRUCT_SETMNTENT mtab;
01850     /* Get the list of mounted file systems */
01851 
01852     if ((mtab = SETMNTENT(MNTTAB, "r")) == 0) {
01853         perror("setmntent");
01854         return TQString::null;
01855     }
01856 
01857     STRUCT_MNTENT me;
01858 
01859     while (true) {
01860         if (!GETMNTENT(mtab, me))
01861             break;
01862 
01863         if ( is_my_mountpoint( MOUNTPOINT(me), realname, max ) )
01864         {
01865             mountPoint = TQFile::decodeName( MOUNTPOINT(me) );
01866             fstype = MOUNTTYPE(me);
01867             check_mount_point(MOUNTTYPE(me), FSNAME(me), isautofs, isslow);
01868             // we don't check if ismanual is Right, if /a/b is manually
01869             // mounted /a/b/c can't be automounted. At least IMO.
01870             if (ismanual == Unseen)
01871             {
01872                 // The next GETMNTENT call may destroy 'me'
01873                 // Copy out the info that we need
01874                 TQCString fsname_me = FSNAME(me);
01875                 TQCString mounttype_me = MOUNTTYPE(me);
01876 
01877                 STRUCT_SETMNTENT fstab;
01878                 if ((fstab = SETMNTENT(FSTAB, "r")) == 0) {
01879                     continue;
01880                 }
01881 
01882                 bool found = false;
01883                 STRUCT_MNTENT fe;
01884                 while (GETMNTENT(fstab, fe))
01885                 {
01886                     if (fsname_me == FSNAME(fe))
01887                     {
01888                         found = true;
01889                         if (HASMNTOPT(fe, "noauto") ||
01890                             !strcmp(MOUNTTYPE(fe), "supermount"))
01891                             ismanual = Right;
01892                         break;
01893                     }
01894                 }
01895                 if (!found || (mounttype_me == "supermount"))
01896                   ismanual = Right;
01897 
01898                 ENDMNTENT(fstab);
01899             }
01900         }
01901     }
01902 
01903     ENDMNTENT(mtab);
01904 
01905 #endif
01906 
01907     if (isautofs == Right && isslow == Unseen)
01908         isslow = Right;
01909 
01910     if (gotDevice)
01911     {
01912        if (!cachedDevice)
01913           cachedDevice = new cachedDevice_t;
01914 
01915        cachedDevice->device = stat_buf.st_dev;
01916        cachedDevice->mountPoint = mountPoint;
01917        cachedDevice->isautofs = isautofs;
01918        cachedDevice->isslow = isslow;
01919        cachedDevice->ismanual = ismanual;
01920        cachedDevice->fstype = fstype;
01921     }
01922 
01923     return mountPoint;
01924 }
01925 
01926 #else //!Q_OS_UNIX
01927 //dummy
01928 TQString TDEIO::findDeviceMountPoint( const TQString& filename )
01929 {
01930     return TQString::null;
01931 }
01932 #endif
01933 
01934 TQString TDEIO::findPathMountPoint(const TQString& filename)
01935 {
01936 #ifdef Q_OS_UNIX
01937   MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong;
01938   TQString fstype;
01939   return get_mount_info(filename, isautofs, isslow, ismanual, fstype);
01940 #else //!Q_OS_UNIX
01941   return TQString::null;
01942 #endif 
01943 }
01944 
01945 bool TDEIO::manually_mounted(const TQString& filename)
01946 {
01947 #ifdef Q_OS_UNIX
01948   MountState isautofs = Unseen, isslow = Unseen, ismanual = Unseen;
01949   TQString fstype;
01950   TQString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype);
01951   return !mountPoint.isNull() && (ismanual == Right);
01952 #else //!Q_OS_UNIX
01953   return false;
01954 #endif 
01955 }
01956 
01957 bool TDEIO::probably_slow_mounted(const TQString& filename)
01958 {
01959 #ifdef Q_OS_UNIX
01960   MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong;
01961   TQString fstype;
01962   TQString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype);
01963   return !mountPoint.isNull() && (isslow == Right);
01964 #else //!Q_OS_UNIX
01965   return false;
01966 #endif 
01967 }
01968 
01969 bool TDEIO::testFileSystemFlag(const TQString& filename, FileSystemFlag flag)
01970 {
01971 #ifdef Q_OS_UNIX
01972   MountState isautofs = Unseen, isslow = Unseen, ismanual = Wrong;
01973   TQString fstype;
01974   TQString mountPoint = get_mount_info(filename, isautofs, isslow, ismanual, fstype);
01975     kdDebug() << "testFileSystemFlag: fstype=" << fstype << endl;
01976   if (mountPoint.isNull())
01977       return false;
01978   bool isMsDos = ( fstype == "msdos" || fstype == "fat" || fstype == "vfat" );
01979   switch (flag)  {
01980   case SupportsChmod:
01981   case SupportsChown:
01982   case SupportsUTime:
01983   case SupportsSymlinks:
01984       return !isMsDos; // it's amazing the number of things FAT doesn't support :)
01985   case CaseInsensitive:
01986       return isMsDos;
01987   }
01988 #endif 
01989   return false;
01990 }
01991 
01992 TDEIO::CacheControl TDEIO::parseCacheControl(const TQString &cacheControl)
01993 {
01994   TQString tmp = cacheControl.lower();
01995 
01996   if (tmp == "cacheonly")
01997      return TDEIO::CC_CacheOnly;
01998   if (tmp == "cache")
01999      return TDEIO::CC_Cache;
02000   if (tmp == "verify")
02001      return TDEIO::CC_Verify;
02002   if (tmp == "refresh")
02003      return TDEIO::CC_Refresh;
02004   if (tmp == "reload")
02005      return TDEIO::CC_Reload;
02006 
02007   kdDebug() << "unrecognized Cache control option:"<<cacheControl<<endl;
02008   return TDEIO::CC_Verify;
02009 }
02010 
02011 TQString TDEIO::getCacheControlString(TDEIO::CacheControl cacheControl)
02012 {
02013     if (cacheControl == TDEIO::CC_CacheOnly)
02014     return "CacheOnly";
02015     if (cacheControl == TDEIO::CC_Cache)
02016     return "Cache";
02017     if (cacheControl == TDEIO::CC_Verify)
02018     return "Verify";
02019     if (cacheControl == TDEIO::CC_Refresh)
02020     return "Refresh";
02021     if (cacheControl == TDEIO::CC_Reload)
02022     return "Reload";
02023     kdDebug() << "unrecognized Cache control enum value:"<<cacheControl<<endl;
02024     return TQString::null;
02025 }

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.6.1
This website is maintained by Timothy Pearson.