• 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 <kstandarddirs.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 <kprocess.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
63static void extractMaticData(TQString& buf, const TQString& filename);
64static TQString printerURI(KMPrinter *p, bool useExistingURI);
65static TQString downloadDriver(KMPrinter *p);
66
67static 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
91KMCupsManager::~KMCupsManager()
92{
93 delete m_socket;
94}
95
96TQString KMCupsManager::driverDbCreationProgram()
97{
98 return TQString(__TDE_BINDIR).append(TQString::fromLatin1("/make_driver_db_cups"));
99}
100
101TQString 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
123TQString KMCupsManager::cupsInstallDir()
124{
125 TDEConfig *conf= KMFactory::self()->printConfig();
126 conf->setGroup("CUPS");
127 TQString dir = conf->readPathEntry("InstallDir");
128 return dir;
129}
130
131void KMCupsManager::reportIppError(IppRequest *req)
132{
133 setErrorMsg(req->statusMessage());
134}
135
136bool 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
205bool KMCupsManager::removePrinter(KMPrinter *p)
206{
207 bool result = setPrinterState(p,CUPS_DELETE_PRINTER);
208 return result;
209}
210
211bool KMCupsManager::enablePrinter(KMPrinter *p, bool state)
212{
213 return setPrinterState(p, (state ? CUPS_ACCEPT_JOBS : CUPS_REJECT_JOBS));
214}
215
216bool KMCupsManager::startPrinter(KMPrinter *p, bool state)
217{
218 return setPrinterState(p, (state ? IPP_RESUME_PRINTER : IPP_PAUSE_PRINTER));
219}
220
221bool KMCupsManager::setDefaultPrinter(KMPrinter *p)
222{
223 return setPrinterState(p,CUPS_SET_DEFAULT);
224}
225
226bool 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
240bool 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
272bool 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
436bool 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
463void KMCupsManager::listPrinters()
464{
465 loadServerPrinters();
466}
467
468void 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
523void 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
581DrMain* 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
615DrMain* 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
627DrMain* KMCupsManager::loadMaticDriver(const TQString& drname)
628{
629 TQStringList comps = TQStringList::split('/', drname, false);
630 TQString tmpFile = locateLocal("tmp", "foomatic_" + kapp->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
678DrMain* 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
696void 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
796bool KMCupsManager::savePrinterDriver(KMPrinter *p, DrMain *d)
797{
798 TQString tmpfilename = locateLocal("tmp","print_") + kapp->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
821void* 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
838void KMCupsManager::unloadCupsdConf()
839{
840 if (m_cupsdconf)
841 {
842 KLibLoader::self()->unloadLibrary("libcupsdconf");
843 m_cupsdconf = 0;
844 }
845}
846
847bool 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
861bool 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
876TQStringList 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
909void 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
917void 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
925void 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
944void 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
973void KMCupsManager::ippReport(IppRequest& req, int group, const TQString& caption)
974{
975 IppReportDlg::report(&req, group, caption);
976}
977
978TQString 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
987void 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
1001void 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
1028void 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
1038void 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
1072void KMCupsManager::hostPingSlot() {
1073 m_hostSuccess = true;
1074 m_lookupDone = true;
1075}
1076
1077void KMCupsManager::hostPingFailedSlot() {
1078 m_hostSuccess = false;
1079 m_lookupDone = true;
1080}
1081
1082//*****************************************************************************************************
1083
1084static 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
1100static 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
1110static 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.15.0
This website is maintained by Timothy Pearson.