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

tdeprint

  • tdeprint
  • lpr
matichandler.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 "matichandler.h"
21#include "printcapentry.h"
22#include "kmprinter.h"
23#include "matichelper.h"
24#include "driver.h"
25#include "kpipeprocess.h"
26#include "kmmanager.h"
27#include "kprinter.h"
28#include "lprsettings.h"
29#include "util.h"
30#include "foomatic2loader.h"
31
32#include <tdelocale.h>
33#include <tdestandarddirs.h>
34#include <tdeapplication.h>
35#include <kdebug.h>
36#include <tdeprocess.h>
37#include <tqfile.h>
38#include <tqtextstream.h>
39#include <tqregexp.h>
40
41#include <stdlib.h>
42#include <sys/wait.h>
43
44MaticHandler::MaticHandler(KMManager *mgr)
45: LprHandler("foomatic", mgr)
46{
47 TQString PATH = getenv("PATH");
48 PATH.append(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin");
49 m_exematicpath = TDEStandardDirs::findExe("lpdomatic", PATH);
50 m_ncpath = TDEStandardDirs::findExe("nc");
51 m_smbpath = TDEStandardDirs::findExe("smbclient");
52 m_rlprpath = TDEStandardDirs::findExe("rlpr");
53}
54
55bool MaticHandler::validate(PrintcapEntry *entry)
56{
57 if (entry)
58 return (entry->field("if").right(9) == "lpdomatic");
59 return false;
60}
61
62KMPrinter* MaticHandler::createPrinter(PrintcapEntry *entry)
63{
64 if (entry && validate(entry))
65 {
66 KMPrinter *prt = new KMPrinter;
67 prt->setName(entry->name);
68 prt->setPrinterName(entry->name);
69 prt->setType(KMPrinter::Printer);
70 //if (entry->field("lp") == "/dev/null" || entry->field("lp").isEmpty())
71 // prt->addType(KMPrinter::Remote);
72 return prt;
73 }
74 return NULL;
75}
76
77bool MaticHandler::completePrinter(KMPrinter *prt, PrintcapEntry *entry, bool shortmode)
78{
79 TQString val = entry->field("lp");
80 if (val == "/dev/null" || val.isEmpty())
81 {
82 prt->setLocation(i18n("Network printer"));
83 }
84 else
85 {
86 prt->setLocation(i18n("Local printer on %1").arg(val));
87 KURL url(val);
88 if (val.find("usb") != -1)
89 url.setProtocol("usb");
90 else
91 url.setProtocol("parallel");
92 prt->setDevice(url.url());
93 }
94 prt->setDescription(entry->aliases.join(", "));
95
96 if (!shortmode)
97 {
98 Foomatic2Loader loader;
99 if ( loader.readFromFile( maticFile( entry ) ) )
100 {
101 TQString postpipe = loader.data()[ "POSTPIPE" ].toString();
102 if (!postpipe.isEmpty())
103 {
104 KURL url ( parsePostpipe(postpipe) );
105 if (!url.isEmpty())
106 {
107 TQString ds = TQString::fromLatin1("%1 (%2)").arg(prt->location()).arg(url.protocol());
108 prt->setDevice(url.url());
109 prt->setLocation(ds);
110 }
111 }
112
113 TQStringVariantMap m = loader.data()[ "VAR" ].toMap();
114 if ( !m.isEmpty() )
115 {
116 prt->setManufacturer(m["make"].toString());
117 prt->setModel(m["model"].toString());
118 prt->setDriverInfo(TQString::fromLatin1("%1 %2 (%3)").arg(prt->manufacturer()).arg(prt->model()).arg(m["driver"].toString()));
119 }
120 }
121 }
122
123 return true;
124}
125
126TQString MaticHandler::parsePostpipe(const TQString& s)
127{
128 TQString url;
129 int p = s.findRev('|');
130 TQStringList args = TQStringList::split(" ", s.right(s.length()-p-1));
131
132 if (args.count() != 0)
133 {
134 // socket printer
135 if (args[0].right(3) == "/nc")
136 {
137 url = "socket://" + args[ 1 ];
138 if ( args.count() > 2 )
139 url += ":" + args[ 2 ];
140 else
141 url += ":9100";
142 }
143 // smb printer
144 else if (args[0].right(10) == "/smbclient")
145 {
146 TQStringList host_components = TQStringList::split(TQRegExp("/|\\\\\""), args[1], false);
147 TQString workgrp, user, pass;
148 for (uint i=2; i<args.count(); i++)
149 {
150 if (args[i] == "-U")
151 user = args[++i];
152 else if (args[i] == "-W")
153 workgrp = args[++i];
154 else if (args[i][0] != '-' && i == 2)
155 pass = args[i];
156 }
157 url = buildSmbURI( workgrp, host_components[ 0 ], host_components[ 1 ], user, pass );
158 }
159 // remote printer
160 else if (args[0].right(5) == "/rlpr")
161 {
162 uint i=1;
163 while (i < args.count())
164 {
165 if (args[i].left(2) != "-P")
166 i++;
167 else
168 {
169 TQString host = (args[i].length() == 2 ? args[i+1] : args[i].right(args[i].length()-2));
170 int p = host.find("\\@");
171 if (p != -1)
172 {
173 url = "lpd://" + host.right(host.length()-p-2) + "/" + host.left(p);
174 }
175 break;
176 }
177 }
178 }
179 }
180
181 return url;
182}
183
184TQString MaticHandler::createPostpipe(const TQString& _url)
185{
186 KURL url( _url );
187 TQString prot = url.protocol();
188 TQString str;
189 if (prot == "socket")
190 {
191 str += ("| " + m_ncpath);
192 str += (" " + url.host());
193 if (url.port() != 0)
194 str += (" " + TQString::number(url.port()));
195 }
196 else if (prot == "lpd")
197 {
198 str += ("| " + m_rlprpath + " -q -h");
199 TQString h = url.host(), p = url.path().mid(1);
200 str += (" -P " + p + "\\@" + h);
201 }
202 else if (prot == "smb")
203 {
204 TQString work, server, printer, user, passwd;
205 if ( splitSmbURI( _url, work, server, printer, user, passwd ) )
206 {
207 str += ("| (\\n echo \\\"print -\\\"\\n cat \\n) | " + m_smbpath);
208 str += (" \\\"//" + server + "/" + printer + "\\\"");
209 if (!passwd.isEmpty())
210 str += (" " + passwd);
211 if (!user.isEmpty())
212 str += (" -U " + user);
213 if (!work.isEmpty())
214 str += (" -W " + work);
215 str += " -N -P";
216 }
217 }
218 return str;
219}
220
221DrMain* MaticHandler::loadDriver(KMPrinter*, PrintcapEntry *entry, bool)
222{
223 // we need to use a copy of the driver, as the driver
224 // is not self-contained. If the printer is removed (when
225 // changing printer name), the template would be also removed
226 TQString origfilename = maticFile(entry);
227 TQString filename = locateLocal("tmp", "foomatic_" + tdeApp->randomString(8));
228 ::system(TQFile::encodeName("cp " + TDEProcess::quote(origfilename) + " " + TDEProcess::quote(filename)));
229 DrMain *driver = Foomatic2Loader::loadDriver(filename);
230 if (driver)
231 {
232 driver->set("template", filename);
233 driver->set("temporary", "true");
234 return driver;
235 }
236 else
237 return NULL;
238}
239
240DrMain* MaticHandler::loadDbDriver(const TQString& path)
241{
242 TQStringList comps = TQStringList::split('/', path, false);
243 if (comps.count() < 3 || comps[0] != "foomatic")
244 {
245 manager()->setErrorMsg(i18n("Internal error."));
246 return NULL;
247 }
248
249 TQString tmpFile = locateLocal("tmp", "foomatic_" + tdeApp->randomString(8));
250 TQString PATH = getenv("PATH") + TQString::fromLatin1(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin");
251 TQString exe = TDEStandardDirs::findExe("foomatic-datafile", PATH);
252 if (exe.isEmpty())
253 {
254 manager()->setErrorMsg(i18n("Unable to find the executable foomatic-datafile "
255 "in your PATH. Check that Foomatic is correctly installed."));
256 return NULL;
257 }
258
259 KPipeProcess in;
260 TQFile out(tmpFile);
261 TQString cmd = TDEProcess::quote(exe);
262 cmd += " -t lpd -d ";
263 cmd += TDEProcess::quote(comps[2]);
264 cmd += " -p ";
265 cmd += TDEProcess::quote(comps[1]);
266 if (in.open(cmd) && out.open(IO_WriteOnly))
267 {
268 TQTextStream tin(&in), tout(&out);
269 TQString line;
270 while (!tin.atEnd())
271 {
272 line = tin.readLine();
273 tout << line << endl;
274 }
275 in.close();
276 out.close();
277
278 DrMain *driver = Foomatic2Loader::loadDriver(tmpFile);
279 if (driver)
280 {
281 driver->set("template", tmpFile);
282 driver->set("temporary", tmpFile);
283 return driver;
284 }
285 }
286 manager()->setErrorMsg(i18n("Unable to create the Foomatic driver [%1,%2]. "
287 "Either that driver does not exist, or you don't have "
288 "the required permissions to perform that operation.").arg(comps[1]).arg(comps[2]));
289 return NULL;
290}
291
292bool MaticHandler::savePrinterDriver(KMPrinter *prt, PrintcapEntry *entry, DrMain *driver, bool*)
293{
294 TQFile tmpFile(locateLocal("tmp", "foomatic_" + tdeApp->randomString(8)));
295 TQFile inFile(driver->get("template"));
296 TQString outFile = maticFile(entry);
297 bool result(false);
298 TQString postpipe = createPostpipe(prt->device());
299
300 if (inFile.open(IO_ReadOnly) && tmpFile.open(IO_WriteOnly))
301 {
302 TQTextStream tin(&inFile), tout(&tmpFile);
303 TQString line, optname;
304 int p(-1), q(-1);
305 if (!postpipe.isEmpty())
306 tout << "$postpipe = \"" << postpipe << "\";" << endl;
307 while (!tin.atEnd())
308 {
309 line = tin.readLine();
310 if (line.stripWhiteSpace().startsWith("$postpipe"))
311 continue;
312 else if ((p = line.find("'name'")) != -1)
313 {
314 p = line.find('\'', p+6)+1;
315 q = line.find('\'', p);
316 optname = line.mid(p, q-p);
317 }
318 else if ((p = line.find("'default'")) != -1)
319 {
320 DrBase *opt = driver->findOption(optname);
321 if (opt)
322 {
323 tout << line.left(p+9) << " => '" << opt->valueText() << "'," << endl;
324 continue;
325 }
326 }
327 tout << line << endl;
328 }
329 inFile.close();
330 tmpFile.close();
331
332 TQString cmd = "mv " + TDEProcess::quote(tmpFile.name()) + " " + TDEProcess::quote(outFile);
333 int status = ::system(TQFile::encodeName(cmd).data());
334 TQFile::remove(tmpFile.name());
335 result = (status != -1 && WEXITSTATUS(status) == 0);
336 }
337
338 if (!result)
339 manager()->setErrorMsg(i18n("You probably don't have the required permissions "
340 "to perform that operation."));
341 TQFile::remove(tmpFile.name());
342 if (!result || entry->field("ppdfile").isEmpty())
343 return result;
344 else
345 return savePpdFile(driver, entry->field("ppdfile"));
346}
347
348bool MaticHandler::savePpdFile(DrMain *driver, const TQString& filename)
349{
350 TQString mdriver(driver->get("matic_driver")), mprinter(driver->get("matic_printer"));
351 if (mdriver.isEmpty() || mprinter.isEmpty())
352 return true;
353
354 TQString PATH = getenv("PATH") + TQString::fromLatin1(":/usr/sbin:/usr/local/sbin:/opt/sbin:/opt/local/sbin");
355 TQString exe = TDEStandardDirs::findExe("foomatic-datafile", PATH);
356 if (exe.isEmpty())
357 {
358 manager()->setErrorMsg(i18n("Unable to find the executable foomatic-datafile "
359 "in your PATH. Check that Foomatic is correctly installed."));
360 return false;
361 }
362
363 KPipeProcess in;
364 TQFile out(filename);
365 if (in.open(exe + " -t cups -d " + mdriver + " -p " + mprinter) && out.open(IO_WriteOnly))
366 {
367 TQTextStream tin(&in), tout(&out);
368 TQString line, optname;
369 TQRegExp re("^\\*Default(\\w+):"), foo("'name'\\s+=>\\s+'(\\w+)'"), foo2("'\\w+'\\s*,\\s*$");
370 while (!tin.atEnd())
371 {
372 line = tin.readLine();
373 if (line.startsWith("*% COMDATA #"))
374 {
375 if (line.find("'default'") != -1)
376 {
377 DrBase *opt = (optname.isEmpty() ? NULL : driver->findOption(optname));
378 if (opt)
379 {
380 line.replace(foo2, "'"+opt->valueText()+"',");
381 }
382 }
383 else if (foo.search(line) != -1)
384 optname = foo.cap(1);
385 }
386 else if (re.search(line) != -1)
387 {
388 DrBase *opt = driver->findOption(re.cap(1));
389 if (opt)
390 {
391 TQString val = opt->valueText();
392 if (opt->type() == DrBase::Boolean)
393 val = (val == "1" ? "True" : "False");
394 tout << "*Default" << opt->name() << ": " << val << endl;
395 continue;
396 }
397 }
398 tout << line << endl;
399 }
400 in.close();
401 out.close();
402
403 return true;
404 }
405 manager()->setErrorMsg(i18n("Unable to create the Foomatic driver [%1,%2]. "
406 "Either that driver does not exist, or you don't have "
407 "the required permissions to perform that operation.").arg(mdriver).arg(mprinter));
408
409 return false;
410}
411
412PrintcapEntry* MaticHandler::createEntry(KMPrinter *prt)
413{
414 KURL url( prt->device() );
415 TQString prot = url.protocol();
416 if ((prot != "lpd" || m_rlprpath.isEmpty()) &&
417 (prot != "socket" || m_ncpath.isEmpty()) &&
418 (prot != "smb" || m_smbpath.isEmpty()) &&
419 prot != "parallel")
420 {
421 manager()->setErrorMsg(i18n("Unsupported backend: %1.").arg(prot));
422 return NULL;
423 }
424 if (m_exematicpath.isEmpty())
425 {
426 manager()->setErrorMsg(i18n("Unable to find executable lpdomatic. "
427 "Check that Foomatic is correctly installed "
428 "and that lpdomatic is installed in a standard "
429 "location."));
430 return NULL;
431 }
432 PrintcapEntry *entry = new PrintcapEntry;
433 entry->addField("lf", Field::String, "/var/log/lp-errs");
434 entry->addField("lp", Field::String, (prot != "parallel" ? "/dev/null" : url.path()));
435 entry->addField("if", Field::String, m_exematicpath);
436 if (LprSettings::self()->mode() == LprSettings::LPRng)
437 {
438 entry->addField("filter_options", Field::String, " --lprng $Z /etc/foomatic/lpd/"+prt->printerName()+".lom");
439 entry->addField("force_localhost", Field::Boolean);
440 entry->addField("ppdfile", Field::String, "/etc/foomatic/"+prt->printerName()+".ppd");
441 }
442 else
443 entry->addField("af", Field::String, "/etc/foomatic/lpd/"+prt->printerName()+".lom");
444 if (!prt->description().isEmpty())
445 entry->aliases << prt->description();
446 return entry;
447}
448
449bool MaticHandler::removePrinter(KMPrinter *prt, PrintcapEntry *entry)
450{
451 // remove Foomatic driver
452 TQString af = entry->field("af");
453 if (af.isEmpty())
454 return true;
455 if (!TQFile::remove(af))
456 {
457 manager()->setErrorMsg(i18n("Unable to remove driver file %1.").arg(af));
458 return false;
459 }
460 return true;
461}
462
463TQString MaticHandler::printOptions(KPrinter *printer)
464{
465 TQMap<TQString,TQString> opts = printer->options();
466 TQString str;
467 for (TQMap<TQString,TQString>::Iterator it=opts.begin(); it!=opts.end(); ++it)
468 {
469 if (it.key().startsWith("kde-") || it.key().startsWith("_kde-") || it.key().startsWith( "app-" ))
470 continue;
471 str += (" " + it.key() + "=" + (*it));
472 }
473 if (!str.isEmpty())
474 str.prepend("-J '").append("'");
475 return str;
476}
477
478TQString MaticHandler::driverDirInternal()
479{
480 return locateDir("foomatic/db/source", "/usr/share:/usr/local/share:/opt/share");
481}
KPrinter
This class is the main interface to access the TDE print framework.
Definition: kprinter.h:89
KPrinter::options
const TQMap< TQString, TQString > & options() const
Returns the complete set of print options from the KPrinter object.
Definition: kprinter.cpp:903

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.4
This website is maintained by Timothy Pearson.