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 QString msg;
00604 DrMain *driver = PPDLoader::loadDriver( fname, &msg );
00605 if ( driver )
00606 {
00607 driver->set( "template", fname );
00608
00609 }
00610 else
00611 setErrorMsg( msg );
00612 return driver;
00613 }
00614 return NULL;
00615 }
00616
00617 void KMCupsManager::saveDriverFile(DrMain *driver, const QString& filename)
00618 {
00619 kdDebug( 500 ) << "Saving PPD file with template=" << driver->get( "template" ) << endl;
00620 QIODevice *in = KFilterDev::deviceForFile( driver->get( "template" ) );
00621 QFile out(filename);
00622 if (in && in->open(IO_ReadOnly) && out.open(IO_WriteOnly))
00623 {
00624 QTextStream tin(in), tout(&out);
00625 QString line, keyword;
00626 bool isnumeric(false);
00627 DrBase *opt(0);
00628
00629 while (!tin.eof())
00630 {
00631 line = tin.readLine();
00632 if (line.startsWith("*% COMDATA #"))
00633 {
00634 int p(-1), q(-1);
00635 if ((p=line.find("'name'")) != -1)
00636 {
00637 p = line.find('\'',p+6)+1;
00638 q = line.find('\'',p);
00639 keyword = line.mid(p,q-p);
00640 opt = driver->findOption(keyword);
00641 if (opt && (opt->type() == DrBase::Integer || opt->type() == DrBase::Float))
00642 isnumeric = true;
00643 else
00644 isnumeric = false;
00645 }
00646
00647
00648
00649
00650
00651
00652
00653
00654 else if ((p=line.find("'default'")) != -1 && !keyword.isEmpty() && opt && isnumeric)
00655 {
00656 QString prefix = line.left(p+9);
00657 tout << prefix << " => '" << opt->valueText() << '\'';
00658 if (line.find(',',p) != -1)
00659 tout << ',';
00660 tout << endl;
00661 continue;
00662 }
00663 tout << line << endl;
00664 }
00665 else if (line.startsWith("*Default"))
00666 {
00667 int p = line.find(':',8);
00668 keyword = line.mid(8,p-8);
00669 DrBase *bopt = 0;
00670 if ( keyword == "PageRegion" || keyword == "ImageableArea" || keyword == "PaperDimension" )
00671 bopt = driver->findOption( QString::fromLatin1( "PageSize" ) );
00672 else
00673 bopt = driver->findOption( keyword );
00674 if (bopt)
00675 switch (bopt->type())
00676 {
00677 case DrBase::List:
00678 case DrBase::Boolean:
00679 {
00680 DrListOption *opt = static_cast<DrListOption*>(bopt);
00681 if (opt && opt->currentChoice())
00682 tout << "*Default" << keyword << ": " << opt->currentChoice()->name() << endl;
00683 else
00684 tout << line << endl;
00685 }
00686 break;
00687 case DrBase::Integer:
00688 {
00689 DrIntegerOption *opt = static_cast<DrIntegerOption*>(bopt);
00690 tout << "*Default" << keyword << ": " << opt->fixedVal() << endl;
00691 }
00692 break;
00693 case DrBase::Float:
00694 {
00695 DrFloatOption *opt = static_cast<DrFloatOption*>(bopt);
00696 tout << "*Default" << keyword << ": " << opt->fixedVal() << endl;
00697 }
00698 break;
00699 default:
00700 tout << line << endl;
00701 break;
00702 }
00703 else
00704 tout << line << endl;
00705 }
00706 else
00707 tout << line << endl;
00708 }
00709 }
00710 delete in;
00711 }
00712
00713 bool KMCupsManager::savePrinterDriver(KMPrinter *p, DrMain *d)
00714 {
00715 QString tmpfilename = locateLocal("tmp","print_") + kapp->randomString(8);
00716
00717
00718 saveDriverFile(d,tmpfilename);
00719
00720
00721 IppRequest req;
00722 QString uri;
00723 bool result(false);
00724
00725 req.setOperation(CUPS_ADD_PRINTER);
00726 uri = printerURI(p, true);
00727 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00728 result = req.doFileRequest("/admin/",tmpfilename);
00729
00730
00731 QFile::remove(tmpfilename);
00732
00733 if (!result)
00734 reportIppError(&req);
00735 return result;
00736 }
00737
00738 void* KMCupsManager::loadCupsdConfFunction(const char *name)
00739 {
00740 if (!m_cupsdconf)
00741 {
00742 m_cupsdconf = KLibLoader::self()->library("cupsdconf");
00743 if (!m_cupsdconf)
00744 {
00745 setErrorMsg(i18n("Library cupsdconf not found. Check your installation."));
00746 return NULL;
00747 }
00748 }
00749 void* func = m_cupsdconf->symbol(name);
00750 if (!func)
00751 setErrorMsg(i18n("Symbol %1 not found in cupsdconf library.").arg(name));
00752 return func;
00753 }
00754
00755 void KMCupsManager::unloadCupsdConf()
00756 {
00757 if (m_cupsdconf)
00758 {
00759 KLibLoader::self()->unloadLibrary("libcupsdconf");
00760 m_cupsdconf = 0;
00761 }
00762 }
00763
00764 bool KMCupsManager::restartServer()
00765 {
00766 QString msg;
00767 bool (*f1)(QString&) = (bool(*)(QString&))loadCupsdConfFunction("restartServer");
00768 bool result(false);
00769 if (f1)
00770 {
00771 result = f1(msg);
00772 if (!result) setErrorMsg(msg);
00773 }
00774 unloadCupsdConf();
00775 return result;
00776 }
00777
00778 bool KMCupsManager::configureServer(QWidget *parent)
00779 {
00780 QString msg;
00781 bool (*f2)(QWidget*, QString&) = (bool(*)(QWidget*, QString&))loadCupsdConfFunction("configureServer");
00782 bool result(false);
00783 if (f2)
00784 {
00785 result = f2(parent, msg);
00786 if ( !result )
00787 setErrorMsg( msg );
00788 }
00789 unloadCupsdConf();
00790 return result;
00791 }
00792
00793 QStringList KMCupsManager::detectLocalPrinters()
00794 {
00795 QStringList list;
00796 IppRequest req;
00797 req.setOperation(CUPS_GET_DEVICES);
00798 if (req.doRequest("/"))
00799 {
00800 QString desc, uri, printer, cl;
00801 ipp_attribute_t *attr = req.first();
00802 while (attr)
00803 {
00804 QString attrname(attr->name);
00805 if (attrname == "device-info") desc = attr->values[0].string.text;
00806 else if (attrname == "device-make-and-model") printer = attr->values[0].string.text;
00807 else if (attrname == "device-uri") uri = attr->values[0].string.text;
00808 else if ( attrname == "device-class" ) cl = attr->values[ 0 ].string.text;
00809 if (attrname.isEmpty() || attr == req.last())
00810 {
00811 if (!uri.isEmpty())
00812 {
00813 if (printer == "Unknown") printer = QString::null;
00814 list << cl << uri << desc << printer;
00815 }
00816 uri = desc = printer = cl = QString::null;
00817 }
00818 attr = attr->next;
00819 }
00820 }
00821 return list;
00822 }
00823
00824 void KMCupsManager::createPluginActions(KActionCollection *coll)
00825 {
00826 KAction *act = new KAction(i18n("&Export Driver..."), "kdeprint_uploadsmb", 0, this, SLOT(exportDriver()), coll, "plugin_export_driver");
00827 act->setGroup("plugin");
00828 act = new KAction(i18n("&Printer IPP Report..."), "kdeprint_report", 0, this, SLOT(printerIppReport()), coll, "plugin_printer_ipp_report");
00829 act->setGroup("plugin");
00830 }
00831
00832 void KMCupsManager::validatePluginActions(KActionCollection *coll, KMPrinter *pr)
00833 {
00834
00835 m_currentprinter = pr;
00836 coll->action("plugin_export_driver")->setEnabled(pr && pr->isLocal() && !pr->isClass(true) && !pr->isSpecial());
00837 coll->action("plugin_printer_ipp_report")->setEnabled(pr && !pr->isSpecial());
00838 }
00839
00840 void KMCupsManager::exportDriver()
00841 {
00842 if (m_currentprinter && m_currentprinter->isLocal() &&
00843 !m_currentprinter->isClass(true) && !m_currentprinter->isSpecial())
00844 {
00845 QString path = cupsInstallDir();
00846 if (path.isEmpty())
00847 path = "/usr/share/cups";
00848 else
00849 path += "/share/cups";
00850 CupsAddSmb::exportDest(m_currentprinter->printerName(), path);
00851 }
00852 }
00853
00854 void KMCupsManager::printerIppReport()
00855 {
00856 if (m_currentprinter && !m_currentprinter->isSpecial())
00857 {
00858 IppRequest req;
00859 QString uri;
00860
00861 req.setOperation(IPP_GET_PRINTER_ATTRIBUTES);
00862 uri = printerURI(m_currentprinter, true);
00863 req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00864
00865
00866
00867
00868
00869
00870
00871 req.dump(2);
00872 if (req.doRequest("/printers/"))
00873 {
00874 ippReport(req, IPP_TAG_PRINTER, i18n("IPP report for %1").arg(m_currentprinter->printerName()));
00875 }
00876 else
00877 {
00878 KMessageBox::error(0, "<p>"+i18n("Unable to retrieve printer information. Error received:")+"</p>"+req.statusMessage());
00879 }
00880 }
00881 }
00882
00883 void KMCupsManager::ippReport(IppRequest& req, int group, const QString& caption)
00884 {
00885 IppReportDlg::report(&req, group, caption);
00886 }
00887
00888 QString KMCupsManager::stateInformation()
00889 {
00890 return i18n("Connected to %1:%2").arg(CupsInfos::self()->host()).arg(CupsInfos::self()->port());
00891 }
00892
00893 void KMCupsManager::checkUpdatePossibleInternal()
00894 {
00895 kdDebug(500) << "Checking for update possible" << endl;
00896 delete m_socket;
00897
00898
00899
00900
00901 m_socket = new QSocket( this );
00902 connect( m_socket, SIGNAL( connected() ), SLOT( slotConnectionSuccess() ) );
00903 connect( m_socket, SIGNAL( error( int ) ), SLOT( slotConnectionFailed( int ) ) );
00904 trials = 5;
00905 QTimer::singleShot( 1, this, SLOT( slotAsyncConnect() ) );
00906 }
00907
00908 void KMCupsManager::slotConnectionSuccess()
00909 {
00910 kdDebug(500) << "Connection success, trying to send a request..." << endl;
00911 m_socket->close();
00912
00913 IppRequest req;
00914 req.setOperation( CUPS_GET_PRINTERS );
00915 req.addKeyword( IPP_TAG_OPERATION, "requested-attributes", QString::fromLatin1( "printer-name" ) );
00916 if ( req.doRequest( "/printers/" ) )
00917 setUpdatePossible( true );
00918 else
00919 {
00920 kdDebug(500) << "Unable to get printer list" << endl;
00921 if ( trials > 0 )
00922 {
00923 trials--;
00924 QTimer::singleShot( 1000, this, SLOT( slotAsyncConnect() ) );
00925 }
00926 else
00927 {
00928 setErrorMsg( i18n( "Connection to CUPS server failed. Check that the CUPS server is correctly installed and running. "
00929 "Error: %1." ).arg( i18n( "the IPP request failed for an unknown reason" ) ) );
00930 setUpdatePossible( false );
00931 }
00932 }
00933 }
00934
00935 void KMCupsManager::slotAsyncConnect()
00936 {
00937 kdDebug(500) << "Starting async connect" << endl;
00938
00939 m_socket->connectToHost( CupsInfos::self()->host(), CupsInfos::self()->port() );
00940 }
00941
00942 void KMCupsManager::slotConnectionFailed( int errcode )
00943 {
00944 kdDebug(500) << "Connection failed trials=" << trials << endl;
00945 if ( trials > 0 )
00946 {
00947
00948
00949 trials--;
00950 m_socket->close();
00951 QTimer::singleShot( 1000, this, SLOT( slotAsyncConnect() ) );
00952 return;
00953 }
00954
00955 setErrorMsg( i18n( "Connection to CUPS server failed. Check that the CUPS server is correctly installed and running. "
00956 "Error: %1." ).arg( errcode == QSocket::ErrConnectionRefused ? i18n( "connection refused" ) : i18n( "host not found" ) ) );
00957 setUpdatePossible( false );
00958 }
00959
00960 void KMCupsManager::hostPingSlot() {
00961 m_hostSuccess = true;
00962 m_lookupDone = true;
00963 }
00964
00965 void KMCupsManager::hostPingFailedSlot() {
00966 m_hostSuccess = false;
00967 m_lookupDone = true;
00968 }
00969
00970
00971
00972 void extractMaticData(QString& buf, const QString& filename)
00973 {
00974 QFile f(filename);
00975 if (f.exists() && f.open(IO_ReadOnly))
00976 {
00977 QTextStream t(&f);
00978 QString line;
00979 while (!t.eof())
00980 {
00981 line = t.readLine();
00982 if (line.startsWith("*% COMDATA #"))
00983 buf.append(line.right(line.length()-12)).append('\n');
00984 }
00985 }
00986 }
00987
00988 QString printerURI(KMPrinter *p, bool use)
00989 {
00990 QString uri;
00991 if (use && !p->uri().isEmpty())
00992 uri = p->uri().prettyURL();
00993 else
00994 uri = QString("ipp://%1:%2/%4/%3").arg(CupsInfos::self()->host()).arg(CupsInfos::self()->port()).arg(p->printerName()).arg((p->isClass(false) ? "classes" : "printers"));
00995 return uri;
00996 }
00997
00998 QString downloadDriver(KMPrinter *p)
00999 {
01000 QString driverfile, prname = p->printerName();
01001 bool changed(false);
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 driverfile = cupsGetPPD(prname.local8Bit());
01021
01022
01023 if (changed)
01024 {
01025 cupsSetServer(CupsInfos::self()->host().local8Bit());
01026 ippSetPort(CupsInfos::self()->port());
01027 }
01028
01029 return driverfile;
01030 }
01031
01032 #include "kmcupsmanager.moc"