00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
00223
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
00262 }
00263 else if (s == "mkdir")
00264 {
00265 m_state = MkDir;
00266
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
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
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
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
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
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
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
00448
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
00451 m_actions << "setdriver" << m_dest;
00452 m_actions << "quit";
00453
00454
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"