| # kdeprint Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# cupsaddsmb2.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., 59 Temple Place - Suite 330,
    00017  *  Boston, MA 02111-1307, USA.
    00018  **/
    00019
    00020 #include "cupsaddsmb2.h"
    00021 #include "cupsinfos.h"
    00022 #include "sidepixmap.h"
    00023
    00024 #include <qtimer.h>
    00025 #include <qprogressbar.h>
    00026 #include <qlabel.h>
    00027 #include <qlayout.h>
    00028 #include <qlineedit.h>
    00029 #include <klocale.h>
    00030 #include <kmessagebox.h>
    00031 #include <qmessagebox.h>
    00032 #include <qfile.h>
    00033 #include <kio/passdlg.h>
    00034 #include <kdebug.h>
    00035 #include <kseparator.h>
    00036 #include <kactivelabel.h>
    00037 #include <qwhatsthis.h>
    00038 #include <kpushbutton.h>
    00039 #include <kstdguiitem.h>
    00040
    00041 #include <cups/cups.h>
    00042 #include <ctype.h>
    00043
    00044 CupsAddSmb::CupsAddSmb(QWidget *parent, const char *name)
    00045 : KDialog(parent, name)
    00046 {
    00047     m_state = None;
    00048     m_status = false;
    00049     m_actionindex = 0;
    00050     connect(&m_proc, SIGNAL(receivedStdout(KProcess*,char*,int)), SLOT(slotReceived(KProcess*,char*,int)));
    00051     connect(&m_proc, SIGNAL(receivedStderr(KProcess*,char*,int)), SLOT(slotReceived(KProcess*,char*,int)));
    00052     connect(&m_proc, SIGNAL(processExited(KProcess*)), SLOT(slotProcessExited(KProcess*)));
    00053
    00054     m_side = new SidePixmap(this);
    00055     m_doit = new QPushButton(i18n("&Export"), this);
    00056     m_cancel = new KPushButton(KStdGuiItem::cancel(), this);
    00057     connect(m_cancel, SIGNAL(clicked()), SLOT(reject()));
    00058     connect(m_doit, SIGNAL(clicked()), SLOT(slotActionClicked()));
    00059     m_bar = new QProgressBar(this);
    00060     m_text = new KActiveLabel(this);
    00061     QLabel  *m_title = new QLabel(i18n("Export Printer Driver to Windows Clients"), this);
    00062     setCaption(m_title->text());
    00063     QFont   f(m_title->font());
    00064     f.setBold(true);
    00065     m_title->setFont(f);
    00066     KSeparator  *m_sep = new KSeparator(Qt::Horizontal, this);
    00067     m_textinfo = new QLabel( this );
    00068     m_logined = new QLineEdit( this );
    00069     m_passwded = new QLineEdit( this );
    00070     m_passwded->setEchoMode( QLineEdit::Password );
    00071     m_servered = new QLineEdit( this );
    00072     QLabel *m_loginlab = new QLabel( i18n( "&Username:" ), this );
    00073     QLabel *m_serverlab = new QLabel( i18n( "&Samba server:" ), this );
    00074     QLabel *m_passwdlab = new QLabel( i18n( "&Password:" ), this );
    00075     m_loginlab->setBuddy( m_logined );
    00076     m_serverlab->setBuddy( m_servered );
    00077     m_passwdlab->setBuddy( m_passwded );
    00078
    00079     QString txt = i18n( "<p><b>Samba server</b></p>"
    00080                         "Adobe Windows PostScript driver files plus the CUPS printer PPD will be "
    00081                         "exported to the <tt>[print$]</tt> special share of the Samba server (to change "
    00082                         "the source CUPS server, use the <nobr><i>Configure Manager -> CUPS server</i></nobr> first). "
    00083                         "The <tt>[print$]</tt> share must exist on the Samba side prior to clicking the "
    00084                         "<b>Export</b> button below." );
    00085     QWhatsThis::add( m_serverlab, txt );
    00086     QWhatsThis::add( m_servered, txt );
    00087
    00088     txt = i18n( "<p><b>Samba username</b></p>"
    00089                 "User needs to have write access to the <tt>[print$]</tt> share on the Samba server. "
    00090                 "<tt>[print$]</tt> holds printer drivers prepared for download to Windows clients. "
    00091                 "This dialog does not work for Samba servers configured with <tt>security = share</tt> "
    00092                 "(but works fine with <tt>security = user</tt>)." );
    00093     QWhatsThis::add( m_loginlab, txt );
    00094     QWhatsThis::add( m_logined, txt );
    00095
    00096     txt = i18n( "<p><b>Samba password</b></p>"
    00097                 "The Samba setting <tt>encrypt passwords = yes</tt> "
    00098                 "(default) requires prior use of <tt>smbpasswd -a [username]</tt> command, "
    00099                 "to create an encrypted Samba password and have Samba recognize it." );
    00100     QWhatsThis::add( m_passwdlab, txt );
    00101     QWhatsThis::add( m_passwded, txt );
    00102
    00103     QHBoxLayout *l0 = new QHBoxLayout(this, 10, 10);
    00104     QVBoxLayout *l1 = new QVBoxLayout(0, 0, 10);
    00105     l0->addWidget(m_side);
    00106     l0->addLayout(l1);
    00107     l1->addWidget(m_title);
    00108     l1->addWidget(m_sep);
    00109     l1->addWidget(m_text);
    00110     QGridLayout *l3 = new QGridLayout( 0, 3, 2, 0, 10 );
    00111     l1->addLayout( l3 );
    00112     l3->addWidget( m_loginlab, 1, 0 );
    00113     l3->addWidget( m_passwdlab, 2, 0 );
    00114     l3->addWidget( m_serverlab, 0, 0 );
    00115     l3->addWidget( m_logined, 1, 1 );
    00116     l3->addWidget( m_passwded, 2, 1 );
    00117     l3->addWidget( m_servered, 0, 1 );
    00118     l3->setColStretch( 1, 1 );
    00119     l1->addSpacing( 10 );
    00120     l1->addWidget(m_bar);
    00121     l1->addWidget( m_textinfo );
    00122     l1->addSpacing(30);
    00123     QHBoxLayout *l2 = new QHBoxLayout(0, 0, 10);
    00124     l1->addLayout(l2);
    00125     l2->addStretch(1);
    00126     l2->addWidget(m_doit);
    00127     l2->addWidget(m_cancel);
    00128
    00129     m_logined->setText( CupsInfos::self()->login() );
    00130     m_passwded->setText( CupsInfos::self()->password() );
    00131     m_servered->setText( cupsServer() );
    00132
    00133     setMinimumHeight(400);
    00134 }
    00135
    00136 CupsAddSmb::~CupsAddSmb()
    00137 {
    00138 }
    00139
    00140 void CupsAddSmb::slotActionClicked()
    00141 {
    00142     if (m_state == None)
    00143         doExport();
    00144     else if (m_proc.isRunning())
    00145         m_proc.kill();
    00146 }
    00147
    00148 void CupsAddSmb::slotReceived(KProcess*, char *buf, int buflen)
    00149 {
    00150     QString line;
    00151     int     index(0);
    00152     bool    partial(false);
    00153     static bool incomplete(false);
    00154
    00155     kdDebug(500) << "slotReceived()" << endl;
    00156     while (1)
    00157     {
    00158         // read a line
    00159         line = QString::fromLatin1("");
    00160         partial = true;
    00161         while (index < buflen)
    00162         {
    00163             QChar   c(buf[index++]);
    00164             if (c == '\n')
    00165             {
    00166                 partial = false;
    00167                 break;
    00168             }
    00169             else if (c.isPrint())
    00170                 line += c;
    00171         }
    00172
    00173         if (line.isEmpty())
    00174         {
    00175             kdDebug(500) << "NOTHING TO READ" << endl;
    00176             return;
    00177         }
    00178
    00179         kdDebug(500) << "ANSWER = " << line << " (END = " << line.length() << ")" << endl;
    00180         if (!partial)
    00181         {
    00182             if (incomplete && m_buffer.count() > 0)
    00183                 m_buffer[m_buffer.size()-1].append(line);
    00184             else
    00185                 m_buffer << line;
    00186             incomplete = false;
    00187             kdDebug(500) << "COMPLETE LINE READ (" << m_buffer.count() << ")" << endl;
    00188         }
    00189         else
    00190         {
    00191             if (line.startsWith("smb:") || line.startsWith("rpcclient $"))
    00192             {
    00193                 kdDebug(500) << "END OF ACTION" << endl;
    00194                 checkActionStatus();
    00195                 if (m_status)
    00196                     nextAction();
    00197                 else
    00198                 {
    00199                     // quit program
    00200                     kdDebug(500) << "EXITING PROGRAM..." << endl;
    00201                     m_proc.writeStdin("quit\n", 5);
    00202                     kdDebug(500) << "SENT" << endl;
    00203                 }
    00204                 return;
    00205             }
    00206             else
    00207             {
    00208                 if (incomplete && m_buffer.count() > 0)
    00209                     m_buffer[m_buffer.size()-1].append(line);
    00210                 else
    00211                     m_buffer << line;
    00212                 incomplete = true;
    00213                 kdDebug(500) << "INCOMPLETE LINE READ (" << m_buffer.count() << ")" << endl;
    00214             }
    00215         }
    00216     }
    00217 }
    00218
    00219 void CupsAddSmb::checkActionStatus()
    00220 {
    00221     m_status = false;
    00222     // when checking the status, we need to take into account the
    00223     // echo of the command in the output buffer.
    00224     switch (m_state)
    00225     {
    00226         case None:
    00227         case Start:
    00228             m_status = true;
    00229             break;
    00230         case Copy:
    00231             m_status = (m_buffer.count() == 0);
    00232             break;
    00233         case MkDir:
    00234             m_status = (m_buffer.count() == 1 || m_buffer[1].find("ERRfilexists") != -1);
    00235             break;
    00236         case AddDriver:
    00237         case AddPrinter:
    00238             m_status = (m_buffer.count() == 1 || !m_buffer[1].startsWith("result"));
    00239             break;
    00240     }
    00241     kdDebug(500) << "ACTION STATUS = " << m_status << endl;
    00242 }
    00243
    00244 void CupsAddSmb::nextAction()
    00245 {
    00246     if (m_actionindex < (int)(m_actions.count()))
    00247         QTimer::singleShot(1, this, SLOT(doNextAction()));
    00248 }
    00249
    00250 void CupsAddSmb::doNextAction()
    00251 {
    00252     m_buffer.clear();
    00253     m_state = None;
    00254     if (m_proc.isRunning())
    00255     {
    00256         QCString    s = m_actions[m_actionindex++].latin1();
    00257         m_bar->setProgress(m_bar->progress()+1);
    00258         kdDebug(500) << "NEXT ACTION = " << s << endl;
    00259         if (s == "quit")
    00260         {
    00261             // do nothing
    00262         }
    00263         else if (s == "mkdir")
    00264         {
    00265             m_state = MkDir;
    00266             //m_text->setText(i18n("Creating directory %1").arg(m_actions[m_actionindex]));
    00267             m_textinfo->setText(i18n("Creating folder %1").arg(m_actions[m_actionindex]));
    00268             s.append(" ").append(m_actions[m_actionindex].latin1());
    00269             m_actionindex++;
    00270         }
    00271         else if (s == "put")
    00272         {
    00273             m_state = Copy;
    00274             //m_text->setText(i18n("Uploading %1").arg(m_actions[m_actionindex+1]));
    00275             m_textinfo->setText(i18n("Uploading %1").arg(m_actions[m_actionindex+1]));
    00276             s.append(" ").append(QFile::encodeName(m_actions[m_actionindex]).data()).append(" ").append(m_actions[m_actionindex+1].latin1());
    00277             m_actionindex += 2;
    00278         }
    00279         else if (s == "adddriver")
    00280         {
    00281             m_state = AddDriver;
    00282             //m_text->setText(i18n("Installing driver for %1").arg(m_actions[m_actionindex]));
    00283             m_textinfo->setText(i18n("Installing driver for %1").arg(m_actions[m_actionindex]));
    00284             s.append(" \"").append(m_actions[m_actionindex].latin1()).append("\" \"").append(m_actions[m_actionindex+1].latin1()).append("\"");
    00285             m_actionindex += 2;
    00286         }
    00287         else if (s == "addprinter" || s == "setdriver")
    00288         {
    00289             m_state = AddPrinter;
    00290             //m_text->setText(i18n("Installing printer %1").arg(m_actions[m_actionindex]));
    00291             m_textinfo->setText(i18n("Installing printer %1").arg(m_actions[m_actionindex]));
    00292             QCString    dest = m_actions[m_actionindex].local8Bit();
    00293             if (s == "addprinter")
    00294                 s.append(" ").append(dest).append(" ").append(dest).append(" \"").append(dest).append("\" \"\"");
    00295             else
    00296                 s.append(" ").append(dest).append(" ").append(dest);
    00297             m_actionindex++;
    00298         }
    00299         else
    00300         {
    00301             kdDebug(500) << "ACTION = unknown action" << endl;
    00302             m_proc.kill();
    00303             return;
    00304         }
    00305         // send action
    00306         kdDebug(500) << "ACTION = " << s << endl;
    00307         s.append("\n");
    00308         m_proc.writeStdin(s.data(), s.length());
    00309     }
    00310 }
    00311
    00312 void CupsAddSmb::slotProcessExited(KProcess*)
    00313 {
    00314     kdDebug(500) << "PROCESS EXITED (" << m_state << ")" << endl;
    00315     if (m_proc.normalExit() && m_state != Start && m_status)
    00316     {
    00317         // last process went OK. If it was smbclient, then switch to rpcclient
    00318         if (qstrncmp(m_proc.args().first(), "smbclient", 9) == 0)
    00319         {
    00320             doInstall();
    00321             return;
    00322         }
    00323         else
    00324         {
    00325             m_doit->setEnabled(false);
    00326             m_cancel->setEnabled(true);
    00327             m_cancel->setText(i18n("&Close"));
    00328             m_cancel->setDefault(true);
    00329             m_cancel->setFocus();
    00330             m_logined->setEnabled( true );
    00331             m_servered->setEnabled( true );
    00332             m_passwded->setEnabled( true );
    00333             m_text->setText(i18n("Driver successfully exported."));
    00334             m_bar->reset();
    00335             m_textinfo->setText( QString::null );
    00336             return;
    00337         }
    00338     }
    00339
    00340     if (m_proc.normalExit())
    00341     {
    00342         showError(
    00343                 i18n("Operation failed. Possible reasons are: permission denied "
    00344                      "or invalid Samba configuration (see <a href=\"man:/cupsaddsmb\">"
    00345                      "cupsaddsmb</a> manual page for detailed information, you need "
    00346                      "<a href=\"http://www.cups.org\">CUPS</a> version 1.1.11 or higher). "
    00347                      "You may want to try again with another login/password."));
    00348
    00349     }
    00350     else
    00351     {
    00352         showError(i18n("Operation aborted (process killed)."));
    00353     }
    00354 }
    00355
    00356 void CupsAddSmb::showError(const QString& msg)
    00357 {
    00358     m_text->setText(i18n("<h3>Operation failed.</h3><p>%1</p>").arg(msg));
    00359     m_cancel->setEnabled(true);
    00360     m_logined->setEnabled( true );
    00361     m_servered->setEnabled( true );
    00362     m_passwded->setEnabled( true );
    00363     m_doit->setText(i18n("&Export"));
    00364     m_state = None;
    00365 }
    00366
    00367 bool CupsAddSmb::exportDest(const QString &dest, const QString& datadir)
    00368 {
    00369     CupsAddSmb  dlg;
    00370     dlg.m_dest = dest;
    00371     dlg.m_datadir = datadir;
    00372     dlg.m_text->setText(
    00373             i18n( "You are about to prepare the <b>%1</b> driver to be "
    00374                   "shared out to Windows clients through Samba. This operation "
    00375                   "requires the <a href=\"http://www.adobe.com/products/printerdrivers/main.html\">Adobe PostScript Driver</a>, a recent version of "
    00376                   "Samba 2.2.x and a running SMB service on the target server. "
    00377                   "Click <b>Export</b> to start the operation. Read the <a href=\"man:/cupsaddsmb\">cupsaddsmb</a> "
    00378                   "manual page in Konqueror or type <tt>man cupsaddsmb</tt> in a "
    00379                   "console window to learn more about this functionality." ).arg( dest ) );
    00380     dlg.exec();
    00381     return dlg.m_status;
    00382 }
    00383
    00384 bool CupsAddSmb::doExport()
    00385 {
    00386     m_status = false;
    00387     m_state = None;
    00388
    00389     if (!QFile::exists(m_datadir+"/drivers/ADOBEPS5.DLL") ||
    00390         !QFile::exists(m_datadir+"/drivers/ADOBEPS4.DRV"))
    00391     {
    00392         showError(
    00393             i18n("Some driver files are missing. You can get them on "
    00394                  "<a href=\"http://www.adobe.com\">Adobe</a> web site. "
    00395                  "See <a href=\"man:/cupsaddsmb\">cupsaddsmb</a> manual "
    00396                  "page for more details (you need <a href=\"http://www.cups.org\">CUPS</a> "
    00397                  "version 1.1.11 or higher)."));
    00398         return false;
    00399     }
    00400
    00401     m_bar->setTotalSteps(18);
    00402     m_bar->setProgress(0);
    00403     //m_text->setText(i18n("<p>Preparing to upload driver to host <b>%1</b>").arg(m_servered->text()));
    00404     m_textinfo->setText(i18n("Preparing to upload driver to host %1").arg(m_servered->text()));
    00405     m_cancel->setEnabled(false);
    00406     m_logined->setEnabled( false );
    00407     m_servered->setEnabled( false );
    00408     m_passwded->setEnabled( false );
    00409     m_doit->setText(i18n("&Abort"));
    00410
    00411     const char  *ppdfile;
    00412
    00413     if ((ppdfile = cupsGetPPD(m_dest.local8Bit())) == NULL)
    00414     {
    00415         showError(i18n("The driver for printer <b>%1</b> could not be found.").arg(m_dest));
    00416         return false;
    00417     }
    00418
    00419     m_actions.clear();
    00420     m_actions << "mkdir" << "W32X86";
    00421     m_actions << "put" << ppdfile << "W32X86/"+m_dest+".PPD";
    00422     m_actions << "put" << m_datadir+"/drivers/ADOBEPS5.DLL" << "W32X86/ADOBEPS5.DLL";
    00423     m_actions << "put" << m_datadir+"/drivers/ADOBEPSU.DLL" << "W32X86/ADOBEPSU.DLL";
    00424     m_actions << "put" << m_datadir+"/drivers/ADOBEPSU.HLP" << "W32X86/ADOBEPSU.HLP";
    00425     m_actions << "mkdir" << "WIN40";
    00426     m_actions << "put" << ppdfile << "WIN40/"+m_dest+".PPD";
    00427     m_actions << "put" << m_datadir+"/drivers/ADFONTS.MFM" << "WIN40/ADFONTS.MFM";
    00428     m_actions << "put" << m_datadir+"/drivers/ADOBEPS4.DRV" << "WIN40/ADOBEPS4.DRV";
    00429     m_actions << "put" << m_datadir+"/drivers/ADOBEPS4.HLP" << "WIN40/ADOBEPS4.HLP";
    00430     m_actions << "put" << m_datadir+"/drivers/DEFPRTR2.PPD" << "WIN40/DEFPRTR2.PPD";
    00431     m_actions << "put" << m_datadir+"/drivers/ICONLIB.DLL" << "WIN40/ICONLIB.DLL";
    00432     m_actions << "put" << m_datadir+"/drivers/PSMON.DLL" << "WIN40/PSMON.DLL";
    00433     m_actions << "quit";
    00434
    00435     m_proc.clearArguments();
    00436     m_proc << "smbclient" << QString::fromLatin1("//")+m_servered->text()+"/print$";
    00437     return startProcess();
    00438 }
    00439
    00440 bool CupsAddSmb::doInstall()
    00441 {
    00442     m_status = false;
    00443     m_state = None;
    00444
    00445     m_actions.clear();
    00446     m_actions << "adddriver" << "Windows NT x86" << m_dest+":ADOBEPS5.DLL:"+m_dest+".PPD:ADOBEPSU.DLL:ADOBEPSU.HLP:NULL:RAW:NULL";
    00447     // seems to be wrong with newer versions of Samba
    00448     //m_actions << "addprinter" << m_dest;
    00449     m_actions << "adddriver" << "Windows 4.0" << m_dest+":ADOBEPS4.DRV:"+m_dest+".PPD:NULL:ADOBEPS4.HLP:PSMON.DLL:RAW:ADFONTS.MFM,DEFPRTR2.PPD,ICONLIB.DLL";
    00450     // seems to be ok with newer versions of Samba
    00451     m_actions << "setdriver" << m_dest;
    00452     m_actions << "quit";
    00453
    00454     //m_text->setText(i18n("Preparing to install driver on host <b>%1</b>").arg(m_servered->text()));
    00455     m_textinfo->setText(i18n("Preparing to install driver on host %1").arg(m_servered->text()));
    00456
    00457     m_proc.clearArguments();
    00458     m_proc << "rpcclient" << m_servered->text();
    00459     return startProcess();
    00460 }
    00461
    00462 bool CupsAddSmb::startProcess()
    00463 {
    00464     m_proc << "-d" << "0" << "-N" << "-U";
    00465     if (m_passwded->text().isEmpty())
    00466         m_proc << m_logined->text();
    00467     else
    00468         m_proc << m_logined->text()+"%"+m_passwded->text();
    00469     m_state = Start;
    00470     m_actionindex = 0;
    00471     m_buffer.clear();
    00472     kdDebug(500) << "PROCESS STARTED = " << m_proc.args()[0] << endl;
    00473     return m_proc.start(KProcess::NotifyOnExit, KProcess::All);
    00474 }
    00475
    00476 #include "cupsaddsmb2.moc"

This file is part of the documentation for kdeprint Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:31:00 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003