kfilesharedlg.cpp
00001 /* This file is part of the KDE project 00002 Copyright (c) 2001 David Faure <david@mandrakesoft.com> 00003 Copyright (c) 2001 Laurent Montel <lmontel@mandrakesoft.com> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "kfilesharedlg.h" 00021 #include <tqvbox.h> 00022 #include <tqlabel.h> 00023 #include <tqdir.h> 00024 #include <tqradiobutton.h> 00025 #include <tqbuttongroup.h> 00026 #include <tqlayout.h> 00027 #include <tqlineedit.h> 00028 #include <kprocess.h> 00029 #include <kprocio.h> 00030 #include <klocale.h> 00031 #include <kglobalsettings.h> 00032 #include <kstandarddirs.h> 00033 #include <kdebug.h> 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <errno.h> 00037 #include <kio/kfileshare.h> 00038 #include <kseparator.h> 00039 #include <tqpushbutton.h> 00040 #include <kapplication.h> 00041 #include <ksimpleconfig.h> 00042 #include <kmessagebox.h> 00043 00044 class KFileSharePropsPlugin::Private 00045 { 00046 public: 00047 TQVBox *m_vBox; 00048 KProcess *m_configProc; 00049 bool m_bAllShared; 00050 bool m_bAllUnshared; 00051 bool m_bAllReadOnly; 00052 }; 00053 00054 KFileSharePropsPlugin::KFileSharePropsPlugin( KPropertiesDialog *_props ) 00055 : KPropsDlgPlugin( _props ) 00056 { 00057 d = new Private; 00058 d->m_vBox = _props->addVBoxPage( i18n("&Share") ); 00059 d->m_configProc = 0; 00060 properties->setFileSharingPage(d->m_vBox); 00061 m_widget = 0L; 00062 init(); 00063 } 00064 00065 KFileSharePropsPlugin::~KFileSharePropsPlugin() 00066 { 00067 if (d->m_configProc) 00068 d->m_configProc->detach(); // Detach to prevent that we kill the process 00069 delete d; 00070 } 00071 00072 bool KFileSharePropsPlugin::supports( const KFileItemList& items ) 00073 { 00074 // Do not show dialog if in advanced mode, 00075 // because the advanced dialog is shown already. 00076 if (KFileShare::shareMode() == KFileShare::Advanced) { 00077 kdDebug() << "KFileSharePropsPlugin::supports: false because sharemode is advanced" << endl; 00078 return false; 00079 } 00080 00081 KFileItemListIterator it( items ); 00082 for ( ; it.current(); ++it ) 00083 { 00084 bool isLocal = ( *it )->isLocalFile(); 00085 // We only support local dirs 00086 if ( !(*it)->isDir() || !isLocal ) 00087 return false; 00088 // And sharing the trash doesn't make sense 00089 if ( isLocal && (*it)->url().path( 1 ) == KGlobalSettings::trashPath() ) 00090 return false; 00091 } 00092 return true; 00093 } 00094 00095 void KFileSharePropsPlugin::init() 00096 { 00097 // We store the main widget, so that it's possible (later) to call init() 00098 // more than once, to update the page if something changed (e.g. after 00099 // the user has been authorized) 00100 delete m_widget; 00101 m_rbShare = 0L; 00102 m_rbUnShare = 0L; 00103 m_rbSharerw = 0L; 00104 m_widget = new TQWidget( d->m_vBox ); 00105 TQVBoxLayout * vbox = new TQVBoxLayout( m_widget ); 00106 //TQHBoxLayout * hbox = new TQHBoxLayout( vbox ); 00107 00108 switch ( KFileShare::authorization() ) { 00109 case KFileShare::Authorized: 00110 { 00111 // Check if all selected dirs are in $HOME 00112 TQString home = TQDir::homeDirPath(); 00113 if ( home[home.length()-1] != '/' ) 00114 home += '/'; 00115 bool ok = true; 00116 KFileItemList items = properties->items(); 00117 // We have 3 possibilities: all shared, all unshared (ro,rw), or mixed. 00118 d->m_bAllShared = true; 00119 d->m_bAllUnshared = true; 00120 d->m_bAllReadOnly = true; 00121 KFileItemListIterator it( items ); 00122 for ( ; it.current() && ok; ++it ) { 00123 TQString path = (*it)->url().path(); 00124 // 0 => not shared 00125 // 1 => shared read only 00126 // 3 => shared writeable 00127 int dirStatus = KFileShare::isDirectoryShared( path ); 00128 if ( !path.startsWith( home ) ) 00129 ok = false; 00130 if ( dirStatus == 1 ) { 00131 d->m_bAllUnshared = false; 00132 } 00133 else if ( dirStatus == 3 ) { 00134 d->m_bAllUnshared = false; 00135 d->m_bAllReadOnly = false; 00136 } 00137 else { 00138 d->m_bAllReadOnly = false; 00139 } 00140 } 00141 if ( !ok ) 00142 { 00143 vbox->addWidget( new TQLabel( i18n( "Only folders in your home folder can be shared."), 00144 m_widget ), 0 ); 00145 } 00146 else 00147 { 00148 // Everything ok, show the share/unshare GUI 00149 vbox->setSpacing( KDialog::spacingHint() ); 00150 vbox->setMargin( KDialog::marginHint() ); 00151 00152 TQButtonGroup *rbGroup = new TQButtonGroup( m_widget ); 00153 rbGroup->hide(); 00154 m_rbUnShare = new TQRadioButton( i18n("Not shared"), m_widget ); 00155 connect( m_rbUnShare, TQT_SIGNAL( toggled(bool) ), TQT_SIGNAL( changed() ) ); 00156 vbox->addWidget( m_rbUnShare, 0 ); 00157 rbGroup->insert( m_rbUnShare ); 00158 00159 m_rbShare = new TQRadioButton( i18n("Shared - read only for others"), m_widget ); 00160 connect( m_rbShare, TQT_SIGNAL( toggled(bool) ), TQT_SIGNAL( changed() ) ); 00161 vbox->addWidget( m_rbShare, 0 ); 00162 rbGroup->insert( m_rbShare ); 00163 00164 m_rbSharerw = new TQRadioButton( i18n("Shared - writeable for others"), m_widget ); 00165 connect( m_rbSharerw, TQT_SIGNAL( toggled(bool) ), TQT_SIGNAL( changed() ) ); 00166 vbox->addWidget( m_rbSharerw, 0 ); 00167 rbGroup->insert( m_rbSharerw ); 00168 00169 //TQLabel *testlabel1 = new TQLabel(i18n("Enter Samba Share Name here"),m_widget); 00170 //m_leSmbShareName = new TQLineEdit(m_widget); 00171 //m_leSmbShareName->setMaxLength(12); 00172 00173 //hbox->addWidget( testlabel1, 0 ); 00174 //hbox->addWidget( m_leSmbShareName ); 00175 //vbox->addLayout( hbox ); 00176 00177 // Activate depending on status 00178 if ( d->m_bAllShared ) 00179 m_rbSharerw->setChecked(true); 00180 if ( d->m_bAllUnshared ) 00181 m_rbUnShare->setChecked(true); 00182 if ( d->m_bAllReadOnly ) 00183 m_rbShare->setChecked(true); 00184 00185 // Some help text 00186 TQLabel *label = new TQLabel( i18n("Sharing this folder makes it available under Linux/UNIX (NFS) and Windows (Samba).") , m_widget ); 00187 label->setAlignment( TQt::AlignAuto | TQt::AlignVCenter | TQt::WordBreak ); 00188 vbox->addWidget( label, 0 ); 00189 00190 KSeparator* sep=new KSeparator(m_widget); 00191 vbox->addWidget( sep, 0 ); 00192 label = new TQLabel( i18n("You can also reconfigure file sharing authorization.") , m_widget ); 00193 label->setAlignment( TQt::AlignAuto | TQt::AlignVCenter | TQt::WordBreak ); 00194 vbox->addWidget( label, 0 ); 00195 m_pbConfig = new TQPushButton( i18n("Configure File Sharing..."), m_widget ); 00196 connect( m_pbConfig, TQT_SIGNAL( clicked() ), TQT_SLOT( slotConfigureFileSharing() ) ); 00197 vbox->addWidget( m_pbConfig, 0, Qt::AlignHCenter ); 00198 00199 vbox->addStretch( 10 ); 00200 00201 if( !KFileShare::sambaActive() && !KFileShare::nfsActive()) 00202 m_widget->setEnabled( false ); 00203 } 00204 } 00205 break; 00206 case KFileShare::ErrorNotFound: 00207 vbox->addWidget( new TQLabel( i18n("Error running 'filesharelist'. Check if installed and in $PATH or /usr/sbin."), 00208 m_widget ), 0 ); 00209 break; 00210 case KFileShare::UserNotAllowed: 00211 { 00212 vbox->setSpacing( 10 ); 00213 if (KFileShare::sharingEnabled()) { 00214 vbox->addWidget( new TQLabel( i18n("You need to be authorized to share folders."), 00215 m_widget ), 0 ); 00216 } else { 00217 vbox->addWidget( new TQLabel( i18n("File sharing is disabled."), 00218 m_widget ), 0 ); 00219 } 00220 TQHBoxLayout* hBox = new TQHBoxLayout( (TQWidget *)0L ); 00221 vbox->addLayout( hBox, 0 ); 00222 m_pbConfig = new TQPushButton( i18n("Configure File Sharing..."), m_widget ); 00223 connect( m_pbConfig, TQT_SIGNAL( clicked() ), TQT_SLOT( slotConfigureFileSharing() ) ); 00224 hBox->addWidget( m_pbConfig, 0, Qt::AlignHCenter ); 00225 vbox->addStretch( 10 ); // align items on top 00226 break; 00227 } 00228 case KFileShare::NotInitialized: 00229 kdWarning() << "KFileShare Authorization still NotInitialized after calling authorization() - impossible" << endl; 00230 break; 00231 } 00232 m_widget->show(); // In case the dialog was shown already. 00233 } 00234 00235 void KFileSharePropsPlugin::slotConfigureFileSharing() 00236 { 00237 if (d->m_configProc) return; 00238 00239 d->m_configProc = new KProcess(this); 00240 (*d->m_configProc) << KStandardDirs::findExe("kdesu") << locate("exe", "kcmshell") << "fileshare"; 00241 if (!d->m_configProc->start( KProcess::NotifyOnExit )) 00242 { 00243 delete d->m_configProc; 00244 d->m_configProc = 0; 00245 return; 00246 } 00247 connect(d->m_configProc, TQT_SIGNAL(processExited(KProcess *)), 00248 this, TQT_SLOT(slotConfigureFileSharingDone())); 00249 m_pbConfig->setEnabled(false); 00250 } 00251 00252 void KFileSharePropsPlugin::slotConfigureFileSharingDone() 00253 { 00254 delete d->m_configProc; 00255 d->m_configProc = 0; 00256 KFileShare::readConfig(); 00257 KFileShare::readShareList(); 00258 init(); 00259 } 00260 00261 void KFileSharePropsPlugin::applyChanges() 00262 { 00263 kdDebug() << "KFileSharePropsPlugin::applyChanges" << endl; 00264 if ( m_rbShare && m_rbUnShare && m_rbSharerw ) 00265 { 00266 bool share = m_rbShare->isChecked(); 00267 00268 if (share && d->m_bAllShared) 00269 return; // Nothing to do 00270 if (!share && d->m_bAllUnshared) 00271 return; // Nothing to do 00272 00273 KFileItemList items = properties->items(); 00274 KFileItemListIterator it( items ); 00275 bool ok = true; 00276 for ( ; it.current() && ok; ++it ) { 00277 TQString path = (*it)->url().path(); 00278 ok = SuSEsetShared( path, share, m_rbSharerw->isChecked() ); 00279 if (!ok) { 00280 if (share) 00281 KMessageBox::detailedError(properties, 00282 i18n("Sharing folder '%1' failed.").arg(path), 00283 i18n("An error occurred while trying to share folder '%1'. " 00284 "Make sure that the Perl script 'fileshareset' is set suid root.") 00285 .arg(path)); 00286 else 00287 KMessageBox::error(properties, 00288 i18n("Unsharing folder '%1' failed.").arg(path), 00289 i18n("An error occurred while trying to unshare folder '%1'. " 00290 "Make sure that the Perl script 'fileshareset' is set suid root.") 00291 .arg(path)); 00292 00293 properties->abortApplying(); 00294 break; 00295 } 00296 } 00297 00298 // Get the change back into our cached info 00299 KFileShare::readShareList(); 00300 } 00301 } 00302 00303 bool KFileSharePropsPlugin::setShared( const TQString& path, bool shared ) 00304 { 00305 return SuSEsetShared( path, shared, true ); 00306 } 00307 00308 bool KFileSharePropsPlugin::SuSEsetShared( const TQString& path, bool shared, bool readonly ) 00309 { 00310 kdDebug() << "KFileSharePropsPlugin::setShared " << path << "," 00311 << shared << readonly << endl; 00312 return KFileShare::SuSEsetShared( path, shared, readonly ); 00313 } 00314 00315 TQWidget* KFileSharePropsPlugin::page() const 00316 { 00317 return d->m_vBox; 00318 } 00319 00320 #include "kfilesharedlg.moc" 00321 00322 //TODO: do we need to monitor /etc/security/fileshare.conf ? 00323 // if the user is added to the 'fileshare' group, we wouldn't be notified 00324 // Of course the config module can notify us. 00325 // TODO: listen to such notifications ;)