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