lprngtoolhandler.cpp

00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation.
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include "lprngtoolhandler.h"
00021 #include "printcapentry.h"
00022 #include "kmprinter.h"
00023 #include "util.h"
00024 #include "lprsettings.h"
00025 #include "driver.h"
00026 #include "kmmanager.h"
00027 #include "kprinter.h"
00028 
00029 #include <qfile.h>
00030 #include <qtextstream.h>
00031 #include <klocale.h>
00032 #include <kdebug.h>
00033 #include <kstandarddirs.h>
00034 
00035 LPRngToolHandler::LPRngToolHandler(KMManager *mgr)
00036 : LprHandler("lprngtool", mgr)
00037 {
00038 }
00039 
00040 bool LPRngToolHandler::validate(PrintcapEntry *entry)
00041 {
00042     if (entry->comment.startsWith("##LPRNGTOOL##") &&
00043         entry->comment.find("UNKNOWN") == -1)
00044         return true;
00045     return false;
00046 }
00047 
00048 bool LPRngToolHandler::completePrinter(KMPrinter *prt, PrintcapEntry *entry, bool shortmode)
00049 {
00050     QString str, lp;
00051 
00052     // look for type in comment
00053     QStringList l = QStringList::split(' ', entry->comment, false);
00054     lp = entry->field("lp");
00055     if (l.count() < 1)
00056         return false;
00057 
00058     if (l[1] == "DEVICE" || l[1] == "SOCKET" || l[1] == "QUEUE")
00059         LprHandler::completePrinter(prt, entry, shortmode);
00060     else if (l[1] == "SMB")
00061     {
00062         QMap<QString,QString>   opts = parseXferOptions(entry->field("xfer_options"));
00063         QString user, pass;
00064         loadAuthFile(LprSettings::self()->baseSpoolDir() + "/" + entry->name + "/" + opts["authfile"], user, pass);
00065         QString uri = buildSmbURI(
00066                 opts[ "workgroup" ],
00067                 opts[ "host" ],
00068                 opts[ "printer" ],
00069                 user,
00070                 pass );
00071         prt->setDevice( uri );
00072         prt->setLocation(i18n("Network printer (%1)").arg("smb"));
00073     }
00074 
00075     // look for comment
00076     if (!(str=entry->field("cm")).isEmpty())
00077         prt->setDescription(str);
00078 
00079     // driver
00080     //if (!shortmode)
00081     //{
00082         if (!(str=entry->field("ifhp")).isEmpty())
00083         {
00084             QString model;
00085             int p = str.find("model");
00086             if (p != -1)
00087             {
00088                 p = str.find('=', p);
00089                 if (p != -1)
00090                 {
00091                     p++;
00092                     int q = str.find(',', p);
00093                     if (q == -1)
00094                         model = str.mid(p);
00095                     else
00096                         model = str.mid(p, q-p);
00097                 }
00098             }
00099             prt->setDriverInfo(i18n("IFHP Driver (%1)").arg((model.isEmpty() ? i18n("unknown") : model)));
00100             prt->setOption("driverID", model);
00101         }
00102     //}
00103     return true;
00104 }
00105 
00106 QMap<QString,QString> LPRngToolHandler::parseXferOptions(const QString& str)
00107 {
00108     uint    p(0), q;
00109     QMap<QString,QString>   opts;
00110     QString key, val;
00111 
00112     while (p < str.length())
00113     {
00114         key = val = QString::null;
00115         // skip spaces
00116         while (p < str.length() && str[p].isSpace())
00117             p++;
00118         q = p;
00119         while (q < str.length() && str[q] != '=')
00120             q++;
00121         key = str.mid(p, q-p);
00122         p = q+2;
00123         while (p < str.length() && str[p] != '"')
00124             p++;
00125         val = str.mid(q+2, p-q-2);
00126         if (!key.isEmpty())
00127             opts[key] = val;
00128         p++;
00129     }
00130     return opts;
00131 }
00132 
00133 void LPRngToolHandler::loadAuthFile(const QString& filename, QString& user, QString& pass)
00134 {
00135     QFile   f(filename);
00136     if (f.open(IO_ReadOnly))
00137     {
00138         QTextStream t(&f);
00139         QString line;
00140         while (!t.atEnd())
00141         {
00142             line = t.readLine().stripWhiteSpace();
00143             if (line.isEmpty())
00144                 continue;
00145             int p = line.find('=');
00146             if (p != -1)
00147             {
00148                 QString key = line.left(p);
00149                 if (key == "username")
00150                     user = line.mid(p+1);
00151                 else if (key == "password")
00152                     pass = line.mid(p+1);
00153             }
00154         }
00155     }
00156 }
00157 
00158 DrMain* LPRngToolHandler::loadDriver(KMPrinter *prt, PrintcapEntry *entry, bool config)
00159 {
00160     if (entry->field("lprngtooloptions").isEmpty())
00161     {
00162         manager()->setErrorMsg(i18n("No driver defined for that printer. It might be a raw printer."));
00163         return NULL;
00164     }
00165 
00166     DrMain* driver = loadToolDriver(locate("data", "kdeprint/lprngtooldriver1"));
00167     if (driver)
00168     {
00169         QString model = prt->option("driverID");
00170         driver->set("text", i18n("LPRngTool Common Driver (%1)").arg((model.isEmpty() ? i18n("unknown") : model)));
00171         if (!model.isEmpty())
00172             driver->set("driverID", model);
00173         QMap<QString,QString>   opts = parseZOptions(entry->field("prefix_z"));
00174         opts["lpr"] = entry->field("lpr");
00175         driver->setOptions(opts);
00176         // if not configuring, don't show the "lpr" options
00177         if (!config)
00178             driver->removeOptionGlobally("lpr");
00179     }
00180     return driver;
00181 }
00182 
00183 DrMain* LPRngToolHandler::loadDbDriver(const QString& s)
00184 {
00185     int p = s.find('/');
00186     DrMain* driver = loadToolDriver(locate("data", "kdeprint/lprngtooldriver1"));
00187     if (driver)
00188         driver->set("driverID", s.mid(p+1));
00189     return driver;
00190 }
00191 
00192 QValueList< QPair<QString,QStringList> > LPRngToolHandler::loadChoiceDict(const QString& filename)
00193 {
00194     QFile   f(filename);
00195     QValueList< QPair<QString,QStringList> >    dict;
00196     if (f.open(IO_ReadOnly))
00197     {
00198         QTextStream t(&f);
00199         QString line, key;
00200         QStringList l;
00201         while (!t.atEnd())
00202         {
00203             line = t.readLine().stripWhiteSpace();
00204             if (line.startsWith("OPTION"))
00205             {
00206                 if (l.count() > 0 && !key.isEmpty())
00207                     dict << QPair<QString,QStringList>(key, l);
00208                 l.clear();
00209                 key = QString::null;
00210                 if (line.contains('|') == 2 || line.right(7) == "BOOLEAN")
00211                 {
00212                     int p = line.find('|', 7);
00213                     key = line.mid(7, p-7);
00214                 }
00215             }
00216             else if (line.startsWith("CHOICE"))
00217             {
00218                 int p = line.find('|', 7);
00219                 l << line.mid(7, p-7);
00220             }
00221         }
00222     }
00223     return dict;
00224 }
00225 
00226 QMap<QString,QString> LPRngToolHandler::parseZOptions(const QString& optstr)
00227 {
00228     QMap<QString,QString>   opts;
00229     QStringList l = QStringList::split(',', optstr, false);
00230     if (l.count() == 0)
00231         return opts;
00232     
00233     if (m_dict.count() == 0)
00234         m_dict = loadChoiceDict(locate("data", "kdeprint/lprngtooldriver1"));
00235 
00236     QString unknown;
00237     for (QStringList::ConstIterator it=l.begin(); it!=l.end(); ++it)
00238     {
00239         bool    found(false);
00240         for (QValueList< QPair<QString,QStringList> >::ConstIterator p=m_dict.begin(); p!=m_dict.end() && !found; ++p)
00241         {
00242             if ((*p).second.find(*it) != (*p).second.end())
00243             {
00244                 opts[(*p).first] = (*it);
00245                 found = true;
00246             }
00247         }
00248         if (!found)
00249         {
00250             unknown.append(*it).append(',');
00251         }
00252     }
00253     if (!unknown.isEmpty())
00254     {
00255         unknown.truncate(unknown.length()-1);
00256         opts["filter"] = unknown;
00257     }
00258     return opts;
00259 }
00260 
00261 QString LPRngToolHandler::filterDir()
00262 {
00263     return driverDirectory();
00264 }
00265 
00266 QString LPRngToolHandler::driverDirInternal()
00267 {
00268     return locateDir("filters", "/usr/lib:/usr/local/lib:/opt/lib:/usr/libexec:/usr/local/libexec:/opt/libexec");
00269 }
00270 
00271 PrintcapEntry* LPRngToolHandler::createEntry(KMPrinter *prt)
00272 {
00273     QString prot = prt->deviceProtocol();
00274     if (prot != "parallel" && prot != "lpd" && prot != "smb" && prot != "socket")
00275     {
00276         manager()->setErrorMsg(i18n("Unsupported backend: %1.").arg(prot));
00277         return NULL;
00278     }
00279     PrintcapEntry   *entry = new PrintcapEntry;
00280     entry->addField("cm", Field::String, prt->description());
00281     QString lp, comment("##LPRNGTOOL## ");
00282     if (prot == "parallel")
00283     {
00284         comment.append("DEVICE ");
00285         lp = prt->device().mid( 9 );
00286         entry->addField("rw@", Field::Boolean);
00287     }
00288     else if (prot == "socket")
00289     {
00290         comment.append("SOCKET ");
00291         KURL url( prt->device() );
00292         lp = url.host();
00293         if (url.port() == 0)
00294             lp.append("%9100");
00295         else
00296             lp.append("%").append(QString::number(url.port()));
00297     }
00298     else if (prot == "lpd")
00299     {
00300         comment.append("QUEUE ");
00301         KURL url( prt->device() );
00302         lp = url.path().mid(1) + "@" + url.host();
00303     }
00304     else if (prot == "smb")
00305     {
00306         comment.append("SMB ");
00307         lp = "| " + filterDir() + "/smbprint";
00308         QString work, server, printer, user, passwd;
00309         if ( splitSmbURI( prt->device(), work, server, printer, user, passwd ) )
00310         {
00311             entry->addField("xfer_options", Field::String, QString::fromLatin1("authfile=\"auth\" crlf=\"0\" hostip=\"\" host=\"%1\" printer=\"%2\" remote_mode=\"SMB\" share=\"//%3/%4\" workgroup=\"%5\"").arg(server).arg(printer).arg(server).arg(printer).arg(work));
00312             QFile   authfile(LprSettings::self()->baseSpoolDir() + "/" + prt->printerName() + "/auth");
00313             if (authfile.open(IO_WriteOnly))
00314             {
00315                 QTextStream t(&authfile);
00316                 t << "username=" << user << endl;
00317                 t << "password=" << passwd << endl;
00318                 authfile.close();
00319             }
00320         }
00321         else
00322         {
00323             manager()->setErrorMsg( i18n( "Invalid printer backend specification: %1" ).arg( prt->device() ) );
00324             delete entry;
00325             return NULL;
00326         }
00327     }
00328 
00329     if (prt->driver())
00330     {
00331         DrMain  *driver = prt->driver();
00332         comment.append("filtertype=IFHP ifhp_options=status@,sync@,pagecount@,waitend@ printerdb_entry=");
00333         comment.append(driver->get("driverID"));
00334         entry->addField("ifhp", Field::String, QString::fromLatin1("model=%1,status@,sync@,pagecount@,waitend@").arg(driver->get("driverID")));
00335         entry->addField("lprngtooloptions", Field::String, QString::fromLatin1("FILTERTYPE=\"IFHP\" IFHP_OPTIONS=\"status@,sync@,pagecount@,waitend@\" PRINTERDB_ENTRY=\"%1\"").arg(driver->get("driverID")));
00336         QMap<QString,QString>   opts;
00337         QString optstr;
00338         driver->getOptions(opts, false);
00339         for (QMap<QString,QString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it)
00340             if (it.key() != "lpr")
00341                 optstr.append(*it).append(",");
00342         if (!optstr.isEmpty())
00343         {
00344             optstr.truncate(optstr.length()-1);
00345             entry->addField("prefix_z", Field::String, optstr);
00346         }
00347         if (!opts["lpr"].isEmpty())
00348             entry->addField("lpr", Field::String, opts["lpr"]);
00349     }
00350 
00351     entry->addField("lp", Field::String, lp);
00352     entry->comment = comment;
00353 
00354     return entry;
00355 }
00356 
00357 bool LPRngToolHandler::savePrinterDriver(KMPrinter*, PrintcapEntry *entry, DrMain *driver, bool *mustSave)
00358 {
00359     // save options in the "prefix_z" field and tell the manager to save the printcap file
00360     QMap<QString,QString>   opts;
00361     QString optstr;
00362     driver->getOptions(opts, false);
00363     for (QMap<QString,QString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it)
00364         if (it.key() != "lpr")
00365             optstr.append(*it).append(",");
00366     if (!optstr.isEmpty())
00367         optstr.truncate(optstr.length()-1);
00368     // save options in any case, otherwise nothing will happen whn
00369     // options are reset to their default value
00370     entry->addField("prefix_z", Field::String, optstr);
00371     entry->addField("lpr", Field::String, opts["lpr"]);
00372     if (mustSave)
00373         *mustSave = true;
00374     return true;
00375 }
00376 
00377 QString LPRngToolHandler::printOptions(KPrinter *printer)
00378 {
00379     QString optstr;
00380     QMap<QString,QString>   opts = printer->options();
00381     for (QMap<QString,QString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it)
00382     {
00383         if (it.key().startsWith("kde-") || it.key().startsWith("_kde-") || it.key() == "lpr" || it.key().startsWith( "app-" ))
00384             continue;
00385         optstr.append(*it).append(",");
00386     }
00387     if (!optstr.isEmpty())
00388     {
00389         optstr.truncate(optstr.length()-1);
00390         optstr.prepend("-Z '").append("'");
00391     }
00392     return optstr;
00393 }
KDE Home | KDE Accessibility Home | Description of Access Keys