20 #include "matichandler.h"
21 #include "printcapentry.h"
22 #include "kmprinter.h"
23 #include "matichelper.h"
25 #include "kpipeprocess.h"
26 #include "kmmanager.h"
28 #include "lprsettings.h"
30 #include "foomatic2loader.h"
32 #include <tdelocale.h>
33 #include <kstandarddirs.h>
34 #include <tdeapplication.h>
36 #include <tdeprocess.h>
38 #include <tqtextstream.h>
44 MaticHandler::MaticHandler(KMManager *mgr)
45 : LprHandler(
"foomatic", mgr)
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");
55 bool MaticHandler::validate(PrintcapEntry *entry)
58 return (entry->field(
"if").right(9) ==
"lpdomatic");
62 KMPrinter* MaticHandler::createPrinter(PrintcapEntry *entry)
64 if (entry && validate(entry))
66 KMPrinter *prt =
new KMPrinter;
67 prt->setName(entry->name);
68 prt->setPrinterName(entry->name);
69 prt->setType(KMPrinter::Printer);
77 bool MaticHandler::completePrinter(KMPrinter *prt, PrintcapEntry *entry,
bool shortmode)
79 TQString val = entry->field(
"lp");
80 if (val ==
"/dev/null" || val.isEmpty())
82 prt->setLocation(i18n(
"Network printer"));
86 prt->setLocation(i18n(
"Local printer on %1").arg(val));
88 if (val.find(
"usb") != -1)
89 url.setProtocol(
"usb");
91 url.setProtocol(
"parallel");
92 prt->setDevice(url.url());
94 prt->setDescription(entry->aliases.join(
", "));
98 Foomatic2Loader loader;
99 if ( loader.readFromFile( maticFile( entry ) ) )
101 TQString postpipe = loader.data()[
"POSTPIPE" ].toString();
102 if (!postpipe.isEmpty())
104 KURL url ( parsePostpipe(postpipe) );
107 TQString ds = TQString::fromLatin1(
"%1 (%2)").arg(prt->location()).arg(url.protocol());
108 prt->setDevice(url.url());
109 prt->setLocation(ds);
113 TQStringVariantMap m = loader.data()[
"VAR" ].toMap();
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()));
126 TQString MaticHandler::parsePostpipe(
const TQString& s)
129 int p = s.findRev(
'|');
130 TQStringList args = TQStringList::split(
" ", s.right(s.length()-p-1));
132 if (args.count() != 0)
135 if (args[0].right(3) ==
"/nc")
137 url =
"socket://" + args[ 1 ];
138 if ( args.count() > 2 )
139 url +=
":" + args[ 2 ];
144 else if (args[0].right(10) ==
"/smbclient")
146 TQStringList host_components = TQStringList::split(TQRegExp(
"/|\\\\\""), args[1],
false);
147 TQString workgrp, user, pass;
148 for (uint i=2; i<args.count(); i++)
152 else if (args[i] ==
"-W")
154 else if (args[i][0] !=
'-' && i == 2)
157 url = buildSmbURI( workgrp, host_components[ 0 ], host_components[ 1 ], user, pass );
160 else if (args[0].right(5) ==
"/rlpr")
163 while (i < args.count())
165 if (args[i].left(2) !=
"-P")
169 TQString host = (args[i].length() == 2 ? args[i+1] : args[i].right(args[i].length()-2));
170 int p = host.find(
"\\@");
173 url =
"lpd://" + host.right(host.length()-p-2) +
"/" + host.left(p);
184 TQString MaticHandler::createPostpipe(
const TQString& _url)
187 TQString prot = url.protocol();
189 if (prot ==
"socket")
191 str += (
"| " + m_ncpath);
192 str += (
" " + url.host());
194 str += (
" " + TQString::number(url.port()));
196 else if (prot ==
"lpd")
198 str += (
"| " + m_rlprpath +
" -q -h");
199 TQString h = url.host(), p = url.path().mid(1);
200 str += (
" -P " + p +
"\\@" + h);
202 else if (prot ==
"smb")
204 TQString work, server, printer, user, passwd;
205 if ( splitSmbURI( _url, work, server, printer, user, passwd ) )
207 str += (
"| (\\n echo \\\"print -\\\"\\n cat \\n) | " + m_smbpath);
208 str += (
" \\\"//" + server +
"/" + printer +
"\\\"");
209 if (!passwd.isEmpty())
210 str += (
" " + passwd);
212 str += (
" -U " + user);
214 str += (
" -W " + work);
221 DrMain* MaticHandler::loadDriver(KMPrinter*, PrintcapEntry *entry,
bool)
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);
232 driver->set(
"template", filename);
233 driver->set(
"temporary",
"true");
240 DrMain* MaticHandler::loadDbDriver(
const TQString& path)
242 TQStringList comps = TQStringList::split(
'/', path,
false);
243 if (comps.count() < 3 || comps[0] !=
"foomatic")
245 manager()->setErrorMsg(i18n(
"Internal error."));
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);
254 manager()->setErrorMsg(i18n(
"Unable to find the executable foomatic-datafile "
255 "in your PATH. Check that Foomatic is correctly installed."));
261 TQString cmd = TDEProcess::quote(exe);
262 cmd +=
" -t lpd -d ";
263 cmd += TDEProcess::quote(comps[2]);
265 cmd += TDEProcess::quote(comps[1]);
266 if (in.open(cmd) && out.open(IO_WriteOnly))
268 TQTextStream tin(&in), tout(&out);
272 line = tin.readLine();
273 tout << line << endl;
278 DrMain *driver = Foomatic2Loader::loadDriver(tmpFile);
281 driver->set(
"template", tmpFile);
282 driver->set(
"temporary", tmpFile);
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]));
292 bool MaticHandler::savePrinterDriver(KMPrinter *prt, PrintcapEntry *entry, DrMain *driver,
bool*)
294 TQFile tmpFile(locateLocal(
"tmp",
"foomatic_" + kapp->randomString(8)));
295 TQFile inFile(driver->get(
"template"));
296 TQString outFile = maticFile(entry);
298 TQString postpipe = createPostpipe(prt->device());
300 if (inFile.open(IO_ReadOnly) && tmpFile.open(IO_WriteOnly))
302 TQTextStream tin(&inFile), tout(&tmpFile);
303 TQString line, optname;
305 if (!postpipe.isEmpty())
306 tout <<
"$postpipe = \"" << postpipe <<
"\";" << endl;
309 line = tin.readLine();
310 if (line.stripWhiteSpace().startsWith(
"$postpipe"))
312 else if ((p = line.find(
"'name'")) != -1)
314 p = line.find(
'\'', p+6)+1;
315 q = line.find(
'\'', p);
316 optname = line.mid(p, q-p);
318 else if ((p = line.find(
"'default'")) != -1)
320 DrBase *opt = driver->findOption(optname);
323 tout << line.left(p+9) <<
" => '" << opt->valueText() <<
"'," << endl;
327 tout << line << endl;
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);
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())
345 return savePpdFile(driver, entry->field(
"ppdfile"));
348 bool MaticHandler::savePpdFile(DrMain *driver,
const TQString& filename)
350 TQString mdriver(driver->get(
"matic_driver")), mprinter(driver->get(
"matic_printer"));
351 if (mdriver.isEmpty() || mprinter.isEmpty())
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);
358 manager()->setErrorMsg(i18n(
"Unable to find the executable foomatic-datafile "
359 "in your PATH. Check that Foomatic is correctly installed."));
364 TQFile out(filename);
365 if (in.open(exe +
" -t cups -d " + mdriver +
" -p " + mprinter) && out.open(IO_WriteOnly))
367 TQTextStream tin(&in), tout(&out);
368 TQString line, optname;
369 TQRegExp re(
"^\\*Default(\\w+):"), foo(
"'name'\\s+=>\\s+'(\\w+)'"), foo2(
"'\\w+'\\s*,\\s*$");
372 line = tin.readLine();
373 if (line.startsWith(
"*% COMDATA #"))
375 if (line.find(
"'default'") != -1)
377 DrBase *opt = (optname.isEmpty() ? NULL : driver->findOption(optname));
380 line.replace(foo2,
"'"+opt->valueText()+
"',");
383 else if (foo.search(line) != -1)
384 optname = foo.cap(1);
386 else if (re.search(line) != -1)
388 DrBase *opt = driver->findOption(re.cap(1));
391 TQString val = opt->valueText();
392 if (opt->type() == DrBase::Boolean)
393 val = (val ==
"1" ?
"True" :
"False");
394 tout <<
"*Default" << opt->name() <<
": " << val << endl;
398 tout << line << endl;
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));
412 PrintcapEntry* MaticHandler::createEntry(KMPrinter *prt)
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()) &&
421 manager()->setErrorMsg(i18n(
"Unsupported backend: %1.").arg(prot));
424 if (m_exematicpath.isEmpty())
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 "
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)
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");
443 entry->addField(
"af", Field::String,
"/etc/foomatic/lpd/"+prt->printerName()+
".lom");
444 if (!prt->description().isEmpty())
445 entry->aliases << prt->description();
449 bool MaticHandler::removePrinter(KMPrinter *prt, PrintcapEntry *entry)
452 TQString af = entry->field(
"af");
455 if (!TQFile::remove(af))
457 manager()->setErrorMsg(i18n(
"Unable to remove driver file %1.").arg(af));
463 TQString MaticHandler::printOptions(
KPrinter *printer)
465 TQMap<TQString,TQString> opts = printer->
options();
467 for (TQMap<TQString,TQString>::Iterator it=opts.begin(); it!=opts.end(); ++it)
469 if (it.key().startsWith(
"kde-") || it.key().startsWith(
"_kde-") || it.key().startsWith(
"app-" ))
471 str += (
" " + it.key() +
"=" + (*it));
474 str.prepend(
"-J '").append(
"'");
478 TQString MaticHandler::driverDirInternal()
480 return locateDir(
"foomatic/db/source",
"/usr/share:/usr/local/share:/opt/share");
This class is the main interface to access the TDE print framework.
const TQMap< TQString, TQString > & options() const
Returns the complete set of print options from the KPrinter object.