00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#include "kdeprintd.h"
00021
#include "kprintprocess.h"
00022
00023
#include <qfile.h>
00024
#include <klocale.h>
00025
#include <knotifyclient.h>
00026
#include <kmessagebox.h>
00027
#include <kdebug.h>
00028
#include <dcopclient.h>
00029
#include <kio/passdlg.h>
00030
#include <kio/authinfo.h>
00031
#include <qlabel.h>
00032
#include <kpushbutton.h>
00033
#include <kiconloader.h>
00034
#include <kstandarddirs.h>
00035
#include <kwin.h>
00036
#include <kapplication.h>
00037
#include <qlayout.h>
00038
#include <qtimer.h>
00039
#include <qregexp.h>
00040
00041
#include <unistd.h>
00042
00043
extern "C"
00044 {
00045 KDEDModule *create_kdeprintd(
const QCString& name)
00046 {
00047
return new KDEPrintd(name);
00048 }
00049 }
00050
00051
class StatusWindow :
public QWidget
00052 {
00053
public:
00054 StatusWindow(
int pid = -1);
00055
void setMessage(
const QString&);
00056
int pid()
const {
return m_pid; }
00057
00058
private:
00059
QLabel *m_label;
00060
QPushButton *m_button;
00061
int m_pid;
00062
QLabel *m_icon;
00063 };
00064
00065 StatusWindow::StatusWindow(
int pid)
00066 :
QWidget(NULL,
"StatusWindow", WType_TopLevel|WStyle_DialogBorder|WStyle_StaysOnTop|WDestructiveClose), m_pid(pid)
00067 {
00068 m_label =
new QLabel(
this);
00069 m_label->setAlignment(AlignCenter);
00070 m_button =
new KPushButton(KStdGuiItem::close(),
this);
00071 m_icon =
new QLabel(
this);
00072 m_icon->setPixmap(DesktopIcon(
"fileprint"));
00073 m_icon->setAlignment(AlignCenter);
00074 KWin::setIcons(winId(), *(m_icon->pixmap()), SmallIcon(
"fileprint"));
00075
QGridLayout *l0 =
new QGridLayout(
this, 2, 3, 10, 10);
00076 l0->
setRowStretch(0, 1);
00077 l0->
setColStretch(1, 1);
00078 l0->
addMultiCellWidget(m_label, 0, 0, 1, 2);
00079 l0->
addWidget(m_button, 1, 2);
00080 l0->
addMultiCellWidget(m_icon, 0, 1, 0, 0);
00081 connect(m_button, SIGNAL(clicked()), SLOT(hide()));
00082 resize(200, 50);
00083 }
00084
00085
void StatusWindow::setMessage(
const QString& msg)
00086 {
00087
00088 m_label->setText(msg);
00089
00090
00091
00092
00093
00094
00095
00096 }
00097
00098
00099
00100 KDEPrintd::KDEPrintd(
const QCString& obj)
00101 : KDEDModule(obj)
00102 {
00103 m_processpool.setAutoDelete(
true);
00104 m_windows.setAutoDelete(
false);
00105 m_requestsPending.setAutoDelete(
true );
00106 }
00107
00108 KDEPrintd::~KDEPrintd()
00109 {
00110 }
00111
00112
int KDEPrintd::print(
const QString& cmd,
const QStringList& files,
bool remflag)
00113 {
00114 KPrintProcess *proc =
new KPrintProcess;
00115
QString command(cmd);
00116
QRegExp re(
"\\$out\\{([^}]*)\\}" );
00117
00118 connect(proc,SIGNAL(printTerminated(KPrintProcess*)),SLOT(slotPrintTerminated(KPrintProcess*)));
00119 connect(proc,SIGNAL(printError(KPrintProcess*,
const QString&)),SLOT(slotPrintError(KPrintProcess*,
const QString&)));
00120 proc->setCommand( command );
00121
if ( re.search( command ) != -1 )
00122 {
00123 KURL url( re.cap( 1 ) );
00124
if ( !url.isLocalFile() )
00125 {
00126
QString tmpFilename = locateLocal(
"tmp",
"kdeprint_" + kapp->randomString( 8 ) );
00127 command.replace( re, KProcess::quote( tmpFilename ) );
00128 proc->setOutput( re.cap( 1 ) );
00129 proc->setTempOutput( tmpFilename );
00130 }
00131
else
00132 command.replace( re, KProcess::quote( re.cap( 1 ) ) );
00133 }
00134
00135
if ( checkFiles( command, files ) )
00136 {
00137 *proc << command;
00138
if ( remflag )
00139 proc->setTempFiles( files );
00140
if ( proc->print() )
00141 {
00142 m_processpool.append( proc );
00143
return (
int )proc->pid();
00144 }
00145 }
00146
00147
delete proc;
00148
return -1;
00149 }
00150
00151
void KDEPrintd::slotPrintTerminated( KPrintProcess *proc )
00152 {
00153 m_processpool.removeRef( proc );
00154 }
00155
00156
void KDEPrintd::slotPrintError( KPrintProcess *proc,
const QString& msg )
00157 {
00158 KNotifyClient::event(
"printerror",i18n(
"<p><nobr>A print error occurred. Error message received from system:</nobr></p><br>%1").arg(msg));
00159 m_processpool.removeRef( proc );
00160 }
00161
00162
QString KDEPrintd::openPassDlg(
const QString& user)
00163 {
00164
QString user_(user), pass_, result;
00165
if (KIO::PasswordDialog::getNameAndPassword(user_, pass_, NULL) == KDialog::Accepted)
00166 result.
append(user_).append(
":").append(pass_);
00167
return result;
00168 }
00169
00170
bool KDEPrintd::checkFiles(
QString& cmd,
const QStringList& files)
00171 {
00172
for (QStringList::ConstIterator it=files.begin(); it!=files.end(); ++it)
00173
if (::access(
QFile::encodeName(*it).data(), R_OK) != 0)
00174 {
00175
if (KMessageBox::warningContinueCancel(0,
00176 i18n(
"Some of the files to print are not readable by the KDE "
00177
"print daemon. This may happen if you are trying to print "
00178
"as a different user to the one currently logged in. To continue "
00179
"printing, you need to provide root's password."),
00180 QString::null,
00181 i18n(
"Provide root's password"),
00182
"provideRootsPassword") == KMessageBox::Continue)
00183 {
00184 cmd = (
"kdesu -c " + KProcess::quote(cmd));
00185
break;
00186 }
00187
else
00188
return false;
00189 }
00190
return true;
00191 }
00192
00193
void KDEPrintd::statusMessage(
const QString& msg,
int pid,
const QString& appName)
00194 {
00195 StatusWindow *w = m_windows.
find(pid);
00196
if (!w && !msg.
isEmpty())
00197 {
00198 w =
new StatusWindow(pid);
00199
if (appName.
isEmpty())
00200 w->setCaption(i18n(
"Printing Status - %1").arg(
"(pid="+QString::number(pid)+
")"));
00201
else
00202 w->setCaption(i18n(
"Printing Status - %1").arg(appName));
00203 connect(w, SIGNAL(destroyed()), SLOT(slotClosed()));
00204 w->show();
00205 m_windows.insert(pid, w);
00206 }
00207
if (w)
00208 {
00209
if (!msg.
isEmpty())
00210 w->setMessage(msg);
00211
else
00212 w->close();
00213 }
00214 }
00215
00216
void KDEPrintd::slotClosed()
00217 {
00218
const StatusWindow *w = static_cast<const StatusWindow*>(sender());
00219
if (w)
00220 {
00221 m_windows.remove(w->pid());
00222 }
00223 }
00224
00225
00226
00227
class KDEPrintd::Request
00228 {
00229
public:
00230 DCOPClientTransaction *transaction;
00231
QString user;
00232
QString uri;
00233
int seqNbr;
00234 };
00235
00236
QString KDEPrintd::requestPassword(
const QString& user,
const QString& host,
int port,
int seqNbr )
00237 {
00238 Request *req =
new Request;
00239 req->user = user;
00240 req->uri =
"print://" + user +
"@" + host +
":" +
QString::number(port);
00241 req->seqNbr = seqNbr;
00242 req->transaction = callingDcopClient()->beginTransaction();
00243 m_requestsPending.append( req );
00244
if ( m_requestsPending.count() == 1 )
00245
QTimer::singleShot( 0,
this, SLOT( processRequest() ) );
00246
return "::";
00247 }
00248
00249
void KDEPrintd::processRequest()
00250 {
00251
if ( m_requestsPending.count() == 0 )
00252
return;
00253
00254 Request *req = m_requestsPending.first();
00255 KIO::AuthInfo info;
00256
QByteArray params, reply;
00257
QCString replyType;
00258
QString authString(
"::" );
00259
00260 info.username = req->user;
00261 info.keepPassword =
true;
00262 info.url = req->uri;
00263 info.comment = i18n(
"Printing system" );
00264
00265
QDataStream input( params, IO_WriteOnly );
00266 input << info << i18n(
"Authentication failed (user name=%1)" ).arg( info.username ) << 0 << req->seqNbr;
00267
if ( callingDcopClient()->call(
"kded",
"kpasswdserver",
"queryAuthInfo(KIO::AuthInfo,QString,long int,long int)",
00268 params, replyType, reply ) )
00269 {
00270
if ( replyType ==
"KIO::AuthInfo" )
00271 {
00272
QDataStream output( reply, IO_ReadOnly );
00273 KIO::AuthInfo result;
00274
int seqNbr;
00275 output >> result >> seqNbr;
00276
00277
if ( result.isModified() )
00278 authString = result.username +
":" + result.password +
":" +
QString::number( seqNbr );
00279 }
00280
else
00281 kdWarning( 500 ) <<
"DCOP returned type error, expected KIO::AuthInfo, received " << replyType << endl;
00282 }
00283
else
00284 kdWarning( 500 ) <<
"Cannot communicate with kded_kpasswdserver" << endl;
00285
00286
QByteArray outputData;
00287
QDataStream output( outputData, IO_WriteOnly );
00288 output << authString;
00289 replyType =
"QString";
00290 callingDcopClient()->endTransaction( req->transaction, replyType, outputData );
00291
00292 m_requestsPending.remove( (
unsigned int )0 );
00293
if ( m_requestsPending.count() > 0 )
00294
QTimer::singleShot( 0,
this, SLOT( processRequest() ) );
00295 }
00296
00297
void KDEPrintd::initPassword(
const QString& user,
const QString& passwd,
const QString& host,
int port )
00298 {
00299
QByteArray params, reply;
00300
QCString replyType;
00301 KIO::AuthInfo info;
00302
00303 info.username = user;
00304 info.password = passwd;
00305 info.url =
"print://" + user +
"@" + host +
":" +
QString::number(port);
00306
00307
QDataStream input( params, IO_WriteOnly );
00308 input << info << (
long int )0;
00309
00310
if ( !callingDcopClient()->call(
"kded",
"kpasswdserver",
"addAuthInfo(KIO::AuthInfo,long int)",
00311 params, replyType, reply ) )
00312 kdWarning( 500 ) <<
"Unable to initialize password, cannot communicate with kded_kpasswdserver" << endl;
00313 }
00314
00315
#include "kdeprintd.moc"