• 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 <kstandarddirs.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 
44 MaticHandler::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 
55 bool MaticHandler::validate(PrintcapEntry *entry)
56 {
57  if (entry)
58  return (entry->field("if").right(9) == "lpdomatic");
59  return false;
60 }
61 
62 KMPrinter* 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 
77 bool 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 
126 TQString 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 
184 TQString 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 
221 DrMain* 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_" + kapp->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 
240 DrMain* 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_" + kapp->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 
292 bool MaticHandler::savePrinterDriver(KMPrinter *prt, PrintcapEntry *entry, DrMain *driver, bool*)
293 {
294  TQFile tmpFile(locateLocal("tmp", "foomatic_" + kapp->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 
348 bool 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 
412 PrintcapEntry* 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 
449 bool 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 
463 TQString 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 
478 TQString 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.1
This website is maintained by Timothy Pearson.