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