00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kmlprmanager.h"
00021 #include "printcapreader.h"
00022 #include "printcapentry.h"
00023 #include "lpchelper.h"
00024 #include "matichandler.h"
00025 #include "apshandler.h"
00026 #include "lprngtoolhandler.h"
00027 #include "lprsettings.h"
00028 #include "driver.h"
00029 #include "editentrydialog.h"
00030
00031 #include <qfileinfo.h>
00032 #include <qptrlist.h>
00033 #include <klocale.h>
00034 #include <kstandarddirs.h>
00035 #include <kdebug.h>
00036 #include <kprinter.h>
00037 #include <kprocess.h>
00038 #include <kaction.h>
00039 #include <kmessagebox.h>
00040 #include <klibloader.h>
00041
00042 #include <stdlib.h>
00043 #include <unistd.h>
00044
00045 KMLprManager::KMLprManager(QObject *parent, const char *name, const QStringList & )
00046 : KMManager(parent,name)
00047 {
00048 m_handlers.setAutoDelete(true);
00049 m_handlerlist.setAutoDelete(false);
00050 m_entries.setAutoDelete(true);
00051
00052 m_lpchelper = new LpcHelper(this);
00053 m_currentprinter = 0;
00054
00055 setHasManagement(getuid() == 0);
00056 setPrinterOperationMask(
00057 KMManager::PrinterEnabling |
00058 KMManager::PrinterConfigure |
00059 KMManager::PrinterTesting |
00060 KMManager::PrinterCreation |
00061 KMManager::PrinterRemoval |
00062 KMManager::PrinterTesting
00063 );
00064
00065 initHandlers();
00066 }
00067
00068 void KMLprManager::listPrinters()
00069 {
00070 QFileInfo fi(LprSettings::self()->printcapFile());
00071
00072 if (m_lpchelper)
00073 m_lpchelper->updateStates();
00074
00075
00076 if (!m_updtime.isValid() || m_updtime < fi.lastModified())
00077 {
00078
00079 m_entries.clear();
00080
00081 QPtrListIterator<LprHandler> hit(m_handlerlist);
00082 for (; hit.current(); ++hit)
00083 hit.current()->reset();
00084
00085
00086 PrintcapReader reader;
00087 QFile f(fi.absFilePath());
00088 PrintcapEntry *entry;
00089 if (f.exists() && f.open(IO_ReadOnly))
00090 {
00091 reader.setPrintcapFile(&f);
00092 while ((entry = reader.nextEntry()) != NULL)
00093 {
00094 QPtrListIterator<LprHandler> it(m_handlerlist);
00095 for (; it.current(); ++it)
00096 if (it.current()->validate(entry))
00097 {
00098 KMPrinter *prt = it.current()->createPrinter(entry);
00099 checkPrinterState(prt);
00100 prt->setOption("kde-lpr-handler", it.current()->name());
00101 addPrinter(prt);
00102 break;
00103 }
00104 m_entries.insert(entry->name, entry);
00105 }
00106 }
00107
00108
00109 m_updtime = fi.lastModified();
00110 }
00111 else
00112 {
00113 QPtrListIterator<KMPrinter> it(m_printers);
00114 for (; it.current(); ++it)
00115 if (!it.current()->isSpecial())
00116 {
00117 it.current()->setDiscarded(false);
00118 checkPrinterState(it.current());
00119 }
00120 }
00121 }
00122
00123 void KMLprManager::insertHandler(LprHandler *handler)
00124 {
00125 m_handlers.insert(handler->name(), handler);
00126 m_handlerlist.append(handler);
00127 kdDebug() << "Handler: " << handler->name() << endl;
00128 }
00129
00130 void KMLprManager::initHandlers()
00131 {
00132 m_handlers.clear();
00133 m_handlerlist.clear();
00134
00135 insertHandler(new MaticHandler(this));
00136 insertHandler(new ApsHandler(this));
00137 insertHandler(new LPRngToolHandler(this));
00138
00139
00140 QStringList l = KGlobal::dirs()->findAllResources("data", "kdeprint/lpr/*.la");
00141 for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it)
00142 {
00143 KLibrary *library = KLibLoader::self()->library(QFile::encodeName(*it));
00144 if (library)
00145 {
00146 kdDebug() << "loading external handler from " << *it << endl;
00147 LprHandler*(*func)(KMManager*) = (LprHandler*(*)(KMManager*))(library->symbol("create_handler"));
00148 if (func)
00149 insertHandler(func(this));
00150 else
00151 kdDebug() << "couldn't find the symbol 'create_handler'" << endl;
00152 }
00153 }
00154
00155
00156 insertHandler(new LprHandler("default", this));
00157 }
00158
00159 LprHandler* KMLprManager::findHandler(KMPrinter *prt)
00160 {
00161 QString handlerstr(prt->option("kde-lpr-handler"));
00162 LprHandler *handler(0);
00163 if (handlerstr.isEmpty() || (handler = m_handlers.find(handlerstr)) == NULL)
00164 {
00165 return NULL;
00166 }
00167 return handler;
00168 }
00169
00170 PrintcapEntry* KMLprManager::findEntry(KMPrinter *prt)
00171 {
00172 PrintcapEntry *entry = m_entries.find(prt->printerName());
00173 if (!entry)
00174 {
00175 return NULL;
00176 }
00177 return entry;
00178 }
00179
00180 bool KMLprManager::completePrinter(KMPrinter *prt)
00181 {
00182 LprHandler *handler = findHandler(prt);
00183 PrintcapEntry *entry = findEntry(prt);
00184 if (handler && entry)
00185 return handler->completePrinter(prt, entry, false);
00186 return false;
00187 }
00188
00189 bool KMLprManager::completePrinterShort(KMPrinter *prt)
00190 {
00191 LprHandler *handler = findHandler(prt);
00192 PrintcapEntry *entry = findEntry(prt);
00193 if (!handler || !entry)
00194 return false;
00195
00196 return handler->completePrinter(prt, entry, true);
00197 }
00198
00199 void KMLprManager::checkPrinterState(KMPrinter *prt)
00200 {
00201 if (m_lpchelper)
00202 {
00203 KMPrinter::PrinterState st = m_lpchelper->state(prt);
00204 prt->setState(st);
00205 prt->setAcceptJobs(!(st & KMPrinter::Rejecting));
00206 }
00207 else
00208 {
00209 prt->setState(KMPrinter::Idle);
00210 prt->setAcceptJobs(true);
00211 }
00212 }
00213
00214 DrMain* KMLprManager::loadPrinterDriver(KMPrinter *prt, bool config)
00215 {
00216 if (!prt)
00217 return NULL;
00218
00219 LprHandler *handler = findHandler(prt);
00220 PrintcapEntry *entry = findEntry(prt);
00221 if (handler && entry)
00222 {
00223 DrMain *driver = handler->loadDriver(prt, entry, config);
00224 if (driver)
00225 driver->set("handler", handler->name());
00226 return driver;
00227 }
00228 return NULL;
00229 }
00230
00231 DrMain* KMLprManager::loadFileDriver(const QString& filename)
00232 {
00233 int p = filename.find('/');
00234 QString handler_str = (p != -1 ? filename.left(p) : QString::fromLatin1("default"));
00235 LprHandler *handler = m_handlers.find(handler_str);
00236 if (handler)
00237 {
00238 DrMain *driver = handler->loadDbDriver(filename);
00239 if (driver)
00240 driver->set("handler", handler->name());
00241 return driver;
00242 }
00243 return NULL;
00244 }
00245
00246 bool KMLprManager::enablePrinter(KMPrinter *prt, bool state)
00247 {
00248 QString msg;
00249 if (!m_lpchelper->enable(prt, state, msg))
00250 {
00251 setErrorMsg(msg);
00252 return false;
00253 }
00254 return true;
00255 }
00256
00257 bool KMLprManager::startPrinter(KMPrinter *prt, bool state)
00258 {
00259 QString msg;
00260 if (!m_lpchelper->start(prt, state, msg))
00261 {
00262 setErrorMsg(msg);
00263 return false;
00264 }
00265 return true;
00266 }
00267
00268 bool KMLprManager::savePrinterDriver(KMPrinter *prt, DrMain *driver)
00269 {
00270 LprHandler *handler = findHandler(prt);
00271 PrintcapEntry *entry = findEntry(prt);
00272 if (handler && entry)
00273 {
00274 bool mustSave(false);
00275 if (handler->savePrinterDriver(prt, entry, driver, &mustSave))
00276 {
00277 if (mustSave)
00278 return savePrintcapFile();
00279 return true;
00280 }
00281 }
00282 return false;
00283 }
00284
00285 bool KMLprManager::savePrintcapFile()
00286 {
00287 if (!LprSettings::self()->isLocalPrintcap())
00288 {
00289 setErrorMsg(i18n("The printcap file is a remote file (NIS). It cannot be written."));
00290 return false;
00291 }
00292 QFile f(LprSettings::self()->printcapFile());
00293 if (f.open(IO_WriteOnly))
00294 {
00295 QTextStream t(&f);
00296 QDictIterator<PrintcapEntry> it(m_entries);
00297 for (; it.current(); ++it)
00298 {
00299 it.current()->writeEntry(t);
00300 }
00301 return true;
00302 }
00303 else
00304 {
00305 setErrorMsg(i18n("Unable to save printcap file. Check that "
00306 "you have write permissions for that file."));
00307 return false;
00308 }
00309 }
00310
00311 bool KMLprManager::createPrinter(KMPrinter *prt)
00312 {
00313
00314 PrintcapEntry *oldEntry = m_entries.find(prt->printerName());
00315
00316
00317 LprHandler *handler(0);
00318
00319
00320
00321
00322 if (prt->driver())
00323 handler = m_handlers.find(prt->driver()->get("handler"));
00324 else if (oldEntry)
00325 handler = findHandler(prt);
00326 else
00327 handler = m_handlers.find("default");
00328 if (!handler)
00329 {
00330 setErrorMsg(i18n("Internal error: no handler defined."));
00331 return false;
00332 }
00333 prt->setOption("kde-lpr-handler", handler->name());
00334
00335
00336
00337
00338 if (!prt->driver() && oldEntry)
00339 prt->setDriver(handler->loadDriver(prt, oldEntry, true));
00340
00341 QString sd = LprSettings::self()->baseSpoolDir();
00342 if (sd.isEmpty())
00343 {
00344 setErrorMsg(i18n("Couldn't determine spool directory. See options dialog."));
00345 return false;
00346 }
00347 sd.append("/").append(prt->printerName());
00348 if (!KStandardDirs::makeDir(sd, 0755))
00349 {
00350 setErrorMsg(i18n("Unable to create the spool directory %1. Check that you "
00351 "have the required permissions for that operation.").arg(sd));
00352 return false;
00353 }
00354 PrintcapEntry *entry = handler->createEntry(prt);
00355 if (!entry)
00356 return false;
00357
00358 m_entries.remove(prt->printerName());
00359 entry->name = prt->printerName();
00360 entry->addField("sh", Field::Boolean);
00361 entry->addField("mx", Field::Integer, "0");
00362 entry->addField("sd", Field::String, sd);
00363 if (!prt->option("kde-aliases").isEmpty())
00364 entry->aliases += QStringList::split("|", prt->option("kde-aliases"), false);
00365
00366
00367 m_entries.insert(prt->printerName(), entry);
00368 bool result = savePrintcapFile();
00369 if (result)
00370 {
00371 if (prt->driver())
00372 {
00373 result = handler->savePrinterDriver(prt, entry, prt->driver());
00374 }
00375
00376
00377 if (LprSettings::self()->mode() == LprSettings::LPRng)
00378 {
00379 QString msg;
00380 if (!m_lpchelper->restart(msg))
00381 {
00382 setErrorMsg(i18n("The printer has been created but the print daemon "
00383 "could not be restarted. %1").arg(msg));
00384 return false;
00385 }
00386 }
00387 }
00388 return result;
00389 }
00390
00391 bool KMLprManager::removePrinter(KMPrinter *prt)
00392 {
00393 LprHandler *handler = findHandler(prt);
00394 PrintcapEntry *entry = findEntry(prt);
00395 if (handler && entry)
00396 {
00397 if (handler->removePrinter(prt, entry))
00398 {
00399 QString sd = entry->field("sd");
00400
00401
00402 m_entries.take(prt->printerName());
00403 bool status = savePrintcapFile();
00404 if (status)
00405 {
00406
00407 delete entry;
00408 status = (::system(QFile::encodeName("rm -rf " + KProcess::quote(sd))) == 0);
00409 if (!status)
00410 setErrorMsg(i18n("Unable to remove spool directory %1. "
00411 "Check that you have write permissions "
00412 "for that directory.").arg(sd));
00413 return status;
00414 }
00415 else
00416
00417 m_entries.insert(prt->printerName(), entry);
00418 }
00419 }
00420 return false;
00421 }
00422
00423 QString KMLprManager::driverDbCreationProgram()
00424 {
00425 return QString::fromLatin1("make_driver_db_lpr");
00426 }
00427
00428 QString KMLprManager::driverDirectory()
00429 {
00430 QPtrListIterator<LprHandler> it(m_handlerlist);
00431 QString dbDirs;
00432 for (; it.current(); ++it)
00433 {
00434 QString dir = it.current()->driverDirectory();
00435 if (!dir.isEmpty())
00436 dbDirs.append(dir).append(":");
00437 }
00438 if (!dbDirs.isEmpty())
00439 dbDirs.truncate(dbDirs.length()-1);
00440 return dbDirs;
00441 }
00442
00443 QString KMLprManager::printOptions(KPrinter *prt)
00444 {
00445 KMPrinter *mprt = findPrinter(prt->printerName());
00446 QString opts;
00447 if (mprt)
00448 {
00449 LprHandler *handler = findHandler(mprt);
00450 if (handler)
00451 return handler->printOptions(prt);
00452 }
00453 return QString::null;
00454 }
00455
00456 void KMLprManager::createPluginActions(KActionCollection *coll)
00457 {
00458 KAction *act = new KAction(i18n("&Edit printcap Entry..."), "kdeprint_report", 0, this, SLOT(slotEditPrintcap()), coll, "plugin_editprintcap");
00459 act->setGroup("plugin");
00460 }
00461
00462 void KMLprManager::validatePluginActions(KActionCollection *coll, KMPrinter *prt)
00463 {
00464 m_currentprinter = prt;
00465
00466 coll->action("plugin_editprintcap")->setEnabled(0 && hasManagement() && prt && !prt->isSpecial());
00467 }
00468
00469 void KMLprManager::slotEditPrintcap()
00470 {
00471 if (!m_currentprinter ||
00472 KMessageBox::warningContinueCancel(NULL,
00473 i18n("Editing a printcap entry manually should only be "
00474 "done by confirmed system administrator. This may "
00475 "prevent your printer from working. Do you want to "
00476 "continue?"), QString::null, KStdGuiItem::cont(),
00477 "editPrintcap") == KMessageBox::Cancel)
00478 return;
00479
00480 PrintcapEntry *entry = findEntry(m_currentprinter);
00481 EditEntryDialog dlg(entry, NULL);
00482 if (dlg.exec())
00483 {
00484 }
00485 }
00486
00487 QString KMLprManager::stateInformation()
00488 {
00489 return i18n("Spooler type: %1").arg(LprSettings::self()->mode() == LprSettings::LPR ? "LPR (BSD compatible)" : "LPRng");
00490 }
00491
00492 #include "kmlprmanager.moc"