Field::FieldList UpdateFolderTask::folderToFields( const GroupWise::FolderItem & folder )
{
	Field::FieldList lst;
	lst.append( new Field::SingleField( NM_A_SZ_OBJECT_ID, 0, NMFIELD_TYPE_UTF8, folder.id ) );
	lst.append( new Field::SingleField( NM_A_SZ_PARENT_ID, 0, NMFIELD_TYPE_UTF8, 0 ) );
	lst.append( new Field::SingleField( NM_A_SZ_TYPE, 0, NMFIELD_TYPE_UTF8, 1 ) );
	lst.append( new Field::SingleField( NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_TYPE_UTF8, folder.sequence ) );
	if ( !folder.name.isEmpty() )
		lst.append( new Field::SingleField( NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_TYPE_UTF8, folder.name ) );
	return lst;
}
void CreateContactInstanceTask::contact( Field::SingleField * id, const QString & displayName, const int parentFolder )
{
	Field::FieldList lst;
	lst.append( new Field::SingleField( Field::NM_A_SZ_PARENT_ID, 0, NMFIELD_TYPE_UTF8, QString::number( parentFolder ) ) );
	// this is either a user Id or a DN
	lst.append( id );
	if ( displayName.isEmpty() ) // fallback so that the contact is created
		lst.append( new Field::SingleField( Field::NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_TYPE_UTF8, m_dn ) );
	else
		lst.append( new Field::SingleField( Field::NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_TYPE_UTF8, displayName ) );
	createTransfer( "createcontact", lst );
}
void UpdateFolderTask::renameFolder( const QString & newName, const GroupWise::FolderItem & existing )
{
	Field::FieldList lst;
	// add the old version of the folder, marked delete
	lst.append( new Field::MultiField( NM_A_FA_FOLDER, NMFIELD_METHOD_DELETE, 0, NMFIELD_TYPE_ARRAY, folderToFields( existing) ) );
	
	GroupWise::FolderItem renamed = existing;
	renamed.name = newName;
	// add the new version of the folder, marked add
	lst.append( new Field::MultiField( NM_A_FA_FOLDER, NMFIELD_METHOD_ADD, 0, NMFIELD_TYPE_ARRAY, folderToFields( renamed ) ) );
	// let our parent class package it up as a contactlist in a transfer
	UpdateItemTask::item( lst );
}
void ChatPropertiesTask::setChat( const QString &displayName )
{
	Field::FieldList lst;
	m_chat = displayName;
	lst.append( new Field::SingleField( NM_A_DISPLAY_NAME, 0, NMFIELD_TYPE_UTF8, m_chat ) );
	createTransfer( "chatproperties", lst );
}
void GetStatusTask::userDN( const QString & dn )
{
	m_userDN = dn;
	// set up Transfer
	Field::FieldList lst;
	// changed from USERID to DN as per Gaim/GWIM
	lst.append( new Field::SingleField( NM_A_SZ_DN, 0, NMFIELD_TYPE_UTF8, m_userDN ) );
	createTransfer( "getstatus", lst );
}
void SetStatusTask::status( Status newStatus, const QString &awayMessage, const QString &autoReply )
{
	if ( newStatus > GroupWise::Invalid )
	{
		setError( 1, "Invalid Status" );
		return;
	}
	
	m_status = newStatus;
	m_awayMessage = awayMessage;
	m_autoReply = autoReply;
	
	Field::FieldList lst;
	lst.append( new Field::SingleField( NM_A_SZ_STATUS, 0, NMFIELD_TYPE_UTF8, QString::number( newStatus ) ) );
	if ( !awayMessage.isNull() )
		lst.append( new Field::SingleField( NM_A_SZ_STATUS_TEXT, 0, NMFIELD_TYPE_UTF8, awayMessage ) );
	if ( !autoReply.isNull() )
		lst.append( new Field::SingleField( NM_A_SZ_MESSAGE_BODY, 0, NMFIELD_TYPE_UTF8, autoReply ) );
	createTransfer( "setstatus", lst );
}
int main()
{
    CoreProtocol testObject;
    RequestFactory testFactory;
    QByteArray command("login");
    Request * firstRequest = testFactory.request( command );
    Field::FieldList lst;
    lst.append( new Field::SingleField( Field::NM_A_SZ_USERID, NMFIELD_METHOD_VALID, 0, NMFIELD_TYPE_UTF8, "*****@*****.**" ) );
    firstRequest->setFields( lst );
    testObject.outgoingTransfer( firstRequest );
    return 0;
}
bool ResponseProtocol::readFields( int fieldCount, Field::FieldList * list )
{
	// build a list of fields.  
	// If there is already a list of fields stored in m_collatingFields, 
	// the list we're reading on this iteration must be a nested list
	// so when we're done reading it, add it to the MultiList element
	// that is the last element in the top list in m_collatingFields.
	// if we find the beginning of a new nested list, push the current list onto m_collatingFields
	debug( "ResponseProtocol::readFields()" );
	if ( fieldCount > 0 )
		debug( QString( "reading %1 fields" ).arg( fieldCount ) );
	Field::FieldList currentList;
	while ( fieldCount != 0 )  // prevents bad input data from ruining our day
	{
		// the field being read
		// read field
		Q_UINT8 type, method;
		Q_UINT32 val;
		QCString tag;
		// read uint8 type
		if ( !okToProceed() )
		{
			currentList.purge();
			return false;
		}
		m_din >> type;
		m_bytes += sizeof( Q_UINT8 );
		// if type is 0 SOMETHING_INVALID, we're at the end of the fields
		if ( type == 0 ) /*&& m_din->atEnd() )*/
		{
			debug( "- end of field list" );
			m_packetState = FieldsRead;
			// do something to indicate we're done
			break;
		}
		// read uint8 method
		if ( !okToProceed() )
		{
			currentList.purge();
			return false;
		}
		m_din >> method;
		m_bytes += sizeof( Q_UINT8 );
		// read tag and length
		if ( !safeReadBytes( tag, val ) )
		{
			currentList.purge();
			return false;
		}

		debug( QString( "- type: %1, method: %2, tag: %3," ).arg( type ).arg( method ).arg( tag.data() ) );
		// if multivalue or array
		if ( type == NMFIELD_TYPE_MV || type == NMFIELD_TYPE_ARRAY )
		{
			// read length uint32
			if ( !okToProceed() )
			{
				currentList.purge();
				return false;
			}
			m_din >> val;
			m_bytes += sizeof( Q_UINT32 );

			// create multifield
			debug( QString( " multi field containing: %1" ).arg( val ) );
			Field::MultiField* m = new Field::MultiField( tag, method, 0, type );
			currentList.append( m );
			if ( !readFields( val, &currentList) )
			{
				currentList.purge();
				return false;
			}
		}
		else 
		{
		
			if ( type == NMFIELD_TYPE_UTF8 || type == NMFIELD_TYPE_DN )
			{
				QCString rawData;
				if( !safeReadBytes( rawData, val ) )
				{
					currentList.purge();
					return false;
				}
				if ( val > NMFIELD_MAX_STR_LENGTH )
				{
					m_packetState = ProtocolError;
					break;
				}
				// convert to unicode - ignore the terminating NUL, because Qt<3.3.2 doesn't sanity check val.
				QString fieldValue = QString::fromUtf8( rawData.data(), val - 1 );
				debug( QString( "- utf/dn single field: %1" ).arg( fieldValue ) );
				// create singlefield
				Field::SingleField* s = new Field::SingleField( tag, method, 0, type, fieldValue );
				currentList.append( s );
			}
			else
			{
				// otherwise ( numeric )
				// read value uint32
				if ( !okToProceed() )
				{
					currentList.purge();
					return false;
				}
				m_din >> val;
				m_bytes += sizeof( Q_UINT32 );
				debug( QString( "- numeric field: %1" ).arg( val ) );
				Field::SingleField* s = new Field::SingleField( tag, method, 0, type, val );
				currentList.append( s );
			}
		}
		// decrease the fieldCount if we're using it
		if ( fieldCount > 0 )
			fieldCount--;
	}
void PollSearchResultsTask::poll( const QString & queryHandle )
{
	Field::FieldList lst;
	lst.append( new Field::SingleField( Field::NM_A_SZ_OBJECT_ID, 0, NMFIELD_TYPE_UTF8, queryHandle ) );
	createTransfer( "getresults", lst );
}