Logo Search packages:      
Sourcecode: akonadi version File versions  Download package

bool Store::handleLine ( const QByteArray &  line  )  [virtual]

Process one line of input.

Parameters:
line The input.
Returns:
false if the handler expects to read more data from the client, true otherwise.

Reimplemented from Akonadi::Handler.

Definition at line 44 of file store.cpp.

References Akonadi::QueryBuilder::addValueCondition(), Akonadi::HandlerHelper::collectionFromIdOrName(), Akonadi::Transaction::commit(), Akonadi::QueryBuilder::exec(), Akonadi::Handler::failureResponse(), Akonadi::Handler::imapSetToQuery(), Akonadi::ImapParser::parseNumber(), Akonadi::ImapParser::parseParenthesizedList(), Akonadi::ImapParser::parseSequenceSet(), Akonadi::ImapParser::parseString(), Akonadi::Handler::responseAvailable(), Akonadi::SelectQueryBuilder< T >::result(), Akonadi::Response::setString(), Akonadi::Response::setSuccess(), Akonadi::Response::setTag(), Akonadi::Response::setUntagged(), Akonadi::ImapParser::splitVersionedKey(), Akonadi::AkonadiConnection::storageBackend(), Akonadi::Handler::tag(), and Akonadi::DataStore::updatePimItem().

{
  int pos = line.indexOf( ' ' ) + 1; // skip tag
  QByteArray buffer;
  pos = ImapParser::parseString( line, buffer, pos );
  bool uidStore = false;
  if ( buffer == "UID" ) {
    uidStore = true;
    pos = ImapParser::parseString( line, buffer, pos ); // skip 'STORE'
  }

  Response response;
  response.setUntagged();

  ImapSet set;
  pos = ImapParser::parseSequenceSet( line, set, pos );
  if ( set.isEmpty() )
    return failureResponse( "No item specified" );

  DataStore *store = connection()->storageBackend();
  Transaction transaction( store );

  SelectQueryBuilder<PimItem> qb;
  imapSetToQuery( set, uidStore, qb );
  if ( !qb.exec() )
    return failureResponse( "Unable to retrieve items" );
  QList<PimItem> pimItems = qb.result();
  if ( pimItems.isEmpty() )
    return failureResponse( "No items found" );

  // parse revision
  qint64 rev;
  bool revCheck = true;
  bool ok;
  pos = ImapParser::parseString( line, buffer, pos ); // skip 'REV'
  if ( buffer == "REV" ) {
    pos = ImapParser::parseNumber( line, rev, &ok, pos );
    if ( !ok ) {
      return failureResponse( "Unable to parse item revision number." );
    }
  }
  else if ( buffer == "NOREV" )
    revCheck   = false;

  for ( int i = 0; i < pimItems.count(); ++i ) {
    if ( revCheck ) {
      // check if revision number of given items and their database equivalents match
      if ( pimItems.at( i ).rev() != (int)rev ) {
        return failureResponse( "Item was modified elsewhere, aborting STORE." );
      }
    }

    // update item revision
    pimItems[ i ].setRev( pimItems[ i ].rev() + 1 );
    pimItems[ i ].setDatetime( QDateTime::currentDateTime() );
    if ( !pimItems[ i ].update() ) {
      return failureResponse( "Unable to update item revision" );
    }
  }

  QList<QByteArray> changes;
  pos = ImapParser::parseParenthesizedList( line, changes, pos );
  for ( int i = 0; i < changes.size() - 1; i += 2 ) {
    // parse command
    QByteArray command = changes[ i ];
    Operation op = Replace;
    bool silent = false;
    if ( command.isEmpty() )
      break;

    if ( command.startsWith( '+' ) ) {
      op = Add;
      command = command.mid( 1 );
    } else if ( command.startsWith( '-' ) ) {
      op = Delete;
      command = command.mid( 1 );
    }
    if ( command.endsWith( ".SILENT" ) ) {
      silent = true;
      command.chop( 7 );
    }
    const QByteArray value = changes[i + 1];

    for ( int i = 0; i < pimItems.count(); ++i ) {
      // handle command
      if ( command == "FLAGS" ) {
        QList<QByteArray> flags;
        ImapParser::parseParenthesizedList( value, flags );
        if ( op == Replace ) {
          if ( !replaceFlags( pimItems[ i ], flags ) )
            return failureResponse( "Unable to replace item flags." );
        } else if ( op == Add ) {
          if ( !addFlags( pimItems[ i ], flags ) )
            return failureResponse( "Unable to add item flags." );
        } else if ( op == Delete ) {
          if ( !deleteFlags( pimItems[ i ], flags ) )
            return failureResponse( "Unable to remove item flags." );
        }
      } else if ( command == "PARTS" ) {
        QList<QByteArray> parts;
        ImapParser::parseParenthesizedList( value, parts );
        if ( op == Delete ) {
          if ( !deleteParts( pimItems[ i ], parts ) )
          return failureResponse( "Unable to remove item parts." );
        }
      } else if ( command == "COLLECTION" ) {
        if ( !store->updatePimItem( pimItems[ i ], HandlerHelper::collectionFromIdOrName( value ) ) )
          return failureResponse( "Unable to move item." );
      } else if ( command == "REMOTEID" ) {
        if ( !store->updatePimItem( pimItems[i], QString::fromUtf8( value ) ) )
          return failureResponse( "Unable to change remote id for item." );
      } else if ( command == "DIRTY" ) {
          PimItem item = pimItems.at( i );
          item.setDirty( false );
          if ( !item.update() )
            return failureResponse( "Unable to update item dirtyness" );
      } else {
        Part part;
        int version = 0;
        QByteArray plainCommand;

        ImapParser::splitVersionedKey( command, plainCommand, version );

        SelectQueryBuilder<Part> qb;
        qb.addValueCondition( Part::pimItemIdColumn(), Query::Equals, pimItems[ i ].id() );
        qb.addValueCondition( Part::nameColumn(), Query::Equals, QString::fromUtf8( plainCommand ) );
        if ( !qb.exec() )
          return failureResponse( "Unable to check item part existence" );
        Part::List result = qb.result();
        if ( !result.isEmpty() ) {
          part = result.first();
        }

        // only update if part contents are not yet in the storage
        if ( part.data() != value )
        {
          part.setData( value );
          part.setDatasize( buffer.size() );
          part.setName( QString::fromUtf8( plainCommand ) );
          part.setVersion( version );
          part.setPimItemId( pimItems[ i ].id() );
          if ( part.isValid() ) {
            if ( !part.update() )
              return failureResponse( "Unable to update item part" );
          } else {
            if ( !part.insert() )
              return failureResponse( "Unable to add item part" );
          }
          store->updatePimItem( pimItems[ i ] );
        }
      }

      if ( !silent ) {
        QList<Flag> flags = pimItems[ i ].flags();
        QStringList flagList;
        for ( int j = 0; j < flags.count(); ++j )
          flagList.append( flags[ j ].name() );

        response.setUntagged();
        // IMAP protocol violation: should actually be the sequence number
        response.setString( QByteArray::number( pimItems[i].id() ) + " FETCH (FLAGS (" + flagList.join( QLatin1String(" ") ).toUtf8() + "))" );
        emit responseAvailable( response );
      }
    }
  }

  if ( !transaction.commit() )
    return failureResponse( "Cannot commit transaction." );

  response.setTag( tag() );
  response.setSuccess();
  response.setString( "STORE completed" );

  emit responseAvailable( response );
  deleteLater();

  return true;
}


Generated by  Doxygen 1.6.0   Back to index