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

tdeprint

  • tdeprint
  • cups
kmcupsmanager.cpp
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (c) 2001 Michael Goffioul <tdeprint@swing.be>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License version 2 as published by the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB. If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  **/
19 
20 #include <config.h>
21 
22 #include "kmcupsmanager.h"
23 #include "kmprinter.h"
24 #include "ipprequest.h"
25 #include "cupsinfos.h"
26 #include "driver.h"
27 #include "kmfactory.h"
28 #include "kmdbentry.h"
29 #include "cupsaddsmb2.h"
30 #include "ippreportdlg.h"
31 #include "kpipeprocess.h"
32 #include "util.h"
33 #include "foomatic2loader.h"
34 #include "ppdloader.h"
35 
36 #include <tqfile.h>
37 #include <tqtextstream.h>
38 #include <tqregexp.h>
39 #include <tqtimer.h>
40 #include <tqsocket.h>
41 #include <tqdatetime.h>
42 
43 #include <kdebug.h>
44 #include <tdeapplication.h>
45 #include <tdelocale.h>
46 #include <tdeconfig.h>
47 #include <tdestandarddirs.h>
48 #include <tdesocketbase.h>
49 #include <klibloader.h>
50 #include <tdemessagebox.h>
51 #include <tdeaction.h>
52 #include <kdialogbase.h>
53 #include <kextendedsocket.h>
54 #include <tdeprocess.h>
55 #include <kbufferedsocket.h>
56 #include <kfilterdev.h>
57 #include <cups/cups.h>
58 #include <cups/ppd.h>
59 #include <math.h>
60 
61 #define ppdi18n(s) i18n(TQString::fromLocal8Bit(s).utf8())
62 
63 static void extractMaticData(TQString& buf, const TQString& filename);
64 static TQString printerURI(KMPrinter *p, bool useExistingURI);
65 static TQString downloadDriver(KMPrinter *p);
66 
67 static int trials = 5;
68 
69 //*****************************************************************************************************
70 
71  KMCupsManager::KMCupsManager(TQObject *parent, const char *name, const TQStringList & /*args*/)
72 : KMManager(parent,name)
73 {
74  // be sure to create the CupsInfos object -> password
75  // management is handled correctly.
76  CupsInfos::self();
77  m_cupsdconf = 0;
78  m_currentprinter = 0;
79  m_socket = 0;
80 
81  setHasManagement(true);
82  setPrinterOperationMask(KMManager::PrinterAll);
83  setServerOperationMask(KMManager::ServerAll);
84 
85  // change LANG variable so that CUPS is always using
86  // english language: translation may only come from the PPD
87  // itself, or from KDE.
88  setenv("LANG", "en_US.UTF-8", 1);
89 }
90 
91 KMCupsManager::~KMCupsManager()
92 {
93  delete m_socket;
94 }
95 
96 TQString KMCupsManager::driverDbCreationProgram()
97 {
98  return TQString(__TDE_BINDIR).append(TQString::fromLatin1("/make_driver_db_cups"));
99 }
100 
101 TQString KMCupsManager::driverDirectory()
102 {
103  TQString d = cupsInstallDir();
104  if (d.isEmpty()) {
105 #if defined(__OpenBSD__) || defined(__FreeBSD__)
106  d = "/usr/local";
107 #else
108  d = "/usr";
109 #endif
110  }
111  d.append("/share/cups/model");
112  // raw foomatic support
113 #if defined(__OpenBSD__) || defined(__FreeBSD__)
114  d.append(":/usr/local/share/foomatic/db/source");
115 #else
116  d.append(":/usr/share/foomatic/db/source");
117  // compressed foomatic support
118  d.append(":/usr/lib/cups/driver/foomatic-db-compressed-ppds");
119 #endif
120  return d;
121 }
122 
123 TQString KMCupsManager::cupsInstallDir()
124 {
125  TDEConfig *conf= KMFactory::self()->printConfig();
126  conf->setGroup("CUPS");
127  TQString dir = conf->readPathEntry("InstallDir");
128  return dir;
129 }
130 
131 void KMCupsManager::reportIppError(IppRequest *req)
132 {
133  setErrorMsg(req->statusMessage());
134 }
135 
136 bool KMCupsManager::createPrinter(KMPrinter *p)
137 {
138  bool isclass = p->isClass(false), result(false);
139  IppRequest req;
140  TQString uri;
141 
142  uri = printerURI(p,false);
143  req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
144  // needed to avoid problems when changing printer name
145  p->setUri(KURL(uri));
146 
147  if (isclass)
148  {
149  req.setOperation(CUPS_ADD_CLASS);
150  TQStringList members = p->members(), uris;
151  TQString s;
152  s = TQString::fromLocal8Bit("ipp://%1/printers/").arg(CupsInfos::self()->hostaddr());
153  for (TQStringList::ConstIterator it=members.begin(); it!=members.end(); ++it)
154  uris.append(s+(*it));
155  req.addURI(IPP_TAG_PRINTER,"member-uris",uris);
156  }
157  else
158  {
159  req.setOperation(CUPS_ADD_PRINTER);
160  // only set the device-uri if needed, otherwise you may loose authentification
161  // data (login/password in URI's like smb or ipp).
162  KMPrinter *otherP = findPrinter(p->printerName());
163  if (!otherP || otherP->device() != p->device())
164  {
170  req.addURI(IPP_TAG_PRINTER,"device-uri",p->device());
171  }
172  if (!p->option("kde-banners").isEmpty())
173  {
174  TQStringList bans = TQStringList::split(',',p->option("kde-banners"),false);
175  while (bans.count() < 2)
176  bans.append("none");
177  req.addName(IPP_TAG_PRINTER,"job-sheets-default",bans);
178  }
179  req.addInteger(IPP_TAG_PRINTER,"job-quota-period",p->option("job-quota-period").toInt());
180  req.addInteger(IPP_TAG_PRINTER,"job-k-limit",p->option("job-k-limit").toInt());
181  req.addInteger(IPP_TAG_PRINTER,"job-page-limit",p->option("job-page-limit").toInt());
182  if (!p->option("requesting-user-name-denied").isEmpty())
183  req.addName(IPP_TAG_PRINTER,"requesting-user-name-denied",TQStringList::split(",",p->option("requesting-user-name-denied"),false));
184  else if (!p->option("requesting-user-name-allowed").isEmpty())
185  req.addName(IPP_TAG_PRINTER,"requesting-user-name-allowed",TQStringList::split(",",p->option("requesting-user-name-allowed"),false));
186  else
187  req.addName(IPP_TAG_PRINTER,"requesting-user-name-allowed",TQString::fromLatin1("all"));
188  }
189  req.addText(IPP_TAG_PRINTER,"printer-info",p->description());
190  req.addText(IPP_TAG_PRINTER,"printer-location",p->location());
191 
192  if (req.doRequest("/admin/"))
193  {
194  result = true;
195  if (p->driver())
196  result = savePrinterDriver(p,p->driver());
197  if (result)
198  upPrinter(p, true);
199  }
200  else reportIppError(&req);
201 
202  return result;
203 }
204 
205 bool KMCupsManager::removePrinter(KMPrinter *p)
206 {
207  bool result = setPrinterState(p,CUPS_DELETE_PRINTER);
208  return result;
209 }
210 
211 bool KMCupsManager::enablePrinter(KMPrinter *p, bool state)
212 {
213  return setPrinterState(p, (state ? CUPS_ACCEPT_JOBS : CUPS_REJECT_JOBS));
214 }
215 
216 bool KMCupsManager::startPrinter(KMPrinter *p, bool state)
217 {
218  return setPrinterState(p, (state ? IPP_RESUME_PRINTER : IPP_PAUSE_PRINTER));
219 }
220 
221 bool KMCupsManager::setDefaultPrinter(KMPrinter *p)
222 {
223  return setPrinterState(p,CUPS_SET_DEFAULT);
224 }
225 
226 bool KMCupsManager::setPrinterState(KMPrinter *p, int state)
227 {
228  IppRequest req;
229  TQString uri;
230 
231  req.setOperation(state);
232  uri = printerURI(p, true);
233  req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
234  if (req.doRequest("/admin/"))
235  return true;
236  reportIppError(&req);
237  return false;
238 }
239 
240 bool KMCupsManager::completePrinter(KMPrinter *p)
241 {
242  if (completePrinterShort(p))
243  {
244  // driver informations
245  TQString ppdname = downloadDriver(p);
246  ppd_file_t *ppd = (ppdname.isEmpty() ? NULL : ppdOpenFile(ppdname.local8Bit()));
247  if (ppd)
248  {
249  KMDBEntry entry;
250  // use the validation mechanism of KMDBEntry to
251  // fill possible missing entries like manufacturer
252  // or model.
253  entry.manufacturer = ppd->manufacturer;
254  entry.model = ppd->shortnickname;
255  entry.modelname = ppd->modelname;
256  // do not check the driver regarding the manager
257  entry.validate(false);
258  // update the KMPrinter object
259  p->setManufacturer(entry.manufacturer);
260  p->setModel(entry.model);
261  p->setDriverInfo(TQString::fromLocal8Bit(ppd->nickname));
262  ppdClose(ppd);
263  }
264  if (!ppdname.isEmpty())
265  TQFile::remove(ppdname);
266 
267  return true;
268  }
269  return false;
270 }
271 
272 bool KMCupsManager::completePrinterShort(KMPrinter *p)
273 {
274  IppRequest req;
275  TQStringList keys;
276  TQString uri;
277 
278  req.setOperation(IPP_GET_PRINTER_ATTRIBUTES);
279  uri = printerURI(p, true);
280  req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
281 
282  /*
283  // change host and port for remote stuffs
284  if (!p->uri().isEmpty())
285  {
286  // THIS IS AN UGLY HACK!! FIXME
287  // This attempts a "pre-connection" to see if the host is
288  // actually reachable. It times out after 2 seconds at most,
289  // preventing application freezes.
290  m_hostSuccess = false;
291  m_lookupDone = false;
292  // Give 2 seconds to connect to the printer, or abort
293  KExtendedSocket *kes = new KExtendedSocket(p->uri().host(),
294  p->uri().port());
295  connect(kes, TQ_SIGNAL(connectionSuccess()), this, TQ_SLOT(hostPingSlot()));
296  connect(kes, TQ_SIGNAL(connectionFailed(int)), this, TQ_SLOT(hostPingFailedSlot()));
297  if (kes->startAsyncConnect() != 0) {
298  delete kes;
299  m_hostSuccess = false;
300  } else {
301  TQDateTime tm = TQDateTime::currentDateTime().addSecs(2);
302  while (!m_lookupDone && (TQDateTime::currentDateTime() < tm))
303  tqApp->processEvents();
304 
305  kes->cancelAsyncConnect();
306 
307  delete kes;
308 
309  if (!m_lookupDone)
310  m_hostSuccess = false;
311  }
312 
313  if (m_hostSuccess == true) {
314  req.setHost(p->uri().host());
315  req.setPort(p->uri().port());
316  }
317  }
318  */
319 
320  // disable location as it has been transferred to listing (for filtering)
321  //keys.append("printer-location");
322  keys.append("printer-info");
323  keys.append("printer-make-and-model");
324  keys.append("job-sheets-default");
325  keys.append("job-sheets-supported");
326  keys.append("job-quota-period");
327  keys.append("job-k-limit");
328  keys.append("job-page-limit");
329  keys.append("requesting-user-name-allowed");
330  keys.append("requesting-user-name-denied");
331  if (p->isClass(true))
332  {
333  keys.append("member-uris");
334  keys.append("member-names");
335  }
336  else
337  {
338  keys.append("device-uri");
339  keys.append("printer-device-id");
340  }
341  req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",keys);
342 
343  if (req.doRequest("/printers/"))
344  {
345  TQString value;
346  if (req.text("printer-info",value)) p->setDescription(value);
347  // disabled location
348  //if (req.text("printer-location",value)) p->setLocation(value);
349  if (req.text("printer-make-and-model",value)) p->setDriverInfo(value);
350  if (req.text("printer-device-id",value))
351  {
352  TQStringList fields = TQStringList::split(";", value, false);
353  for (const TQString &field : fields)
354  {
355  int separator = field.find(':');
356  if (separator <= 0)
357  {
358  continue;
359  }
360 
361  TQString key = field.left(separator).stripWhiteSpace().upper();
362  TQString fieldValue = field.mid(separator + 1).stripWhiteSpace();
363  if (fieldValue.isEmpty())
364  {
365  continue;
366  }
367  if (key == "MFG" || key == "MANUFACTURER")
368  {
369  if (p->manufacturer().isEmpty())
370  {
371  p->setManufacturer(fieldValue);
372  }
373  }
374  else if (key == "MDL" || key == "MODEL")
375  {
376  if (p->model().isEmpty())
377  {
378  p->setModel(fieldValue);
379  }
380  }
381  }
382  }
383  if (req.uri("device-uri",value))
384  {
389  p->setDevice( value );
390  }
391  TQStringList values;
392  /* if (req.uri("member-uris",values))
393  {
394  TQStringList members;
395  for (TQStringList::ConstIterator it=values.begin(); it!=values.end(); ++it)
396  {
397  int p = (*it).findRev('/');
398  if (p != -1)
399  members.append((*it).right((*it).length()-p-1));
400  }
401  p->setMembers(members);
402  }*/
403  if (req.name("member-names",values))
404  p->setMembers(values);
405  // banners
406  req.name("job-sheets-default",values);
407  while (values.count() < 2) values.append("none");
408  p->setOption("kde-banners",values.join(TQString::fromLatin1(",")));
409  if (req.name("job-sheets-supported",values)) p->setOption("kde-banners-supported",values.join(TQString::fromLatin1(",")));
410 
411  // quotas
412  int ival;
413  if (req.integer("job-quota-period",ival)) p->setOption("job-quota-period",TQString::number(ival));
414  if (req.integer("job-k-limit",ival)) p->setOption("job-k-limit",TQString::number(ival));
415  if (req.integer("job-page-limit",ival)) p->setOption("job-page-limit",TQString::number(ival));
416 
417  // access permissions (allow and deny are mutually exclusives)
418  if (req.name("requesting-user-name-allowed",values) && values.count() > 0)
419  {
420  p->removeOption("requesting-user-name-denied");
421  p->setOption("requesting-user-name-allowed",values.join(","));
422  }
423  if (req.name("requesting-user-name-denied",values) && values.count() > 0)
424  {
425  p->removeOption("requesting-user-name-allowed");
426  p->setOption("requesting-user-name-denied",values.join(","));
427  }
428 
429  return true;
430  }
431 
432  reportIppError(&req);
433  return false;
434 }
435 
436 bool KMCupsManager::testPrinter(KMPrinter *p)
437 {
438  return KMManager::testPrinter(p);
439  /*
440  TQString testpage = testPage();
441  if (testpage.isEmpty())
442  {
443  setErrorMsg(i18n("Unable to locate test page."));
444  return false;
445  }
446 
447  IppRequest req;
448  TQString uri;
449 
450  req.setOperation(IPP_PRINT_JOB);
451  uri = printerURI(p);
452  req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
453  req.addMime(IPP_TAG_OPERATION,"document-format","application/postscript");
454  if (!CupsInfos::self()->login().isEmpty()) req.addName(IPP_TAG_OPERATION,"requesting-user-name",CupsInfos::self()->login());
455  req.addName(IPP_TAG_OPERATION,"job-name",TQString::fromLatin1("TDE Print Test"));
456  if (req.doFileRequest("/printers/",testpage))
457  return true;
458  reportIppError(&req);
459  return false;
460  */
461 }
462 
463 void KMCupsManager::listPrinters()
464 {
465  loadServerPrinters();
466 }
467 
468 void KMCupsManager::loadServerPrinters()
469 {
470  IppRequest req;
471  TQStringList keys;
472 
473  // get printers
474  req.setOperation(CUPS_GET_PRINTERS);
475  keys.append("printer-name");
476  keys.append("printer-type");
477  keys.append("printer-state");
478  // location needed for filtering
479  keys.append("printer-location");
480  keys.append("printer-uri-supported");
481  keys.append("printer-is-accepting-jobs");
482  req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",keys);
483 
484  // filtering by username (hides printers user doesn't have allowance to use)
485  req.addName(IPP_TAG_OPERATION, "requesting-user-name", TQString(cupsUser()));
486 
487  if (req.doRequest("/printers/"))
488  {
489  processRequest(&req);
490 
491  // get classes
492  req.init();
493  req.setOperation(CUPS_GET_CLASSES);
494  req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",keys);
495 
496  if (req.doRequest("/classes/"))
497  {
498  processRequest(&req);
499 
500  // load default
501  req.init();
502  req.setOperation(CUPS_GET_DEFAULT);
503  req.addKeyword(IPP_TAG_OPERATION,"requested-attributes",TQString::fromLatin1("printer-name"));
504  if (req.doRequest("/printers/"))
505  {
506  TQString s = TQString::null;
507  req.name("printer-name",s);
508  setHardDefault(findPrinter(s));
509  }
510  // This request may fails for example if no printer is defined. Just
511  // discard the error message. Indeed as we successfully got printers
512  // and classes, the most probable reason why this request may fail is
513  // because of no printer defined. The best would be to actually check
514  // there's no printer (TODO).
515  return;
516  }
517  }
518 
519  // something went wrong if we get there, report the error
520  reportIppError(&req);
521 }
522 
523 void KMCupsManager::processRequest(IppRequest* req)
524 {
525  ipp_attribute_t *attr = req->first();
526  ipp_attribute_t *nextAttr;
527  KMPrinter *printer = new KMPrinter();
528  while (attr)
529  {
530  TQString attrname(ippGetName(attr));
531  if (attrname == "printer-name")
532  {
533  TQString value = TQString::fromLocal8Bit(ippGetString(attr, 0, NULL));
534  printer->setName(value);
535  printer->setPrinterName(value);
536  }
537  else if (attrname == "printer-type")
538  {
539  int value = ippGetInteger(attr, 0);
540  printer->setType(0);
541  printer->addType(((value & CUPS_PRINTER_CLASS) || (value & CUPS_PRINTER_IMPLICIT) ? KMPrinter::Class : KMPrinter::Printer));
542  if ((value & CUPS_PRINTER_REMOTE)) printer->addType(KMPrinter::Remote);
543  if ((value & CUPS_PRINTER_IMPLICIT)) printer->addType(KMPrinter::Implicit);
544 
545  // convert printer-type attribute
546  printer->setPrinterCap( ( value & CUPS_PRINTER_OPTIONS ) >> 2 );
547  }
548  else if (attrname == "printer-state")
549  {
550  switch (ippGetInteger(attr, 0))
551  {
552  case IPP_PRINTER_IDLE: printer->setState(KMPrinter::Idle); break;
553  case IPP_PRINTER_PROCESSING: printer->setState(KMPrinter::Processing); break;
554  case IPP_PRINTER_STOPPED: printer->setState(KMPrinter::Stopped); break;
555  }
556  }
557  else if (attrname == "printer-uri-supported")
558  {
559  printer->setUri(KURL(ippGetString(attr, 0, NULL)));
560  }
561  else if (attrname == "printer-location")
562  {
563  printer->setLocation(TQString::fromLocal8Bit(ippGetString(attr, 0, NULL)));
564  }
565  else if (attrname == "printer-is-accepting-jobs")
566  {
567  printer->setAcceptJobs(ippGetBoolean(attr, 0));
568  }
569 
570  nextAttr = ippNextAttribute(req->request());
571  if (attrname.isEmpty() || (!nextAttr))
572  {
573  addPrinter(printer);
574  printer = new KMPrinter();
575  }
576  attr = nextAttr;
577  }
578  delete printer;
579 }
580 
581 DrMain* KMCupsManager::loadPrinterDriver(KMPrinter *p, bool)
582 {
583  if (!p)
584  return NULL;
585 
586  if (p->isClass(true))
587  {
588  KMPrinter *first_class_member = NULL;
589  /* find the first printer in the class */
590  first_class_member = findPrinter(p->members().first());
591 
592  if (first_class_member == NULL)
593  {
594  /* we didn't find a printer in the class */
595  return NULL;
596  }
597  else
598  {
599  p = first_class_member;
600  }
601  }
602 
603  TQString fname = downloadDriver(p);
604  DrMain *driver(0);
605  if (!fname.isEmpty())
606  {
607  driver = loadDriverFile(fname);
608  if (driver)
609  driver->set("temporary",fname);
610  }
611 
612  return driver;
613 }
614 
615 DrMain* KMCupsManager::loadFileDriver(const TQString& filename)
616 {
617  if (filename.startsWith("ppd:"))
618  return loadDriverFile(filename.mid(4));
619  else if (filename.startsWith("compressed-ppd:"))
620  return loadDriverFile(filename);
621  else if (filename.startsWith("foomatic/"))
622  return loadMaticDriver(filename);
623  else
624  return loadDriverFile(filename);
625 }
626 
627 DrMain* KMCupsManager::loadMaticDriver(const TQString& drname)
628 {
629  TQStringList comps = TQStringList::split('/', drname, false);
630  TQString tmpFile = locateLocal("tmp", "foomatic_" + tdeApp->randomString(8));
631 #if defined(__OpenBSD__) || defined(__FreeBSD__)
632  TQString PATH = getenv("PATH") + TQString::fromLatin1(":/usr/local/bin:/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin");
633 #else
634  TQString PATH = getenv("PATH") + TQString::fromLatin1(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin");
635 #endif
636  TQString exe = TDEStandardDirs::findExe("foomatic-datafile", PATH);
637  if (exe.isEmpty())
638  {
639  setErrorMsg(i18n("Unable to find the executable foomatic-datafile "
640  "in your PATH. Check that Foomatic is correctly installed."));
641  return NULL;
642  }
643 
644  KPipeProcess in;
645  TQFile out(tmpFile);
646  TQString cmd = TDEProcess::quote(exe);
647  cmd += " -t cups -d ";
648  cmd += TDEProcess::quote(comps[2]);
649  cmd += " -p ";
650  cmd += TDEProcess::quote(comps[1]);
651  if (in.open(cmd) && out.open(IO_WriteOnly))
652  {
653  TQTextStream tin(&in), tout(&out);
654  TQString line;
655  while (!tin.atEnd())
656  {
657  line = tin.readLine();
658  tout << line << endl;
659  }
660  in.close();
661  out.close();
662 
663  DrMain *driver = loadDriverFile(tmpFile);
664  if (driver)
665  {
666  driver->set("template", tmpFile);
667  driver->set("temporary", tmpFile);
668  return driver;
669  }
670  }
671  setErrorMsg(i18n("Unable to create the Foomatic driver [%1,%2]. "
672  "Either that driver does not exist, or you don't have "
673  "the required permissions to perform that operation.").arg(comps[1]).arg(comps[2]));
674  TQFile::remove(tmpFile);
675  return NULL;
676 }
677 
678 DrMain* KMCupsManager::loadDriverFile(const TQString& fname)
679 {
680  if ((fname.startsWith("compressed-ppd:")) || TQFile::exists(fname))
681  {
682  TQString msg; /* possible error message */
683  DrMain *driver = PPDLoader::loadDriver( fname, &msg );
684  if ( driver )
685  {
686  driver->set( "template", fname );
687  // FIXME: should fix option in group "install"
688  }
689  else
690  setErrorMsg( msg );
691  return driver;
692  }
693  return NULL;
694 }
695 
696 void KMCupsManager::saveDriverFile(DrMain *driver, const TQString& filename)
697 {
698  kdDebug( 500 ) << "Saving PPD file with template=" << driver->get( "template" ) << endl;
699  TQString templateFile = driver->get( "template" );
700  if (templateFile.startsWith("compressed-ppd:")) {
701  templateFile = driver->get( "temporary-cppd" );
702  }
703  TQIODevice *in = KFilterDev::deviceForFile( templateFile );
704  TQFile out(filename);
705  if (in && in->open(IO_ReadOnly) && out.open(IO_WriteOnly))
706  {
707  TQTextStream tin(in), tout(&out);
708  TQString line, keyword;
709  bool isnumeric(false);
710  DrBase *opt(0);
711 
712  while (!tin.eof())
713  {
714  line = tin.readLine();
715  if (line.startsWith("*% COMDATA #"))
716  {
717  int p(-1), q(-1);
718  if ((p=line.find("'name'")) != -1)
719  {
720  p = line.find('\'',p+6)+1;
721  q = line.find('\'',p);
722  keyword = line.mid(p,q-p);
723  opt = driver->findOption(keyword);
724  if (opt && (opt->type() == DrBase::Integer || opt->type() == DrBase::Float))
725  isnumeric = true;
726  else
727  isnumeric = false;
728  }
729  /*else if ((p=line.find("'type'")) != -1)
730  {
731  p = line.find('\'',p+6)+1;
732  if (line.find("float",p) != -1 || line.find("int",p) != -1)
733  isnumeric = true;
734  else
735  isnumeric = false;
736  }*/
737  else if ((p=line.find("'default'")) != -1 && !keyword.isEmpty() && opt && isnumeric)
738  {
739  TQString prefix = line.left(p+9);
740  tout << prefix << " => '" << opt->valueText() << '\'';
741  if (line.find(',',p) != -1)
742  tout << ',';
743  tout << endl;
744  continue;
745  }
746  tout << line << endl;
747  }
748  else if (line.startsWith("*Default"))
749  {
750  int p = line.find(':',8);
751  keyword = line.mid(8,p-8);
752  DrBase *bopt = 0;
753  if ( keyword == "PageRegion" || keyword == "ImageableArea" || keyword == "PaperDimension" )
754  bopt = driver->findOption( TQString::fromLatin1( "PageSize" ) );
755  else
756  bopt = driver->findOption( keyword );
757  if (bopt)
758  switch (bopt->type())
759  {
760  case DrBase::List:
761  case DrBase::Boolean:
762  {
763  DrListOption *opt = static_cast<DrListOption*>(bopt);
764  if (opt && opt->currentChoice())
765  tout << "*Default" << keyword << ": " << opt->currentChoice()->name() << endl;
766  else
767  tout << line << endl;
768  }
769  break;
770  case DrBase::Integer:
771  {
772  DrIntegerOption *opt = static_cast<DrIntegerOption*>(bopt);
773  tout << "*Default" << keyword << ": " << opt->fixedVal() << endl;
774  }
775  break;
776  case DrBase::Float:
777  {
778  DrFloatOption *opt = static_cast<DrFloatOption*>(bopt);
779  tout << "*Default" << keyword << ": " << opt->fixedVal() << endl;
780  }
781  break;
782  default:
783  tout << line << endl;
784  break;
785  }
786  else
787  tout << line << endl;
788  }
789  else
790  tout << line << endl;
791  }
792  }
793  delete in;
794 }
795 
796 bool KMCupsManager::savePrinterDriver(KMPrinter *p, DrMain *d)
797 {
798  TQString tmpfilename = locateLocal("tmp","print_") + tdeApp->randomString(8);
799 
800  // first save the driver in a temporary file
801  saveDriverFile(d,tmpfilename);
802 
803  // then send a request
804  IppRequest req;
805  TQString uri;
806  bool result(false);
807 
808  req.setOperation(CUPS_ADD_PRINTER);
809  uri = printerURI(p, true);
810  req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
811  result = req.doFileRequest("/admin/",tmpfilename);
812 
813  // remove temporary file
814  TQFile::remove(tmpfilename);
815 
816  if (!result)
817  reportIppError(&req);
818  return result;
819 }
820 
821 void* KMCupsManager::loadCupsdConfFunction(const char *name)
822 {
823  if (!m_cupsdconf)
824  {
825  m_cupsdconf = KLibLoader::self()->library("cupsdconf");
826  if (!m_cupsdconf)
827  {
828  setErrorMsg(i18n("Library cupsdconf not found. Check your installation."));
829  return NULL;
830  }
831  }
832  void* func = m_cupsdconf->symbol(name);
833  if (!func)
834  setErrorMsg(i18n("Symbol %1 not found in cupsdconf library.").arg(name));
835  return func;
836 }
837 
838 void KMCupsManager::unloadCupsdConf()
839 {
840  if (m_cupsdconf)
841  {
842  KLibLoader::self()->unloadLibrary("libcupsdconf");
843  m_cupsdconf = 0;
844  }
845 }
846 
847 bool KMCupsManager::restartServer()
848 {
849  TQString msg;
850  bool (*f1)(TQString&) = (bool(*)(TQString&))loadCupsdConfFunction("restartServer");
851  bool result(false);
852  if (f1)
853  {
854  result = f1(msg);
855  if (!result) setErrorMsg(msg);
856  }
857  unloadCupsdConf();
858  return result;
859 }
860 
861 bool KMCupsManager::configureServer(TQWidget *parent)
862 {
863  TQString msg;
864  bool (*f2)(TQWidget*, TQString&) = (bool(*)(TQWidget*, TQString&))loadCupsdConfFunction("configureServer");
865  bool result(false);
866  if (f2)
867  {
868  result = f2(parent, msg);
869  if ( !result )
870  setErrorMsg( msg );
871  }
872  unloadCupsdConf();
873  return result;
874 }
875 
876 TQStringList KMCupsManager::detectLocalPrinters()
877 {
878  TQStringList list;
879  IppRequest req;
880  ipp_attribute_t *nextAttr;
881  req.setOperation(CUPS_GET_DEVICES);
882  if (req.doRequest("/"))
883  {
884  TQString desc, uri, printer, cl;
885  ipp_attribute_t *attr = req.first();
886  while (attr)
887  {
888  TQString attrname(ippGetName(attr));
889  if (attrname == "device-info") desc = ippGetString(attr, 0, NULL);
890  else if (attrname == "device-make-and-model") printer = ippGetString(attr, 0, NULL);
891  else if (attrname == "device-uri") uri = ippGetString(attr, 0, NULL);
892  else if ( attrname == "device-class" ) cl = ippGetString(attr, 0, NULL);
893  nextAttr = ippNextAttribute(req.request());
894  if (attrname.isEmpty() || (!nextAttr))
895  {
896  if (!uri.isEmpty())
897  {
898  if (printer == "Unknown") printer = TQString::null;
899  list << cl << uri << desc << printer;
900  }
901  uri = desc = printer = cl = TQString::null;
902  }
903  attr = nextAttr;
904  }
905  }
906  return list;
907 }
908 
909 void KMCupsManager::createPluginActions(TDEActionCollection *coll)
910 {
911  TDEAction *act = new TDEAction(i18n("&Export Driver..."), "tdeprint_uploadsmb", 0, this, TQ_SLOT(exportDriver()), coll, "plugin_export_driver");
912  act->setGroup("plugin");
913  act = new TDEAction(i18n("&Printer IPP Report"), "tdeprint_report", 0, this, TQ_SLOT(printerIppReport()), coll, "plugin_printer_ipp_report");
914  act->setGroup("plugin");
915 }
916 
917 void KMCupsManager::validatePluginActions(TDEActionCollection *coll, KMPrinter *pr)
918 {
919  // save selected printer for future use in slots
920  m_currentprinter = pr;
921  coll->action("plugin_export_driver")->setEnabled(pr && pr->isLocal() && !pr->isClass(true) && !pr->isSpecial());
922  coll->action("plugin_printer_ipp_report")->setEnabled(pr && !pr->isSpecial());
923 }
924 
925 void KMCupsManager::exportDriver()
926 {
927  if (m_currentprinter && m_currentprinter->isLocal() &&
928  !m_currentprinter->isClass(true) && !m_currentprinter->isSpecial())
929  {
930  TQString path = cupsInstallDir();
931  if (path.isEmpty()) {
932 #if defined(__OpenBSD__) || defined(__FreeBSD__)
933  path = "/usr/local/share/cups";
934 #else
935  path = "/usr/share/cups";
936 #endif
937  } else {
938  path += "/share/cups";
939  }
940  CupsAddSmb::exportDest(m_currentprinter->printerName(), path);
941  }
942 }
943 
944 void KMCupsManager::printerIppReport()
945 {
946  if (m_currentprinter && !m_currentprinter->isSpecial())
947  {
948  IppRequest req;
949  TQString uri;
950 
951  req.setOperation(IPP_GET_PRINTER_ATTRIBUTES);
952  uri = printerURI(m_currentprinter, true);
953  req.addURI(IPP_TAG_OPERATION,"printer-uri",uri);
954  /*
955  if (!m_currentprinter->uri().isEmpty())
956  {
957  req.setHost(m_currentprinter->uri().host());
958  req.setPort(m_currentprinter->uri().port());
959  }
960  */
961  req.dump(2);
962  if (req.doRequest("/printers/"))
963  {
964  ippReport(req, IPP_TAG_PRINTER, i18n("IPP Report for %1").arg(m_currentprinter->printerName()));
965  }
966  else
967  {
968  KMessageBox::error(0, "<p>"+i18n("Unable to retrieve printer information. Error received:")+"</p>"+req.statusMessage());
969  }
970  }
971 }
972 
973 void KMCupsManager::ippReport(IppRequest& req, int group, const TQString& caption)
974 {
975  IppReportDlg::report(&req, group, caption);
976 }
977 
978 TQString KMCupsManager::stateInformation()
979 {
980  return TQString("%1: %2")
981  .arg(i18n("Server"))
982  .arg(CupsInfos::self()->host()[0] != '/' ?
983  TQString(TQString("%1:%2").arg(CupsInfos::self()->host()).arg(CupsInfos::self()->port()))
984  : CupsInfos::self()->host());
985 }
986 
987 void KMCupsManager::checkUpdatePossibleInternal()
988 {
989  kdDebug(500) << "Checking for update possible" << endl;
990  delete m_socket;
991  m_socket = new KNetwork::TDEBufferedSocket;
992  m_socket->setTimeout( 1500 );
993  connect( m_socket, TQ_SIGNAL( connected(const KResolverEntry&) ),
994  TQ_SLOT( slotConnectionSuccess() ) );
995  connect( m_socket, TQ_SIGNAL( gotError( int ) ), TQ_SLOT( slotConnectionFailed( int ) ) );
996 
997  trials = 5;
998  TQTimer::singleShot( 1, this, TQ_SLOT( slotAsyncConnect() ) );
999 }
1000 
1001 void KMCupsManager::slotConnectionSuccess()
1002 {
1003  kdDebug(500) << "Connection success, trying to send a request..." << endl;
1004  m_socket->close();
1005 
1006  IppRequest req;
1007  req.setOperation( CUPS_GET_PRINTERS );
1008  req.addKeyword( IPP_TAG_OPERATION, "requested-attributes", TQString::fromLatin1( "printer-name" ) );
1009  if ( req.doRequest( "/printers/" ) )
1010  setUpdatePossible( true );
1011  else
1012  {
1013  kdDebug(500) << "Unable to get printer list" << endl;
1014  if ( trials > 0 )
1015  {
1016  trials--;
1017  TQTimer::singleShot( 1000, this, TQ_SLOT( slotAsyncConnect() ) );
1018  }
1019  else
1020  {
1021  setErrorMsg( i18n( "Connection to CUPS server failed. Check that the CUPS server is correctly installed and running. "
1022  "Error: %1." ).arg( i18n( "the IPP request failed for an unknown reason" ) ) );
1023  setUpdatePossible( false );
1024  }
1025  }
1026 }
1027 
1028 void KMCupsManager::slotAsyncConnect()
1029 {
1030  kdDebug(500) << "Starting async connect to " << CupsInfos::self()->hostaddr() << endl;
1031  //m_socket->startAsyncConnect();
1032  if (CupsInfos::self()->host().startsWith("/"))
1033  m_socket->connect( TQString(), CupsInfos::self()->host());
1034  else
1035  m_socket->connectToHost( CupsInfos::self()->host(), CupsInfos::self()->port() );
1036 }
1037 
1038 void KMCupsManager::slotConnectionFailed( int errcode )
1039 {
1040  kdDebug(500) << "Connection failed trials=" << trials << endl;
1041  if ( trials > 0 )
1042  {
1043  //m_socket->setTimeout( ++to );
1044  //m_socket->cancelAsyncConnect();
1045  trials--;
1046  m_socket->close();
1047  TQTimer::singleShot( 1000, this, TQ_SLOT( slotAsyncConnect() ) );
1048  return;
1049  }
1050 
1051  TQString einfo;
1052 
1053  switch (errcode) {
1054  case KNetwork::TDESocketBase::ConnectionRefused:
1055  case KNetwork::TDESocketBase::ConnectionTimedOut:
1056  einfo = i18n("connection refused") + TQString(" (%1)").arg(errcode);
1057  break;
1058  case KNetwork::TDESocketBase::LookupFailure:
1059  einfo = i18n("host not found") + TQString(" (%1)").arg(errcode);
1060  break;
1061  case KNetwork::TDESocketBase::WouldBlock:
1062  default:
1063  einfo = i18n("read failed (%1)").arg(errcode);
1064  break;
1065  }
1066 
1067  setErrorMsg( i18n( "Connection to CUPS server failed. Check that the CUPS server is correctly installed and running. "
1068  "Error: %2: %1." ).arg( einfo, CupsInfos::self()->host()));
1069  setUpdatePossible( false );
1070 }
1071 
1072 void KMCupsManager::hostPingSlot() {
1073  m_hostSuccess = true;
1074  m_lookupDone = true;
1075 }
1076 
1077 void KMCupsManager::hostPingFailedSlot() {
1078  m_hostSuccess = false;
1079  m_lookupDone = true;
1080 }
1081 
1082 //*****************************************************************************************************
1083 
1084 static void extractMaticData(TQString& buf, const TQString& filename)
1085 {
1086  TQFile f(filename);
1087  if (f.exists() && f.open(IO_ReadOnly))
1088  {
1089  TQTextStream t(&f);
1090  TQString line;
1091  while (!t.eof())
1092  {
1093  line = t.readLine();
1094  if (line.startsWith("*% COMDATA #"))
1095  buf.append(line.right(line.length()-12)).append('\n');
1096  }
1097  }
1098 }
1099 
1100 static TQString printerURI(KMPrinter *p, bool use)
1101 {
1102  TQString uri;
1103  if (use && !p->uri().isEmpty())
1104  uri = p->uri().prettyURL();
1105  else
1106  uri = TQString("ipp://%1/%3/%2").arg(CupsInfos::self()->hostaddr()).arg(p->printerName()).arg((p->isClass(false) ? "classes" : "printers"));
1107  return uri;
1108 }
1109 
1110 static TQString downloadDriver(KMPrinter *p)
1111 {
1112  TQString driverfile, prname = p->printerName();
1113  bool changed(false);
1114 
1115  /*
1116  if (!p->uri().isEmpty())
1117  {
1118  // try to load the driver from the host:port
1119  // specified in its URI. Doing so may also change
1120  // the printer name to use. Note that for remote
1121  // printer, this operation is read-only, no counterpart
1122  // for saving operation.
1123  cupsSetServer(p->uri().host().local8Bit());
1124  ippSetPort(p->uri().port());
1125  // strip any "@..." from the printer name
1126  prname = prname.replace(TQRegExp("@.*"), "");
1127  changed = true;
1128  }
1129  */
1130 
1131  // download driver
1132  driverfile = cupsGetPPD(prname.local8Bit());
1133 
1134  // restore host:port (if they have changed)
1135  if (changed)
1136  {
1137  cupsSetServer(CupsInfos::self()->host().local8Bit());
1138  ippSetPort(CupsInfos::self()->port());
1139  }
1140 
1141  return driverfile;
1142 }
1143 
1144 #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.9.1
This website is maintained by Timothy Pearson.