KHTML
kjavaappletserver.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 * 00003 * Copyright (C) 2000 Richard Moore <rich@kde.org> 00004 * 2000 Wynn Wilkes <wynnw@caldera.com> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Library General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Library General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Library General Public License 00017 * along with this library; see the file COPYING.LIB. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "kjavaappletserver.h" 00023 00024 #include "kjavaappletcontext.h" 00025 #include "kjavaprocess.h" 00026 #include "kjavadownloader.h" 00027 00028 #include <config.h> 00029 00030 #include <kdebug.h> 00031 #include <kconfig.h> 00032 #include <kconfiggroup.h> 00033 #include <klocale.h> 00034 #include <kparts/browserextension.h> 00035 #include <kstandarddirs.h> 00036 00037 #include <kio/job.h> 00038 #include <kio/kprotocolmanager.h> 00039 #include <ksslcertificate.h> 00040 #include <ksslcertchain.h> 00041 #include <kssl.h> 00042 00043 #include <QtCore/QTimer> 00044 #include <QtCore/QPointer> 00045 #include <QtCore/QDir> 00046 #include <QtCore/QEventLoop> 00047 #include <QtGui/QApplication> 00048 #include <QtGui/QLabel> 00049 #include <QtGui/QDialog> 00050 #include <QtGui/QPushButton> 00051 #include <QtGui/QLayout> 00052 #include <QtCore/QRegExp> 00053 00054 #include <stdlib.h> 00055 #include <assert.h> 00056 #include <QtCore/QAbstractEventDispatcher> 00057 00058 #define KJAS_CREATE_CONTEXT (char)1 00059 #define KJAS_DESTROY_CONTEXT (char)2 00060 #define KJAS_CREATE_APPLET (char)3 00061 #define KJAS_DESTROY_APPLET (char)4 00062 #define KJAS_START_APPLET (char)5 00063 #define KJAS_STOP_APPLET (char)6 00064 #define KJAS_INIT_APPLET (char)7 00065 #define KJAS_SHOW_DOCUMENT (char)8 00066 #define KJAS_SHOW_URLINFRAME (char)9 00067 #define KJAS_SHOW_STATUS (char)10 00068 #define KJAS_RESIZE_APPLET (char)11 00069 #define KJAS_GET_URLDATA (char)12 00070 #define KJAS_URLDATA (char)13 00071 #define KJAS_SHUTDOWN_SERVER (char)14 00072 #define KJAS_JAVASCRIPT_EVENT (char)15 00073 #define KJAS_GET_MEMBER (char)16 00074 #define KJAS_CALL_MEMBER (char)17 00075 #define KJAS_PUT_MEMBER (char)18 00076 #define KJAS_DEREF_OBJECT (char)19 00077 #define KJAS_AUDIOCLIP_PLAY (char)20 00078 #define KJAS_AUDIOCLIP_LOOP (char)21 00079 #define KJAS_AUDIOCLIP_STOP (char)22 00080 #define KJAS_APPLET_STATE (char)23 00081 #define KJAS_APPLET_FAILED (char)24 00082 #define KJAS_DATA_COMMAND (char)25 00083 #define KJAS_PUT_URLDATA (char)26 00084 #define KJAS_PUT_DATA (char)27 00085 #define KJAS_SECURITY_CONFIRM (char)28 00086 #define KJAS_SHOW_CONSOLE (char)29 00087 00088 00089 class JSStackFrame; 00090 00091 typedef QMap< int, KJavaKIOJob* > KIOJobMap; 00092 typedef QMap< int, JSStackFrame* > JSStack; 00093 00094 class JSStackFrame { 00095 public: 00096 JSStackFrame(JSStack & stack, QStringList & a) 00097 : jsstack(stack), args(a), ticket(counter++), ready(false), exit (false) { 00098 jsstack.insert( ticket, this ); 00099 } 00100 ~JSStackFrame() { 00101 jsstack.remove( ticket ); 00102 } 00103 JSStack & jsstack; 00104 QStringList & args; 00105 int ticket; 00106 bool ready : 1; 00107 bool exit : 1; 00108 static int counter; 00109 }; 00110 00111 int JSStackFrame::counter = 0; 00112 00113 class KJavaAppletServerPrivate 00114 { 00115 friend class KJavaAppletServer; 00116 private: 00117 KJavaAppletServerPrivate() : kssl( 0L ) {} 00118 ~KJavaAppletServerPrivate() { 00119 delete kssl; 00120 } 00121 int counter; 00122 QMap< int, QPointer<KJavaAppletContext> > contexts; 00123 QString appletLabel; 00124 JSStack jsstack; 00125 KIOJobMap kiojobs; 00126 bool javaProcessFailed; 00127 bool useKIO; 00128 KSSL * kssl; 00129 //int locked_context; 00130 //QValueList<QByteArray> java_requests; 00131 }; 00132 00133 static KJavaAppletServer* self = 0; 00134 00135 KJavaAppletServer::KJavaAppletServer() 00136 : d(new KJavaAppletServerPrivate) 00137 { 00138 process = new KJavaProcess(); 00139 00140 connect( process, SIGNAL(received(const QByteArray&)), 00141 this, SLOT(slotJavaRequest(const QByteArray&)) ); 00142 00143 setupJava( process ); 00144 00145 if( process->startJava() ) { 00146 d->appletLabel = i18n( "Loading Applet" ); 00147 d->javaProcessFailed = false; 00148 } 00149 else { 00150 d->appletLabel = i18n( "Error: java executable not found" ); 00151 d->javaProcessFailed = true; 00152 } 00153 } 00154 00155 KJavaAppletServer::~KJavaAppletServer() 00156 { 00157 quit(); 00158 00159 delete process; 00160 delete d; 00161 } 00162 00163 QString KJavaAppletServer::getAppletLabel() 00164 { 00165 if( self ) 00166 return self->appletLabel(); 00167 else 00168 return QString(); 00169 } 00170 00171 QString KJavaAppletServer::appletLabel() 00172 { 00173 return d->appletLabel; 00174 } 00175 00176 KJavaAppletServer* KJavaAppletServer::allocateJavaServer() 00177 { 00178 if( self == 0 ) 00179 { 00180 self = new KJavaAppletServer(); 00181 self->d->counter = 0; 00182 } 00183 00184 ++(self->d->counter); 00185 return self; 00186 } 00187 00188 void KJavaAppletServer::freeJavaServer() 00189 { 00190 --(self->d->counter); 00191 00192 if( self->d->counter == 0 ) 00193 { 00194 //instead of immediately quitting here, set a timer to kill us 00195 //if there are still no servers- give us one minute 00196 //this is to prevent repeated loading and unloading of the jvm 00197 KConfig config( "konquerorrc" ); 00198 KConfigGroup group = config.group( "Java/JavaScript Settings" ); 00199 if( group.readEntry( "ShutdownAppletServer", true ) ) 00200 { 00201 const int value = group.readEntry( "AppletServerTimeout", 60 ); 00202 QTimer::singleShot( value*1000, self, SLOT( checkShutdown() ) ); 00203 } 00204 } 00205 } 00206 00207 void KJavaAppletServer::checkShutdown() 00208 { 00209 if( self->d->counter == 0 ) 00210 { 00211 delete self; 00212 self = 0; 00213 } 00214 } 00215 00216 void KJavaAppletServer::setupJava( KJavaProcess *p ) 00217 { 00218 KConfig configFile ( "konquerorrc" ); 00219 KConfigGroup config(&configFile, "Java/JavaScript Settings" ); 00220 00221 QString jvm_path = "java"; 00222 00223 QString jPath = config.readPathEntry( "JavaPath", QString() ); 00224 if ( !jPath.isEmpty() && jPath != "java" ) 00225 { 00226 // Cut off trailing slash if any 00227 if( jPath[jPath.length()-1] == '/' ) 00228 jPath.remove(jPath.length()-1, 1); 00229 00230 QDir dir( jPath ); 00231 if( dir.exists( "bin/java" ) ) 00232 { 00233 jvm_path = jPath + "/bin/java"; 00234 } 00235 else if (dir.exists( "/jre/bin/java" ) ) 00236 { 00237 jvm_path = jPath + "/jre/bin/java"; 00238 } 00239 else if( QFile::exists(jPath) ) 00240 { 00241 //check here to see if they entered the whole path the java exe 00242 jvm_path = jPath; 00243 } 00244 } 00245 00246 //check to see if jvm_path is valid and set d->appletLabel accordingly 00247 p->setJVMPath( jvm_path ); 00248 00249 // Prepare classpath variable 00250 QString kjava_class = KStandardDirs::locate("data", "kjava/kjava.jar"); 00251 kDebug(6100) << "kjava_class = " << kjava_class; 00252 if( kjava_class.isNull() ) // Should not happen 00253 return; 00254 00255 QDir dir( kjava_class ); 00256 dir.cdUp(); 00257 kDebug(6100) << "dir = " << dir.absolutePath(); 00258 00259 const QStringList entries = dir.entryList(QDir::nameFiltersFromString( "*.jar" )); 00260 kDebug(6100) << "entries = " << entries.join( ":" ); 00261 00262 QString classes; 00263 { 00264 QStringList::ConstIterator it = entries.begin(); 00265 const QStringList::ConstIterator itEnd = entries.end(); 00266 for( ; it != itEnd; ++it ) 00267 { 00268 if( !classes.isEmpty() ) 00269 classes += ':'; 00270 classes += dir.absoluteFilePath( *it ); 00271 } 00272 } 00273 p->setClasspath( classes ); 00274 00275 // Fix all the extra arguments 00276 const QString extraArgs = config.readEntry( "JavaArgs" ); 00277 p->setExtraArgs( extraArgs ); 00278 00279 if( config.readEntry( "UseSecurityManager", true ) ) 00280 { 00281 QString class_file = KStandardDirs::locate( "data", "kjava/kjava.policy" ); 00282 p->setSystemProperty( "java.security.policy", class_file ); 00283 00284 p->setSystemProperty( "java.security.manager", 00285 "org.kde.kjas.server.KJASSecurityManager" ); 00286 } 00287 00288 d->useKIO = config.readEntry("UseKio", false); 00289 if( d->useKIO ) 00290 { 00291 p->setSystemProperty( "kjas.useKio", QString() ); 00292 } 00293 00294 //check for http proxies... 00295 if( KProtocolManager::useProxy() ) 00296 { 00297 // only proxyForUrl honors automatic proxy scripts 00298 // we do not know the applet url here so we just use a dummy url 00299 // this is a workaround for now 00300 // FIXME 00301 const KUrl dummyURL( "http://www.kde.org/" ); 00302 const QString httpProxy = KProtocolManager::proxyForUrl(dummyURL); 00303 kDebug(6100) << "httpProxy is " << httpProxy; 00304 00305 const KUrl url( httpProxy ); 00306 p->setSystemProperty( "http.proxyHost", url.host() ); 00307 p->setSystemProperty( "http.proxyPort", QString::number( url.port() ) ); 00308 } 00309 00310 //set the main class to run 00311 p->setMainClass( "org.kde.kjas.server.Main" ); 00312 } 00313 00314 void KJavaAppletServer::createContext( int contextId, KJavaAppletContext* context ) 00315 { 00316 // kDebug(6100) << "createContext: " << contextId; 00317 if ( d->javaProcessFailed ) return; 00318 00319 d->contexts.insert( contextId, context ); 00320 00321 QStringList args; 00322 args.append( QString::number( contextId ) ); 00323 process->send( KJAS_CREATE_CONTEXT, args ); 00324 } 00325 00326 void KJavaAppletServer::destroyContext( int contextId ) 00327 { 00328 // kDebug(6100) << "destroyContext: " << contextId; 00329 if ( d->javaProcessFailed ) return; 00330 d->contexts.remove( contextId ); 00331 00332 QStringList args; 00333 args.append( QString::number( contextId ) ); 00334 process->send( KJAS_DESTROY_CONTEXT, args ); 00335 } 00336 00337 bool KJavaAppletServer::createApplet( int contextId, int appletId, 00338 const QString & name, const QString & clazzName, 00339 const QString & baseURL, const QString & user, 00340 const QString & password, const QString & authname, 00341 const QString & codeBase, const QString & jarFile, 00342 QSize size, const QMap<QString,QString>& params, 00343 const QString & windowTitle ) 00344 { 00345 // kDebug(6100) << "createApplet: contextId = " << contextId << endl 00346 // << " appletId = " << appletId << endl 00347 // << " name = " << name << endl 00348 // << " clazzName = " << clazzName << endl 00349 // << " baseURL = " << baseURL << endl 00350 // << " codeBase = " << codeBase << endl 00351 // << " jarFile = " << jarFile << endl 00352 // << " width = " << size.width() << endl 00353 // << " height = " << size.height() << endl; 00354 00355 if ( d->javaProcessFailed ) return false; 00356 00357 QStringList args; 00358 args.append( QString::number( contextId ) ); 00359 args.append( QString::number( appletId ) ); 00360 00361 //it's ok if these are empty strings, I take care of it later... 00362 args.append( name ); 00363 args.append( clazzName ); 00364 args.append( baseURL ); 00365 args.append( user ); 00366 args.append( password ); 00367 args.append( authname ); 00368 args.append( codeBase ); 00369 args.append( jarFile ); 00370 00371 args.append( QString::number( size.width() ) ); 00372 args.append( QString::number( size.height() ) ); 00373 00374 args.append( windowTitle ); 00375 00376 //add on the number of parameter pairs... 00377 const int num = params.count(); 00378 const QString num_params = QString("%1").arg( num, 8 ); 00379 args.append( num_params ); 00380 00381 QMap< QString, QString >::ConstIterator it = params.begin(); 00382 const QMap< QString, QString >::ConstIterator itEnd = params.end(); 00383 00384 for( ; it != itEnd; ++it ) 00385 { 00386 args.append( it.key() ); 00387 args.append( it.value() ); 00388 } 00389 00390 process->send( KJAS_CREATE_APPLET, args ); 00391 00392 return true; 00393 } 00394 00395 void KJavaAppletServer::initApplet( int contextId, int appletId ) 00396 { 00397 if ( d->javaProcessFailed ) return; 00398 QStringList args; 00399 args.append( QString::number( contextId ) ); 00400 args.append( QString::number( appletId ) ); 00401 00402 process->send( KJAS_INIT_APPLET, args ); 00403 } 00404 00405 void KJavaAppletServer::destroyApplet( int contextId, int appletId ) 00406 { 00407 if ( d->javaProcessFailed ) return; 00408 QStringList args; 00409 args.append( QString::number(contextId) ); 00410 args.append( QString::number(appletId) ); 00411 00412 process->send( KJAS_DESTROY_APPLET, args ); 00413 } 00414 00415 void KJavaAppletServer::startApplet( int contextId, int appletId ) 00416 { 00417 if ( d->javaProcessFailed ) return; 00418 QStringList args; 00419 args.append( QString::number(contextId) ); 00420 args.append( QString::number(appletId) ); 00421 00422 process->send( KJAS_START_APPLET, args ); 00423 } 00424 00425 void KJavaAppletServer::stopApplet( int contextId, int appletId ) 00426 { 00427 if ( d->javaProcessFailed ) return; 00428 QStringList args; 00429 args.append( QString::number(contextId) ); 00430 args.append( QString::number(appletId) ); 00431 00432 process->send( KJAS_STOP_APPLET, args ); 00433 } 00434 00435 void KJavaAppletServer::showConsole() { 00436 if ( d->javaProcessFailed ) return; 00437 QStringList args; 00438 process->send( KJAS_SHOW_CONSOLE, args ); 00439 } 00440 00441 void KJavaAppletServer::sendURLData( int loaderID, int code, const QByteArray& data ) 00442 { 00443 QStringList args; 00444 args.append( QString::number(loaderID) ); 00445 args.append( QString::number(code) ); 00446 00447 process->send( KJAS_URLDATA, args, data ); 00448 } 00449 00450 void KJavaAppletServer::removeDataJob( int loaderID ) 00451 { 00452 const KIOJobMap::iterator it = d->kiojobs.find( loaderID ); 00453 if (it != d->kiojobs.end()) { 00454 it.value()->deleteLater(); 00455 d->kiojobs.erase( it ); 00456 } 00457 } 00458 00459 void KJavaAppletServer::quit() 00460 { 00461 const QStringList args; 00462 00463 process->send( KJAS_SHUTDOWN_SERVER, args ); 00464 process->waitForFinished( 10000 ); 00465 } 00466 00467 void KJavaAppletServer::slotJavaRequest( const QByteArray& qb ) 00468 { 00469 // qb should be one command only without the length string, 00470 // we parse out the command and it's meaning here... 00471 QString cmd; 00472 QStringList args; 00473 int index = 0; 00474 const int qb_size = qb.size(); 00475 00476 //get the command code 00477 const char cmd_code = qb[ index++ ]; 00478 ++index; //skip the next sep 00479 00480 //get contextID 00481 QString contextID; 00482 while( qb[index] != 0 && index < qb_size ) 00483 { 00484 contextID += qb[ index++ ]; 00485 } 00486 bool ok; 00487 const int ID_num = contextID.toInt( &ok ); // context id or kio job id 00488 /*if (d->locked_context > -1 && 00489 ID_num != d->locked_context && 00490 (cmd_code == KJAS_JAVASCRIPT_EVENT || 00491 cmd_code == KJAS_APPLET_STATE || 00492 cmd_code == KJAS_APPLET_FAILED)) 00493 { 00494 / * Don't allow requests from other contexts if we're waiting 00495 * on a return value that can trigger JavaScript events 00496 * / 00497 d->java_requests.push_back(qb); 00498 return; 00499 }*/ 00500 ++index; //skip the sep 00501 00502 if (cmd_code == KJAS_PUT_DATA) { 00503 // rest of the data is for kio put 00504 if (ok) { 00505 KIOJobMap::iterator it = d->kiojobs.find( ID_num ); 00506 if (ok && it != d->kiojobs.end()) { 00507 QByteArray qba; 00508 qba = QByteArray::fromRawData(qb.data() + index, qb.size() - index - 1); 00509 it.value()->data(qba); 00510 qba = QByteArray::fromRawData(qb.data() + index, qb.size() - index - 1); 00511 } 00512 kDebug(6100) << "PutData(" << ID_num << ") size=" << qb.size() - index; 00513 } else 00514 kError(6100) << "PutData error " << ok << endl; 00515 return; 00516 } 00517 //now parse out the arguments 00518 while( index < qb_size ) 00519 { 00520 int sep_pos = qb.indexOf( (char) 0, index ); 00521 if (sep_pos < 0) { 00522 kError(6100) << "Missing separation byte" << endl; 00523 sep_pos = qb_size; 00524 } 00525 //kDebug(6100) << "KJavaAppletServer::slotJavaRequest: "<< QString::fromLocal8Bit( qb.data() + index, sep_pos - index ); 00526 args.append( QString::fromLocal8Bit( qb.data() + index, sep_pos - index ) ); 00527 index = sep_pos + 1; //skip the sep 00528 } 00529 //here I should find the context and call the method directly 00530 //instead of emitting signals 00531 switch( cmd_code ) 00532 { 00533 case KJAS_SHOW_DOCUMENT: 00534 cmd = QLatin1String( "showdocument" ); 00535 break; 00536 00537 case KJAS_SHOW_URLINFRAME: 00538 cmd = QLatin1String( "showurlinframe" ); 00539 break; 00540 00541 case KJAS_SHOW_STATUS: 00542 cmd = QLatin1String( "showstatus" ); 00543 break; 00544 00545 case KJAS_RESIZE_APPLET: 00546 cmd = QLatin1String( "resizeapplet" ); 00547 break; 00548 00549 case KJAS_GET_URLDATA: 00550 if (ok && !args.empty() ) { 00551 d->kiojobs.insert(ID_num, new KJavaDownloader(ID_num, args.first())); 00552 kDebug(6100) << "GetURLData(" << ID_num << ") url=" << args.first(); 00553 } else 00554 kError(6100) << "GetURLData error " << ok << " args:" << args.size() << endl; 00555 return; 00556 case KJAS_PUT_URLDATA: 00557 if (ok && !args.empty()) { 00558 KJavaUploader* const job = new KJavaUploader(ID_num, args.first()); 00559 d->kiojobs.insert(ID_num, job); 00560 job->start(); 00561 kDebug(6100) << "PutURLData(" << ID_num << ") url=" << args.first(); 00562 } else 00563 kError(6100) << "PutURLData error " << ok << " args:" << args.size() << endl; 00564 return; 00565 case KJAS_DATA_COMMAND: 00566 if (ok && !args.empty()) { 00567 const int cmd = args.first().toInt( &ok ); 00568 KIOJobMap::iterator it = d->kiojobs.find( ID_num ); 00569 if (ok && it != d->kiojobs.end()) 00570 it.value()->jobCommand( cmd ); 00571 kDebug(6100) << "KIO Data command: " << ID_num << " " << args.first(); 00572 } else 00573 kError(6100) << "KIO Data command error " << ok << " args:" << args.size() << endl; 00574 return; 00575 case KJAS_JAVASCRIPT_EVENT: 00576 cmd = QLatin1String( "JS_Event" ); 00577 00578 if(!args.empty()) { 00579 kDebug(6100) << "Javascript request: "<< contextID 00580 << " code: " << args[0] << endl; 00581 } else { 00582 kError(6100) << "Expected args not to be empty!" << endl; 00583 } 00584 00585 break; 00586 case KJAS_GET_MEMBER: 00587 case KJAS_PUT_MEMBER: 00588 case KJAS_CALL_MEMBER: { 00589 if(!args.empty()) { 00590 const int ticket = args[0].toInt(); 00591 JSStack::iterator it = d->jsstack.find(ticket); 00592 if (it != d->jsstack.end()) { 00593 kDebug(6100) << "slotJavaRequest: " << ticket; 00594 args.pop_front(); 00595 it.value()->args.operator=(args); // just in case .. 00596 it.value()->ready = true; 00597 it.value()->exit = true; 00598 } else 00599 kDebug(6100) << "Error: Missed return member data"; 00600 } else { 00601 kError(6100) << "Expected args not to be empty!" << endl; 00602 } 00603 return; 00604 } 00605 case KJAS_AUDIOCLIP_PLAY: 00606 cmd = QLatin1String( "audioclip_play" ); 00607 if(!args.empty()) 00608 kDebug(6100) << "Audio Play: url=" << args[0]; 00609 else 00610 kError(6100) << "Expected args not to be empty!" << endl; 00611 00612 break; 00613 case KJAS_AUDIOCLIP_LOOP: 00614 cmd = QLatin1String( "audioclip_loop" ); 00615 if(!args.empty()) 00616 kDebug(6100) << "Audio Loop: url=" << args[0]; 00617 else 00618 kError(6100) << "Expected args not to be empty!" << endl; 00619 00620 break; 00621 case KJAS_AUDIOCLIP_STOP: 00622 cmd = QLatin1String( "audioclip_stop" ); 00623 if(!args.empty()) 00624 kDebug(6100) << "Audio Stop: url=" << args[0]; 00625 else 00626 kError(6100) << "Expected args not to be empty!" << endl; 00627 00628 break; 00629 case KJAS_APPLET_STATE: 00630 if(args.size() > 1) 00631 kDebug(6100) << "Applet State Notification for Applet " << args[0] << ". New state=" << args[1]; 00632 else 00633 kError(6100) << "Expected args not to be empty!" << endl; 00634 00635 cmd = QLatin1String( "AppletStateNotification" ); 00636 break; 00637 case KJAS_APPLET_FAILED: 00638 if(args.size() > 1) 00639 kDebug(6100) << "Applet " << args[0] << " Failed: " << args[1]; 00640 else 00641 kError(6100) << "Expected args not to be empty!" << endl; 00642 00643 cmd = QLatin1String( "AppletFailed" ); 00644 break; 00645 case KJAS_SECURITY_CONFIRM: { 00646 if (KSSL::doesSSLWork() && !d->kssl) 00647 d->kssl = new KSSL; 00648 QStringList sl; 00649 QString answer( "invalid" ); 00650 00651 if (!d->kssl) { 00652 answer = "nossl"; 00653 } else if (args.size() > 2) { 00654 const int certsnr = args[1].toInt(); 00655 Q_ASSERT(args.size() > certsnr + 1); 00656 QString text; 00657 QList<KSSLCertificate *> certs; 00658 for (int i = certsnr - 1; i >= 0; --i) { 00659 const QByteArray &arg = args[i + 2].toAscii(); 00660 KSSLCertificate * cert = KSSLCertificate::fromString(arg.constData()); 00661 if (cert) { 00662 certs.prepend(cert); 00663 if (cert->isSigner()) 00664 text += i18n("Signed by (validation: %1)", KSSLCertificate::verifyText(cert->validate())); 00665 else 00666 text += i18n("Certificate (validation: %1)", KSSLCertificate::verifyText(cert->validate())); 00667 text += "\n"; 00668 QString subject = cert->getSubject() + QChar('\n'); 00669 QRegExp reg(QString("/[A-Z]+=")); 00670 int pos = 0; 00671 while ((pos = subject.indexOf(reg, pos)) > -1) 00672 subject.replace(pos, 1, QString("\n ")); 00673 text += subject.mid(1); 00674 } 00675 } 00676 kDebug(6100) << "Security confirm " << args.first() << certs.count(); 00677 if ( !certs.isEmpty() ) { 00678 KSSLCertChain chain; 00679 chain.setChain( certs ); 00680 if ( chain.isValid() ) 00681 answer = PermissionDialog( qApp->activeWindow() ).exec( text, args[0] ); 00682 } 00683 qDeleteAll(certs); 00684 } 00685 sl.push_front( answer ); 00686 sl.push_front( QString::number(ID_num) ); 00687 process->send( KJAS_SECURITY_CONFIRM, sl ); 00688 return; 00689 } 00690 default: 00691 return; 00692 break; 00693 } 00694 00695 00696 if( !ok ) 00697 { 00698 kError(6100) << "could not parse out contextID to call command on" << endl; 00699 return; 00700 } 00701 00702 KJavaAppletContext* const context = d->contexts[ ID_num ]; 00703 if( context ) 00704 context->processCmd( cmd, args ); 00705 else if (cmd != "AppletStateNotification") 00706 kError(6100) << "no context object for this id" << endl; 00707 } 00708 00709 void KJavaAppletServer::killTimers() 00710 { 00711 QAbstractEventDispatcher::instance()->unregisterTimers(this); 00712 } 00713 00714 void KJavaAppletServer::endWaitForReturnData() { 00715 kDebug(6100) << "KJavaAppletServer::endWaitForReturnData"; 00716 killTimers(); 00717 JSStack::iterator it = d->jsstack.begin(); 00718 JSStack::iterator itEnd = d->jsstack.end(); 00719 for (; it != itEnd; ++it) 00720 it.value()->exit = true; 00721 } 00722 00723 void KJavaAppletServer::timerEvent(QTimerEvent *) { 00724 endWaitForReturnData(); 00725 kDebug(6100) << "KJavaAppletServer::timerEvent timeout"; 00726 } 00727 00728 void KJavaAppletServer::waitForReturnData(JSStackFrame * frame) { 00729 kDebug(6100) << ">KJavaAppletServer::waitForReturnData"; 00730 killTimers(); 00731 startTimer(15000); 00732 while (!frame->exit) { 00733 QAbstractEventDispatcher::instance()->processEvents (QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents); 00734 } 00735 if (d->jsstack.size() <= 1) 00736 killTimers(); 00737 kDebug(6100) << "<KJavaAppletServer::waitForReturnData stacksize:" << d->jsstack.size(); 00738 } 00739 00740 bool KJavaAppletServer::getMember(QStringList & args, QStringList & ret_args) { 00741 JSStackFrame frame( d->jsstack, ret_args ); 00742 args.push_front( QString::number(frame.ticket) ); 00743 00744 process->send( KJAS_GET_MEMBER, args ); 00745 waitForReturnData( &frame ); 00746 00747 return frame.ready; 00748 } 00749 00750 bool KJavaAppletServer::putMember( QStringList & args ) { 00751 QStringList ret_args; 00752 JSStackFrame frame( d->jsstack, ret_args ); 00753 args.push_front( QString::number(frame.ticket) ); 00754 00755 process->send( KJAS_PUT_MEMBER, args ); 00756 waitForReturnData( &frame ); 00757 00758 return frame.ready && ret_args.count() > 0 && ret_args[0].toInt(); 00759 } 00760 00761 bool KJavaAppletServer::callMember(QStringList & args, QStringList & ret_args) { 00762 JSStackFrame frame( d->jsstack, ret_args ); 00763 args.push_front( QString::number(frame.ticket) ); 00764 00765 process->send( KJAS_CALL_MEMBER, args ); 00766 waitForReturnData( &frame ); 00767 00768 return frame.ready; 00769 } 00770 00771 void KJavaAppletServer::derefObject( QStringList & args ) { 00772 process->send( KJAS_DEREF_OBJECT, args ); 00773 } 00774 00775 bool KJavaAppletServer::usingKIO() { 00776 return d->useKIO; 00777 } 00778 00779 00780 PermissionDialog::PermissionDialog( QWidget* parent ) 00781 : QObject(parent), m_button("no") 00782 {} 00783 00784 QString PermissionDialog::exec( const QString & cert, const QString & perm ) { 00785 QPointer<QDialog> dialog = new QDialog( static_cast<QWidget*>(parent()) ); 00786 00787 dialog->setObjectName("PermissionDialog"); 00788 QSizePolicy sizeplcy( QSizePolicy::Minimum, QSizePolicy::Minimum); 00789 sizeplcy.setHeightForWidth(dialog->sizePolicy().hasHeightForWidth()); 00790 dialog->setSizePolicy(sizeplcy); 00791 dialog->setModal( true ); 00792 dialog->setWindowTitle( i18n("Security Alert") ); 00793 00794 QVBoxLayout* const dialogLayout = new QVBoxLayout( dialog ); 00795 dialogLayout->setObjectName("dialogLayout"); 00796 00797 dialogLayout->addWidget( new QLabel( i18n("Do you grant Java applet with certificate(s):"), dialog ) ); 00798 dialogLayout->addWidget( new QLabel( cert, dialog ) ); 00799 dialogLayout->addWidget( new QLabel( i18n("the following permission"), dialog ) ); 00800 dialogLayout->addWidget( new QLabel( perm, dialog ) ); 00801 QSpacerItem* const spacer2 = new QSpacerItem( 20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding ); 00802 dialogLayout->addItem( spacer2 ); 00803 00804 QHBoxLayout* const buttonLayout = new QHBoxLayout(); 00805 buttonLayout->setMargin(0); 00806 buttonLayout->setObjectName("buttonLayout"); 00807 00808 QPushButton* const no = new QPushButton( i18n("&No"), dialog ); 00809 no->setDefault( true ); 00810 buttonLayout->addWidget( no ); 00811 00812 QPushButton* const reject = new QPushButton( i18n("&Reject All"), dialog ); 00813 buttonLayout->addWidget( reject ); 00814 00815 QPushButton* const yes = new QPushButton( i18n("&Yes"), dialog ); 00816 buttonLayout->addWidget( yes ); 00817 00818 QPushButton* const grant = new QPushButton( i18n("&Grant All"), dialog ); 00819 buttonLayout->addWidget( grant ); 00820 dialogLayout->addLayout( buttonLayout ); 00821 dialog->resize( dialog->minimumSizeHint() ); 00822 //clearWState( WState_Polished ); 00823 00824 connect( no, SIGNAL( clicked() ), this, SLOT( clicked() ) ); 00825 connect( reject, SIGNAL( clicked() ), this, SLOT( clicked() ) ); 00826 connect( yes, SIGNAL( clicked() ), this, SLOT( clicked() ) ); 00827 connect( grant, SIGNAL( clicked() ), this, SLOT( clicked() ) ); 00828 00829 dialog->exec(); 00830 delete dialog; 00831 00832 return m_button; 00833 } 00834 00835 PermissionDialog::~PermissionDialog() 00836 {} 00837 00838 void PermissionDialog::clicked() 00839 { 00840 m_button = sender()->objectName(); 00841 static_cast<const QWidget*>(sender())->parentWidget()->close(); 00842 } 00843 00844 #include "kjavaappletserver.moc"
KDE 4.6 API Reference