00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
00076 if (!(str=entry->field("cm")).isEmpty())
00077 prt->setDescription(str);
00078
00079
00080
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
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
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
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
00369
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 }