smbview.cpp
00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be> 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 "smbview.h" 00021 00022 #include <kprocess.h> 00023 #include <ktempfile.h> 00024 #include <qheader.h> 00025 #include <qapplication.h> 00026 00027 #include <kiconloader.h> 00028 #include <klocale.h> 00029 #include <kdebug.h> 00030 #include <kmessagebox.h> 00031 #include <kcursor.h> 00032 00033 #include <qfile.h> 00034 #include <qtextstream.h> 00035 #include <cstdlib> 00036 00037 00038 //********************************************************************************************* 00039 00040 SmbView::SmbView(QWidget *parent, const char *name) 00041 : KListView(parent,name) 00042 { 00043 addColumn(i18n("Printer")); 00044 addColumn(i18n("Comment")); 00045 setFrameStyle(QFrame::WinPanel|QFrame::Sunken); 00046 setLineWidth(1); 00047 setAllColumnsShowFocus(true); 00048 setRootIsDecorated(true); 00049 00050 m_state = Idle; 00051 m_current = 0; 00052 m_proc = new KProcess(); 00053 m_proc->setUseShell(true); 00054 m_passwdFile = 0; 00055 connect(m_proc,SIGNAL(processExited(KProcess*)),SLOT(slotProcessExited(KProcess*))); 00056 connect(m_proc,SIGNAL(receivedStdout(KProcess*,char*,int)),SLOT(slotReceivedStdout(KProcess*,char*,int))); 00057 connect(this,SIGNAL(selectionChanged(QListViewItem*)),SLOT(slotSelectionChanged(QListViewItem*))); 00058 } 00059 00060 SmbView::~SmbView() 00061 { 00062 delete m_proc; 00063 delete m_passwdFile; 00064 } 00065 00066 void SmbView::setLoginInfos(const QString& login, const QString& password) 00067 { 00068 m_login = login; 00069 m_password = password; 00070 00071 // We can't pass the password via the command line or the environment 00072 // because the command line is publically accessible on most OSes and 00073 // the environment is publically accessible on some OSes. 00074 // Therefor we write the password to a file and pass that file to 00075 // smbclient with the -A option 00076 delete m_passwdFile; 00077 m_passwdFile = new KTempFile; 00078 m_passwdFile->setAutoDelete(true); 00079 00080 QTextStream *passwdFile = m_passwdFile->textStream(); 00081 if (!passwdFile) return; // Error 00082 (*passwdFile) << "username = " << m_login << endl; 00083 (*passwdFile) << "password = " << m_password << endl; 00084 // (*passwdFile) << "domain = " << ???? << endl; 00085 00086 m_passwdFile->close(); 00087 } 00088 00089 void SmbView::startProcess(int state) 00090 { 00091 m_buffer = QString::null; 00092 m_state = state; 00093 QApplication::setOverrideCursor(KCursor::waitCursor()); 00094 m_proc->start(KProcess::NotifyOnExit,KProcess::Stdout); 00095 emit running(true); 00096 } 00097 00098 void SmbView::endProcess() 00099 { 00100 switch (m_state) 00101 { 00102 case GroupListing: 00103 processGroups(); 00104 break; 00105 case ServerListing: 00106 processServers(); 00107 break; 00108 case ShareListing: 00109 processShares(); 00110 break; 00111 default: 00112 break; 00113 } 00114 m_state = Idle; 00115 QApplication::restoreOverrideCursor(); 00116 emit running(false); 00117 // clean up for future usage 00118 m_proc->clearArguments(); 00119 } 00120 00121 void SmbView::slotProcessExited(KProcess*) 00122 { 00123 endProcess(); 00124 } 00125 00126 void SmbView::slotReceivedStdout(KProcess*, char *buf, int len) 00127 { 00128 m_buffer.append(QString::fromLocal8Bit(buf,len)); 00129 } 00130 00131 void SmbView::init() 00132 { 00133 // Open Samba configuration file and check if a WINS server is defined 00134 m_wins_server = QString::null; 00135 QString wins_keyword("wins server"); 00136 QFile smb_conf ("/etc/samba/smb.conf"); 00137 if (smb_conf.exists () && smb_conf.open (IO_ReadOnly)) 00138 { 00139 QTextStream smb_stream (&smb_conf); 00140 while (!smb_stream.atEnd ()) 00141 { 00142 QString smb_line = smb_stream.readLine (); 00143 if (smb_line.contains (wins_keyword, FALSE) > 0) 00144 { 00145 QString key = smb_line.section ('=', 0, 0); 00146 key = key.stripWhiteSpace(); 00147 if (key.lower() == wins_keyword) 00148 { 00149 continue; 00150 } 00151 m_wins_server = smb_line.section ('=', 1, 1); 00152 // take only the first declared WINS server 00153 m_wins_server = m_wins_server.section(',', 0, 0); 00154 m_wins_server = m_wins_server.stripWhiteSpace (); 00155 m_wins_server = m_wins_server.section(' ', 0, 0); 00156 // strip any server tag (see man smb.conf(5)) 00157 if (m_wins_server.section(':', 1, 1) != NULL) 00158 { 00159 m_wins_server = m_wins_server.section(':', 1, 1); 00160 } 00161 break; 00162 } 00163 } 00164 smb_conf.close (); 00165 } 00166 m_wins_server = m_wins_server.isEmpty ()? " " : " -U " + m_wins_server + " "; 00167 QString cmd ("nmblookup" + m_wins_server + 00168 "-M -- - | grep '<01>' | awk '{print $1}' | xargs nmblookup -A | grep '<1d>'"); 00169 *m_proc << cmd; 00170 startProcess(GroupListing); 00171 } 00172 00173 void SmbView::setOpen(QListViewItem *item, bool on) 00174 { 00175 if (on && item->childCount() == 0) 00176 { 00177 if (item->depth() == 0) 00178 { // opening group 00179 m_current = item; 00180 *m_proc << "nmblookup"+m_wins_server+"-M "; 00181 *m_proc << KProcess::quote(item->text(0)); 00182 *m_proc << " -S | grep '<20>' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*<20>.*//' | xargs -Iserv_name smbclient -N -L 'serv_name' -W "; 00183 *m_proc << KProcess::quote(item->text(0)); 00184 *m_proc << " -A "; 00185 *m_proc << KProcess::quote(m_passwdFile->name()); 00186 startProcess(ServerListing); 00187 } 00188 else if (item->depth() == 1) 00189 { // opening server 00190 m_current = item; 00191 *m_proc << "smbclient -N -L "; 00192 *m_proc << KProcess::quote(item->text(0)); 00193 *m_proc << " -W "; 00194 *m_proc << KProcess::quote(item->parent()->text(0)); 00195 *m_proc << " -A "; 00196 *m_proc << KProcess::quote(m_passwdFile->name()); 00197 startProcess(ShareListing); 00198 } 00199 } 00200 QListView::setOpen(item,on); 00201 } 00202 00203 void SmbView::processGroups() 00204 { 00205 QStringList grps = QStringList::split('\n',m_buffer,false); 00206 clear(); 00207 for (QStringList::ConstIterator it=grps.begin(); it!=grps.end(); ++it) 00208 { 00209 int p = (*it).find("<1d>"); 00210 if (p == -1) 00211 continue; 00212 QListViewItem *item = new QListViewItem(this,(*it).left(p).stripWhiteSpace()); 00213 item->setExpandable(true); 00214 item->setPixmap(0,SmallIcon("network")); 00215 } 00216 } 00217 00218 void SmbView::processServers() 00219 { 00220 QStringList lines = QStringList::split('\n',m_buffer,true); 00221 QString line; 00222 uint index(0); 00223 for (;index < lines.count();index++) 00224 if (lines[index].stripWhiteSpace().startsWith("Server")) 00225 break; 00226 index += 2; 00227 while (index < lines.count()) 00228 { 00229 line = lines[index++].stripWhiteSpace(); 00230 if (line.isEmpty()) 00231 break; 00232 QStringList words = QStringList::split(' ',line,false); 00233 QListViewItem *item = new QListViewItem(m_current,words[0]); 00234 item->setExpandable(true); 00235 item->setPixmap(0,SmallIcon("kdeprint_computer")); 00236 } 00237 } 00238 00239 void SmbView::processShares() 00240 { 00241 QStringList lines = QStringList::split('\n',m_buffer,true); 00242 QString line; 00243 uint index(0); 00244 for (;index < lines.count();index++) 00245 if (lines[index].stripWhiteSpace().startsWith("Sharename")) 00246 break; 00247 index += 2; 00248 while (index < lines.count()) 00249 { 00250 line = lines[index++].stripWhiteSpace(); 00251 if (line.isEmpty()) 00252 break; 00253 else if ( line.startsWith( "Error returning" ) ) 00254 { 00255 KMessageBox::error( this, line ); 00256 break; 00257 } 00258 QString typestr(line.mid(15, 10).stripWhiteSpace()); 00259 //QStringList words = QStringList::split(' ',line,false); 00260 //if (words[1] == "Printer") 00261 if (typestr == "Printer") 00262 { 00263 QString comm(line.mid(25).stripWhiteSpace()), sharen(line.mid(0, 15).stripWhiteSpace()); 00264 //for (uint i=2; i<words.count(); i++) 00265 // comm += (words[i]+" "); 00266 //QListViewItem *item = new QListViewItem(m_current,words[0],comm); 00267 QListViewItem *item = new QListViewItem(m_current,sharen,comm); 00268 item->setPixmap(0,SmallIcon("kdeprint_printer")); 00269 } 00270 } 00271 } 00272 00273 void SmbView::slotSelectionChanged(QListViewItem *item) 00274 { 00275 if (item && item->depth() == 2) 00276 emit printerSelected(item->parent()->parent()->text(0),item->parent()->text(0),item->text(0)); 00277 } 00278 00279 void SmbView::abort() 00280 { 00281 if (m_proc->isRunning()) 00282 m_proc->kill(); 00283 } 00284 #include "smbview.moc"