20#include "matichandler.h" 
   21#include "printcapentry.h" 
   23#include "matichelper.h" 
   25#include "kpipeprocess.h" 
   28#include "lprsettings.h" 
   30#include "foomatic2loader.h" 
   33#include <tdestandarddirs.h> 
   34#include <tdeapplication.h> 
   36#include <tdeprocess.h> 
   38#include <tqtextstream.h> 
   44MaticHandler::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");
 
   55bool MaticHandler::validate(PrintcapEntry *entry)
 
   58        return (entry->field(
"if").right(9) == 
"lpdomatic");
 
   62KMPrinter* 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);
 
   77bool 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()));
 
  126TQString 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);
 
  184TQString 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);
 
  221DrMain* MaticHandler::loadDriver(KMPrinter*, PrintcapEntry *entry, 
bool)
 
  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);
 
  232        driver->set(
"template", filename);
 
  233        driver->set(
"temporary", 
"true");
 
  240DrMain* 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_" + 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);
 
  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]));
 
  292bool MaticHandler::savePrinterDriver(KMPrinter *prt, PrintcapEntry *entry, DrMain *driver, 
bool*)
 
  294    TQFile  tmpFile(locateLocal(
"tmp", 
"foomatic_" + tdeApp->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"));
 
  348bool 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));
 
  412PrintcapEntry* 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();
 
  449bool 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));
 
  463TQString 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(
"'");
 
  478TQString 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.