00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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 <QtCore/QFile>
00030 #include <QtCore/QDir>
00031 #include <QtCore/QTextStream>
00032 #include <QtCore/QStack>
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").endsWith("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 if (!shortmode) {
00063 QMap<QString, QString> opts = loadResources(entry);
00064 if (opts.contains("PRINTER")) {
00065 prt->setDescription(i18n("APS Driver (%1)", opts["PRINTER"]));
00066 prt->setDriverInfo(prt->description());
00067 }
00068 }
00069 if (prt->device().isEmpty()) {
00070 QString prot;
00071 QString smbname(sysconfDir() + '/' + prt->printerName() + "/smbclient.conf");
00072 QString ncpname(sysconfDir() + '/' + prt->printerName() + "/netware.conf");
00073 if (QFile::exists(smbname)) {
00074 QMap<QString, QString> opts = loadVarFile(smbname);
00075 if (opts.count() == 0)
00076 prt->setDevice("smb://<unknown>/<unknown>");
00077 else {
00078 prt->setDevice(buildSmbURI(
00079 opts[ "SMB_WORKGROUP" ],
00080 opts[ "SMB_SERVER" ],
00081 opts[ "SMB_PRINTER" ],
00082 opts[ "SMB_USER" ],
00083 opts[ "SMB_PASSWD" ]));
00084 }
00085 prot = "smb";
00086 } else if (QFile::exists(ncpname)) {
00087 QMap<QString, QString> opts = loadVarFile(ncpname);
00088 if (opts.count() == 0)
00089 prt->setDevice("ncp://<unknown>/<unknown>");
00090 else {
00091 QString uri = buildSmbURI(
00092 QString(),
00093 opts[ "NCP_SERVER" ],
00094 opts[ "NCP_PRINTER" ],
00095 opts[ "NCP_USER" ],
00096 opts[ "NCP_PASSWD" ]);
00097 uri.replace(0, 3, "ncp");
00098 prt->setDevice(uri);
00099 }
00100 prot = "ncp";
00101 }
00102 if (!prt->device().isEmpty())
00103 prt->setLocation(i18n("Network printer (%1)", prot));
00104 }
00105 return true;
00106 }
00107 return false;
00108 }
00109
00110 QString ApsHandler::sysconfDir()
00111 {
00112 return QFile::encodeName("/etc/apsfilter");
00113 }
00114
00115 QString ApsHandler::shareDir()
00116 {
00117 return driverDirectory();
00118 }
00119
00120 QString ApsHandler::driverDirInternal()
00121 {
00122 return locateDir("apsfilter/setup", "/usr/share:/usr/local/share:/opt/share");
00123 }
00124
00125 QMap<QString, QString> ApsHandler::loadResources(PrintcapEntry *entry)
00126 {
00127 return loadVarFile(sysconfDir() + '/' + (entry ? entry->name : QString()) + "/apsfilterrc");
00128 }
00129
00130 QMap<QString, QString> ApsHandler::loadVarFile(const QString& filename)
00131 {
00132 QMap<QString, QString> opts;
00133 QFile f(filename);
00134 if (f.open(QIODevice::ReadOnly)) {
00135 QTextStream t(&f);
00136 QString line;
00137 int p(-1);
00138 while (!t.atEnd()) {
00139 line = t.readLine().trimmed();
00140 if (line.isEmpty() || line[0] == '#' || (p = line.indexOf('=')) == -1)
00141 continue;
00142 QString variable = line.left(p).trimmed();
00143 QString value = line.mid(p + 1).trimmed();
00144 if (!value.isEmpty() && value[0] == '\'')
00145 value = value.mid(1, value.length() - 2);
00146 opts[variable] = value;
00147 }
00148 }
00149 return opts;
00150 }
00151
00152 DrMain* ApsHandler::loadDriver(KMPrinter*, PrintcapEntry *entry, bool config)
00153 {
00154 DrMain *driver = loadApsDriver(config);
00155 if (driver ) {
00156 QMap<QString, QString> opts = loadResources(entry);
00157 if (!config && opts.contains("PAPERSIZE")) {
00158
00159
00160 opts[ "PageSize" ] = opts[ "PAPERSIZE" ];
00161
00162
00163
00164
00165 DrBase *opt = driver->findOption("PageSize");
00166 if (opt)
00167 opt->set("default", opts[ "PageSize" ]);
00168 }
00169 driver->setOptions(opts);
00170 driver->set("gsdriver", opts["PRINTER"]);
00171 }
00172 return driver;
00173 }
00174
00175 DrMain* ApsHandler::loadDbDriver(const QString& s)
00176 {
00177 int p = s.indexOf('/');
00178 DrMain *driver = loadApsDriver(true);
00179 if (driver)
00180 driver->set("gsdriver", s.mid(p + 1));
00181 return driver;
00182 }
00183
00184 DrMain* ApsHandler::loadApsDriver(bool config)
00185 {
00186 DrMain *driver = loadToolDriver(KStandardDirs::locate("data", (config ? "kdeprint/apsdriver1" : "kdeprint/apsdriver2")));
00187 if (driver)
00188 driver->set("text", "APS Common Driver");
00189 return driver;
00190 }
00191
00192 void ApsHandler::reset()
00193 {
00194 m_counter = 1;
00195 }
00196
00197 PrintcapEntry* ApsHandler::createEntry(KMPrinter *prt)
00198 {
00199 QString prot = prt->deviceProtocol();
00200 if (prot != "parallel" && prot != "lpd" && prot != "smb" && prot != "ncp") {
00201 manager()->setErrorMsg(i18n("Unsupported backend: %1.", prot));
00202 return NULL;
00203 }
00204 QString path = sysconfDir() + '/' + prt->printerName();
00205 if (!KStandardDirs::makeDir(path, 0755)) {
00206 manager()->setErrorMsg(i18n("Unable to create directory %1.", path));
00207 return NULL;
00208 }
00209 if (prot == "smb" || prot == "ncp") {
00210
00211 QFile::remove(path + "/smbclient.conf");
00212 QFile::remove(path + "/netware.conf");
00213 QFile f;
00214 if (prot == "smb") {
00215 f.setFileName(path + "/smbclient.conf");
00216 if (f.open(QIODevice::WriteOnly)) {
00217 QTextStream t(&f);
00218 QString work, server, printer, user, passwd;
00219 if (splitSmbURI(prt->device(), work, server, printer, user, passwd)) {
00220 if (work.isEmpty()) {
00221 manager()->setErrorMsg(i18n("Missing element: %1.", QString("Workgroup")));
00222 return NULL;
00223 }
00224 t << "SMB_SERVER='" << server << "'" << endl;
00225 t << "SMB_PRINTER='" << printer << "'" << endl;
00226 t << "SMB_IP=''" << endl;
00227 t << "SMB_WORKGROUP='" << work << "'" << endl;
00228 t << "SMB_BUFFER=1400" << endl;
00229 t << "SMB_FLAGS='-N'" << endl;
00230 if (!user.isEmpty()) {
00231 t << "SMB_USER='" << user << "'" << endl;
00232 t << "SMB_PASSWD='" << passwd << "'" << endl;
00233 }
00234 } else {
00235 manager()->setErrorMsg(i18n("Invalid printer backend specification: %1" , prt->device()));
00236 return NULL;
00237 }
00238 } else {
00239 manager()->setErrorMsg(i18n("Unable to create the file %1.", f.fileName()));
00240 return NULL;
00241 }
00242 } else {
00243 f.setFileName(path + "/netware.conf");
00244 if (f.open(QIODevice::WriteOnly)) {
00245 QString work, server, printer, user, passwd;
00246 QString uri = prt->device();
00247 uri.replace(0, 3, "smb");
00248 if (splitSmbURI(uri, work, server, printer, user, passwd)) {
00249 QTextStream t(&f);
00250 t << "NCP_SERVER='" << server << "'" << endl;
00251 t << "NCP_PRINTER='" << printer << "'" << endl;
00252 if (!user.isEmpty()) {
00253 t << "NCP_USER='" << user << "'" << endl;
00254 t << "NCP_PASSWD='" << passwd << "'" << endl;
00255 }
00256 } else {
00257 manager()->setErrorMsg(i18n("Invalid printer backend specification: %1" , prt->device()));
00258 return NULL;
00259 }
00260 } else {
00261 manager()->setErrorMsg(i18n("Unable to create the file %1.", f.fileName()));
00262 return NULL;
00263 }
00264 }
00265
00266 ::chmod(QFile::encodeName(f.fileName()).data(), S_IRUSR | S_IWUSR);
00267 }
00268 PrintcapEntry *entry = LprHandler::createEntry(prt);
00269 if (!entry) {
00270 entry = new PrintcapEntry;
00271 entry->addField("lp", Field::String, "/dev/null");
00272 }
00273 QString sd = LprSettings::self()->baseSpoolDir() + '/' + prt->printerName();
00274 entry->addField("af", Field::String, sd + "/acct");
00275 entry->addField("lf", Field::String, sd + "/log");
00276 entry->addField("if", Field::String, sysconfDir() + "/basedir/bin/apsfilter");
00277 entry->comment = QString::fromLatin1("# APS%1_BEGIN:printer%2").arg(m_counter).arg(m_counter);
00278 entry->postcomment = QString::fromLatin1("# APS%1_END").arg(m_counter);
00279 m_counter++;
00280 return entry;
00281 }
00282
00283 bool ApsHandler::savePrinterDriver(KMPrinter *prt, PrintcapEntry*, DrMain *driver, bool*)
00284 {
00285 if (driver->get("gsdriver").isEmpty()) {
00286 manager()->setErrorMsg(i18n("The APS driver is not defined."));
00287 return false;
00288 }
00289 QFile f(sysconfDir() + '/' + prt->printerName() + "/apsfilterrc");
00290 if (f.open(QIODevice::WriteOnly)) {
00291 QTextStream t(&f);
00292 t << "# File generated by KDEPrint" << endl;
00293 t << "PRINTER='" << driver->get("gsdriver") << "'" << endl;
00294 QStack<DrGroup*> stack;
00295 stack.push(driver);
00296 while (stack.count() > 0) {
00297 DrGroup *grp = stack.pop();
00298 foreach(DrGroup* subgroup, grp->groups())
00299 stack.push(subgroup);
00300 QString value;
00301 foreach(DrBase* option, grp->options()) {
00302 value = option->valueText();
00303 switch (option->type()) {
00304 case DrBase::Boolean:
00305 if (value == "true")
00306 t << option->name() << "='" << value << "'" << endl;
00307 break;
00308 case DrBase::List:
00309 if (value != "(empty)")
00310 t << option->name() << "='" << value << "'" << endl;
00311 break;
00312 case DrBase::String:
00313 if (!value.isEmpty())
00314 t << option->name() << "='" << value << "'" << endl;
00315 break;
00316 default:
00317 break;
00318 }
00319 }
00320 }
00321 return true;
00322 } else {
00323 manager()->setErrorMsg(i18n("Unable to create the file %1.", f.fileName()));
00324 return false;
00325 }
00326 }
00327
00328 bool ApsHandler::removePrinter(KMPrinter*, PrintcapEntry *entry)
00329 {
00330 QString path(sysconfDir() + '/' + entry->name);
00331 QFile::remove(path + "/smbclient.conf");
00332 QFile::remove(path + "/netware.conf");
00333 QFile::remove(path + "/apsfilterrc");
00334 if (!QDir(path).rmdir(path)) {
00335 manager()->setErrorMsg(i18n("Unable to remove directory %1.", path));
00336 return false;
00337 }
00338 return true;
00339 }
00340
00341 QString ApsHandler::printOptions(KPrinter *printer)
00342 {
00343 QString optstr;
00344 QMap<QString, QString> opts = printer->options();
00345 for (QMap<QString, QString>::ConstIterator it = opts.begin(); it != opts.end(); ++it) {
00346 if (it.key().startsWith("kde-") || it.key().startsWith("_kde-") || it.key().startsWith("app-"))
00347 continue;
00348 optstr.append((*it)).append(":");
00349 }
00350 if (!optstr.isEmpty()) {
00351 optstr = optstr.left(optstr.length() - 1);
00352 if (LprSettings::self()->mode() == LprSettings::LPR)
00353 optstr.prepend("-C '").append("'");
00354 else
00355 optstr.prepend("-Z '").append("'");
00356 }
00357 return optstr;
00358 }