• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDEPrint

cupsaddsmb2.cpp

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

KDEPrint

Skip menu "KDEPrint"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  •   KDEPrint
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal