/* Kopete Groupwise Protocol logintask.cpp - Send our credentials to the server and process the contact list and privacy details that it returns. Copyright (c) 2004 SUSE Linux AG http://www.suse.com Based on Iris, Copyright (C) 2003 Justin Karneges Kopete (c) 2002-2004 by the Kopete developers ************************************************************************* * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * ************************************************************************* */ #include "client.h" #include "response.h" #include "privacymanager.h" #include "userdetailsmanager.h" #include "logintask.h" LoginTask::LoginTask( Task * parent ) : RequestTask( parent ) { } LoginTask::~LoginTask() { } void LoginTask::initialise() { QString command = QString::fromLatin1("login:%1:%2").arg( client()->host() ).arg( client()->port() ); Field::FieldList lst; lst.append( new Field::SingleField( NM_A_SZ_USERID, 0, NMFIELD_TYPE_UTF8, client()->userId() ) ); lst.append( new Field::SingleField( NM_A_SZ_CREDENTIALS, 0, NMFIELD_TYPE_UTF8, client()->password() ) ); lst.append( new Field::SingleField( NM_A_SZ_USER_AGENT, 0, NMFIELD_TYPE_UTF8, client()->userAgent() ) ); lst.append( new Field::SingleField( NM_A_UD_BUILD, 0, NMFIELD_TYPE_UDWORD, client()->protocolVersion() ) ); lst.append( new Field::SingleField( NM_A_IP_ADDRESS, 0, NMFIELD_TYPE_UTF8, client()->ipAddress() ) ); createTransfer( command, lst ); } bool LoginTask::take( Transfer * transfer ) { if ( !forMe( transfer ) ) return false; Response * response = dynamic_cast( transfer ); if ( !response ) return false; if ( response->resultCode() ) { setError( response->resultCode() ); return true; } response->fields().dump( true ); // read in myself()'s metadata fields and emit signal Field::FieldList loginResponseFields = response->fields(); ContactDetails cd = extractUserDetails( loginResponseFields ); emit gotMyself( cd ); // read the privacy settings first, because this affects all contacts' apparent status extractPrivacy( loginResponseFields ); extractCustomStatuses( loginResponseFields ); // CREATE CONTACT LIST // locate contact list Field::MultiField * contactList = loginResponseFields.findMultiField( NM_A_FA_CONTACT_LIST ); if ( contactList ) { Field::FieldList contactListFields = contactList->fields(); Field::MultiField * container; // read folders for ( Field::FieldListIterator it = contactListFields.find( NM_A_FA_FOLDER ); it != contactListFields.end(); it = contactListFields.find( ++it, NM_A_FA_FOLDER ) ) { container = static_cast( *it ); extractFolder( container ); } // read contacts for ( Field::FieldListIterator it = contactListFields.find( NM_A_FA_CONTACT ); it != contactListFields.end(); it = contactListFields.find( ++it, NM_A_FA_CONTACT ) ) { container = static_cast( *it ); extractContact( container ); } } extractKeepalivePeriod( loginResponseFields ); setSuccess(); return true; } void LoginTask::extractFolder( Field::MultiField * folderContainer ) { FolderItem folder; Field::SingleField * current; Field::FieldList fl = folderContainer->fields(); // object id current = fl.findSingleField( NM_A_SZ_OBJECT_ID ); folder.id = current->value().toInt(); // sequence number current = fl.findSingleField( NM_A_SZ_SEQUENCE_NUMBER ); folder.sequence = current->value().toInt(); // name current = fl.findSingleField( NM_A_SZ_DISPLAY_NAME ); folder.name = current->value().toString(); // parent current = fl.findSingleField( NM_A_SZ_PARENT_ID ); folder.parentId = current->value().toInt(); client()->debug( QString( "Got folder: %1, obj: %2, parent: %3, seq: %3." ).arg( folder.name ).arg( folder.id ).arg( folder.parentId ).arg( folder.sequence ) ); // tell the world about it emit gotFolder( folder ); } void LoginTask::extractContact( Field::MultiField * contactContainer ) { if ( contactContainer->tag() != NM_A_FA_CONTACT ) return; ContactItem contact; Field::SingleField * current; Field::FieldList fl = contactContainer->fields(); // sequence number, object and parent IDs are a numeric values but are stored as strings... current = fl.findSingleField( NM_A_SZ_OBJECT_ID ); contact.id = current->value().toInt(); current = fl.findSingleField( NM_A_SZ_PARENT_ID ); contact.parentId = current->value().toInt(); current = fl.findSingleField( NM_A_SZ_SEQUENCE_NUMBER ); contact.sequence = current->value().toInt(); current = fl.findSingleField( NM_A_SZ_DISPLAY_NAME ); contact.displayName = current->value().toString(); current = fl.findSingleField( NM_A_SZ_DN ); contact.dn = current->value().toString().lower(); emit gotContact( contact ); Field::MultiField * details = fl.findMultiField( NM_A_FA_USER_DETAILS ); if ( details ) // not all contact list contacts have these { Field::FieldList detailsFields = details->fields(); ContactDetails cd = extractUserDetails( detailsFields ); if ( cd.dn.isEmpty() ) cd.dn = contact.dn; // tell the UserDetailsManager that we have this contact's details client()->userDetailsManager()->addDetails( cd ); emit gotContactUserDetails( cd ); } } ContactDetails LoginTask::extractUserDetails( Field::FieldList & fields ) { ContactDetails cd; cd.status = GroupWise::Invalid; cd.archive = false; // read the supplied fields, set metadata and status. Field::SingleField * sf; if ( ( sf = fields.findSingleField ( NM_A_SZ_AUTH_ATTRIBUTE ) ) ) cd.authAttribute = sf->value().toString(); if ( ( sf = fields.findSingleField ( NM_A_SZ_DN ) ) ) cd.dn = sf->value().toString().lower(); // HACK: lowercased DN if ( ( sf = fields.findSingleField ( "CN" ) ) ) cd.cn = sf->value().toString(); if ( ( sf = fields.findSingleField ( "Given Name" ) ) ) cd.givenName = sf->value().toString(); if ( ( sf = fields.findSingleField ( "Surname" ) ) ) cd.surname = sf->value().toString(); if ( ( sf = fields.findSingleField ( "Full Name" ) ) ) cd.fullName = sf->value().toString(); if ( ( sf = fields.findSingleField ( "nnmArchive" ) ) ) cd.archive = ( sf->value().toInt() == 1 ); if ( ( sf = fields.findSingleField ( NM_A_SZ_STATUS ) ) ) cd.status = sf->value().toInt(); if ( ( sf = fields.findSingleField ( NM_A_SZ_MESSAGE_BODY ) ) ) cd.awayMessage = sf->value().toString(); Field::MultiField * mf; QMap< QString, QString > propMap; if ( ( mf = fields.findMultiField ( NM_A_FA_INFO_DISPLAY_ARRAY ) ) ) { Field::FieldList fl = mf->fields(); const Field::FieldListIterator end = fl.end(); for ( Field::FieldListIterator it = fl.begin(); it != end; ++it ) { Field::SingleField * propField = dynamic_cast( *it ); if ( propField ) { QString propName = propField->tag(); QString propValue = propField->value().toString(); propMap.insert( propName, propValue ); } else { Field::MultiField * propList = dynamic_cast( *it ); if ( propList ) { // Hello A Nagappan. GW gave us a multiple field where we previously got a single field QString parentName = propList->tag(); Field::FieldList propFields = propList->fields(); const Field::FieldListIterator end = propFields.end(); for ( Field::FieldListIterator it = propFields.begin(); it != end; ++it ) { propField = dynamic_cast( *it ); if ( propField /*&& propField->tag() == parentName */) { QString propValue = propField->value().toString(); QString contents = propMap[ propField->tag() ]; if ( !contents.isEmpty() ) contents.append( ", " ); contents.append( propField->value().toString()); propMap.insert( propField->tag(), contents ); } } } } } } if ( !propMap.empty() ) { cd.properties = propMap; } return cd; } void LoginTask::extractPrivacy( Field::FieldList & fields ) { bool privacyLocked = false; bool defaultDeny = false; QStringList allowList; QStringList denyList; // read blocking // may be a single field or may be an array Field::FieldListIterator it = fields.find( NM_A_LOCKED_ATTR_LIST ); if ( it != fields.end() ) { if ( Field::SingleField * sf = dynamic_cast( *it ) ) { if ( sf->value().toString().find( NM_A_BLOCKING ) ) privacyLocked = true; } else if ( Field::MultiField * mf = dynamic_cast( *it ) ) { Field::FieldList fl = mf->fields(); for ( Field::FieldListIterator it = fl.begin(); it != fl.end(); ++it ) { if ( Field::SingleField * sf = dynamic_cast( *it ) ) { if ( sf->tag() == NM_A_BLOCKING ) { privacyLocked = true; break; } } } } } // read default privacy policy Field::SingleField * sf = fields.findSingleField( NM_A_BLOCKING ); if ( sf ) defaultDeny = ( sf->value().toInt() != 0 ); // read deny list denyList = readPrivacyItems( NM_A_BLOCKING_DENY_LIST, fields ); // read allow list allowList = readPrivacyItems( NM_A_BLOCKING_ALLOW_LIST, fields ); emit gotPrivacySettings( privacyLocked, defaultDeny, allowList, denyList ); kdDebug( GROUPWISE_DEBUG_GLOBAL ) << "locked is " << privacyLocked << ", default is " << defaultDeny << "\nallow list is: " << allowList << "\ndeny list is: " << denyList << endl; } QStringList LoginTask::readPrivacyItems( const QCString & tag, Field::FieldList & fields ) { QStringList items; Field::FieldListIterator it = fields.find( tag ); if ( it != fields.end() ) { if ( Field::SingleField * sf = dynamic_cast( *it ) ) { items.append( sf->value().toString().lower() ); } else if ( Field::MultiField * mf = dynamic_cast( *it ) ) { Field::FieldList fl = mf->fields(); for ( Field::FieldListIterator it = fl.begin(); it != fl.end(); ++it ) { if ( Field::SingleField * sf = dynamic_cast( *it ) ) { items.append( sf->value().toString().lower() ); } } } } return items; } void LoginTask::extractCustomStatuses( Field::FieldList & fields ) { Field::FieldListIterator it = fields.find( NM_A_FA_CUSTOM_STATUSES ); if ( it != fields.end() ) { if ( Field::MultiField * mf = dynamic_cast( *it ) ) { Field::FieldList fl = mf->fields(); for ( Field::FieldListIterator custStatIt = fl.begin(); custStatIt != fl.end(); ++custStatIt ) { Field::MultiField * mf2 = dynamic_cast( *custStatIt ); if ( mf2 && ( mf2->tag() == NM_A_FA_STATUS ) ) { GroupWise::CustomStatus custom; Field::FieldList fl2 = mf2->fields(); for ( Field::FieldListIterator custContentIt = fl2.begin(); custContentIt != fl2.end(); ++custContentIt ) { if ( Field::SingleField * sf3 = dynamic_cast( *custContentIt ) ) { if ( sf3->tag() == NM_A_SZ_TYPE ) custom.status = (GroupWise::Status)sf3->value().toInt(); else if ( sf3->tag() == NM_A_SZ_DISPLAY_NAME ) custom.name = sf3->value().toString(); else if ( sf3->tag() == NM_A_SZ_MESSAGE_BODY ) custom.autoReply = sf3->value().toString(); } } emit gotCustomStatus( custom ); } } } } } void LoginTask::extractKeepalivePeriod( Field::FieldList & fields ) { Field::FieldListIterator it = fields.find( NM_A_UD_KEEPALIVE ); if ( it != fields.end() ) { if ( Field::SingleField * sf = dynamic_cast( *it ) ) { bool ok; int period = sf->value().toInt( &ok ); if ( ok ) { emit gotKeepalivePeriod( period ); } } } } #include "logintask.moc"