|
- /***************************************************************************
- smb4kpreviewer - This class queries a remote share for a preview
- -------------------
- begin : Mo Mai 28 2007
- copyright : (C) 2007 by Alexander Reinholdt
- email : dustpuppy@users.berlios.de
- ***************************************************************************/
-
- /***************************************************************************
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
- * General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
- * MA 02110-1301 USA *
- ***************************************************************************/
-
- // TQt includes
- #include <tqapplication.h>
-
- // KDE includes
- #include <kapplication.h>
- #include <kdebug.h>
-
- // application specific includes
- #include "smb4kpreviewer.h"
- #include "smb4kpreviewitem.h"
- #include "smb4kdefs.h"
- #include "smb4kglobal.h"
- #include "smb4kpasswordhandler.h"
- #include "smb4kauthinfo.h"
- #include "smb4ksambaoptionshandler.h"
- #include "smb4kerror.h"
-
- using namespace Smb4KGlobal;
-
-
- Smb4KPreviewer::Smb4KPreviewer( TQObject *parent, const char *name )
- : TQObject( parent, name )
- {
- m_item = NULL;
-
- m_buffer = TQString();
-
- m_working = false;
-
- m_proc = new KProcess( this, "PreviewProcess" );
- m_proc->setUseShell( true );
-
- connect( m_proc, TQT_SIGNAL( receivedStdout( KProcess *, char *, int ) ),
- this, TQT_SLOT( slotReceivedStdout( KProcess *, char *, int ) ) );
-
- connect( m_proc, TQT_SIGNAL( processExited( KProcess* ) ),
- this, TQT_SLOT( slotProcessExited( KProcess * ) ) );
-
- connect( m_proc, TQT_SIGNAL( receivedStderr( KProcess *, char *, int ) ),
- this, TQT_SLOT( slotReceivedStderr( KProcess *, char *, int ) ) );
- }
-
-
- Smb4KPreviewer::~Smb4KPreviewer()
- {
- // Do not delete m_item here, because it belongs to an
- // outside class.
- }
-
-
- bool Smb4KPreviewer::preview( Smb4KPreviewItem *item )
- {
- // If there is no item, stop right here.
- if ( !item )
- {
- return false;
- }
-
- if ( TQString::compare( item->share(), "homes" ) == 0 )
- {
- TQString share_name = specifyUser( item->host(), kapp->mainWidget() ? kapp->mainWidget() : 0, "SpecifyUser" );
-
- if ( !share_name.isEmpty() )
- {
- // The Smb4KPreviewItem::setShare() function will take care
- // that no share name is overwritten, that is *not* named
- // 'homes'.
- item->setShare( share_name );
- }
- else
- {
- return false;
- }
- }
-
- m_timer_id = startTimer( TIMER_INTERVAL );
-
- m_queue.enqueue( item );
-
- return true;
- }
-
-
- void Smb4KPreviewer::abort()
- {
- m_queue.clear();
-
- if ( m_proc->isRunning() )
- {
- m_proc->kill();
- }
- }
-
-
- void Smb4KPreviewer::timerEvent( TQTimerEvent * )
- {
- if ( m_working )
- {
- return;
- }
-
- // Declare the previewer working:
- emit state( PREVIEWER_START );
-
- m_working = true;
-
- m_item = m_queue.dequeue();
-
- // Assemble the command.
- //
- // Here are some things to remember:
- // (a) Do not convert the path to local 8 bit. It won't work with umlauts or other
- // special characters.
- // (b) Do not pass the path unquoted, or you'll get a NT_STATUS_OBJECT_NAME_NOT_FOUND
- // error message in the case the path is empty.
- TQString command;
- command.append( TQString( "smbclient //%1/%2 " ).tqarg( KProcess::quote( m_item->host() ), KProcess::quote( m_item->share() ) ) );
- command.append( TQString( " -d1 -W %1 -D %2 " ).tqarg( KProcess::quote( m_item->workgroup() ), KProcess::quote( m_item->path() ) ) );
- command.append( " -c \"ls\" " );
-
- if ( !m_item->ip().isEmpty() )
- {
- command.append( TQString( " -I %1 " ).tqarg( m_item->ip() ) );
- }
-
- command.append( optionsHandler()->smbclientOptions( "//"+m_item->host()+"/"+m_item->share() ) );
-
- Smb4KAuthInfo *auth = passwordHandler()->readAuth( new Smb4KAuthInfo( m_item->workgroup(), m_item->host(), m_item->share() ) );
-
- if ( !auth->user().isEmpty() )
- {
- command.append( TQString( " -U %1" ).tqarg( KProcess::quote( auth->user() ) ) );
-
- if ( !auth->password().isEmpty() )
- {
- m_proc->setEnvironment( "PASSWD", auth->password() );
- }
- }
- else
- {
- command.append( " -U guest%" );
- }
-
- delete auth;
-
- *m_proc << command;
-
- TQApplication::setOverrideCursor( waitCursor );
-
- m_proc->start( KProcess::NotifyOnExit, KProcess::AllOutput );
- }
-
-
- /////////////////////////////////////////////////////////////////////////////
- // TQT_SLOT IMPLEMENTATIONS
- /////////////////////////////////////////////////////////////////////////////
-
- void Smb4KPreviewer::slotReceivedStdout( KProcess *, char *buf, int len )
- {
- m_buffer.append( TQString::fromLocal8Bit( buf, len ) );
- }
-
-
- void Smb4KPreviewer::slotReceivedStderr( KProcess *, char *buf, int len )
- {
- m_buffer.append( TQString::fromLocal8Bit( buf, len ) );
- }
-
-
- void Smb4KPreviewer::slotProcessExited( KProcess * )
- {
- // Disconnect the timer:
- if ( m_queue.isEmpty() )
- {
- killTimer( m_timer_id );
- }
-
- m_proc->clearArguments();
-
- TQStringList list = TQStringList::split( "\n", m_buffer, false );
-
- m_buffer = TQString();
-
- // Check whether an error occurred:
- if ( list.grep( "NT_STATUS" ).count() != 0 )
- {
- // Something went wrong. Let's check if this "only" an
- // authentication issue or if we have to error out:
-
- TQString error_code = list.grep( "NT_STATUS" ).first().stripWhiteSpace().section( " ", 0, 0 );
-
- // The error output of smbclient is a little bit inconsistent:
- if ( error_code.contains( "NT_STATUS" ) == 0 )
- {
- error_code = list.grep( "NT_STATUS" ).first().stripWhiteSpace().section( " ", -1, -1 );
- }
-
- // Authentication issue?
- if ( TQString::compare( error_code, "NT_STATUS_ACCESS_DENIED" ) == 0 ||
- TQString::compare( error_code, "NT_STATUS_LOGON_FAILURE" ) == 0 )
- {
- int state = Smb4KPasswordHandler::None;
-
- if ( TQString::compare( error_code, "NT_STATUS_ACCESS_DENIED" ) == 0 )
- {
- state = Smb4KPasswordHandler::AccessDenied;
- }
- else if ( TQString::compare( error_code, "NT_STATUS_LOGON_FAILURE" ) == 0 )
- {
- state = Smb4KPasswordHandler::LogonFailure;
- }
-
- if ( passwordHandler()->askpass( m_item->workgroup(), m_item->host(),
- m_item->share(), state,
- kapp->mainWidget() ? kapp->mainWidget() : 0,
- "AskPass" ) )
- {
- // Now we have a password. Retry.
- // NOTE: Since the item is appended to the queue, there might
- // be the case, that another preview is generated before the
- // retry is executed. I think, we can live with that.
- preview( m_item );
- }
- else
- {
- // The user cancelled the askpass dialog. We won't show an
- // error dialog here, but will only clear the contents of
- // the preview item and emit the failed() signal.
- m_item->clearContents();
-
- emit failed();
- }
- }
- else
- {
- // OK, error out. We cannot recover from it:
- Smb4KError::error( ERROR_GETTING_PREVIEW, TQString(), m_buffer );
-
- m_item->clearContents();
-
- emit failed();
- }
- }
- else if ( list.grep( "Connection to" ).count() != 0 ||
- (list.grep( "Error returning browse list:" ).count() != 0 &&
- list.grep( "NT_STATUS" ).count() == 0) )
- {
- // These are errors that we cannot work around. Error out.
- Smb4KError::error( ERROR_GETTING_PREVIEW, TQString(), m_buffer );
-
- m_item->clearContents();
-
- emit failed();
- }
- else
- {
- for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
- {
- if ( (*it).stripWhiteSpace().startsWith( "Domain" ) ||
- (*it).stripWhiteSpace().startsWith( "OS" ) ||
- (*it).stripWhiteSpace().startsWith( "Anonymous" ) )
- {
- continue;
- }
- else if ( (*it).contains( "blocks of size" ) != 0 )
- {
- continue;
- }
- else
- {
- TQString tmp = (*it).stripWhiteSpace().section( " ", 0, -9 ).stripWhiteSpace();
-
- TQString item = tmp.section( " ", 0, -2 ).stripWhiteSpace();
-
- if ( !item.isEmpty() && tmp.section( " ", -1, -1 ).contains( "D" ) != 0 )
- {
- // We have a directory here.
- if ( item.startsWith( "." ) &&
- (TQString::compare( item.stripWhiteSpace(), "." ) != 0 &&
- TQString::compare( item.stripWhiteSpace(), ".." ) != 0) )
- {
- m_item->addContents( ContentsItem( Smb4KPreviewItem::HiddenDirectory, item ) );
- }
- else
- {
- m_item->addContents( ContentsItem( Smb4KPreviewItem::Directory, item ) );
- }
-
- continue;
- }
- else if ( item.isEmpty() || tmp.section( " ", -1, -1 ).contains( "D" ) == 0 )
- {
- // We have a file
- if ( item.isEmpty() )
- {
- if ( tmp.startsWith( "." ) )
- {
- m_item->addContents( ContentsItem( Smb4KPreviewItem::HiddenFile, tmp ) );
- }
- else
- {
- m_item->addContents( ContentsItem( Smb4KPreviewItem::File, tmp ) );
- }
- }
- else
- {
- if ( item.startsWith( "." ) )
- {
- m_item->addContents( ContentsItem( Smb4KPreviewItem::HiddenFile, item ) );
- }
- else
- {
- m_item->addContents( ContentsItem( Smb4KPreviewItem::File, item ) );
- }
- }
-
- continue;
- }
- else
- {
- continue;
- }
- }
- }
- }
-
- emit result( m_item );
-
- TQApplication::restoreOverrideCursor();
-
- m_working = false;
-
- emit state( PREVIEWER_STOP );
- }
-
- #include "smb4kpreviewer.moc"
|