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 if (req.doRequest("/printers/"))
00435 {
00436 processRequest(&req);
00437
00438
00439 req.init();
00440 req.setOperation(CUPS_GET_CLASSES);
00441 req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",keys);
00442
00443 if (req.doRequest("/classes/"))
00444 {
00445 processRequest(&req);
00446
00447
00448 req.init();
00449 req.setOperation(CUPS_GET_DEFAULT);
00450 req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",QString::fromLatin1("printer-name"));
00451 if (req.doRequest("/printers/"))
00452 {
00453 QString s = QString::null;
00454 req.name("printer-name",s);
00455 setHardDefault(findPrinter(s));
00456 }
00457
00458
00459
00460
00461
00462 return;
00463 }
00464 }
00465
00466
00467 reportIppError(&req);
00468 }
00469
00470 void KMCupsManager::processRequest(IppRequest* req)
00471 {
00472 ipp_attribute_t *attr = req->first();
00473 KMPrinter *printer = new KMPrinter();
00474 while (attr)
00475 {
00476 QString attrname(attr->name);
00477 if (attrname == "printer-name")
00478 {
00479 QString value = QString::fromLocal8Bit(attr->values[0].string.text);
00480 printer->setName(value);
00481 printer->setPrinterName(value);
00482 }
00483 else if (attrname == "printer-type")
00484 {
00485 int value = attr->values[0].integer;
00486 printer->setType(0);
00487 printer->addType(((value & CUPS_PRINTER_CLASS) || (value & CUPS_PRINTER_IMPLICIT) ? KMPrinter::Class : KMPrinter::Printer));
00488 if ((value & CUPS_PRINTER_REMOTE)) printer->addType(KMPrinter::Remote);
00489 if ((value & CUPS_PRINTER_IMPLICIT)) printer->addType(KMPrinter::Implicit);
00490
00491
00492 printer->setPrinterCap( ( value & CUPS_PRINTER_OPTIONS ) >> 2 );
00493 }
00494 else if (attrname == "printer-state")
00495 {
00496 switch (attr->values[0].integer)
00497 {
00498 case IPP_PRINTER_IDLE: printer->setState(KMPrinter::Idle); break;
00499 case IPP_PRINTER_PROCESSING: printer->setState(KMPrinter::Processing); break;
00500 case IPP_PRINTER_STOPPED: printer->setState(KMPrinter::Stopped); break;
00501 }
00502 }
00503 else if (attrname == "printer-uri-supported")
00504 {
00505 printer->setUri(KURL(attr->values[0].string.text));
00506 }
00507 else if (attrname == "printer-location")
00508 {
00509 printer->setLocation(QString::fromLocal8Bit(attr->values[0].string.text));
00510 }
00511 else if (attrname == "printer-is-accepting-jobs")
00512 {
00513 printer->setAcceptJobs(attr->values[0].boolean);
00514 }
00515 if (attrname.isEmpty() || attr == req->last())
00516 {
00517 addPrinter(printer);
00518 printer = new KMPrinter();
00519 }
00520 attr = attr->next;
00521 }
00522 delete printer;
00523 }
00524
00525 DrMain* KMCupsManager::loadPrinterDriver(KMPrinter *p, bool)
00526 {
00527 if (!p || p->isClass(true))
00528 return NULL;
00529
00530 QString fname = downloadDriver(p);
00531 DrMain *driver(0);
00532 if (!fname.isEmpty())
00533 {
00534 driver = loadDriverFile(fname);
00535 if (driver)
00536 driver->set("temporary",fname);
00537 }
00538
00539 return driver;
00540 }
00541
00542 DrMain* KMCupsManager::loadFileDriver(const QString& filename)
00543 {
00544 if (filename.startsWith("ppd:"))
00545 return loadDriverFile(filename.mid(4));
00546 else if (filename.startsWith("foomatic/"))
00547 return loadMaticDriver(filename);
00548 else
00549 return loadDriverFile(filename);
00550 }
00551
00552 DrMain* KMCupsManager::loadMaticDriver(const QString& drname)
00553 {
00554 QStringList comps = QStringList::split('/', drname, false);
00555 QString tmpFile = locateLocal("tmp", "foomatic_" + kapp->randomString(8));
00556 QString PATH = getenv("PATH") + QString::fromLatin1(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin");
00557 QString exe = KStandardDirs::findExe("foomatic-datafile", PATH);
00558 if (exe.isEmpty())
00559 {
00560 setErrorMsg(i18n("Unable to find the executable foomatic-datafile "
00561 "in your PATH. Check that Foomatic is correctly installed."));
00562 return NULL;
00563 }
00564
00565 KPipeProcess in;
00566 QFile out(tmpFile);
00567 QString cmd = KProcess::quote(exe);
00568 cmd += " -t cups -d ";
00569 cmd += KProcess::quote(comps[2]);
00570 cmd += " -p ";
00571 cmd += KProcess::quote(comps[1]);
00572 if (in.open(cmd) && out.open(IO_WriteOnly))
00573 {
00574 QTextStream tin(&in), tout(&out);
00575 QString line;
00576 while (!tin.atEnd())
00577 {
00578 line = tin.readLine();
00579 tout << line << endl;
00580 }
00581 in.close();
00582 out.close();
00583
00584 DrMain *driver = loadDriverFile(tmpFile);
00585 if (driver)
00586 {
00587 driver->set("template", tmpFile);
00588 driver->set("temporary", tmpFile);
00589 return driver;
00590 }
00591 }
00592 setErrorMsg(i18n("Unable to create the Foomatic driver [%1,%2]. "
00593 "Either that driver does not exist, or you don't have "
00594 "the required permissions to perform that operation.").arg(comps[1]).arg(comps[2]));
00595 QFile::remove(tmpFile);
00596 return NULL;
00597 }
00598
00599 DrMain* KMCupsManager::loadDriverFile(const QString& fname)
00600 {
00601 if (QFile::exists(fname))
00602 {
00603 DrMain *driver = PPDLoader::loadDriver( fname );
00604 if ( driver )
00605 {
00606 driver->set( "template", fname );
00607
00608 }
00609 return driver;
00610 }
00611 return NULL;
00612 }
00613
00614 void KMCupsManager::saveDriverFile(DrMain *driver, const QString& filename)
00615 {
00616 kdDebug( 500 ) << "Saving PPD file with template=" << driver->get( "template" ) << endl;
00617 QIODevice *in = KFilterDev::deviceForFile( driver->get( "template" ) );
00618 QFile out(filename);
00619 if (in && in->open(IO_ReadOnly) && out.open(IO_WriteOnly))
00620 {
00621 QTextStream tin(in), tout(&out);
00622 QString line, keyword;
00623 bool isnumeric(false);
00624 DrBase *opt(0);
00625
00626 while (!tin.eof())
00627 {
00628 line = tin.readLine();
00629 if (line.startsWith("*% COMDATA #"))
00630 {
00631 int p(-1), q(-1);
00632 if ((p=line.find("'name'")) != -1)
00633 {
00634 p = line.find('\'',p+6)+1;
00635 q = line.find('\'',p);
00636 keyword = line.mid(p,q-p);
00637 opt = driver->findOption(keyword);
00638 if (opt && (opt->type() == DrBase::Integer || opt->type() == DrBase::Float))
00639 isnumeric = true;
00640 else
00641 isnumeric = false;
00642 }
00643
00644
00645
00646
00647
00648
00649
00650
00651 else if ((p=line.find("'default'")) != -1 && !keyword.isEmpty() && opt && isnumeric)
00652 {
00653 QString prefix = line.left(p+9);
00654 tout << prefix << " => '" << opt->valueText() << '\'';
00655 if (line.find(',',p) != -1)
00656 tout << ',';
00657 tout << endl;
00658 continue;
00659 }
00660 tout << line << endl;
00661 }
00662 else if (line.startsWith("*Default"))
00663 {
00664 int p = line.find(':',8);
00665 keyword = line.mid(8,p-8);
00666 DrBase *bopt = 0;
00667 if ( keyword == "PageRegion" || keyword == "ImageableArea" || keyword == "PaperDimension" )
00668 bopt = driver->findOption( QString::fromLatin1( "PageSize" ) );
00669 else
00670 bopt = driver->findOption( keyword );
00671 if (bopt)
00672 switch (bopt->type())
00673 {
00674 case DrBase::List:
00675 case DrBase::Boolean:
00676 {
00677 DrListOption *opt = static_cast<DrListOption*>(bopt);
00678 if (opt && opt->currentChoice())
00679 tout << "*Default" << keyword << ": " << opt->currentChoice()->name() << endl;
00680 else
00681 tout << line << endl;
00682 }
00683 break;
00684 case DrBase::Integer:
00685 {
00686 DrIntegerOption *opt = static_cast<DrIntegerOption*>(bopt);
00687 tout << "*Default" << keyword << ": " << opt->fixedVal() << endl;
00688 }
00689 break;
00690 case DrBase::Float:
00691 {
00692 DrFloatOption *opt = static_cast<DrFloatOption*>(bopt);
00693 tout << "*Default" << keyword << ": " << opt->fixedVal() << endl;
00694 }
00695 break;
00696 default:
00697 tout << line << endl;
00698 break;
00699 }
00700 else
00701 tout << line << endl;
00702 }
00703 else
00704 tout << line << endl;
00705 }
00706 }
00707 delete in;
00708 }
00709
00710 bool KMCupsManager::savePrinterDriver(KMPrinter *p, DrMain *d)
00711 {
00712 QString tmpfilename = locateLocal("tmp","print_") + kapp->randomString(8);
00713
00714
00715 saveDriverFile(d,tmpfilename);
00716
00717
00718 IppRequest req;
00719 QString uri;
00720 bool result(false);
00721
00722 req.setOperation(CUPS_ADD_PRINTER);
00723 uri = printerURI(p, true);
00724 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00725 result = req.doFileRequest("/admin/",tmpfilename);
00726
00727
00728 QFile::remove(tmpfilename);
00729
00730 if (!result)
00731 reportIppError(&req);
00732 return result;
00733 }
00734
00735 void* KMCupsManager::loadCupsdConfFunction(const char *name)
00736 {
00737 if (!m_cupsdconf)
00738 {
00739 m_cupsdconf = KLibLoader::self()->library("libcupsdconf");
00740 if (!m_cupsdconf)
00741 {
00742 setErrorMsg(i18n("Library libcupsdconf not found. Check your installation."));
00743 return NULL;
00744 }
00745 }
00746 void* func = m_cupsdconf->symbol(name);
00747 if (!func)
00748 setErrorMsg(i18n("Symbol %1 not found in libcupsdconf library.").arg(name));
00749 return func;
00750 }
00751
00752 void KMCupsManager::unloadCupsdConf()
00753 {
00754 if (m_cupsdconf)
00755 {
00756 KLibLoader::self()->unloadLibrary("libcupsdconf");
00757 m_cupsdconf = 0;
00758 }
00759 }
00760
00761 bool KMCupsManager::restartServer()
00762 {
00763 QString msg;
00764 bool (*f1)(QString&) = (bool(*)(QString&))loadCupsdConfFunction("restartServer");
00765 bool result(false);
00766 if (f1)
00767 {
00768 result = f1(msg);
00769 if (!result) setErrorMsg(msg);
00770 }
00771 unloadCupsdConf();
00772 return result;
00773 }
00774
00775 bool KMCupsManager::configureServer(QWidget *parent)
00776 {
00777 QString msg;
00778 bool (*f2)(QWidget*, QString&) = (bool(*)(QWidget*, QString&))loadCupsdConfFunction("configureServer");
00779 bool result(false);
00780 if (f2)
00781 {
00782 result = f2(parent, msg);
00783 if ( !result )
00784 setErrorMsg( msg );
00785 }
00786 unloadCupsdConf();
00787 return result;
00788 }
00789
00790 QStringList KMCupsManager::detectLocalPrinters()
00791 {
00792 QStringList list;
00793 IppRequest req;
00794 req.setOperation(CUPS_GET_DEVICES);
00795 if (req.doRequest("/"))
00796 {
00797 QString desc, uri, printer, cl;
00798 ipp_attribute_t *attr = req.first();
00799 while (attr)
00800 {
00801 QString attrname(attr->name);
00802 if (attrname == "device-info") desc = attr->values[0].string.text;
00803 else if (attrname == "device-make-and-model") printer = attr->values[0].string.text;
00804 else if (attrname == "device-uri") uri = attr->values[0].string.text;
00805 else if ( attrname == "device-class" ) cl = attr->values[ 0 ].string.text;
00806 if (attrname.isEmpty() || attr == req.last())
00807 {
00808 if (!uri.isEmpty())
00809 {
00810 if (printer == "Unknown") printer = QString::null;
00811 list << cl << uri << desc << printer;
00812 }
00813 uri = desc = printer = cl = QString::null;
00814 }
00815 attr = attr->next;
00816 }
00817 }
00818 return list;
00819 }
00820
00821 void KMCupsManager::createPluginActions(KActionCollection *coll)
00822 {
00823 KAction *act = new KAction(i18n("&Export Driver..."), "kdeprint_uploadsmb", 0, this, SLOT(exportDriver()), coll, "plugin_export_driver");
00824 act->setGroup("plugin");
00825 act = new KAction(i18n("&Printer IPP Report..."), "kdeprint_report", 0, this, SLOT(printerIppReport()), coll, "plugin_printer_ipp_report");
00826 act->setGroup("plugin");
00827 }
00828
00829 void KMCupsManager::validatePluginActions(KActionCollection *coll, KMPrinter *pr)
00830 {
00831
00832 m_currentprinter = pr;
00833 coll->action("plugin_export_driver")->setEnabled(pr && pr->isLocal() && !pr->isClass(true) && !pr->isSpecial());
00834 coll->action("plugin_printer_ipp_report")->setEnabled(pr && !pr->isSpecial());
00835 }
00836
00837 void KMCupsManager::exportDriver()
00838 {
00839 if (m_currentprinter && m_currentprinter->isLocal() &&
00840 !m_currentprinter->isClass(true) && !m_currentprinter->isSpecial())
00841 {
00842 QString path = cupsInstallDir();
00843 if (path.isEmpty())
00844 path = "/usr/share/cups";
00845 else
00846 path += "/share/cups";
00847 CupsAddSmb::exportDest(m_currentprinter->printerName(), path);
00848 }
00849 }
00850
00851 void KMCupsManager::printerIppReport()
00852 {
00853 if (m_currentprinter && !m_currentprinter->isSpecial())
00854 {
00855 IppRequest req;
00856 QString uri;
00857
00858 req.setOperation(IPP_GET_PRINTER_ATTRIBUTES);
00859 uri = printerURI(m_currentprinter, true);
00860 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00861
00862
00863
00864
00865
00866
00867
00868 req.dump(2);
00869 if (req.doRequest("/printers/"))
00870 {
00871 ippReport(req, IPP_TAG_PRINTER, i18n("IPP report for %1").arg(m_currentprinter->printerName()));
00872 }
00873 else
00874 {
00875 KMessageBox::error(0, "<p>"+i18n("Unable to retrieve printer information. Error received:")+"</p>"+req.statusMessage());
00876 }
00877 }
00878 }
00879
00880 void KMCupsManager::ippReport(IppRequest& req, int group, const QString& caption)
00881 {
00882 IppReportDlg::report(&req, group, caption);
00883 }
00884
00885 QString KMCupsManager::stateInformation()
00886 {
00887 return i18n("Connected to %1:%2").arg(CupsInfos::self()->host()).arg(CupsInfos::self()->port());
00888 }
00889
00890 void KMCupsManager::checkUpdatePossibleInternal()
00891 {
00892 kdDebug(500) << "Checking for update possible" << endl;
00893 delete m_socket;
00894
00895
00896
00897
00898 m_socket = new QSocket( this );
00899 connect( m_socket, SIGNAL( connected() ), SLOT( slotConnectionSuccess() ) );
00900 connect( m_socket, SIGNAL( error( int ) ), SLOT( slotConnectionFailed( int ) ) );
00901 trials = 5;
00902 QTimer::singleShot( 1, this, SLOT( slotAsyncConnect() ) );
00903 }
00904
00905 void KMCupsManager::slotConnectionSuccess()
00906 {
00907 kdDebug(500) << "Connection success, trying to send a request..." << endl;
00908 m_socket->close();
00909
00910 IppRequest req;
00911 req.setOperation( CUPS_GET_PRINTERS );
00912 req.addKeyword( IPP_TAG_OPERATION, "requested-attributes", QString::fromLatin1( "printer-name" ) );
00913 if ( req.doRequest( "/printers/" ) )
00914 setUpdatePossible( true );
00915 else
00916 {
00917 kdDebug(500) << "Unable to get printer list" << endl;
00918 if ( trials > 0 )
00919 {
00920 trials--;
00921 QTimer::singleShot( 1000, this, SLOT( slotAsyncConnect() ) );
00922 }
00923 else
00924 {
00925 setErrorMsg( i18n( "Connection to CUPS server failed. Check that the CUPS server is correctly installed and running. "
00926 "Error: %1." ).arg( i18n( "the IPP request failed for an unknown reason" ) ) );
00927 setUpdatePossible( false );
00928 }
00929 }
00930 }
00931
00932 void KMCupsManager::slotAsyncConnect()
00933 {
00934 kdDebug(500) << "Starting async connect" << endl;
00935
00936 m_socket->connectToHost( CupsInfos::self()->host(), CupsInfos::self()->port() );
00937 }
00938
00939 void KMCupsManager::slotConnectionFailed( int errcode )
00940 {
00941 kdDebug(500) << "Connection failed trials=" << trials << endl;
00942 if ( trials > 0 )
00943 {
00944
00945
00946 trials--;
00947 m_socket->close();
00948 QTimer::singleShot( 1000, this, SLOT( slotAsyncConnect() ) );
00949 return;
00950 }
00951
00952 setErrorMsg( i18n( "Connection to CUPS server failed. Check that the CUPS server is correctly installed and running. "
00953 "Error: %1." ).arg( errcode == QSocket::ErrConnectionRefused ? i18n( "connection refused" ) : i18n( "host not found" ) ) );
00954 setUpdatePossible( false );
00955 }
00956
00957 void KMCupsManager::hostPingSlot() {
00958 m_hostSuccess = true;
00959 m_lookupDone = true;
00960 }
00961
00962 void KMCupsManager::hostPingFailedSlot() {
00963 m_hostSuccess = false;
00964 m_lookupDone = true;
00965 }
00966
00967
00968
00969 void extractMaticData(QString& buf, const QString& filename)
00970 {
00971 QFile f(filename);
00972 if (f.exists() && f.open(IO_ReadOnly))
00973 {
00974 QTextStream t(&f);
00975 QString line;
00976 while (!t.eof())
00977 {
00978 line = t.readLine();
00979 if (line.startsWith("*% COMDATA #"))
00980 buf.append(line.right(line.length()-12)).append('\n');
00981 }
00982 }
00983 }
00984
00985 QString printerURI(KMPrinter *p, bool use)
00986 {
00987 QString uri;
00988 if (use && !p->uri().isEmpty())
00989 uri = p->uri().prettyURL();
00990 else
00991 uri = QString("ipp://%1:%2/%4/%3").arg(CupsInfos::self()->host()).arg(CupsInfos::self()->port()).arg(p->printerName()).arg((p->isClass(false) ? "classes" : "printers"));
00992 return uri;
00993 }
00994
00995 QString downloadDriver(KMPrinter *p)
00996 {
00997 QString driverfile, prname = p->printerName();
00998 bool changed(false);
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017 driverfile = cupsGetPPD(prname.local8Bit());
01018
01019
01020 if (changed)
01021 {
01022 cupsSetServer(CupsInfos::self()->host().local8Bit());
01023 ippSetPort(CupsInfos::self()->port());
01024 }
01025
01026 return driverfile;
01027 }
01028
01029 #include "kmcupsmanager.moc"