TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
8.9KB

  1. /*
  2. * This file is part of the KDE libraries
  3. * Copyright (c) 2001 Michael Goffioul <tdeprint@swing.be>
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Library General Public
  7. * License version 2 as published by the Free Software Foundation.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public License
  15. * along with this library; see the file COPYING.LIB. If not, write to
  16. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301, USA.
  18. **/
  19. #include "tdeprintd.h"
  20. #include "kprintprocess.h"
  21. #include <tqfile.h>
  22. #include <klocale.h>
  23. #include <knotifyclient.h>
  24. #include <kmessagebox.h>
  25. #include <kdebug.h>
  26. #include <dcopclient.h>
  27. #include <kio/passdlg.h>
  28. #include <kio/authinfo.h>
  29. #include <tqlabel.h>
  30. #include <kpushbutton.h>
  31. #include <kiconloader.h>
  32. #include <kstandarddirs.h>
  33. #include <twin.h>
  34. #include <kapplication.h>
  35. #include <tqlayout.h>
  36. #include <tqtimer.h>
  37. #include <tqregexp.h>
  38. #include <unistd.h>
  39. extern "C"
  40. {
  41. KDE_EXPORT KDEDModule *create_tdeprintd(const TQCString& name)
  42. {
  43. return new KDEPrintd(name);
  44. }
  45. }
  46. class StatusWindow : public TQWidget
  47. {
  48. public:
  49. StatusWindow(int pid = -1);
  50. void setMessage(const TQString&);
  51. int pid() const { return m_pid; }
  52. private:
  53. TQLabel *m_label;
  54. TQPushButton *m_button;
  55. int m_pid;
  56. TQLabel *m_icon;
  57. };
  58. StatusWindow::StatusWindow(int pid)
  59. : TQWidget(NULL, "StatusWindow", (WFlags)(WType_TopLevel|WStyle_DialogBorder|WStyle_StaysOnTop|WDestructiveClose)), m_pid(pid)
  60. {
  61. m_label = new TQLabel(this);
  62. m_label->setAlignment(AlignCenter);
  63. m_button = new KPushButton(KStdGuiItem::close(), this);
  64. m_icon = new TQLabel(this);
  65. m_icon->setPixmap(DesktopIcon("fileprint"));
  66. m_icon->setAlignment(AlignCenter);
  67. KWin::setIcons(winId(), *(m_icon->pixmap()), SmallIcon("fileprint"));
  68. TQGridLayout *l0 = new TQGridLayout(this, 2, 3, 10, 10);
  69. l0->setRowStretch(0, 1);
  70. l0->setColStretch(1, 1);
  71. l0->addMultiCellWidget(m_label, 0, 0, 1, 2);
  72. l0->addWidget(m_button, 1, 2);
  73. l0->addMultiCellWidget(m_icon, 0, 1, 0, 0);
  74. connect(m_button, TQT_SIGNAL(clicked()), TQT_SLOT(hide()));
  75. resize(200, 50);
  76. }
  77. void StatusWindow::setMessage(const TQString& msg)
  78. {
  79. //QSize oldSz = size();
  80. m_label->setText(msg);
  81. //QSize sz = m_label->sizeHint();
  82. //sz += TQSize(layout()->margin()*2, layout()->margin()*2+layout()->spacing()+m_button->sizeHint().height());
  83. // dialog will never be smaller
  84. //sz = sz.expandedTo(oldSz);
  85. //resize(sz);
  86. //setFixedSize(sz);
  87. //layout()->activate();
  88. }
  89. //*****************************************************************************************************
  90. KDEPrintd::KDEPrintd(const TQCString& obj)
  91. : KDEDModule(obj)
  92. {
  93. m_processpool.setAutoDelete(true);
  94. m_windows.setAutoDelete(false);
  95. m_requestsPending.setAutoDelete( true );
  96. }
  97. KDEPrintd::~KDEPrintd()
  98. {
  99. }
  100. int KDEPrintd::print(const TQString& cmd, const TQStringList& files, bool remflag)
  101. {
  102. KPrintProcess *proc = new KPrintProcess;
  103. TQString command(cmd);
  104. TQRegExp re( "\\$out\\{([^}]*)\\}" );
  105. connect(proc,TQT_SIGNAL(printTerminated(KPrintProcess*)),TQT_SLOT(slotPrintTerminated(KPrintProcess*)));
  106. connect(proc,TQT_SIGNAL(printError(KPrintProcess*,const TQString&)),TQT_SLOT(slotPrintError(KPrintProcess*,const TQString&)));
  107. proc->setCommand( command );
  108. if ( re.search( command ) != -1 )
  109. {
  110. KURL url( re.cap( 1 ) );
  111. if ( !url.isLocalFile() )
  112. {
  113. TQString tmpFilename = locateLocal( "tmp", "tdeprint_" + kapp->randomString( 8 ) );
  114. command.replace( re, KProcess::quote( tmpFilename ) );
  115. proc->setOutput( re.cap( 1 ) );
  116. proc->setTempOutput( tmpFilename );
  117. }
  118. else
  119. command.replace( re, KProcess::quote( re.cap( 1 ) ) );
  120. }
  121. if ( checkFiles( command, files ) )
  122. {
  123. *proc << command;
  124. if ( remflag )
  125. proc->setTempFiles( files );
  126. if ( proc->print() )
  127. {
  128. m_processpool.append( proc );
  129. return ( int )proc->pid();
  130. }
  131. }
  132. delete proc;
  133. return -1;
  134. }
  135. void KDEPrintd::slotPrintTerminated( KPrintProcess *proc )
  136. {
  137. m_processpool.removeRef( proc );
  138. }
  139. void KDEPrintd::slotPrintError( KPrintProcess *proc, const TQString& msg )
  140. {
  141. KNotifyClient::event("printerror",i18n("<p><nobr>A print error occurred. Error message received from system:</nobr></p><br>%1").arg(msg));
  142. m_processpool.removeRef( proc );
  143. }
  144. TQString KDEPrintd::openPassDlg(const TQString& user)
  145. {
  146. TQString user_(user), pass_, result;
  147. if (KIO::PasswordDialog::getNameAndPassword(user_, pass_, NULL) == KDialog::Accepted)
  148. result.append(user_).append(":").append(pass_);
  149. return result;
  150. }
  151. bool KDEPrintd::checkFiles(TQString& cmd, const TQStringList& files)
  152. {
  153. for (TQStringList::ConstIterator it=files.begin(); it!=files.end(); ++it)
  154. if (::access(TQFile::encodeName(*it).data(), R_OK) != 0)
  155. {
  156. if (KMessageBox::warningContinueCancel(0,
  157. i18n("Some of the files to print are not readable by the TDE "
  158. "print daemon. This may happen if you are trying to print "
  159. "as a different user to the one currently logged in. To continue "
  160. "printing, you need to provide root's password."),
  161. TQString::null,
  162. i18n("Provide root's Password"),
  163. "provideRootsPassword") == KMessageBox::Continue)
  164. {
  165. cmd = ("tdesu -c " + KProcess::quote(cmd));
  166. break;
  167. }
  168. else
  169. return false;
  170. }
  171. return true;
  172. }
  173. void KDEPrintd::statusMessage(const TQString& msg, int pid, const TQString& appName)
  174. {
  175. StatusWindow *w = m_windows.find(pid);
  176. if (!w && !msg.isEmpty())
  177. {
  178. w = new StatusWindow(pid);
  179. if (appName.isEmpty())
  180. w->setCaption(i18n("Printing Status - %1").arg("(pid="+TQString::number(pid)+")"));
  181. else
  182. w->setCaption(i18n("Printing Status - %1").arg(appName));
  183. connect(w, TQT_SIGNAL(destroyed()), TQT_SLOT(slotClosed()));
  184. w->show();
  185. m_windows.insert(pid, w);
  186. }
  187. if (w)
  188. {
  189. if (!msg.isEmpty())
  190. w->setMessage(msg);
  191. else
  192. w->close();
  193. }
  194. }
  195. void KDEPrintd::slotClosed()
  196. {
  197. const StatusWindow *w = static_cast<const StatusWindow*>(sender());
  198. if (w)
  199. {
  200. m_windows.remove(w->pid());
  201. }
  202. }
  203. //******************************************************************************************
  204. class KDEPrintd::Request
  205. {
  206. public:
  207. DCOPClientTransaction *transaction;
  208. TQString user;
  209. TQString uri;
  210. int seqNbr;
  211. };
  212. TQString KDEPrintd::requestPassword( const TQString& user, const TQString& host, int port, int seqNbr )
  213. {
  214. Request *req = new Request;
  215. req->user = user;
  216. req->uri = "print://" + user + "@" + host + ":" + TQString::number(port);
  217. req->seqNbr = seqNbr;
  218. req->transaction = callingDcopClient()->beginTransaction();
  219. m_requestsPending.append( req );
  220. if ( m_requestsPending.count() == 1 )
  221. TQTimer::singleShot( 0, this, TQT_SLOT( processRequest() ) );
  222. return "::";
  223. }
  224. void KDEPrintd::processRequest()
  225. {
  226. if ( m_requestsPending.count() == 0 )
  227. return;
  228. Request *req = m_requestsPending.first();
  229. KIO::AuthInfo info;
  230. TQByteArray params, reply;
  231. TQCString replyType;
  232. TQString authString( "::" );
  233. info.username = req->user;
  234. info.keepPassword = true;
  235. info.url = req->uri;
  236. info.comment = i18n( "Printing system" );
  237. TQDataStream input( params, IO_WriteOnly );
  238. input << info << TQString(i18n( "Authentication failed (user name=%1)" ).arg( info.username )) << 0L << (long int) req->seqNbr;
  239. if ( callingDcopClient()->call( "kded", "kpasswdserver", "queryAuthInfo(KIO::AuthInfo,TQString,long int,long int)",
  240. params, replyType, reply ) )
  241. {
  242. if ( replyType == "KIO::AuthInfo" )
  243. {
  244. TQDataStream output( reply, IO_ReadOnly );
  245. KIO::AuthInfo result;
  246. int seqNbr;
  247. output >> result >> seqNbr;
  248. if ( result.isModified() )
  249. authString = result.username + ":" + result.password + ":" + TQString::number( seqNbr );
  250. }
  251. else
  252. kdWarning( 500 ) << "DCOP returned type error, expected KIO::AuthInfo, received " << replyType << endl;
  253. }
  254. else
  255. kdWarning( 500 ) << "Cannot communicate with kded_kpasswdserver" << endl;
  256. TQByteArray outputData;
  257. TQDataStream output( outputData, IO_WriteOnly );
  258. output << authString;
  259. replyType = "TQString";
  260. callingDcopClient()->endTransaction( req->transaction, replyType, outputData );
  261. m_requestsPending.remove( ( unsigned int )0 );
  262. if ( m_requestsPending.count() > 0 )
  263. TQTimer::singleShot( 0, this, TQT_SLOT( processRequest() ) );
  264. }
  265. void KDEPrintd::initPassword( const TQString& user, const TQString& passwd, const TQString& host, int port )
  266. {
  267. TQByteArray params, reply;
  268. TQCString replyType;
  269. KIO::AuthInfo info;
  270. info.username = user;
  271. info.password = passwd;
  272. info.url = "print://" + user + "@" + host + ":" + TQString::number(port);
  273. TQDataStream input( params, IO_WriteOnly );
  274. input << info << ( long int )0;
  275. if ( !callingDcopClient()->call( "kded", "kpasswdserver", "addAuthInfo(KIO::AuthInfo,long int)",
  276. params, replyType, reply ) )
  277. kdWarning( 500 ) << "Unable to initialize password, cannot communicate with kded_kpasswdserver" << endl;
  278. }
  279. #include "tdeprintd.moc"