/* This file is part of KDE. Copyright (c) 2004 Cornelius Schumacher Copyright (c) 2004 Tobias Koenig This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // The namespace mapping table is required and associates namespace prefixes // with namespace names: #include "GroupWiseBinding.nsmap" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ksslsocket.h" #include "contactconverter.h" #include "incidenceconverter.h" #include "kcal_resourcegroupwise.h" #include "soapH.h" #include "stdsoap2.h" #include "soapGroupWiseBindingProxy.h" #include #include #include #include #include "groupwiseserver.h" static TQMap mServerMap; int myOpen( struct soap *soap, const char *endpoint, const char *host, int port ) { TQMap::ConstIterator it; it = mServerMap.find( soap ); if ( it == mServerMap.end() ) { soap->error = SOAP_FAULT; return SOAP_INVALID_SOCKET; } return (*it)->gSoapOpen( soap, endpoint, host, port ); } int myClose( struct soap *soap ) { TQMap::ConstIterator it; it = mServerMap.find( soap ); if ( it == mServerMap.end() ) return SOAP_FAULT; return (*it)->gSoapClose( soap ); } int mySendCallback( struct soap *soap, const char *s, size_t n ) { TQMap::ConstIterator it; it = mServerMap.find( soap ); if ( it == mServerMap.end() ) return SOAP_FAULT; return (*it)->gSoapSendCallback( soap, s, n ); } size_t myReceiveCallback( struct soap *soap, char *s, size_t n ) { TQMap::ConstIterator it; it = mServerMap.find( soap ); if ( it == mServerMap.end() ) { kdDebug() << "No soap object found" << endl; soap->error = SOAP_FAULT; return 0; } return (*it)->gSoapReceiveCallback( soap, s, n ); } int GroupwiseServer::gSoapOpen( struct soap *soap, const char *, const char *host, int port ) { // kdDebug() << "GroupwiseServer::gSoapOpen()" << endl; if ( m_sock ) { kdError() << "m_sock non-null: " << (void*)m_sock << endl; delete m_sock; } if ( mSSL ) { // kdDebug() << "Creating KSSLSocket()" << endl; m_sock = new KSSLSocket(); m_sock->setTimeout( KProtocolManager::connectTimeout() ); connect( m_sock, TQT_SIGNAL( sslFailure() ), TQT_SLOT( slotSslError() ) ); } else { m_sock = new KExtendedSocket(); } mErrorText = TQString(); m_sock->reset(); m_sock->setBlockingMode( false ); m_sock->setSocketFlags( KExtendedSocket::inetSocket ); m_sock->setAddress( host, port ); int rc = m_sock->lookup(); if (rc != 0 ) { kdError() << "gSoapOpen: lookup of " << host << " failed " << rc << endl; TQString errorMessage; errorMessage = TQString::tqfromLatin1( strerror( errno ) ); perror( 0 ); soap->error = SOAP_TCP_ERROR; mErrorText = i18n("Connect failed: %1.").tqarg( errorMessage ); return SOAP_INVALID_SOCKET; } rc = m_sock->connect(); if ( rc != 0 ) { kdError() << "gSoapOpen: connect failed " << rc << endl; TQString errorMessage; if ( rc == -1 ) { errorMessage = TQString::tqfromLatin1( strerror( errno ) ); perror( 0 ); } //set the soap struct's error here! else { if ( rc == -3 ) errorMessage = TQString::tqfromLatin1( "Connection timed out. Check host and port number" ); } mErrorText = i18n("Connect failed: %1.").tqarg( errorMessage ); soap->error =SOAP_TCP_ERROR; return SOAP_INVALID_SOCKET; } m_sock->enableRead( true ); m_sock->enableWrite( true ); // hopefully never really used by SOAP #if 0 return m_sock->fd(); #else return 0; #endif } int GroupwiseServer::gSoapClose( struct soap * ) { // kdDebug() << "GroupwiseServer::gSoapClose()" << endl; delete m_sock; m_sock = 0; #if 0 m_sock->close(); m_sock->reset(); #endif return SOAP_OK; } int GroupwiseServer::gSoapSendCallback( struct soap * soap, const char *s, size_t n ) { // kdDebug() << "GroupwiseServer::gSoapSendCallback()" << endl; if ( !m_sock ) { kdError() << "no open connection" << endl; soap->error = SOAP_TCP_ERROR; return SOAP_TCP_ERROR; } if ( mError ) { kdError() << "SSL is in error state." << endl; soap->error = SOAP_SSL_ERROR; return SOAP_SSL_ERROR; } if ( getenv("DEBUG_GW_RESOURCE") ) { qDebug("*************************"); char p[99999]; strncpy(p, s, n); p[n]='\0'; qDebug("%s", p ); qDebug("\n*************************"); } log( "SENT", s, n ); int ret; while ( n > 0 ) { ret = m_sock->writeBlock( s, n ); if ( ret < 0 ) { kdError() << "Send failed: " << strerror( m_sock->systemError() ) << " " << m_sock->socketStatus() << " " << m_sock->fd() << endl; soap->error = SOAP_TCP_ERROR; return SOAP_TCP_ERROR; } n -= ret; } if ( n !=0 ) { kdError() << "Send failed: " << strerror( m_sock->systemError() ) << " " << m_sock->socketStatus() << " " << m_sock->fd() << endl; soap->error = SOAP_TCP_ERROR; } m_sock->flush(); return SOAP_OK; } size_t GroupwiseServer::gSoapReceiveCallback( struct soap *soap, char *s, size_t n ) { // kdDebug() << "GroupwiseServer::gSoapReceiveCallback()" << endl; if ( !m_sock ) { kdError() << "no open connection" << endl; soap->error = SOAP_FAULT; return 0; } if ( mError ) { kdError() << "SSL is in error state." << endl; soap->error = SOAP_SSL_ERROR; return 0; } // m_sock->open(); long ret = m_sock->readBlock( s, n ); if ( ret < 0 ) { kdError() << "Receive failed: " << strerror( m_sock->systemError() ) << " " << m_sock->socketStatus() << " " << m_sock->fd() << endl; } else { if ( getenv("DEBUG_GW_RESOURCE") ) { qDebug("*************************"); char p[99999]; strncpy(p, s, ret); p[ret]='\0'; qDebug("%s", p ); qDebug("\n*************************"); qDebug("kioReceiveCallback return %ld", ret); } log( "RECV", s, ret ); } return ret; } GroupwiseServer::GroupwiseServer( const TQString &url, const TQString &user, const TQString &password, TQObject *parent ) : TQObject( parent, "GroupwiseServer" ), mUrl( url ), mUser( user ), mPassword( password ), mSSL( url.left(6)=="https:" ), m_sock( 0 ), mError( 0 ) { mBinding = new GroupWiseBinding; mSoap = mBinding->soap; kdDebug() << "GroupwiseServer(): URL: " << url << endl; soap_init( mSoap ); #if 1 // disable this block to use native gSOAP network functions mSoap->fopen = myOpen; mSoap->fsend = mySendCallback; mSoap->frecv = myReceiveCallback; mSoap->fclose = myClose; KConfig cfg( "groupwiserc" ); cfg.setGroup( "Debug" ); mLogFile = cfg.readEntry( "LogFile" ); if ( !mLogFile.isEmpty() ) { kdDebug() << "Debug log file enabled: " << mLogFile << endl; } #endif mServerMap.insert( mSoap, this ); } GroupwiseServer::~GroupwiseServer() { delete mSoap; mSoap = 0; } bool GroupwiseServer::login() { _ngwm__loginResponse loginResp; _ngwm__loginRequest loginReq; loginReq.application = soap_new_std__string( mSoap, -1 ); loginReq.application->append( "KDEPIM" ); loginReq.language.append( "us" ); loginReq.version.append( "1" ); GWConverter conv( mSoap ); ngwt__PlainText pt; pt.username = mUser.utf8().data(); pt.password = conv.qStringToString( mPassword ); loginReq.auth = &pt; mSoap->userid = strdup( mUser.utf8() ); mSoap->passwd = strdup( mPassword.utf8() ); mSession = ""; kdDebug() << "GroupwiseServer::login() URL: " << mUrl << endl; int result = 1, maxTries = 3; mBinding->endpoint = mUrl.latin1(); // while ( --maxTries && result ) { result = soap_call___ngw__loginRequest( mSoap, mUrl.latin1(), NULL, &loginReq, &loginResp ); /*result = mBinding->__ngw__loginRequest( &loginReq, &loginResp );*/ // } if ( !checkResponse( result, loginResp.status ) ) return false; mSession = *(loginResp.session); if ( mSession.size() == 0 ) // workaround broken loginResponse error reporting { kdDebug() << "Login failed but the server didn't report an error" << endl; mErrorText = i18n( "Login failed, but the GroupWise server did not report an error" ); return false; } mSoap->header = new( SOAP_ENV__Header ); mUserName = ""; mUserEmail = ""; mUserUuid = ""; ngwt__UserInfo *userinfo = loginResp.userinfo; if ( userinfo ) { kdDebug() << "HAS USERINFO" << endl; mUserName = conv.stringToTQString( userinfo->name ); if ( userinfo->email ) mUserEmail = conv.stringToTQString( userinfo->email ); if ( userinfo->uuid ) mUserUuid = conv.stringToTQString( userinfo->uuid ); // can also get userid here in GW7 (userinfo->userid) } kdDebug() << "USER: name: " << mUserName << " email: " << mUserEmail << " uuid: " << mUserUuid << endl; return true; } bool GroupwiseServer::getCategoryList() { if ( mSession.empty() ) { kdError() << "GroupwiseServer::getCategoryList(): no session." << endl; return false; } /*SOAP_FMAC5 int SOAP_FMAC6 soap_call___ngw__getCategoryListRequest(struct soap *soap, const char *soap_endpoint, const char *soap_action, _ngwm__getCategoryListRequest *ngwm__getCategoryListRequest, _ngwm__getCategoryListResponse *ngwm__getCategoryListResponse);*/ _ngwm__getCategoryListRequest catListReq; _ngwm__getCategoryListResponse catListResp; mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__getCategoryListRequest( mSoap, mUrl.latin1(), 0, &catListReq, &catListResp); if ( !checkResponse( result, catListResp.status ) ) return false; if ( catListResp.categories ) { std::vector *categories; categories = &catListResp.categories->category; std::vector::const_iterator it; for( it = categories->begin(); it != categories->end(); ++it ) { // kdDebug() << "CATEGORY" << endl; dumpItem( *it ); } } return true; } bool GroupwiseServer::dumpData() { mSoap->header->ngwt__session = mSession; _ngwm__getAddressBookListRequest addressBookListRequest; _ngwm__getAddressBookListResponse addressBookListResponse; soap_call___ngw__getAddressBookListRequest( mSoap, mUrl.latin1(), NULL, &addressBookListRequest, &addressBookListResponse ); soap_print_fault(mSoap, stderr); if ( addressBookListResponse.books ) { std::vector *addressBooks = &addressBookListResponse.books->book; std::vector::const_iterator it; for( it = addressBooks->begin(); it != addressBooks->end(); ++it ) { ngwt__AddressBook *book = *it; if ( book->description ) { kdDebug() << "ADDRESSBOOK: description: " << book->description->c_str() << endl; } if ( book->id ) { kdDebug() << "ADDRESSBOOK: id: " << book->id->c_str() << endl; } if ( book->name ) { kdDebug() << "ADDRESSBOOK: name: " << book->name->c_str() << endl; } _ngwm__getItemsRequest itemsRequest; if ( !book->id ) { kdError() << "Missing book id" << endl; } else { itemsRequest.container = book->id; } itemsRequest.filter = 0; itemsRequest.items = 0; // itemsRequest.count = -1; mSoap->header->ngwt__session = mSession; _ngwm__getItemsResponse itemsResponse; soap_call___ngw__getItemsRequest( mSoap, mUrl.latin1(), 0, &itemsRequest, &itemsResponse ); std::vector *items = &itemsResponse.items->item; if ( items ) { std::vector::const_iterator it2; for( it2 = items->begin(); it2 != items->end(); ++it2 ) { kdDebug() << "ITEM" << endl; dumpItem( *it2 ); if ( true ) { _ngwm__getItemRequest itemRequest; if ( !(*it2)->id ) { kdError() << "Missing item id" << endl; } else { itemRequest.id = *( (*it2)->id ); } itemRequest.view = 0; mSoap->header->ngwt__session = mSession; _ngwm__getItemResponse itemResponse; soap_call___ngw__getItemRequest( mSoap, mUrl.latin1(), 0, &itemRequest, &itemResponse ); ngwt__Item *item = itemResponse.item; ngwt__Contact *contact = dynamic_cast( item ); if ( !contact ) { kdError() << "Cast failed." << endl; } else { kdDebug() << "Cast succeeded." << endl; } } } } } } return true; } void GroupwiseServer::dumpFolderList() { mSoap->header->ngwt__session = mSession; _ngwm__getFolderListRequest folderListReq; folderListReq.parent = "folders"; folderListReq.recurse = true; _ngwm__getFolderListResponse folderListRes; soap_call___ngw__getFolderListRequest( mSoap, mUrl.latin1(), 0, &folderListReq, &folderListRes ); if ( folderListRes.folders ) { std::vector *folders = &folderListRes.folders->folder; if ( folders ) { std::vector::const_iterator it; for ( it = folders->begin(); it != folders->end(); ++it ) { kdDebug() << "FOLDER" << endl; dumpFolder( *it ); #if 0 if ( (*it)->type && *((*it)->type) == "Calendar" ) { if ( !(*it)->id ) { kdError() << "Missing calendar id" << endl; } else { dumpCalendarFolder( *( (*it)->id ) ); } } #else if ( !(*it)->id ) { kdError() << "Missing calendar id" << endl; } else { dumpCalendarFolder( *( (*it)->id ) ); } #endif } } } } void GroupwiseServer::dumpCalendarFolder( const std::string &id ) { _ngwm__getItemsRequest itemsRequest; itemsRequest.container = soap_new_std__string( mSoap, -1 ); *(itemsRequest.container) = id; std::string *str = soap_new_std__string( mSoap, -1 ); str->append( "recipients message recipienStatus" ); itemsRequest.view = str; itemsRequest.filter = 0; itemsRequest.items = 0; // itemsRequest.count = 5; mSoap->header->ngwt__session = mSession; _ngwm__getItemsResponse itemsResponse; soap_call___ngw__getItemsRequest( mSoap, mUrl.latin1(), 0, &itemsRequest, &itemsResponse ); soap_print_fault(mSoap, stderr); std::vector *items = &itemsResponse.items->item; if ( items ) { std::vector::const_iterator it; for( it = items->begin(); it != items->end(); ++it ) { #if 0 if ( (*it)->type ) { kdDebug() << "ITEM type '" << (*it)->type->c_str() << "'" << endl; } else { kdDebug() << "ITEM no type" << endl; } #endif ngwt__Appointment *a = dynamic_cast( *it ); if ( !a ) { kdError() << "Appointment cast failed." << endl; } else { kdDebug() << "CALENDAR ITEM" << endl; dumpAppointment( a ); } ngwt__Task *t = dynamic_cast( *it ); if ( !t ) { kdError() << "Task cast failed." << endl; } else { kdDebug() << "TASK" << endl; dumpTask( t ); } } } } void GroupwiseServer::dumpMail( ngwt__Mail *m ) { dumpItem( m ); kdDebug() << " SUBJECT: " << m->subject << endl; } void GroupwiseServer::dumpTask( ngwt__Task *t ) { dumpMail( t ); if ( t->completed ) { kdDebug() << " COMPLETED: " << ( t->completed ? "true" : "false" ) << endl; } } void GroupwiseServer::dumpAppointment( ngwt__Appointment *a ) { dumpMail( a ); kdDebug() << " START DATE: " << a->startDate << endl; kdDebug() << " END DATE: " << a->endDate << endl; if ( a->allDayEvent ) { kdDebug() << " ALL DAY: " << ( a->allDayEvent ? "true" : "false" ) << endl; } } void GroupwiseServer::dumpFolder( ngwt__Folder *f ) { dumpItem( f ); kdDebug() << " PARENT: " << f->parent.c_str() << endl; if ( f->description ) { kdDebug() << " DESCRIPTION: " << f->description->c_str() << endl; } // FIXME: More fields // int *count; // bool *hasUnread; // int *unreadCount; // unsigned long sequence; // std::string *settings; // bool *hasSubfolders; // ngwt__SharedFolderNotification *notification; } void GroupwiseServer::dumpItem( ngwt__Item *i ) { if ( !i ) return; if ( i->id ) { kdDebug() << " ID: " << i->id->c_str() << endl; } if ( i->name ) { kdDebug() << " NAME: " << i->name->c_str() << endl; } kdDebug() << " VERSION: " << i->version << endl; kdDebug() << " MODIFIED: " << i->modified << endl; if ( i->changes ) kdDebug() << " HASCHANGES" << endl; #if 0 if ( i->type ) { kdDebug() << " TYPE: " << i->type->c_str() << endl; } #endif } bool GroupwiseServer::logout() { // FIXME: Send logoutRequest mSoap->header->ngwt__session = mSession; _ngwm__logoutRequest request; _ngwm__logoutResponse response; int result = soap_call___ngw__logoutRequest( mSoap, mUrl.latin1(), NULL, &request, &response); soap_print_fault( mSoap, stderr ); if (!checkResponse( result, response.status ) ) kdDebug() << "error while logging out" << endl; soap_end( mSoap ); soap_done( mSoap ); delete mSoap->header; mSoap->header = 0; return true; } GroupWise::DeltaInfo GroupwiseServer::getDeltaInfo( const TQStringList & addressBookIds ) { GroupWise::DeltaInfo info; info.count = 0; info.firstSequence = 0; info.lastSequence = 0; info.lastTimePORebuild = 0; if ( mSession.empty() ) { kdError() << "GroupwiseServer::getDeltaInfo(): no session." << endl; return info; } mSoap->header->ngwt__session = mSession; _ngwm__getDeltaInfoRequest request; _ngwm__getDeltaInfoResponse response; GWConverter conv( mSoap ); request.container.append( addressBookIds.first().latin1() ); int result = soap_call___ngw__getDeltaInfoRequest( mSoap, mUrl.latin1(), NULL, &request, &response); soap_print_fault( mSoap, stderr ); if (!checkResponse( result, response.status ) ) return info; if ( response.deltaInfo->count ) info.count = *( response.deltaInfo->count ); if ( response.deltaInfo->firstSequence ) info.firstSequence = *( response.deltaInfo->firstSequence ); if ( response.deltaInfo->lastSequence ) info.lastSequence = *( response.deltaInfo->lastSequence ); if ( response.deltaInfo->lastTimePORebuild ) info.lastTimePORebuild = response.deltaInfo->lastTimePORebuild; return info; } GroupWise::AddressBook::List GroupwiseServer::addressBookList() { GroupWise::AddressBook::List books; if ( mSession.empty() ) { kdError() << "GroupwiseServer::addressBookList(): no session." << endl; return books; } mSoap->header->ngwt__session = mSession; _ngwm__getAddressBookListRequest addressBookListRequest; _ngwm__getAddressBookListResponse addressBookListResponse; int result = soap_call___ngw__getAddressBookListRequest( mSoap, mUrl.latin1(), NULL, &addressBookListRequest, &addressBookListResponse ); if ( !checkResponse( result, addressBookListResponse.status ) ) { return books; } if ( addressBookListResponse.books ) { std::vector *addressBooks = &addressBookListResponse.books->book; std::vector::const_iterator it; for ( it = addressBooks->begin(); it != addressBooks->end(); ++it ) { GroupWise::AddressBook ab; ab.id = GWConverter::stringToTQString( (*it)->id ); ab.name = GWConverter::stringToTQString( (*it)->name ); ab.description = GWConverter::stringToTQString( (*it)->description ); if ( (*it)->isPersonal ) ab.isPersonal = (*it)->isPersonal; if ( (*it)->isFrequentContacts ) { ab.isFrequentContacts = (*it)->isFrequentContacts; } books.append( ab ); } } return books; } bool GroupwiseServer::readAddressBooksSynchronous( const TQStringList &addrBookIds ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::readAddressBooksSynchronous(): no session." << endl; return false; } ReadAddressBooksJob *job = new ReadAddressBooksJob( this, mSoap, mUrl, mSession ); job->setAddressBookIds( addrBookIds ); job->run(); return true; } bool GroupwiseServer::updateAddressBooks( const TQStringList &addrBookIds, const unsigned long startSequenceNumber, const unsigned long lastPORebuildTime ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::updateAddressBooks(): no session." << endl; return false; } UpdateAddressBooksJob * job = new UpdateAddressBooksJob( this, mSoap, mUrl, mSession ); job->setAddressBookIds( addrBookIds ); job->setStartSequenceNumber( startSequenceNumber ); job->setLastPORebuildTime( lastPORebuildTime ); job->run(); if ( job->error() == GroupWise::RefreshNeeded ) { mError = 1; mErrorText = "The System Address Book must be refreshed"; return false; } return true; } std::string GroupwiseServer::getFullIDFor( const TQString & gwRecordIDFromIcal ) { // first get the ID of the calendar folder - because we don't store this in the resource we have to fetch it manually std::string calendarFolderID; _ngwm__getFolderListRequest folderListReq; _ngwm__getFolderListResponse folderListRes; folderListReq.parent = "folders"; folderListReq.view = soap_new_std__string( mSoap, -1 ); folderListReq.view->append( "id type" ); folderListReq.recurse = false; mSoap->header->ngwt__session = mSession; soap_call___ngw__getFolderListRequest( mSoap, mUrl.latin1(), 0, &folderListReq, &folderListRes ); if ( folderListRes.folders ) { std::vector *folders = &folderListRes.folders->folder; if ( folders ) { std::vector::const_iterator it; for ( it = folders->begin(); it != folders->end(); ++it ) { ngwt__SystemFolder * fld = dynamic_cast( *it ); if ( fld && *(fld->folderType) == Calendar ) if ( !fld->id ) { kdError() << "No folder id" << endl; } else { calendarFolderID = *fld->id; } } } } if ( calendarFolderID.empty() ) { kdError() << "couldn't get calendar folder ID in order to accept invitation" << endl; return std::string(); } // now get the full Item ID of the std::string fullItemID; _ngwm__getItemsRequest getItemRequest; _ngwm__getItemsResponse getItemResponse; //getItemRequest.id.append( gwRecordID.latin1() ); getItemRequest.view = 0; getItemRequest.filter = soap_new_ngwt__Filter( mSoap, -1 ); ngwt__FilterEntry * fe = soap_new_ngwt__FilterEntry( mSoap, -1 ); fe->op = eq; fe->field = soap_new_std__string( mSoap, -1 ); fe->field->append( "id" ); fe->value = soap_new_std__string( mSoap, -1 ); fe->value->append( gwRecordIDFromIcal.latin1() ); fe->custom = 0; fe->date = 0; getItemRequest.filter->element = fe; getItemRequest.container = &calendarFolderID; getItemRequest.items = 0; getItemRequest.count = 1; mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__getItemsRequest( mSoap, mUrl.latin1(), 0, &getItemRequest, &getItemResponse ); if ( !checkResponse( result, getItemResponse.status ) ) return std::string(); std::vector *items = &getItemResponse.items->item; if ( items ) { std::vector::const_iterator it = items->begin(); if ( it != items->end() ) { ngwt__Item * item = *it; fullItemID = *item->id; } } if ( !fullItemID.empty() ) { kdDebug() << " obtained full item id " << fullItemID.c_str() << endl; } return fullItemID; } bool GroupwiseServer::acceptIncidence( KCal::Incidence *incidence ) { kdDebug() << "GroupwiseServer::acceptIncidence() " << incidence->schedulingID() << " : " << incidence->summary() << endl; if ( mSession.empty() ) { kdError() << "GroupwiseServer::acceptIncidence(): no session." << endl; return false; } GWConverter conv( mSoap ); TQString qGwUid = incidence->customProperty( "GWRESOURCE", "UID" ); std::string gwUID; if ( qGwUid.isEmpty() ) { TQString gwRecordIDFromIcal = incidence->nonKDECustomProperty( "X-GWRECORDID" ); // we need to do a getItem to get the item's complete ID, including the container portion // this is only necessary because the Ical GWRECORDID property is incomplete gwUID = getFullIDFor( gwRecordIDFromIcal ); } else gwUID = qGwUid.latin1(); if ( gwUID.empty() ) { kdError() << "GroupwiseServer::declineIncidence(): no GroupWise item ID." << endl; return false; } _ngwm__acceptRequest request; _ngwm__acceptResponse response; request.comment = 0; request.acceptLevel = 0; request.recurrenceAllInstances = 0; /*FIXME: This should be the recurrence key for recurring events */ request.items = soap_new_ngwt__ItemRefList( mSoap, -1 ); /* std::string acceptedItem; acceptedItem.append( gwRecordID.utf8() );*/ request.items->item.push_back( gwUID ); mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__acceptRequest( mSoap, mUrl.latin1(), 0, &request, &response ); if ( !checkResponse( result, response.status ) ) return false; return true; } bool GroupwiseServer::declineIncidence( KCal::Incidence *incidence ) { kdDebug() << "GroupwiseServer::declineIncidence() " << incidence->schedulingID() << " : " << incidence->summary() << endl; if ( mSession.empty() ) { kdError() << "GroupwiseServer::declineIncidence(): no session." << endl; return false; } GWConverter conv( mSoap ); std::string gwUID = incidence->customProperty( "GWRESOURCE", "UID" ).latin1(); if ( gwUID.empty() ) { TQString gwRecordIDFromIcal = incidence->nonKDECustomProperty( "X-GWRECORDID" ); // we need to do a getItem to get the item's complete ID, including the container portion // this is only necessary because the Ical GWRECORDID property is incomplete gwUID = getFullIDFor( gwRecordIDFromIcal ); } if ( gwUID.empty() ) { kdError() << "GroupwiseServer::declineIncidence(): no GroupWise item ID." << endl; return false; } _ngwm__declineRequest request; _ngwm__declineResponse response; request.comment = 0; request.recurrenceAllInstances = 0; /*FIXME: This should be the recurrence key for recurring events */ request.items = soap_new_ngwt__ItemRefList( mSoap, -1 ); /* std::string acceptedItem; acceptedItem.append( gwRecordID.utf8() );*/ request.items->item.push_back( gwUID ); mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__declineRequest( mSoap, mUrl.latin1(), 0, &request, &response ); if ( !checkResponse( result, response.status ) ) return false; return true; } bool GroupwiseServer::addIncidence( KCal::Incidence *incidence, KCal::ResourceCached * ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::addIncidence(): no session." << endl; return false; } kdDebug() << "GroupwiseServer::addIncidence() " << incidence->summary() << endl; TQString gwRecordIDFromIcal = incidence->nonKDECustomProperty( "X-GWRECORDID" ); if( !gwRecordIDFromIcal.isEmpty() || !incidence->customProperty( "GWRESOURCE", "UID" ).isEmpty() ) { kdDebug() << "Incidence has GroupWise ID already: (" << gwRecordIDFromIcal << "ical|" << incidence->customProperty( "GWRESOURCE", "UID" ) << "soap) and organizer : " << incidence->organizer().email() << endl; return acceptIncidence( incidence ); } else kdDebug() << "Incidence has no scheduling ID." << endl; IncidenceConverter converter( mSoap ); converter.setFrom( mUserName, mUserEmail, mUserUuid ); incidence->setCustomProperty( "GWRESOURCE", "CONTAINER", converter.stringToTQString( mCalendarFolder ) ); ngwt__Item *item; if ( incidence->type() == "Event" ) { item = converter.convertToAppointment( static_cast( incidence ) ); } else if ( incidence->type() == "Todo" ) { item = converter.convertToTask( static_cast( incidence ) ); } else if ( incidence->type() == "Journal" ) { item = converter.convertToNote( static_cast( incidence ) );; } else { kdError() << "KCal::GroupwiseServer::addIncidence(): Unknown type: " << incidence->type() << endl; return false; } _ngwm__sendItemRequest request; request.item = item; _ngwm__sendItemResponse response; mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__sendItemRequest( mSoap, mUrl.latin1(), 0, &request, &response ); if ( !checkResponse( result, response.status ) ) return false; // kdDebug() << "RESPONDED UID: " << response.id.c_str() << endl; // what if this returns multiple IDs - does a single recurring incidence create multiple ids on the server? if ( response.id.size() == 1 ) { std::string firstId = *(response.id.begin() ); incidence->setCustomProperty( "GWRESOURCE", "UID", TQString::fromUtf8( firstId.c_str() ) ); } return true; } bool GroupwiseServer::changeIncidence( KCal::Incidence *incidence ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::changeIncidence(): no session." << endl; return false; } kdDebug() << "GroupwiseServer::changeIncidence() " << incidence->summary() << endl; bool success = true; bool todoCompletionChanged = false; IncidenceConverter converter( mSoap ); converter.setFrom( mUserName, mUserEmail, mUserUuid ); incidence->setCustomProperty( "GWRESOURCE", "CONTAINER", converter.stringToTQString( mCalendarFolder ) ); ngwt__Item *item; if ( incidence->type() == "Event" ) { item = converter.convertToAppointment( static_cast( incidence ) ); } else if ( incidence->type() == "Todo" ) { item = converter.convertToTask( static_cast( incidence ) ); } else if ( incidence->type() == "Journal" ) { item = converter.convertToNote( static_cast( incidence ) );; } else { kdError() << "KCal::GroupwiseServer::changeIncidence(): Unknown type: " << incidence->type() << endl; return false; } if ( iAmTheOrganizer( incidence ) ) { if ( incidence->attendeeCount() > 0 ) { kdDebug() << "GroupwiseServer::changeIncidence() - retracting old incidence " << endl; if ( !retractRequest( incidence, DueToResend ) ) { kdDebug() << "GroupwiseServer::changeIncidence() - retracting failed." << endl; return false; } kdDebug() << "GroupwiseServer::changeIncidence() - adding new meeting with attendees" << endl; if ( !addIncidence( incidence, 0 ) ) { kdDebug() << "GroupwiseServer::changeIncidence() - adding failed." << endl; return false; } return true; } } else // If I am not the organizer restrict my changes to accept or decline requests or task completion { // find myself as attendee. GWConverter conv( mSoap ); KCal::Attendee::List attendees = incidence->attendees(); KCal::Attendee::List::ConstIterator it; for( it = attendees.begin(); it != attendees.end(); ++it ) { if ( conv.emailsMatch( (*it)->email(), mUserEmail ) ) { if ( (*it)->status() == KCal::Attendee::Accepted ) success &= acceptIncidence( incidence ); else if ( (*it)->status() == KCal::Attendee::Declined ) success &= declineIncidence( incidence ); break; } } // task completion if ( incidence->type() == "Todo" ) { KCal::Todo * todo = static_cast( incidence ); success &= setCompleted( todo ); //assume nothing else to change } return success; // if we are attending, but not the organiser, and we have not accepted or declined, there's nothing else to do. return true; } _ngwm__modifyItemRequest request; if ( !item->id ) { kdError() << "Missing incidence id" << endl; } else { request.id = *item->id; } request.updates = soap_new_ngwt__ItemChanges( mSoap, -1 ); request.updates->add = 0; request.updates->_delete = 0; request.updates->update = item; request.notification = 0; request.recurrenceAllInstances = 0; _ngwm__modifyItemResponse response; mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__modifyItemRequest( mSoap, mUrl.latin1(), 0, &request, &response ); success &= checkResponse( result, response.status ); // task completion after modify if ( incidence->type() == "Todo" ) { KCal::Todo * todo = static_cast( incidence ); success &= setCompleted( todo ); } return success; } bool GroupwiseServer::checkResponse( int result, ngwt__tqStatus *status ) { if ( result != 0 ) { soap_print_fault( mSoap, stderr ); return false; } else { kdDebug() << "SOAP call succeeded" << endl; } if ( status && status->code != 0 ) { TQString msg = "SOAP Response Status: " + TQString::number( status->code ); if ( status->description ) { msg += " "; msg += status->description->c_str(); mErrorText = status->description->c_str(); } kdError() << msg << endl; return false; } else { return true; } } bool GroupwiseServer::deleteIncidence( KCal::Incidence *incidence ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::deleteIncidence(): no session." << endl; return false; } kdDebug() << "GroupwiseServer::deleteIncidence(): " << incidence->summary() << endl; // decline if necessary on the server TQString gwRecordIDFromIcal = incidence->nonKDECustomProperty( "X-GWRECORDID" ); // debug contents of message custom properties kdDebug() << "incidence custom properties BEGIN" << endl; typedef TQMap PropMap; PropMap customs = incidence->customProperties(); PropMap::Iterator it; for ( it = customs.begin(); it != customs.end(); ++it ) kdDebug() << "key: " << it.key() << ", data: " << it.data() << endl; kdDebug() << "incidence custom properties END" << endl; if ( incidence->attendeeCount() > 0 ) { kdDebug() << "Incidence has GroupWise ID already: (" << gwRecordIDFromIcal << "ical|" << incidence->customProperty( "GWRESOURCE", "UID" ) << "soap) and organizer : " << incidence->organizer().email() << endl; return declineIncidence( incidence ); } #if 0 kdDebug() << "UID: " << incidence->customProperty( "GWRESOURCE", "UID" ) << endl; kdDebug() << "CONTAINER: " << incidence->customProperty( "GWRESOURCE", "CONTAINER" ) << endl; #endif if ( incidence->customProperty( "GWRESOURCE", "UID" ).isEmpty() || incidence->customProperty( "GWRESOURCE", "CONTAINER" ).isEmpty() ) return false; _ngwm__removeItemRequest request; _ngwm__removeItemResponse response; mSoap->header->ngwt__session = mSession; GWConverter converter( mSoap ); request.container = converter.qStringToString( incidence->customProperty( "GWRESOURCE", "CONTAINER" ) ); request.id = std::string( incidence->customProperty( "GWRESOURCE", "UID" ).utf8() ); int result = soap_call___ngw__removeItemRequest( mSoap, mUrl.latin1(), 0, &request, &response ); return checkResponse( result, response.status ); } bool GroupwiseServer::retractRequest( KCal::Incidence *incidence, RetractCause cause ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::retractRequest(): no session." << endl; return false; } kdDebug() << "GroupwiseServer::retractRequest(): " << incidence->summary() << endl; IncidenceConverter converter( mSoap ); converter.setFrom( mUserName, mUserEmail, mUserUuid ); incidence->setCustomProperty( "GWRESOURCE", "CONTAINER", converter.stringToTQString( mCalendarFolder ) ); ngwt__Item *item; if ( incidence->type() == "Event" ) { item = converter.convertToAppointment( static_cast( incidence ) ); } else if ( incidence->type() == "Todo" ) { item = converter.convertToTask( static_cast( incidence ) ); } else if ( incidence->type() == "Journal" ) { item = converter.convertToNote( static_cast( incidence ) );; } else { kdError() << "KCal::GroupwiseServer::addIncidence(): Unknown type: " << incidence->type() << endl; return false; } _ngwm__retractRequest request; _ngwm__retractResponse response; mSoap->header->ngwt__session = mSession; request.items = soap_new_ngwt__ItemRefList( mSoap, 1 ); request.items->item.push_back( *( item->id ) ); request.comment = 0; request.retractCausedByResend = (bool*)soap_malloc( mSoap, 1 ); request.retractingAllInstances = (bool*)soap_malloc( mSoap, 1 ); request.retractCausedByResend = ( cause == DueToResend ); request.retractingAllInstances = true; ngwt__RetractType * rt = new ngwt__RetractType; *rt = allMailboxes; request.retractType = rt; int result = soap_call___ngw__retractRequest( mSoap, mUrl.latin1(), 0, &request, &response ); delete rt; return checkResponse( result, response.status ); } bool GroupwiseServer::insertAddressee( const TQString &addrBookId, KABC::Addressee &addr ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::insertAddressee(): no session." << endl; return false; } ContactConverter converter( mSoap ); addr.insertCustom( "GWRESOURCE", "CONTAINER", addrBookId ); ngwt__Contact* contact = converter.convertToContact( addr ); _ngwm__createItemRequest request; request.item = contact; request.notification = 0; _ngwm__createItemResponse response; mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__createItemRequest( mSoap, mUrl.latin1(), 0, &request, &response ); if ( !checkResponse( result, response.status ) ) return false; addr.insertCustom( "GWRESOURCE", "UID", TQString::fromUtf8( response.id.front().c_str() ) ); addr.setChanged( false ); return true; } bool GroupwiseServer::changeAddressee( const KABC::Addressee &addr ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::changeAddressee(): no session." << endl; return false; } ContactConverter converter( mSoap ); ngwt__Contact* contact = converter.convertToContact( addr ); _ngwm__modifyItemRequest request; if ( !contact->id ) { kdError() << "Missing addressee id" << endl; } else { request.id = *contact->id; } request.updates = soap_new_ngwt__ItemChanges( mSoap, -1 ); request.updates->add = 0; request.updates->_delete = 0; request.updates->update = contact; request.notification = 0; request.recurrenceAllInstances = 0; _ngwm__modifyItemResponse response; mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__modifyItemRequest( mSoap, mUrl.latin1(), 0, &request, &response ); return checkResponse( result, response.status ); } bool GroupwiseServer::removeAddressee( const KABC::Addressee &addr ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::removeAddressee(): no session." << endl; return false; } if ( addr.custom( "GWRESOURCE", "UID" ).isEmpty() || addr.custom( "GWRESOURCE", "CONTAINER" ).isEmpty() ) return false; _ngwm__removeItemRequest request; _ngwm__removeItemResponse response; mSoap->header->ngwt__session = mSession; GWConverter converter( mSoap ); request.container = converter.qStringToString( addr.custom( "GWRESOURCE", "CONTAINER" ) ); request.id = std::string( addr.custom( "GWRESOURCE", "UID" ).utf8() ); int result = soap_call___ngw__removeItemRequest( mSoap, mUrl.latin1(), 0, &request, &response ); return checkResponse( result, response.status ); } bool GroupwiseServer::readCalendarSynchronous( KCal::Calendar *cal ) { kdDebug() << "GroupwiseServer::readCalendar()" << endl; if ( mSession.empty() ) { kdError() << "GroupwiseServer::readCalendar(): no session." << endl; return false; } ReadCalendarJob *job = new ReadCalendarJob( this, mSoap, mUrl, mSession ); job->setCalendarFolder( &mCalendarFolder ); job->setChecklistFolder( &mCheckListFolder ); job->setCalendar( cal ); job->run(); return true; } bool GroupwiseServer::readFreeBusy( const TQString &email, const TQDate &start, const TQDate &end, KCal::FreeBusy *freeBusy ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::readFreeBusy(): no session." << endl; return false; } kdDebug() << "GroupwiseServer::readFreeBusy()" << endl; GWConverter conv( mSoap ); // Setup input data ngwt__NameAndEmail user; user.displayName = 0; user.uuid = 0; user.email = conv.qStringToString( email ); std::vector users; users.push_back( &user ); ngwt__FreeBusyUserList userList; userList.user = users; // Start session _ngwm__startFreeBusySessionRequest startSessionRequest; startSessionRequest.users = &userList; startSessionRequest.startDate = conv.qDateToChar( start ); startSessionRequest.endDate = conv.qDateToChar( end ); _ngwm__startFreeBusySessionResponse startSessionResponse; mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__startFreeBusySessionRequest( mSoap, mUrl.latin1(), NULL, &startSessionRequest, &startSessionResponse ); if ( !checkResponse( result, startSessionResponse.status ) ) return false; int fbSessionId = *startSessionResponse.freeBusySessionId; kdDebug() << "Free/Busy session ID: " << fbSessionId << endl; // Get free/busy data _ngwm__getFreeBusyRequest getFreeBusyRequest; getFreeBusyRequest.freeBusySessionId = TQString::number( fbSessionId ).utf8().data(); _ngwm__getFreeBusyResponse getFreeBusyResponse; bool done = false; do { mSoap->header->ngwt__session = mSession; result = soap_call___ngw__getFreeBusyRequest( mSoap, mUrl.latin1(), NULL, &getFreeBusyRequest, &getFreeBusyResponse ); if ( !checkResponse( result, getFreeBusyResponse.status ) ) { return false; } ngwt__FreeBusyStats *stats = getFreeBusyResponse.freeBusyStats; if ( !stats || stats->outstanding == 0 ) done = true; if ( !stats ) { kdDebug() << "NO STATS!" << endl; } else { kdDebug() << "COUNT: " << stats->responded << " " << stats->outstanding << " " << stats->total << endl; } std::vector *infos = 0; if ( getFreeBusyResponse.freeBusyInfo ) infos = &getFreeBusyResponse.freeBusyInfo->user; if ( infos ) { std::vector::const_iterator it; for( it = infos->begin(); it != infos->end(); ++it ) { std::vector *blocks = 0; if ( (*it)->blocks ) blocks = &(*it)->blocks->block; if ( blocks ) { std::vector::const_iterator it2; for( it2 = blocks->begin(); it2 != blocks->end(); ++it2 ) { TQDateTime blockStart = conv.charToTQDateTime( (*it2)->startDate ); TQDateTime blockEnd = conv.charToTQDateTime( (*it2)->endDate ); ngwt__AcceptLevel acceptLevel = *(*it2)->acceptLevel; /* TODO: show Free/Busy subject in diagram - we need to support these as people use it for checking others' calendars */ /* if ( (*it2)->subject ) std::string subject = *(*it2)->subject;*/ // kdDebug() << "BLOCK Subject: " << subject.c_str() << endl; if ( acceptLevel == Busy || acceptLevel == OutOfOffice ) { freeBusy->addPeriod( blockStart, blockEnd ); } } } } } } while ( !done ); // Close session _ngwm__closeFreeBusySessionRequest closeSessionRequest; closeSessionRequest.freeBusySessionId = fbSessionId; _ngwm__closeFreeBusySessionResponse closeSessionResponse; mSoap->header->ngwt__session = mSession; result = soap_call___ngw__closeFreeBusySessionRequest( mSoap, mUrl.latin1(), NULL, &closeSessionRequest, &closeSessionResponse ); if ( !checkResponse( result, closeSessionResponse.status ) ) return false; return true; } void GroupwiseServer::slotSslError() { kdDebug() << "********************** SSL ERROR" << endl; mErrorText = i18n("SSL Error"); } void GroupwiseServer::emitReadAddressBookTotalSize( int s ) { emit readAddressBookTotalSize( s ); } void GroupwiseServer::emitReadAddressBookProcessedSize( int s ) { emit readAddressBookProcessedSize( s ); } void GroupwiseServer::emitErrorMessage( const TQString & msg, bool fatal ) { emit errorMessage( msg, fatal ); } void GroupwiseServer::emitGotAddressees( const KABC::Addressee::List addressees ) { emit gotAddressees( addressees ); } void GroupwiseServer::log( const TQString &prefix, const char *s, size_t n ) { if ( mLogFile.isEmpty() ) return; kdDebug() << "GroupwiseServer::log() " << prefix << " " << n << " bytes" << endl; TQString log = mLogFile + "_" + TQString::number( getpid() ) + "_" + prefix + ".log"; TQFile f( log ); if ( !f.open( IO_WriteOnly | IO_Append ) ) { kdError() << "Unable to open log file '" << log << "'" << endl; } else { uint written = 0; while ( written < n ) { kdDebug() << "written: " << written << endl; int w = f.writeBlock( s + written, n - written ); kdDebug() << "w: " << w << endl; if ( w < 0 ) { kdError() << "Unable to write log '" << log << "'" << endl; break; } written += w; } f.putch( '\n' ); f.close(); } } bool GroupwiseServer::readUserSettings( ngwt__Settings *&returnedSettings ) { if ( mSession.empty() ) { kdError() << "GroupwiseServer::userSettings(): no session." << endl; returnedSettings = 0; return returnedSettings; } _ngwm__getSettingsRequest request; #if 0 // server doesn't give return any settings keys even if id is a null string request.id = soap_new_std__string( mSoap, -1 ); request.id->append("allowSharedFolders"); #else request.id = 0; #endif _ngwm__getSettingsResponse response; mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__getSettingsRequest( mSoap, mUrl.latin1(), 0, &request, &response ); if ( !checkResponse( result, response.status ) ) { kdDebug() << "GroupwiseServer::userSettings() - checkResponse() failed" << endl; returnedSettings = 0; return returnedSettings; } returnedSettings = response.settings; if ( !returnedSettings ) { kdDebug() << "GroupwiseServer::userSettings() - no settings in response. " << endl; // debug data pending server fix // settings returnedSettings = new ngwt__Settings; // list of groups //returnedSettings->group = new std::vector; // sample group ngwt__SettingsGroup * grp = new ngwt__SettingsGroup; grp->type = new std::string; grp->type->append( "GROUP 1" ); // list of settings //grp->setting = new std::vector; // 2 sample settings ngwt__Custom * setting1 = new ngwt__Custom; setting1->field.append("Setting 1"); setting1->value = new std::string; setting1->value->append("Value 1 "); setting1->locked = new bool; *(setting1->locked) = false; ngwt__Custom * setting2 = new ngwt__Custom; setting2->field.append("Setting 2"); setting2->value = new std::string; setting2->value->append("Value 2"); setting2->locked = new bool; *(setting2->locked) = true; grp->setting.push_back( setting1 ); grp->setting.push_back( setting2 ); returnedSettings->group.push_back( grp ); } kdDebug() << "GroupwiseServer::userSettings() - done. " << endl; return true; /** FIXME return false if no settings fetched */ } bool GroupwiseServer::modifyUserSettings( TQMap & settings ) { kdDebug() << "GroupwiseServer::userSettings()" << endl; if ( mSession.empty() ) { kdError() << "GroupwiseServer::userSettings(): no session." << endl; return false; } _ngwm__modifySettingsRequest request; _ngwm__modifySettingsResponse response; request.settings = soap_new_ngwt__SettingsList( mSoap, -1 ); TQMap::Iterator it; for ( it = settings.begin(); it != settings.end(); ++it ) { kdDebug() << " creating Custom for " << it.key() << ", " << it.data() << endl; ngwt__Custom * custom = soap_new_ngwt__Custom( mSoap, -1 ); custom->locked = 0; custom->field.append( it.key().utf8() ); custom->value = soap_new_std__string( mSoap, -1 ); custom->value->append( it.data().utf8() ); request.settings->setting.push_back( custom ); } mSoap->header->ngwt__session = mSession; int result = soap_call___ngw__modifySettingsRequest( mSoap, mUrl.latin1(), 0, &request, &response ); if ( !checkResponse( result, response.status ) ) { kdDebug() << "GroupwiseServer::modifyUserSettings() - checkResponse() failed" << endl; return false; } kdError() << "GroupwiseServer::userSettings() - success" << endl; return true; } bool GroupwiseServer::iAmTheOrganizer( KCal::Incidence * incidence ) { return ( incidence->organizer().email() == mUserEmail ); } bool GroupwiseServer::setCompleted( KCal::Todo * todo ) { if ( todo ) { GWConverter conv( mSoap ); TQString id = todo->customProperty( "GWRESOURCE", "UID" ); ngwt__ItemRefList * items = soap_new_ngwt__ItemRefList( mSoap, 1 ); items->item.push_back( *( conv.qStringToString( id ) ) ); if ( todo->isCompleted() ) { _ngwm__completeRequest request; _ngwm__completeResponse response; mSoap->header->ngwt__session = mSession; request.items = items; int result = soap_call___ngw__completeRequest( mSoap, mUrl.latin1(), 0, &request, &response ); return checkResponse( result, response.status ); } else { _ngwm__uncompleteRequest request; _ngwm__uncompleteResponse response; mSoap->header->ngwt__session = mSession; request.items = items; int result = soap_call___ngw__uncompleteRequest( mSoap, mUrl.latin1(), 0, &request, &response ); return checkResponse( result, response.status ); } } return false; } #include "groupwiseserver.moc"