00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include "kmcupsmanager.h"
00023 #include "kmprinter.h"
00024 #include "ipprequest.h"
00025 #include "cupsinfos.h"
00026 #include "driver.h"
00027 #include "kmfactory.h"
00028 #include "kmdbentry.h"
00029 #include "cupsaddsmb2.h"
00030 #include "ippreportdlg.h"
00031 #include "kpipeprocess.h"
00032 #include "util.h"
00033 #include "foomatic2loader.h"
00034 #include "ppdloader.h"
00035
00036 #include <qfile.h>
00037 #include <qtextstream.h>
00038 #include <qregexp.h>
00039 #include <qtimer.h>
00040 #include <qsocket.h>
00041 #include <qdatetime.h>
00042
00043 #include <kdebug.h>
00044 #include <kapplication.h>
00045 #include <klocale.h>
00046 #include <kconfig.h>
00047 #include <kstandarddirs.h>
00048 #include <klibloader.h>
00049 #include <kmessagebox.h>
00050 #include <kaction.h>
00051 #include <kdialogbase.h>
00052 #include <kextendedsocket.h>
00053 #include <kprocess.h>
00054 #include <kfilterdev.h>
00055 #include <cups/cups.h>
00056 #include <cups/ppd.h>
00057 #include <math.h>
00058
00059 #define ppdi18n(s) i18n(QString::fromLocal8Bit(s).utf8())
00060
00061 void extractMaticData(QString& buf, const QString& filename);
00062 QString printerURI(KMPrinter *p, bool useExistingURI = false);
00063 QString downloadDriver(KMPrinter *p);
00064
00065 static int trials = 5;
00066
00067
00068
00069 KMCupsManager::KMCupsManager(QObject *parent, const char *name, const QStringList & )
00070 : KMManager(parent,name)
00071 {
00072
00073
00074 CupsInfos::self();
00075 m_cupsdconf = 0;
00076 m_currentprinter = 0;
00077 m_socket = 0;
00078
00079 setHasManagement(true);
00080 setPrinterOperationMask(KMManager::PrinterAll);
00081 setServerOperationMask(KMManager::ServerAll);
00082
00083
00084
00085
00086 setenv("LANG", "en", 1);
00087 }
00088
00089 KMCupsManager::~KMCupsManager()
00090 {
00091
00092 }
00093
00094 QString KMCupsManager::driverDbCreationProgram()
00095 {
00096 return QString::fromLatin1("make_driver_db_cups");
00097 }
00098
00099 QString KMCupsManager::driverDirectory()
00100 {
00101 QString d = cupsInstallDir();
00102 if (d.isEmpty())
00103 d = "/usr";
00104 d.append("/share/cups/model");
00105
00106 d.append(":/usr/share/foomatic/db/source");
00107 return d;
00108 }
00109
00110 QString KMCupsManager::cupsInstallDir()
00111 {
00112 KConfig *conf= KMFactory::self()->printConfig();
00113 conf->setGroup("CUPS");
00114 QString dir = conf->readPathEntry("InstallDir");
00115 return dir;
00116 }
00117
00118 void KMCupsManager::reportIppError(IppRequest *req)
00119 {
00120 setErrorMsg(req->statusMessage());
00121 }
00122
00123 bool KMCupsManager::createPrinter(KMPrinter *p)
00124 {
00125 bool isclass = p->isClass(false), result(false);
00126 IppRequest req;
00127 QString uri;
00128
00129 uri = printerURI(p,false);
00130 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00131
00132 p->setUri(KURL(uri));
00133
00134 if (isclass)
00135 {
00136 req.setOperation(CUPS_ADD_CLASS);
00137 QStringList members = p->members(), uris;
00138 QString s = QString::fromLocal8Bit("ipp://%1:%2/printers/").arg(CupsInfos::self()->host()).arg(CupsInfos::self()->port());
00139 for (QStringList::ConstIterator it=members.begin(); it!=members.end(); ++it)
00140 uris.append(s+(*it));
00141 req.addURI(IPP_TAG_PRINTER,"member-uris",uris);
00142 }
00143 else
00144 {
00145 req.setOperation(CUPS_ADD_PRINTER);
00146
00147
00148 KMPrinter *otherP = findPrinter(p->printerName());
00149 if (!otherP || otherP->device() != p->device())
00150 {
00156 req.addURI(IPP_TAG_PRINTER,"device-uri",p->device());
00157 }
00158 if (!p->option("kde-banners").isEmpty())
00159 {
00160 QStringList bans = QStringList::split(',',p->option("kde-banners"),false);
00161 while (bans.count() < 2)
00162 bans.append("none");
00163 req.addName(IPP_TAG_PRINTER,"job-sheets-default",bans);
00164 }
00165 req.addInteger(IPP_TAG_PRINTER,"job-quota-period",p->option("job-quota-period").toInt());
00166 req.addInteger(IPP_TAG_PRINTER,"job-k-limit",p->option("job-k-limit").toInt());
00167 req.addInteger(IPP_TAG_PRINTER,"job-page-limit",p->option("job-page-limit").toInt());
00168 if (!p->option("requesting-user-name-denied").isEmpty())
00169 req.addName(IPP_TAG_PRINTER,"requesting-user-name-denied",QStringList::split(",",p->option("requesting-user-name-denied"),false));
00170 else if (!p->option("requesting-user-name-allowed").isEmpty())
00171 req.addName(IPP_TAG_PRINTER,"requesting-user-name-allowed",QStringList::split(",",p->option("requesting-user-name-allowed"),false));
00172 else
00173 req.addName(IPP_TAG_PRINTER,"requesting-user-name-allowed",QString::fromLatin1("all"));
00174 }
00175 req.addText(IPP_TAG_PRINTER,"printer-info",p->description());
00176 req.addText(IPP_TAG_PRINTER,"printer-location",p->location());
00177
00178 if (req.doRequest("/admin/"))
00179 {
00180 result = true;
00181 if (p->driver())
00182 result = savePrinterDriver(p,p->driver());
00183 if (result)
00184 upPrinter(p, true);
00185 }
00186 else reportIppError(&req);
00187
00188 return result;
00189 }
00190
00191 bool KMCupsManager::removePrinter(KMPrinter *p)
00192 {
00193 bool result = setPrinterState(p,CUPS_DELETE_PRINTER);
00194 return result;
00195 }
00196
00197 bool KMCupsManager::enablePrinter(KMPrinter *p, bool state)
00198 {
00199 return setPrinterState(p, (state ? CUPS_ACCEPT_JOBS : CUPS_REJECT_JOBS));
00200 }
00201
00202 bool KMCupsManager::startPrinter(KMPrinter *p, bool state)
00203 {
00204 return setPrinterState(p, (state ? IPP_RESUME_PRINTER : IPP_PAUSE_PRINTER));
00205 }
00206
00207 bool KMCupsManager::setDefaultPrinter(KMPrinter *p)
00208 {
00209 return setPrinterState(p,CUPS_SET_DEFAULT);
00210 }
00211
00212 bool KMCupsManager::setPrinterState(KMPrinter *p, int state)
00213 {
00214 IppRequest req;
00215 QString uri;
00216
00217 req.setOperation(state);
00218 uri = printerURI(p);
00219 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00220 if (req.doRequest("/admin/"))
00221 return true;
00222 reportIppError(&req);
00223 return false;
00224 }
00225
00226 bool KMCupsManager::completePrinter(KMPrinter *p)
00227 {
00228 if (completePrinterShort(p))
00229 {
00230
00231 QString ppdname = downloadDriver(p);
00232 ppd_file_t *ppd = (ppdname.isEmpty() ? NULL : ppdOpenFile(ppdname.local8Bit()));
00233 if (ppd)
00234 {
00235 KMDBEntry entry;
00236
00237
00238
00239 entry.manufacturer = ppd->manufacturer;
00240 entry.model = ppd->shortnickname;
00241 entry.modelname = ppd->modelname;
00242
00243 entry.validate(false);
00244
00245 p->setManufacturer(entry.manufacturer);
00246 p->setModel(entry.model);
00247 p->setDriverInfo(QString::fromLocal8Bit(ppd->nickname));
00248 ppdClose(ppd);
00249 }
00250 if (!ppdname.isEmpty())
00251 QFile::remove(ppdname);
00252
00253 return true;
00254 }
00255 return false;
00256 }
00257
00258 bool KMCupsManager::completePrinterShort(KMPrinter *p)
00259 {
00260 IppRequest req;
00261 QStringList keys;
00262 QString uri;
00263
00264 req.setOperation(IPP_GET_PRINTER_ATTRIBUTES);
00265 uri = printerURI(p, true);
00266 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 keys.append("printer-info");
00309 keys.append("printer-make-and-model");
00310 keys.append("job-sheets-default");
00311 keys.append("job-sheets-supported");
00312 keys.append("job-quota-period");
00313 keys.append("job-k-limit");
00314 keys.append("job-page-limit");
00315 keys.append("requesting-user-name-allowed");
00316 keys.append("requesting-user-name-denied");
00317 if (p->isClass(true))
00318 {
00319 keys.append("member-uris");
00320 keys.append("member-names");
00321 }
00322 else
00323 keys.append("device-uri");
00324 req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",keys);
00325
00326 if (req.doRequest("/printers/"))
00327 {
00328 QString value;
00329 if (req.text("printer-info",value)) p->setDescription(value);
00330
00331
00332 if (req.text("printer-make-and-model",value)) p->setDriverInfo(value);
00333 if (req.uri("device-uri",value))
00334 {
00339 p->setDevice( value );
00340 }
00341 QStringList values;
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 if (req.name("member-names",values))
00354 p->setMembers(values);
00355
00356 req.name("job-sheets-default",values);
00357 while (values.count() < 2) values.append("none");
00358 p->setOption("kde-banners",values.join(QString::fromLatin1(",")));
00359 if (req.name("job-sheets-supported",values)) p->setOption("kde-banners-supported",values.join(QString::fromLatin1(",")));
00360
00361
00362 int ival;
00363 if (req.integer("job-quota-period",ival)) p->setOption("job-quota-period",QString::number(ival));
00364 if (req.integer("job-k-limit",ival)) p->setOption("job-k-limit",QString::number(ival));
00365 if (req.integer("job-page-limit",ival)) p->setOption("job-page-limit",QString::number(ival));
00366
00367
00368 if (req.name("requesting-user-name-allowed",values) && values.count() > 0)
00369 {
00370 p->removeOption("requesting-user-name-denied");
00371 p->setOption("requesting-user-name-allowed",values.join(","));
00372 }
00373 if (req.name("requesting-user-name-denied",values) && values.count() > 0)
00374 {
00375 p->removeOption("requesting-user-name-allowed");
00376 p->setOption("requesting-user-name-denied",values.join(","));
00377 }
00378
00379 return true;
00380 }
00381
00382 reportIppError(&req);
00383 return false;
00384 }
00385
00386 bool KMCupsManager::testPrinter(KMPrinter *p)
00387 {
00388 return KMManager::testPrinter(p);
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 }
00412
00413 void KMCupsManager::listPrinters()
00414 {
00415 loadServerPrinters();
00416 }
00417
00418 void KMCupsManager::loadServerPrinters()
00419 {
00420 IppRequest req;
00421 QStringList keys;
00422
00423
00424 req.setOperation(CUPS_GET_PRINTERS);
00425 keys.append("printer-name");
00426 keys.append("printer-type");
00427 keys.append("printer-state");
00428
00429 keys.append("printer-location");
00430 keys.append("printer-uri-supported");
00431 keys.append("printer-is-accepting-jobs");
00432 req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",keys);
00433
00434
00435 req.addName(IPP_TAG_OPERATION, "requesting-user-name", QString(cupsUser()));
00436
00437 if (req.doRequest("/printers/"))
00438 {
00439 processRequest(&req);
00440
00441
00442 req.init();
00443 req.setOperation(CUPS_GET_CLASSES);
00444 req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",keys);
00445
00446 if (req.doRequest("/classes/"))
00447 {
00448 processRequest(&req);
00449
00450
00451 req.init();
00452 req.setOperation(CUPS_GET_DEFAULT);
00453 req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",QString::fromLatin1("printer-name"));
00454 if (req.doRequest("/printers/"))
00455 {
00456 QString s = QString::null;
00457 req.name("printer-name",s);
00458 setHardDefault(findPrinter(s));
00459 }
00460
00461
00462
00463
00464
00465 return;
00466 }
00467 }
00468
00469
00470 reportIppError(&req);
00471 }
00472
00473 void KMCupsManager::processRequest(IppRequest* req)
00474 {
00475 ipp_attribute_t *attr = req->first();
00476 KMPrinter *printer = new KMPrinter();
00477 while (attr)
00478 {
00479 QString attrname(attr->name);
00480 if (attrname == "printer-name")
00481 {
00482 QString value = QString::fromLocal8Bit(attr->values[0].string.text);
00483 printer->setName(value);
00484 printer->setPrinterName(value);
00485 }
00486 else if (attrname == "printer-type")
00487 {
00488 int value = attr->values[0].integer;
00489 printer->setType(0);
00490 printer->addType(((value & CUPS_PRINTER_CLASS) || (value & CUPS_PRINTER_IMPLICIT) ? KMPrinter::Class : KMPrinter::Printer));
00491 if ((value & CUPS_PRINTER_REMOTE)) printer->addType(KMPrinter::Remote);
00492 if ((value & CUPS_PRINTER_IMPLICIT)) printer->addType(KMPrinter::Implicit);
00493
00494
00495 printer->setPrinterCap( ( value & CUPS_PRINTER_OPTIONS ) >> 2 );
00496 }
00497 else if (attrname == "printer-state")
00498 {
00499 switch (attr->values[0].integer)
00500 {
00501 case IPP_PRINTER_IDLE: printer->setState(KMPrinter::Idle); break;
00502 case IPP_PRINTER_PROCESSING: printer->setState(KMPrinter::Processing); break;
00503 case IPP_PRINTER_STOPPED: printer->setState(KMPrinter::Stopped); break;
00504 }
00505 }
00506 else if (attrname == "printer-uri-supported")
00507 {
00508 printer->setUri(KURL(attr->values[0].string.text));
00509 }
00510 else if (attrname == "printer-location")
00511 {
00512 printer->setLocation(QString::fromLocal8Bit(attr->values[0].string.text));
00513 }
00514 else if (attrname == "printer-is-accepting-jobs")
00515 {
00516 printer->setAcceptJobs(attr->values[0].boolean);
00517 }
00518 if (attrname.isEmpty() || attr == req->last())
00519 {
00520 addPrinter(printer);
00521 printer = new KMPrinter();
00522 }
00523 attr = attr->next;
00524 }
00525 delete printer;
00526 }
00527
00528 DrMain* KMCupsManager::loadPrinterDriver(KMPrinter *p, bool)
00529 {
00530 if (!p)
00531 return NULL;
00532
00533 if (p->isClass(true))
00534 {
00535 KMPrinter *first_class_member = NULL;
00536
00537 first_class_member = findPrinter(p->members().first());
00538
00539 if (first_class_member == NULL)
00540 {
00541
00542 return NULL;
00543 }
00544 else
00545 {
00546 p = first_class_member;
00547 }
00548 }
00549
00550 QString fname = downloadDriver(p);
00551 DrMain *driver(0);
00552 if (!fname.isEmpty())
00553 {
00554 driver = loadDriverFile(fname);
00555 if (driver)
00556 driver->set("temporary",fname);
00557 }
00558
00559 return driver;
00560 }
00561
00562 DrMain* KMCupsManager::loadFileDriver(const QString& filename)
00563 {
00564 if (filename.startsWith("ppd:"))
00565 return loadDriverFile(filename.mid(4));
00566 else if (filename.startsWith("foomatic/"))
00567 return loadMaticDriver(filename);
00568 else
00569 return loadDriverFile(filename);
00570 }
00571
00572 DrMain* KMCupsManager::loadMaticDriver(const QString& drname)
00573 {
00574 QStringList comps = QStringList::split('/', drname, false);
00575 QString tmpFile = locateLocal("tmp", "foomatic_" + kapp->randomString(8));
00576 QString PATH = getenv("PATH") + QString::fromLatin1(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin");
00577 QString exe = KStandardDirs::findExe("foomatic-datafile", PATH);
00578 if (exe.isEmpty())
00579 {
00580 setErrorMsg(i18n("Unable to find the executable foomatic-datafile "
00581 "in your PATH. Check that Foomatic is correctly installed."));
00582 return NULL;
00583 }
00584
00585 KPipeProcess in;
00586 QFile out(tmpFile);
00587 QString cmd = KProcess::quote(exe);
00588 cmd += " -t cups -d ";
00589 cmd += KProcess::quote(comps[2]);
00590 cmd += " -p ";
00591 cmd += KProcess::quote(comps[1]);
00592 if (in.open(cmd) && out.open(IO_WriteOnly))
00593 {
00594 QTextStream tin(&in), tout(&out);
00595 QString line;
00596 while (!tin.atEnd())
00597 {
00598 line = tin.readLine();
00599 tout << line << endl;
00600 }
00601 in.close();
00602 out.close();
00603
00604 DrMain *driver = loadDriverFile(tmpFile);
00605 if (driver)
00606 {
00607 driver->set("template", tmpFile);
00608 driver->set("temporary", tmpFile);
00609 return driver;
00610 }
00611 }
00612 setErrorMsg(i18n("Unable to create the Foomatic driver [%1,%2]. "
00613 "Either that driver does not exist, or you don't have "
00614 "the required permissions to perform that operation.").arg(comps[1]).arg(comps[2]));
00615 QFile::remove(tmpFile);
00616 return NULL;
00617 }
00618
00619 DrMain* KMCupsManager::loadDriverFile(const QString& fname)
00620 {
00621 if (QFile::exists(fname))
00622 {
00623 QString msg;
00624 DrMain *driver = PPDLoader::loadDriver( fname, &msg );
00625 if ( driver )
00626 {
00627 driver->set( "template", fname );
00628
00629 }
00630 else
00631 setErrorMsg( msg );
00632 return driver;
00633 }
00634 return NULL;
00635 }
00636
00637 void KMCupsManager::saveDriverFile(DrMain *driver, const QString& filename)
00638 {
00639 kdDebug( 500 ) << "Saving PPD file with template=" << driver->get( "template" ) << endl;
00640 QIODevice *in = KFilterDev::deviceForFile( driver->get( "template" ) );
00641 QFile out(filename);
00642 if (in && in->open(IO_ReadOnly) && out.open(IO_WriteOnly))
00643 {
00644 QTextStream tin(in), tout(&out);
00645 QString line, keyword;
00646 bool isnumeric(false);
00647 DrBase *opt(0);
00648
00649 while (!tin.eof())
00650 {
00651 line = tin.readLine();
00652 if (line.startsWith("*% COMDATA #"))
00653 {
00654 int p(-1), q(-1);
00655 if ((p=line.find("'name'")) != -1)
00656 {
00657 p = line.find('\'',p+6)+1;
00658 q = line.find('\'',p);
00659 keyword = line.mid(p,q-p);
00660 opt = driver->findOption(keyword);
00661 if (opt && (opt->type() == DrBase::Integer || opt->type() == DrBase::Float))
00662 isnumeric = true;
00663 else
00664 isnumeric = false;
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674 else if ((p=line.find("'default'")) != -1 && !keyword.isEmpty() && opt && isnumeric)
00675 {
00676 QString prefix = line.left(p+9);
00677 tout << prefix << " => '" << opt->valueText() << '\'';
00678 if (line.find(',',p) != -1)
00679 tout << ',';
00680 tout << endl;
00681 continue;
00682 }
00683 tout << line << endl;
00684 }
00685 else if (line.startsWith("*Default"))
00686 {
00687 int p = line.find(':',8);
00688 keyword = line.mid(8,p-8);
00689 DrBase *bopt = 0;
00690 if ( keyword == "PageRegion" || keyword == "ImageableArea" || keyword == "PaperDimension" )
00691 bopt = driver->findOption( QString::fromLatin1( "PageSize" ) );
00692 else
00693 bopt = driver->findOption( keyword );
00694 if (bopt)
00695 switch (bopt->type())
00696 {
00697 case DrBase::List:
00698 case DrBase::Boolean:
00699 {
00700 DrListOption *opt = static_cast<DrListOption*>(bopt);
00701 if (opt && opt->currentChoice())
00702 tout << "*Default" << keyword << ": " << opt->currentChoice()->name() << endl;
00703 else
00704 tout << line << endl;
00705 }
00706 break;
00707 case DrBase::Integer:
00708 {
00709 DrIntegerOption *opt = static_cast<DrIntegerOption*>(bopt);
00710 tout << "*Default" << keyword << ": " << opt->fixedVal() << endl;
00711 }
00712 break;
00713 case DrBase::Float:
00714 {
00715 DrFloatOption *opt = static_cast<DrFloatOption*>(bopt);
00716 tout << "*Default" << keyword << ": " << opt->fixedVal() << endl;
00717 }
00718 break;
00719 default:
00720 tout << line << endl;
00721 break;
00722 }
00723 else
00724 tout << line << endl;
00725 }
00726 else
00727 tout << line << endl;
00728 }
00729 }
00730 delete in;
00731 }
00732
00733 bool KMCupsManager::savePrinterDriver(KMPrinter *p, DrMain *d)
00734 {
00735 QString tmpfilename = locateLocal("tmp","print_") + kapp->randomString(8);
00736
00737
00738 saveDriverFile(d,tmpfilename);
00739
00740
00741 IppRequest req;
00742 QString uri;
00743 bool result(false);
00744
00745 req.setOperation(CUPS_ADD_PRINTER);
00746 uri = printerURI(p, true);
00747 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00748 result = req.doFileRequest("/admin/",tmpfilename);
00749
00750
00751 QFile::remove(tmpfilename);
00752
00753 if (!result)
00754 reportIppError(&req);
00755 return result;
00756 }
00757
00758 void* KMCupsManager::loadCupsdConfFunction(const char *name)
00759 {
00760 if (!m_cupsdconf)
00761 {
00762 m_cupsdconf = KLibLoader::self()->library("cupsdconf");
00763 if (!m_cupsdconf)
00764 {
00765 setErrorMsg(i18n("Library cupsdconf not found. Check your installation."));
00766 return NULL;
00767 }
00768 }
00769 void* func = m_cupsdconf->symbol(name);
00770 if (!func)
00771 setErrorMsg(i18n("Symbol %1 not found in cupsdconf library.").arg(name));
00772 return func;
00773 }
00774
00775 void KMCupsManager::unloadCupsdConf()
00776 {
00777 if (m_cupsdconf)
00778 {
00779 KLibLoader::self()->unloadLibrary("libcupsdconf");
00780 m_cupsdconf = 0;
00781 }
00782 }
00783
00784 bool KMCupsManager::restartServer()
00785 {
00786 QString msg;
00787 bool (*f1)(QString&) = (bool(*)(QString&))loadCupsdConfFunction("restartServer");
00788 bool result(false);
00789 if (f1)
00790 {
00791 result = f1(msg);
00792 if (!result) setErrorMsg(msg);
00793 }
00794 unloadCupsdConf();
00795 return result;
00796 }
00797
00798 bool KMCupsManager::configureServer(QWidget *parent)
00799 {
00800 QString msg;
00801 bool (*f2)(QWidget*, QString&) = (bool(*)(QWidget*, QString&))loadCupsdConfFunction("configureServer");
00802 bool result(false);
00803 if (f2)
00804 {
00805 result = f2(parent, msg);
00806 if ( !result )
00807 setErrorMsg( msg );
00808 }
00809 unloadCupsdConf();
00810 return result;
00811 }
00812
00813 QStringList KMCupsManager::detectLocalPrinters()
00814 {
00815 QStringList list;
00816 IppRequest req;
00817 req.setOperation(CUPS_GET_DEVICES);
00818 if (req.doRequest("/"))
00819 {
00820 QString desc, uri, printer, cl;
00821 ipp_attribute_t *attr = req.first();
00822 while (attr)
00823 {
00824 QString attrname(attr->name);
00825 if (attrname == "device-info") desc = attr->values[0].string.text;
00826 else if (attrname == "device-make-and-model") printer = attr->values[0].string.text;
00827 else if (attrname == "device-uri") uri = attr->values[0].string.text;
00828 else if ( attrname == "device-class" ) cl = attr->values[ 0 ].string.text;
00829 if (attrname.isEmpty() || attr == req.last())
00830 {
00831 if (!uri.isEmpty())
00832 {
00833 if (printer == "Unknown") printer = QString::null;
00834 list << cl << uri << desc << printer;
00835 }
00836 uri = desc = printer = cl = QString::null;
00837 }
00838 attr = attr->next;
00839 }
00840 }
00841 return list;
00842 }
00843
00844 void KMCupsManager::createPluginActions(KActionCollection *coll)
00845 {
00846 KAction *act = new KAction(i18n("&Export Driver..."), "kdeprint_uploadsmb", 0, this, SLOT(exportDriver()), coll, "plugin_export_driver");
00847 act->setGroup("plugin");
00848 act = new KAction(i18n("&Printer IPP Report"), "kdeprint_report", 0, this, SLOT(printerIppReport()), coll, "plugin_printer_ipp_report");
00849 act->setGroup("plugin");
00850 }
00851
00852 void KMCupsManager::validatePluginActions(KActionCollection *coll, KMPrinter *pr)
00853 {
00854
00855 m_currentprinter = pr;
00856 coll->action("plugin_export_driver")->setEnabled(pr && pr->isLocal() && !pr->isClass(true) && !pr->isSpecial());
00857 coll->action("plugin_printer_ipp_report")->setEnabled(pr && !pr->isSpecial());
00858 }
00859
00860 void KMCupsManager::exportDriver()
00861 {
00862 if (m_currentprinter && m_currentprinter->isLocal() &&
00863 !m_currentprinter->isClass(true) && !m_currentprinter->isSpecial())
00864 {
00865 QString path = cupsInstallDir();
00866 if (path.isEmpty())
00867 path = "/usr/share/cups";
00868 else
00869 path += "/share/cups";
00870 CupsAddSmb::exportDest(m_currentprinter->printerName(), path);
00871 }
00872 }
00873
00874 void KMCupsManager::printerIppReport()
00875 {
00876 if (m_currentprinter && !m_currentprinter->isSpecial())
00877 {
00878 IppRequest req;
00879 QString uri;
00880
00881 req.setOperation(IPP_GET_PRINTER_ATTRIBUTES);
00882 uri = printerURI(m_currentprinter, true);
00883 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00884
00885
00886
00887
00888
00889
00890
00891 req.dump(2);
00892 if (req.doRequest("/printers/"))
00893 {
00894 ippReport(req, IPP_TAG_PRINTER, i18n("IPP Report for %1").arg(m_currentprinter->printerName()));
00895 }
00896 else
00897 {
00898 KMessageBox::error(0, "<p>"+i18n("Unable to retrieve printer information. Error received:")+"</p>"+req.statusMessage());
00899 }
00900 }
00901 }
00902
00903 void KMCupsManager::ippReport(IppRequest& req, int group, const QString& caption)
00904 {
00905 IppReportDlg::report(&req, group, caption);
00906 }
00907
00908 QString KMCupsManager::stateInformation()
00909 {
00910 return QString("%1: %2:%3")
00911 .arg(i18n("Server"))
00912 .arg(CupsInfos::self()->host())
00913 .arg(CupsInfos::self()->port());
00914 }
00915
00916 void KMCupsManager::checkUpdatePossibleInternal()
00917 {
00918 kdDebug(500) << "Checking for update possible" << endl;
00919 delete m_socket;
00920
00921
00922
00923
00924 m_socket = new QSocket( this );
00925 connect( m_socket, SIGNAL( connected() ), SLOT( slotConnectionSuccess() ) );
00926 connect( m_socket, SIGNAL( error( int ) ), SLOT( slotConnectionFailed( int ) ) );
00927 trials = 5;
00928 QTimer::singleShot( 1, this, SLOT( slotAsyncConnect() ) );
00929 }
00930
00931 void KMCupsManager::slotConnectionSuccess()
00932 {
00933 kdDebug(500) << "Connection success, trying to send a request..." << endl;
00934 m_socket->close();
00935
00936 IppRequest req;
00937 req.setOperation( CUPS_GET_PRINTERS );
00938 req.addKeyword( IPP_TAG_OPERATION, "requested-attributes", QString::fromLatin1( "printer-name" ) );
00939 if ( req.doRequest( "/printers/" ) )
00940 setUpdatePossible( true );
00941 else
00942 {
00943 kdDebug(500) << "Unable to get printer list" << endl;
00944 if ( trials > 0 )
00945 {
00946 trials--;
00947 QTimer::singleShot( 1000, this, SLOT( slotAsyncConnect() ) );
00948 }
00949 else
00950 {
00951 setErrorMsg( i18n( "Connection to CUPS server failed. Check that the CUPS server is correctly installed and running. "
00952 "Error: %1." ).arg( i18n( "the IPP request failed for an unknown reason" ) ) );
00953 setUpdatePossible( false );
00954 }
00955 }
00956 }
00957
00958 void KMCupsManager::slotAsyncConnect()
00959 {
00960 kdDebug(500) << "Starting async connect" << endl;
00961
00962 m_socket->connectToHost( CupsInfos::self()->host(), CupsInfos::self()->port() );
00963 }
00964
00965 void KMCupsManager::slotConnectionFailed( int errcode )
00966 {
00967 kdDebug(500) << "Connection failed trials=" << trials << endl;
00968 if ( trials > 0 )
00969 {
00970
00971
00972 trials--;
00973 m_socket->close();
00974 QTimer::singleShot( 1000, this, SLOT( slotAsyncConnect() ) );
00975 return;
00976 }
00977
00978 setErrorMsg( i18n( "Connection to CUPS server failed. Check that the CUPS server is correctly installed and running. "
00979 "Error: %1." ).arg( errcode == QSocket::ErrConnectionRefused ? i18n( "connection refused" ) : i18n( "host not found" ) ) );
00980 setUpdatePossible( false );
00981 }
00982
00983 void KMCupsManager::hostPingSlot() {
00984 m_hostSuccess = true;
00985 m_lookupDone = true;
00986 }
00987
00988 void KMCupsManager::hostPingFailedSlot() {
00989 m_hostSuccess = false;
00990 m_lookupDone = true;
00991 }
00992
00993
00994
00995 void extractMaticData(QString& buf, const QString& filename)
00996 {
00997 QFile f(filename);
00998 if (f.exists() && f.open(IO_ReadOnly))
00999 {
01000 QTextStream t(&f);
01001 QString line;
01002 while (!t.eof())
01003 {
01004 line = t.readLine();
01005 if (line.startsWith("*% COMDATA #"))
01006 buf.append(line.right(line.length()-12)).append('\n');
01007 }
01008 }
01009 }
01010
01011 QString printerURI(KMPrinter *p, bool use)
01012 {
01013 QString uri;
01014 if (use && !p->uri().isEmpty())
01015 uri = p->uri().prettyURL();
01016 else
01017 uri = QString("ipp://%1:%2/%4/%3").arg(CupsInfos::self()->host()).arg(CupsInfos::self()->port()).arg(p->printerName()).arg((p->isClass(false) ? "classes" : "printers"));
01018 return uri;
01019 }
01020
01021 QString downloadDriver(KMPrinter *p)
01022 {
01023 QString driverfile, prname = p->printerName();
01024 bool changed(false);
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 driverfile = cupsGetPPD(prname.local8Bit());
01044
01045
01046 if (changed)
01047 {
01048 cupsSetServer(CupsInfos::self()->host().local8Bit());
01049 ippSetPort(CupsInfos::self()->port());
01050 }
01051
01052 return driverfile;
01053 }
01054
01055 #include "kmcupsmanager.moc"