cupsddialog.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 "cupsddialog.h"
00021 
00022 #include "cupsdpage.h"
00023 #include "cupsdconf.h"
00024 #include "cupsdsplash.h"
00025 #include "cupsdserverpage.h"
00026 #include "cupsdlogpage.h"
00027 #include "cupsdjobspage.h"
00028 #include "cupsdfilterpage.h"
00029 #include "cupsddirpage.h"
00030 #include "cupsdnetworkpage.h"
00031 #include "cupsdbrowsingpage.h"
00032 #include "cupsdsecuritypage.h"
00033 
00034 #include <qdir.h>
00035 #include <qvbox.h>
00036 #include <kmessagebox.h>
00037 #include <klocale.h>
00038 #include <qfile.h>
00039 #include <qfileinfo.h>
00040 #include <kglobal.h>
00041 #include <kiconloader.h>
00042 #include <qstringlist.h>
00043 #include <qwhatsthis.h>
00044 #include <kio/passdlg.h>
00045 #include <kguiitem.h>
00046 #include <kprocess.h>
00047 
00048 #include <signal.h>
00049 #include <cups/cups.h>
00050 
00051 static bool dynamically_loaded = false;
00052 static QString  pass_string;
00053 
00054 extern "C"
00055 {
00056 #include "cups-util.h"
00057     KDEPRINT_EXPORT bool restartServer(QString& msg)
00058     {
00059         return CupsdDialog::restartServer(msg);
00060     }
00061     KDEPRINT_EXPORT bool configureServer(QWidget *parent, QString& msg)
00062     {
00063         dynamically_loaded = true;
00064         bool result = CupsdDialog::configure(QString::null, parent, &msg);
00065         dynamically_loaded = false;
00066         return result;
00067     }
00068 }
00069 
00070 int getServerPid()
00071 {
00072     QDir    dir("/proc",QString::null,QDir::Name,QDir::Dirs);
00073     for (uint i=0;i<dir.count();i++)
00074     {
00075         if (dir[i] == "." || dir[i] == ".." || dir[i] == "self") continue;
00076         QFile   f("/proc/" + dir[i] + "/cmdline");
00077         if (f.exists() && f.open(IO_ReadOnly))
00078         {
00079             QTextStream t(&f);
00080             QString line;
00081             t >> line;
00082             f.close();
00083             if (line.right(5) == "cupsd" ||
00084                 line.right(6).left(5) == "cupsd")   // second condition for 2.4.x kernels
00085                                 // which add a null byte at the end
00086                 return dir[i].toInt();
00087         }
00088     }
00089     return (-1);
00090 }
00091 
00092 const char* getPassword(const char*)
00093 {
00094     QString user(cupsUser());
00095     QString pass;
00096 
00097     if (KIO::PasswordDialog::getNameAndPassword(user, pass, NULL) == QDialog::Accepted)
00098     {
00099         cupsSetUser(user.latin1());
00100         pass_string = pass;
00101         if (pass_string.isEmpty())
00102             return "";
00103         else
00104             return pass_string.latin1();
00105     }
00106     else
00107         return NULL;
00108 }
00109 
00110 //---------------------------------------------------
00111 
00112 CupsdDialog::CupsdDialog(QWidget *parent, const char *name)
00113     : KDialogBase(IconList, "", Ok|Cancel|User1, Ok, parent, name, true, true, KGuiItem(i18n("Short Help"), "help"))
00114 {
00115     KGlobal::iconLoader()->addAppDir("kdeprint");
00116     KGlobal::locale()->insertCatalogue("cupsdconf");
00117 
00118     setShowIconsInTreeList(true);
00119     setRootIsDecorated(false);
00120 
00121     pagelist_.setAutoDelete(false);
00122     filename_ = "";
00123     conf_ = 0;
00124     constructDialog();
00125 
00126         setCaption(i18n("CUPS Server Configuration"));
00127 
00128         //resize(500, 400);
00129 }
00130 
00131 CupsdDialog::~CupsdDialog()
00132 {
00133         delete conf_;
00134 }
00135 
00136 void CupsdDialog::addConfPage(CupsdPage *page)
00137 {
00138     QPixmap icon = KGlobal::instance()->iconLoader()->loadIcon(
00139                                                                page->pixmap(),
00140                                                                    KIcon::NoGroup,
00141                                                                    KIcon::SizeMedium
00142                                                               );
00143 
00144     QVBox   *box = addVBoxPage(page->pageLabel(), page->header(), icon);
00145     page->reparent(box, QPoint(0,0));
00146     pagelist_.append(page);
00147 }
00148 
00149 void CupsdDialog::constructDialog()
00150 {
00151     addConfPage(new CupsdSplash(0));
00152     addConfPage(new CupsdServerPage(0));
00153     addConfPage(new CupsdNetworkPage(0));
00154     addConfPage(new CupsdSecurityPage(0));
00155     addConfPage(new CupsdLogPage(0));
00156     addConfPage(new CupsdJobsPage(0));
00157     addConfPage(new CupsdFilterPage(0));
00158     addConfPage(new CupsdDirPage(0));
00159     addConfPage(new CupsdBrowsingPage(0));
00160 
00161     conf_ = new CupsdConf();
00162     for (pagelist_.first();pagelist_.current();pagelist_.next())
00163         {
00164                 pagelist_.current()->setInfos(conf_);
00165         }
00166 }
00167 
00168 bool CupsdDialog::setConfigFile(const QString& filename)
00169 {
00170     filename_ = filename;
00171     if (!conf_->loadFromFile(filename_))
00172     {
00173         KMessageBox::error(this, i18n("Error while loading configuration file!"), i18n("CUPS Configuration Error"));
00174         return false;
00175     }
00176     if (conf_->unknown_.count() > 0)
00177     {
00178         // there were some unknown options, warn the user
00179         QString msg;
00180         for (QValueList< QPair<QString,QString> >::ConstIterator it=conf_->unknown_.begin(); it!=conf_->unknown_.end(); ++it)
00181             msg += ((*it).first + " = " + (*it).second + "<br>");
00182         msg.prepend("<p>" + i18n("Some options were not recognized by this configuration tool. "
00183                                   "They will be left untouched and you won't be able to change them.") + "</p>");
00184         KMessageBox::sorry(this, msg, i18n("Unrecognized Options"));
00185     }
00186     bool    ok(true);
00187     QString msg;
00188     for (pagelist_.first();pagelist_.current() && ok;pagelist_.next())
00189         ok = pagelist_.current()->loadConfig(conf_, msg);
00190     if (!ok)
00191     {
00192         KMessageBox::error(this, msg.prepend("<qt>").append("</qt>"), i18n("CUPS Configuration Error"));
00193         return false;
00194     }
00195     return true;
00196 }
00197 
00198 bool CupsdDialog::restartServer(QString& msg)
00199 {
00200     int serverPid = getServerPid();
00201         msg.truncate(0);
00202     if (serverPid <= 0)
00203     {
00204         msg = i18n("Unable to find a running CUPS server");
00205     }
00206     else
00207     {
00208                 bool success = false;
00209                 if (getuid() == 0 )
00210                         success = (::kill(serverPid, SIGHUP) == 0);
00211                 else
00212                 {
00213                         KProcess proc;
00214                         proc << "kdesu" << "-c" << "kill -SIGHUP " + QString::number( serverPid );
00215                         success = proc.start( KProcess::Block ) && proc.normalExit();
00216                 }
00217                 if( !success )    
00218             msg = i18n("Unable to restart CUPS server (pid = %1)").arg(serverPid);
00219     }
00220         return (msg.isEmpty());
00221 }
00222 
00223 bool CupsdDialog::configure(const QString& filename, QWidget *parent, QString *msg)
00224 {
00225     bool needUpload(false);
00226     QString errormsg;
00227     bool result = true;
00228 
00229     // init password dialog if needed
00230     if (!dynamically_loaded)
00231         cupsSetPasswordCB(getPassword);
00232 
00233     // load config file from server
00234     QString fn(filename);
00235     if (fn.isEmpty())
00236     {
00237         fn = cupsGetConf();
00238         if (fn.isEmpty())
00239             errormsg = i18n("Unable to retrieve configuration file from the CUPS server. "
00240                         "You probably don't have the access permissions to perform this operation.");
00241         else needUpload = true;
00242     }
00243 
00244     // check read state (only if needed)
00245     if (!fn.isEmpty())
00246     {
00247         QFileInfo   fi(fn);
00248         if (!fi.exists() || !fi.isReadable() || !fi.isWritable())
00249             errormsg = i18n("Internal error: file '%1' not readable/writable!").arg(fn);
00250         // check file size
00251         if (fi.size() == 0)
00252             errormsg = i18n("Internal error: empty file '%1'!").arg(fn);
00253     }
00254 
00255     if (!errormsg.isEmpty())
00256     {
00257         if ( !dynamically_loaded )
00258             KMessageBox::error(parent, errormsg.prepend("<qt>").append("</qt>"), i18n("CUPS Configuration Error"));
00259         result = false;
00260     }
00261     else
00262     {
00263         KGlobal::locale()->insertCatalogue("cupsdconf"); // Must be before dialog is created to translate "Short Help"
00264         CupsdDialog dlg(parent);
00265         if (dlg.setConfigFile(fn) && dlg.exec())
00266         {
00267             QCString    encodedFn = QFile::encodeName(fn);
00268             if (!needUpload)
00269                 KMessageBox::information(parent,
00270                     i18n("The config file has not been uploaded to the "
00271                          "CUPS server. The daemon will not be restarted."));
00272             else if (!cupsPutConf(encodedFn.data()))
00273             {
00274                 errormsg = i18n("Unable to upload the configuration file to CUPS server. "
00275                          "You probably don't have the access permissions to perform this operation.");
00276                 if ( !dynamically_loaded )
00277                     KMessageBox::error(parent, errormsg, i18n("CUPS configuration error"));
00278                 result = false;
00279             }
00280         }
00281 
00282     }
00283     if (needUpload)
00284         QFile::remove(fn);
00285 
00286     if ( msg )
00287         *msg = errormsg;
00288     return result;
00289 }
00290 
00291 void CupsdDialog::slotOk()
00292 {
00293     if (conf_ && !filename_.isEmpty())
00294     { // try to save the file
00295         bool    ok(true);
00296         QString msg;
00297         CupsdConf   newconf_;
00298         for (pagelist_.first();pagelist_.current() && ok;pagelist_.next())
00299             ok = pagelist_.current()->saveConfig(&newconf_, msg);
00300         // copy unknown options
00301         newconf_.unknown_ = conf_->unknown_;
00302         if (!ok)
00303         {
00304             ; // do nothing
00305         }
00306         else if (!newconf_.saveToFile(filename_))
00307         {
00308             msg = i18n("Unable to write configuration file %1").arg(filename_);
00309                 ok = false;
00310         }
00311         if (!ok)
00312         {
00313             KMessageBox::error(this, msg.prepend("<qt>").append("</qt>"), i18n("CUPS Configuration Error"));
00314         }
00315         else
00316             KDialogBase::slotOk();
00317     }
00318 }
00319 
00320 void CupsdDialog::slotUser1()
00321 {
00322     QWhatsThis::enterWhatsThisMode();
00323 }
00324 
00325 int CupsdDialog::serverPid()
00326 {
00327     return getServerPid();
00328 }
00329 
00330 int CupsdDialog::serverOwner()
00331 {
00332     int pid = getServerPid();
00333     if (pid > 0)
00334     {
00335         QString str;
00336         str.sprintf("/proc/%d/status",pid);
00337         QFile   f(str);
00338         if (f.exists() && f.open(IO_ReadOnly))
00339         {
00340             QTextStream t(&f);
00341             while (!t.eof())
00342             {
00343                 str = t.readLine();
00344                 if (str.find("Uid:",0,false) == 0)
00345                 {
00346                     QStringList list = QStringList::split('\t', str, false);
00347                     if (list.count() >= 2)
00348                     {
00349                         bool    ok;
00350                         int u = list[1].toInt(&ok);
00351                         if (ok) return u;
00352                     }
00353                 }
00354             }
00355         }
00356     }
00357     return (-1);
00358 }
00359 
00360 #include "cupsddialog.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys