00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "cupsddialog.h"
00021
00022 #include <config.h>
00023
00024 #include <kdeprint_export.h>
00025
00026 #include "cupsdpage.h"
00027 #include "cupsdconf.h"
00028 #include "cupsdsplash.h"
00029 #include "cupsdserverpage.h"
00030 #include "cupsdlogpage.h"
00031 #include "cupsdjobspage.h"
00032 #include "cupsdfilterpage.h"
00033 #include "cupsddirpage.h"
00034 #include "cupsdnetworkpage.h"
00035 #include "cupsdbrowsingpage.h"
00036 #include "cupsdsecuritypage.h"
00037
00038 #include <QtCore/QDir>
00039 #include <QtGui/QWhatsThis>
00040 #include <kvbox.h>
00041 #include <kmessagebox.h>
00042 #include <klocale.h>
00043 #include <QtCore/QFile>
00044 #include <QtCore/QFileInfo>
00045 #include <QtGui/QIcon>
00046 #include <QtGui/QPixmap>
00047 #include <kglobal.h>
00048 #include <kicon.h>
00049 #include <kiconloader.h>
00050 #include <kcomponentdata.h>
00051 #include <kpagewidgetmodel.h>
00052 #include <QtCore/QStringList>
00053 #include <kpassworddialog.h>
00054 #include <kguiitem.h>
00055 #include <QtCore/Q_PID>
00056
00057 #include <signal.h>
00058 #include <cups/cups.h>
00059
00060 static bool dynamically_loaded = false;
00061 static QString pass_string;
00062
00063 extern "C"
00064 {
00065 #include "cups-util.h"
00066 KDEPRINT_EXPORT bool restartServer(QString& msg) {
00067 return CupsdDialog::restartServer(msg);
00068 }
00069 KDEPRINT_EXPORT bool configureServer(QWidget *parent, QString& msg) {
00070 dynamically_loaded = true;
00071 bool result = CupsdDialog::configure(QString(), parent, &msg);
00072 dynamically_loaded = false;
00073 return result;
00074 }
00075 }
00076
00077 int getServerPid()
00078 {
00079 QDir dir("/proc", QString(), QDir::Name, QDir::Dirs);
00080 for (uint i = 0;i < dir.count();i++) {
00081 if (dir[i] == "." || dir[i] == ".." || dir[i] == "self") continue;
00082 QFile f("/proc/" + dir[i] + "/cmdline");
00083 if (f.exists() && f.open(QIODevice::ReadOnly)) {
00084 QTextStream t(&f);
00085 QString line;
00086 t >> line;
00087 f.close();
00088 if (line.endsWith("cupsd") ||
00089 line.right(6).left(5) == "cupsd")
00090
00091 return dir[i].toInt();
00092 }
00093 }
00094 return (-1);
00095 }
00096
00097 const char* getPassword(const char*)
00098 {
00099 static char buffer[1024];
00100 KPasswordDialog dlg(0L, KPasswordDialog::ShowUsernameLine | KPasswordDialog::UsernameReadOnly);
00101 dlg.setUsername(cupsUser());
00102 if (!dlg.exec())
00103 return NULL;
00104 strlcpy(buffer, dlg.password().toLocal8Bit() , 1024);
00105 return buffer;
00106 }
00107
00108
00109
00110 CupsdDialog::CupsdDialog(QWidget *parent, const char *name)
00111 : KPageDialog(parent)
00112 {
00113 setFaceType(List);
00114 setCaption(i18n("CUPS Server Configuration"));
00115 setButtons(Ok | Cancel | User1);
00116 setButtonGuiItem(User1, KGuiItem(i18n("Short Help"), "help-contents"));
00117 setDefaultButton(Ok);
00118 setObjectName(name);
00119 setModal(true);
00120 showButtonSeparator(true);
00121
00122 KIconLoader::global()->addAppDir("kdeprint4");
00123 KGlobal::locale()->insertCatalog("cupsdconf4");
00124
00125 filename_ = "";
00126 conf_ = 0;
00127 constructDialog();
00128 connect(this, SIGNAL(user1Clicked()), this, SLOT(slotUser1()));
00129 connect(this, SIGNAL(okClicked()), this, SLOT(slotOk()));
00130 }
00131
00132 CupsdDialog::~CupsdDialog()
00133 {
00134 delete conf_;
00135 }
00136
00137 void CupsdDialog::addConfPage(CupsdPage *page)
00138 {
00139 QPixmap icon = KIconLoader::global()->loadIcon(page->pixmap(),
00140 KIconLoader::NoGroup,
00141 KIconLoader::SizeMedium
00142 );
00143
00144 KVBox *box = new KVBox(this);
00145 page->setParent(box);
00146 pagelist_.append(page);
00147
00148 KPageWidgetItem *item = addPage(box, page->pageLabel());
00149 item->setHeader(page->header());
00150 item->setIcon(KIcon(QIcon(icon)));
00151 }
00152
00153 void CupsdDialog::constructDialog()
00154 {
00155 addConfPage(new CupsdSplash(0));
00156 addConfPage(new CupsdServerPage(0));
00157 addConfPage(new CupsdNetworkPage(0));
00158 addConfPage(new CupsdSecurityPage(0));
00159 addConfPage(new CupsdLogPage(0));
00160 addConfPage(new CupsdJobsPage(0));
00161 addConfPage(new CupsdFilterPage(0));
00162 addConfPage(new CupsdDirPage(0));
00163 addConfPage(new CupsdBrowsingPage(0));
00164
00165 conf_ = new CupsdConf();
00166 QListIterator<CupsdPage*> it(pagelist_);
00167 while (it.hasNext())
00168 it.next()->setInfos(conf_);
00169 }
00170
00171 bool CupsdDialog::setConfigFile(const QString& filename)
00172 {
00173 filename_ = filename;
00174 if (!conf_->loadFromFile(filename_)) {
00175 KMessageBox::error(this, i18n("Error while loading configuration file."), i18n("CUPS Configuration Error"));
00176 return false;
00177 }
00178 if (conf_->unknown_.count() > 0) {
00179
00180 QString msg;
00181 for (QList< QPair<QString, QString> >::ConstIterator it = conf_->unknown_.begin(); it != conf_->unknown_.end(); ++it)
00182 msg += ((*it).first + " = " + (*it).second + "<br>");
00183 msg.prepend("<p>" + i18n("Some options were not recognized by this configuration tool. "
00184 "They will be left untouched and you won't be able to change them.") + "</p>");
00185 KMessageBox::sorry(this, msg, i18n("Unrecognized Options"));
00186 }
00187 bool ok(true);
00188 QString msg;
00189 QListIterator<CupsdPage*> it(pagelist_);
00190 while (it.hasNext() && ok)
00191 ok = it.next()->loadConfig(conf_, msg);
00192
00193 if (!ok) {
00194 KMessageBox::error(this, msg.prepend("<qt>").append("</qt>"), i18n("CUPS Configuration Error"));
00195 return false;
00196 }
00197 return true;
00198 }
00199
00200 bool CupsdDialog::restartServer(QString& msg)
00201 {
00202 int serverPid = getServerPid();
00203 msg.truncate(0);
00204 if (serverPid <= 0) {
00205 msg = i18n("Unable to find a running CUPS server");
00206 } else {
00207 bool success = false;
00208 if (getuid() == 0)
00209 success = (::kill(serverPid, SIGHUP) == 0);
00210 else {
00211 success = !QProcess::execute("kdesu",
00212 QStringList() << "-c" << ("kill -SIGHUP " + QString::number(serverPid)));
00213 }
00214 if (!success)
00215 msg = i18n("Unable to restart CUPS server (pid = %1)", serverPid);
00216 }
00217 return (msg.isEmpty());
00218 }
00219
00220 bool CupsdDialog::configure(const QString& filename, QWidget *parent, QString *msg)
00221 {
00222 bool needUpload(false);
00223 QString errormsg;
00224 bool result = true;
00225
00226
00227 if (!dynamically_loaded)
00228 cupsSetPasswordCB(getPassword);
00229
00230
00231 QString fn(filename);
00232 if (fn.isEmpty()) {
00233 fn = cupsGetConf();
00234 if (fn.isEmpty())
00235 errormsg = i18n("Unable to retrieve configuration file from the CUPS server. "
00236 "You probably don't have the access permissions to perform this operation.");
00237 else needUpload = true;
00238 }
00239
00240
00241 if (!fn.isEmpty()) {
00242 QFileInfo fi(fn);
00243 if (!fi.exists() || !fi.isReadable() || !fi.isWritable())
00244 errormsg = i18n("Internal error: file '%1' not readable/writable.", fn);
00245
00246 if (fi.size() == 0)
00247 errormsg = i18n("Internal error: empty file '%1'.", fn);
00248 }
00249
00250 if (!errormsg.isEmpty()) {
00251 if (!dynamically_loaded)
00252 KMessageBox::error(parent, errormsg.prepend("<qt>").append("</qt>"), i18n("CUPS Configuration Error"));
00253 result = false;
00254 } else {
00255 KGlobal::locale()->insertCatalog("cupsdconf4");
00256 CupsdDialog dlg(parent);
00257 if (dlg.setConfigFile(fn) && dlg.exec()) {
00258 QByteArray encodedFn = QFile::encodeName(fn);
00259 if (!needUpload)
00260 KMessageBox::information(parent,
00261 i18n("The config file has not been uploaded to the "
00262 "CUPS server. The daemon will not be restarted."));
00263 else if (!cupsPutConf(encodedFn.data())) {
00264 errormsg = i18n("Unable to upload the configuration file to CUPS server. "
00265 "You probably don't have the access permissions to perform this operation.");
00266 if (!dynamically_loaded)
00267 KMessageBox::error(parent, errormsg, i18n("CUPS configuration error"));
00268 result = false;
00269 }
00270 }
00271
00272 }
00273 if (needUpload)
00274 QFile::remove(fn);
00275
00276 if (msg)
00277 *msg = errormsg;
00278 return result;
00279 }
00280
00281 void CupsdDialog::slotOk()
00282 {
00283 if (conf_ && !filename_.isEmpty()) {
00284 bool ok(true);
00285 QString msg;
00286 CupsdConf newconf_;
00287 QListIterator<CupsdPage*> it(pagelist_);
00288 while (it.hasNext() && ok)
00289 ok = it.next()->saveConfig(&newconf_, msg);
00290
00291 newconf_.unknown_ = conf_->unknown_;
00292 if (!ok) {
00293 ;
00294 } else if (!newconf_.saveToFile(filename_)) {
00295 msg = i18n("Unable to write configuration file %1", filename_);
00296 ok = false;
00297 }
00298 if (!ok) {
00299 KMessageBox::error(this, msg.prepend("<qt>").append("</qt>"), i18n("CUPS Configuration Error"));
00300 } else
00301 KPageDialog::accept();
00302 }
00303 }
00304
00305 void CupsdDialog::slotUser1()
00306 {
00307 QWhatsThis::enterWhatsThisMode();
00308 }
00309
00310 int CupsdDialog::serverPid()
00311 {
00312 return getServerPid();
00313 }
00314
00315 int CupsdDialog::serverOwner()
00316 {
00317 int pid = getServerPid();
00318 if (pid > 0) {
00319 QString str;
00320 str.sprintf("/proc/%d/status", pid);
00321 QFile f(str);
00322 if (f.exists() && f.open(QIODevice::ReadOnly)) {
00323 QTextStream t(&f);
00324 while (!t.atEnd()) {
00325 str = t.readLine();
00326 if (str.indexOf("Uid:", 0, Qt::CaseInsensitive) == 0) {
00327 QStringList list = str.split('\t', QString::SkipEmptyParts);
00328 if (list.count() >= 2) {
00329 bool ok;
00330 int u = list[1].toInt(&ok);
00331 if (ok) return u;
00332 }
00333 }
00334 }
00335 }
00336 }
00337 return (-1);
00338 }
00339
00340 #include "cupsddialog.moc"