apshandler.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 "apshandler.h"
00021 #include "driver.h"
00022 #include "printcapentry.h"
00023 #include "kmprinter.h"
00024 #include "lprsettings.h"
00025 #include "kmmanager.h"
00026 #include "util.h"
00027 #include "kprinter.h"
00028 
00029 #include <qfile.h>
00030 #include <qdir.h>
00031 #include <qtextstream.h>
00032 #include <qvaluestack.h>
00033 #include <kstandarddirs.h>
00034 #include <klocale.h>
00035 #include <kdebug.h>
00036 
00037 #include <sys/types.h>
00038 #include <sys/stat.h>
00039 
00040 ApsHandler::ApsHandler(KMManager *mgr)
00041 : LprHandler("apsfilter", mgr)
00042 {
00043     m_counter = 1;
00044 }
00045 
00046 bool ApsHandler::validate(PrintcapEntry *entry)
00047 {
00048     return (entry->field("if").right(9) == "apsfilter");
00049 }
00050 
00051 KMPrinter* ApsHandler::createPrinter(PrintcapEntry *entry)
00052 {
00053     entry->comment = QString::fromLatin1("# APS%1_BEGIN:printer%2").arg(m_counter).arg(m_counter);
00054     entry->postcomment = QString::fromLatin1("# APS%1_END - don't delete this").arg(m_counter);
00055     m_counter++;
00056     return LprHandler::createPrinter(entry);
00057 }
00058 
00059 bool ApsHandler::completePrinter(KMPrinter *prt, PrintcapEntry *entry, bool shortmode)
00060 {
00061     if (LprHandler::completePrinter(prt, entry, shortmode))
00062     {
00063         if (!shortmode)
00064         {
00065             QMap<QString,QString>   opts = loadResources(entry);
00066             if (opts.contains("PRINTER"))
00067             {
00068                 prt->setDescription(i18n("APS Driver (%1)").arg(opts["PRINTER"]));
00069                 prt->setDriverInfo(prt->description());
00070             }
00071         }
00072         if (prt->device().isEmpty())
00073         {
00074             QString prot;
00075             QString smbname(sysconfDir() + "/" + prt->printerName() + "/smbclient.conf");
00076             QString ncpname(sysconfDir() + "/" + prt->printerName() + "/netware.conf");
00077             if (QFile::exists(smbname))
00078             {
00079                 QMap<QString,QString>   opts = loadVarFile(smbname);
00080                 if (opts.count() == 0)
00081                     prt->setDevice("smb://<unknown>/<unknown>");
00082                 else
00083                 {
00084                     prt->setDevice(buildSmbURI(
00085                                 opts[ "SMB_WORKGROUP" ],
00086                                 opts[ "SMB_SERVER" ],
00087                                 opts[ "SMB_PRINTER" ],
00088                                 opts[ "SMB_USER" ],
00089                                 opts[ "SMB_PASSWD" ] ) );
00090                 }
00091                 prot = "smb";
00092             }
00093             else if (QFile::exists(ncpname))
00094             {
00095                 QMap<QString,QString>   opts = loadVarFile(ncpname);
00096                 if (opts.count() == 0)
00097                     prt->setDevice("ncp://<unknown>/<unknown>");
00098                 else
00099                 {
00100                     QString uri = buildSmbURI( 
00101                             QString::null,
00102                             opts[ "NCP_SERVER" ],
00103                             opts[ "NCP_PRINTER" ],
00104                             opts[ "NCP_USER" ],
00105                             opts[ "NCP_PASSWD" ] );
00106                     uri.replace( 0, 3, "ncp" );
00107                     prt->setDevice(uri);
00108                 }
00109                 prot = "ncp";
00110             }
00111             if (!prt->device().isEmpty())
00112                 prt->setLocation(i18n("Network printer (%1)").arg(prot));
00113         }
00114         return true;
00115     }
00116     return false;
00117 }
00118 
00119 QString ApsHandler::sysconfDir()
00120 {
00121     return QFile::encodeName("/etc/apsfilter");
00122 }
00123 
00124 QString ApsHandler::shareDir()
00125 {
00126     return driverDirectory();
00127 }
00128 
00129 QString ApsHandler::driverDirInternal()
00130 {
00131     return locateDir("apsfilter/setup", "/usr/share:/usr/local/share:/opt/share");
00132 }
00133 
00134 QMap<QString,QString> ApsHandler::loadResources(PrintcapEntry *entry)
00135 {
00136     return loadVarFile(sysconfDir() + "/" + (entry ? entry->name : QString::null) + "/apsfilterrc");
00137 }
00138 
00139 QMap<QString,QString> ApsHandler::loadVarFile(const QString& filename)
00140 {
00141     QMap<QString,QString>   opts;
00142     QFile   f(filename);
00143     if (f.open(IO_ReadOnly))
00144     {
00145         QTextStream t(&f);
00146         QString line;
00147         int p(-1);
00148         while (!t.atEnd())
00149         {
00150             line = t.readLine().stripWhiteSpace();
00151             if (line.isEmpty() || line[0] == '#' || (p = line.find('=')) == -1)
00152                 continue;
00153             QString variable = line.left(p).stripWhiteSpace();
00154             QString value = line.mid(p+1).stripWhiteSpace();
00155             if (!value.isEmpty() && value[0] == '\'')
00156                 value = value.mid(1, value.length()-2);
00157             opts[variable] = value;
00158         }
00159     }
00160     return opts;
00161 }
00162 
00163 DrMain* ApsHandler::loadDriver(KMPrinter *prt, PrintcapEntry *entry, bool config)
00164 {
00165     DrMain  *driver = loadApsDriver(config);
00166     if (driver /* && config */ )    // Load resources in all case, to get the correct page size
00167     {
00168         QMap<QString,QString>   opts = loadResources(entry);
00169         if ( !config && opts.contains( "PAPERSIZE" ) )
00170         {
00171             // this is needed to keep applications informed
00172             // about the current selected page size
00173             opts[ "PageSize" ] = opts[ "PAPERSIZE" ];
00174 
00175             // default page size needs to be set to the actual
00176             // value of the printer driver, otherwise it's blocked
00177             // to A4
00178             DrBase *opt = driver->findOption( "PageSize" );
00179             if ( opt )
00180                 opt->set( "default", opts[ "PageSize" ] );
00181         }
00182         driver->setOptions(opts);
00183         driver->set("gsdriver", opts["PRINTER"]);
00184     }
00185     return driver;
00186 }
00187 
00188 DrMain* ApsHandler::loadDbDriver(const QString& s)
00189 {
00190     int p = s.find('/');
00191     DrMain  *driver = loadApsDriver(true);
00192     if (driver)
00193         driver->set("gsdriver", s.mid(p+1));
00194     return driver;
00195 }
00196 
00197 DrMain* ApsHandler::loadApsDriver(bool config)
00198 {
00199     DrMain  *driver = loadToolDriver(locate("data", (config ? "kdeprint/apsdriver1" : "kdeprint/apsdriver2")));
00200     if (driver)
00201         driver->set("text", "APS Common Driver");
00202     return driver;
00203 }
00204 
00205 void ApsHandler::reset()
00206 {
00207     m_counter = 1;
00208 }
00209 
00210 PrintcapEntry* ApsHandler::createEntry(KMPrinter *prt)
00211 {
00212     QString prot = prt->deviceProtocol();
00213     if (prot != "parallel" && prot != "lpd" && prot != "smb" && prot != "ncp")
00214     {
00215         manager()->setErrorMsg(i18n("Unsupported backend: %1.").arg(prot));
00216         return NULL;
00217     }
00218     QString path = sysconfDir() + "/" + prt->printerName();
00219     if (!KStandardDirs::makeDir(path, 0755))
00220     {
00221         manager()->setErrorMsg(i18n("Unable to create directory %1.").arg(path));
00222         return NULL;
00223     }
00224     if (prot == "smb" || prot == "ncp")
00225     {
00226         // either "smb" or "ncp"
00227         QFile::remove(path + "/smbclient.conf");
00228         QFile::remove(path + "/netware.conf");
00229         QFile   f;
00230         if (prot == "smb")
00231         {
00232             f.setName(path + "/smbclient.conf");
00233             if (f.open(IO_WriteOnly))
00234             {
00235                 QTextStream t(&f);
00236                 QString work, server, printer, user, passwd;
00237                 if ( splitSmbURI( prt->device(), work, server, printer, user, passwd ) )
00238                 {
00239                     if (work.isEmpty())
00240                     {
00241                         manager()->setErrorMsg(i18n("Missing element: %1.").arg("Workgroup"));
00242                         return NULL;
00243                     }
00244                     t << "SMB_SERVER='" << server << "'" << endl;
00245                     t << "SMB_PRINTER='" << printer << "'" << endl;
00246                     t << "SMB_IP=''" << endl;
00247                     t << "SMB_WORKGROUP='" << work << "'" << endl;
00248                     t << "SMB_BUFFER=1400" << endl;
00249                     t << "SMB_FLAGS='-N'" << endl;
00250                     if (!user.isEmpty())
00251                     {
00252                         t << "SMB_USER='" << user << "'" << endl;
00253                         t << "SMB_PASSWD='" << passwd << "'" << endl;
00254                     }
00255                 }
00256                 else
00257                 {
00258                     manager()->setErrorMsg( i18n( "Invalid printer backend specification: %1" ).arg( prt->device() ) );
00259                     return NULL;
00260                 }
00261             }
00262             else
00263             {
00264                 manager()->setErrorMsg(i18n("Unable to create the file %1.").arg(f.name()));
00265                 return NULL;
00266             }
00267         }
00268         else
00269         {
00270             f.setName(path + "/netware.conf");
00271             if (f.open(IO_WriteOnly))
00272             {
00273                 QString work, server, printer, user, passwd;
00274                 QString uri = prt->device();
00275                 uri.replace( 0, 3, "smb" );
00276                 if ( splitSmbURI( uri, work, server, printer, user, passwd ) )
00277                 {
00278                     QTextStream t(&f);
00279                     t << "NCP_SERVER='" << server << "'" << endl;
00280                     t << "NCP_PRINTER='" << printer << "'" << endl;
00281                     if (!user.isEmpty())
00282                     {
00283                         t << "NCP_USER='" << user << "'" << endl;
00284                         t << "NCP_PASSWD='" << passwd << "'" << endl;
00285                     }
00286                 }
00287                 else
00288                 {
00289                     manager()->setErrorMsg( i18n( "Invalid printer backend specification: %1" ).arg( prt->device() ) );
00290                     return NULL;
00291                 }
00292             }
00293             else
00294             {
00295                 manager()->setErrorMsg(i18n("Unable to create the file %1.").arg(f.name()));
00296                 return NULL;
00297             }
00298         }
00299         // change file permissions
00300         ::chmod(QFile::encodeName(f.name()).data(), S_IRUSR|S_IWUSR);
00301     }
00302     PrintcapEntry   *entry = LprHandler::createEntry(prt);
00303     if (!entry)
00304     {
00305         entry = new PrintcapEntry;
00306         entry->addField("lp", Field::String, "/dev/null");
00307     }
00308     QString sd = LprSettings::self()->baseSpoolDir() + "/" + prt->printerName();
00309     entry->addField("af", Field::String, sd + "/acct");
00310     entry->addField("lf", Field::String, sd + "/log");
00311     entry->addField("if", Field::String, sysconfDir() + "/basedir/bin/apsfilter");
00312     entry->comment = QString::fromLatin1("# APS%1_BEGIN:printer%2").arg(m_counter).arg(m_counter);
00313     entry->postcomment = QString::fromLatin1("# APS%1_END").arg(m_counter);
00314     m_counter++;
00315     return entry;
00316 }
00317 
00318 bool ApsHandler::savePrinterDriver(KMPrinter *prt, PrintcapEntry *entry, DrMain *driver, bool*)
00319 {
00320     if (driver->get("gsdriver").isEmpty())
00321     {
00322         manager()->setErrorMsg(i18n("The APS driver is not defined."));
00323         return false;
00324     }
00325     QFile   f(sysconfDir() + "/" + prt->printerName() + "/apsfilterrc");
00326     if (f.open(IO_WriteOnly))
00327     {
00328         QTextStream t(&f);
00329         t << "# File generated by KDEPrint" << endl;
00330         t << "PRINTER='" << driver->get("gsdriver") << "'" << endl;
00331         QValueStack<DrGroup*>   stack;
00332         stack.push(driver);
00333         while (stack.count() > 0)
00334         {
00335             DrGroup *grp = stack.pop();
00336             QPtrListIterator<DrGroup>   git(grp->groups());
00337             for (; git.current(); ++git)
00338                 stack.push(git.current());
00339             QPtrListIterator<DrBase>    oit(grp->options());
00340             QString value;
00341             for (; oit.current(); ++oit)
00342             {
00343                 value = oit.current()->valueText();
00344                 switch (oit.current()->type())
00345                 {
00346                     case DrBase::Boolean:
00347                         if (value == "true")
00348                             t << oit.current()->name() << "='" << value << "'" << endl;
00349                         break;
00350                     case DrBase::List:
00351                         if (value != "(empty)")
00352                             t << oit.current()->name() << "='" << value << "'" << endl;
00353                         break;
00354                     case DrBase::String:
00355                         if (!value.isEmpty())
00356                             t << oit.current()->name() << "='" << value << "'" << endl;
00357                         break;
00358                     default:
00359                         break;
00360                 }
00361             }
00362         }
00363         return true;
00364     }
00365     else
00366     {
00367         manager()->setErrorMsg(i18n("Unable to create the file %1.").arg(f.name()));
00368         return false;
00369     }
00370 }
00371 
00372 bool ApsHandler::removePrinter(KMPrinter*, PrintcapEntry *entry)
00373 {
00374     QString path(sysconfDir() + "/" + entry->name);
00375     QFile::remove(path + "/smbclient.conf");
00376     QFile::remove(path + "/netware.conf");
00377     QFile::remove(path + "/apsfilterrc");
00378     if (!QDir(path).rmdir(path))
00379     {
00380         manager()->setErrorMsg(i18n("Unable to remove directory %1.").arg(path));
00381         return false;
00382     }
00383     return true;
00384 }
00385 
00386 QString ApsHandler::printOptions(KPrinter *printer)
00387 {
00388     QString optstr;
00389     QMap<QString,QString>   opts = printer->options();
00390     for (QMap<QString,QString>::ConstIterator it=opts.begin(); it!=opts.end(); ++it)
00391     {
00392         if (it.key().startsWith("kde-") || it.key().startsWith("_kde-") || it.key().startsWith( "app-" ))
00393             continue;
00394         optstr.append((*it)).append(":");
00395     }
00396     if (!optstr.isEmpty())
00397     {
00398         optstr = optstr.left(optstr.length()-1);
00399         if (LprSettings::self()->mode() == LprSettings::LPR)
00400             optstr.prepend("-C '").append("'");
00401         else
00402             optstr.prepend("-Z '").append("'");
00403     }
00404     return optstr;
00405 }
KDE Home | KDE Accessibility Home | Description of Access Keys