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