• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeprint
 

tdeprint

kmcupsmanager.cpp
00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (c) 2001 Michael Goffioul <tdeprint@swing.be>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation.
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
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 & /*args*/)
00072 : KMManager(parent,name)
00073 {
00074     // be sure to create the CupsInfos object -> password
00075     // management is handled correctly.
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     // change LANG variable so that CUPS is always using
00086     // english language: translation may only come from the PPD
00087     // itself, or from KDE.
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     // raw foomatic support
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     // compressed foomatic support
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     // needed to avoid problems when changing printer name
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         // only set the device-uri if needed, otherwise you may loose authentification
00161         // data (login/password in URI's like smb or ipp).
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         // driver informations
00245         TQString    ppdname = downloadDriver(p);
00246         ppd_file_t  *ppd = (ppdname.isEmpty() ? NULL : ppdOpenFile(ppdname.local8Bit()));
00247         if (ppd)
00248         {
00249             KMDBEntry   entry;
00250             // use the validation mechanism of KMDBEntry to
00251             // fill possible missing entries like manufacturer
00252             // or model.
00253             entry.manufacturer = ppd->manufacturer;
00254             entry.model = ppd->shortnickname;
00255             entry.modelname = ppd->modelname;
00256             // do not check the driver regarding the manager
00257             entry.validate(false);
00258             // update the KMPrinter object
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     // change host and port for remote stuffs
00284     if (!p->uri().isEmpty())
00285     {
00286     // THIS IS AN UGLY HACK!! FIXME
00287     // This attempts a "pre-connection" to see if the host is
00288     // actually reachable.  It times out after 2 seconds at most,
00289     // preventing application freezes.
00290     m_hostSuccess = false;
00291     m_lookupDone = false;
00292     // Give 2 seconds to connect to the printer, or abort
00293     KExtendedSocket *kes = new KExtendedSocket(p->uri().host(),
00294     p->uri().port());
00295     connect(kes, TQT_SIGNAL(connectionSuccess()), this, TQT_SLOT(hostPingSlot()));
00296     connect(kes, TQT_SIGNAL(connectionFailed(int)), this, TQT_SLOT(hostPingFailedSlot()));
00297     if (kes->startAsyncConnect() != 0) {
00298     delete kes;
00299     m_hostSuccess = false;
00300     } else {
00301     TQDateTime tm = TQDateTime::currentDateTime().addSecs(2);
00302     while (!m_lookupDone && (TQDateTime::currentDateTime() < tm))
00303     tqApp->processEvents();
00304 
00305     kes->cancelAsyncConnect();
00306 
00307     delete kes;
00308 
00309     if (!m_lookupDone)
00310     m_hostSuccess = false;
00311     }
00312 
00313     if (m_hostSuccess == true) {
00314     req.setHost(p->uri().host());
00315     req.setPort(p->uri().port());
00316     }
00317     }
00318     */
00319 
00320     // disable location as it has been transferred to listing (for filtering)
00321     //keys.append("printer-location");
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         // disabled location
00345         //if (req.text("printer-location",value)) p->setLocation(value);
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         /*      if (req.uri("member-uris",values))
00357                 {
00358                 TQStringList    members;
00359                 for (TQStringList::ConstIterator it=values.begin(); it!=values.end(); ++it)
00360                 {
00361                 int p = (*it).findRev('/');
00362                 if (p != -1)
00363                 members.append((*it).right((*it).length()-p-1));
00364                 }
00365                 p->setMembers(members);
00366                 }*/
00367         if (req.name("member-names",values))
00368             p->setMembers(values);
00369         // banners
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         // quotas
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         // access permissions (allow and deny are mutually exclusives)
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        TQString testpage = testPage();
00405        if (testpage.isEmpty())
00406        {
00407        setErrorMsg(i18n("Unable to locate test page."));
00408        return false;
00409        }
00410 
00411        IppRequest   req;
00412        TQString     uri;
00413 
00414        req.setOperation(IPP_PRINT_JOB);
00415        uri = printerURI(p);
00416        req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
00417        req.addMime(IPP_TAG_OPERATION,"document-format","application/postscript");
00418        if (!CupsInfos::self()->login().isEmpty()) req.addName(IPP_TAG_OPERATION,"requesting-user-name",CupsInfos::self()->login());
00419        req.addName(IPP_TAG_OPERATION,"job-name",TQString::fromLatin1("TDE Print Test"));
00420        if (req.doFileRequest("/printers/",testpage))
00421        return true;
00422        reportIppError(&req);
00423        return false;
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     // get printers
00438     req.setOperation(CUPS_GET_PRINTERS);
00439     keys.append("printer-name");
00440     keys.append("printer-type");
00441     keys.append("printer-state");
00442     // location needed for filtering
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     // filtering by username (hides printers user doesn't have allowance to use)
00449     req.addName(IPP_TAG_OPERATION, "requesting-user-name", TQString(cupsUser()));
00450 
00451     if (req.doRequest("/printers/"))
00452     {
00453         processRequest(&req);
00454 
00455         // get classes
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             // load default
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             // This request may fails for example if no printer is defined. Just
00475             // discard the error message. Indeed as we successfully got printers
00476             // and classes, the most probable reason why this request may fail is
00477             // because of no printer defined. The best would be to actually check
00478             // there's no printer (TODO).
00479             return;
00480         }
00481     }
00482 
00483     // something went wrong if we get there, report the error
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             // convert printer-type attribute
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             // convert printer-type attribute
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         /* find the first printer in the class */
00602         first_class_member = findPrinter(p->members().first());
00603       
00604         if (first_class_member == NULL) 
00605         {
00606             /* we didn't find a printer in the class */
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; /* possible error message */
00695         DrMain *driver = PPDLoader::loadDriver( fname, &msg );
00696         if ( driver )
00697         {
00698             driver->set( "template", fname );
00699             // FIXME: should fix option in group "install"
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                 /*else if ((p=line.find("'type'")) != -1)
00742                 {
00743                     p = line.find('\'',p+6)+1;
00744                     if (line.find("float",p) != -1 || line.find("int",p) != -1)
00745                         isnumeric = true;
00746                     else
00747                         isnumeric = false;
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     // first save the driver in a temporary file
00813     saveDriverFile(d,tmpfilename);
00814 
00815     // then send a request
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     // remove temporary file
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     // save selected printer for future use in slots
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         if (!m_currentprinter->uri().isEmpty())
00986         {
00987             req.setHost(m_currentprinter->uri().host());
00988             req.setPort(m_currentprinter->uri().port());
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     //m_socket->startAsyncConnect();
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         //m_socket->setTimeout( ++to );
01074         //m_socket->cancelAsyncConnect();
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     if (!p->uri().isEmpty())
01147     {
01148         // try to load the driver from the host:port
01149         // specified in its URI. Doing so may also change
01150         // the printer name to use. Note that for remote
01151         // printer, this operation is read-only, no counterpart
01152         // for saving operation.
01153         cupsSetServer(p->uri().host().local8Bit());
01154         ippSetPort(p->uri().port());
01155         // strip any "@..." from the printer name
01156         prname = prname.replace(TQRegExp("@.*"), "");
01157         changed = true;
01158     }
01159     */
01160 
01161     // download driver
01162     driverfile = cupsGetPPD(prname.local8Bit());
01163 
01164     // restore host:port (if they have changed)
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"

tdeprint

Skip menu "tdeprint"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

tdeprint

Skip menu "tdeprint"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeprint by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.