btobexprofiles/obexsendservices/obexservicesendutils/src/BTSBPPObjectRequest.cpp
branchRCL_3
changeset 56 9386f31cc85b
parent 55 613943a21004
child 61 269724087bed
equal deleted inserted replaced
55:613943a21004 56:9386f31cc85b
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  GetReferencedObjects -operation implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "BTServiceUtils.h"
       
    22 #include "BTSBPPObjectRequest.h"
       
    23 #include "BTSUDataConverter.h"
       
    24 #include "BTSUImageConverter.h"
       
    25 #include "BTSUDebug.h"
       
    26 
       
    27 #include <f32file.h>    // RFile
       
    28 #include <s32mem.h>     // RBufWriteStream
       
    29 #include <s32file.h>    // RFileReadStream
       
    30 
       
    31 // CONSTANTS
       
    32 const TInt KBTSBPPFileSizeNotSet         = 0;
       
    33 const TInt KBTSBPPFileSizeRequested      = 1;
       
    34 const TInt KBTSBPPFileSizeUnknown        = -1;
       
    35 const TInt KBTSBPPRestOfTheFileRequested = -1;
       
    36 
       
    37 // The field lengths of Application Parameters -header in bytes
       
    38 //
       
    39 const TInt KBTSBPPFieldTag       = 1;
       
    40 const TInt KBTSBPPFieldLength    = 1;
       
    41 const TInt KBTSBPPValue          = 4;
       
    42 const TInt KBTSBPPAppParamLength = KBTSBPPFieldTag + KBTSBPPFieldLength + KBTSBPPValue;
       
    43 
       
    44 _LIT8(KBTSBPPRefObjectOper, "x-obex/referencedobject\0");
       
    45 
       
    46 static const TUint8 KBTSBPPFileSizeTag = 0x04;
       
    47 static const TUint8 KBTSBPPFileSizeLength = 0x04;
       
    48 
       
    49 // MODULE DATA STRUCTURES
       
    50 enum KBTSBPPAppParamTags
       
    51     {
       
    52     KBTSBPPTagOffset = 1,
       
    53     KBTSBPPTagCount,
       
    54     KBTSBPPTagJobId, // used only in JobBased-printing
       
    55     KBTSBPPTagFileSize
       
    56     };
       
    57 
       
    58 // ============================ MEMBER FUNCTIONS ===============================
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // CBTSBPPObjectRequest::CBTSBPPObjectRequest
       
    62 // C++ default constructor can NOT contain any code, that
       
    63 // might leave.
       
    64 // -----------------------------------------------------------------------------
       
    65 //
       
    66 CBTSBPPObjectRequest::CBTSBPPObjectRequest( CObexBaseObject* aGetOperation,
       
    67     const CDesCArray* aRefObjectList ) : iRequest( aGetOperation ), 
       
    68                                          iObjectList( aRefObjectList )
       
    69     {
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // CBTSBPPObjectRequest::ConstructL
       
    74 // Symbian 2nd phase constructor can leave.
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 void CBTSBPPObjectRequest::ConstructL()
       
    78     {
       
    79     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::ConstructL()"));
       
    80 
       
    81     User::LeaveIfError( iFileSession.Connect() );
       
    82 
       
    83     // Check the validity of the operation and it's paramters.
       
    84     //
       
    85     CheckGetRequestL();
       
    86 
       
    87     // Execute any tasks needed and create the requested object.
       
    88     //
       
    89     ExecuteGetRequestL();
       
    90 
       
    91     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::ConstructL() completed"));
       
    92     }
       
    93 
       
    94 // -----------------------------------------------------------------------------
       
    95 // CBTSBPPObjectRequest::NewL
       
    96 // Two-phased constructor.
       
    97 // -----------------------------------------------------------------------------
       
    98 //
       
    99 CBTSBPPObjectRequest* CBTSBPPObjectRequest::NewL( CObexBaseObject* aGetOperation,
       
   100                                               const CDesCArray* aRefObjectList )
       
   101     {
       
   102     CBTSBPPObjectRequest* self = new( ELeave ) CBTSBPPObjectRequest( aGetOperation,
       
   103                                                                  aRefObjectList );
       
   104     CleanupStack::PushL( self );
       
   105     self->ConstructL();
       
   106     CleanupStack::Pop();
       
   107     return self;
       
   108     }
       
   109 
       
   110     
       
   111 // Destructor
       
   112 CBTSBPPObjectRequest::~CBTSBPPObjectRequest()
       
   113     {
       
   114     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::~CBTSBPPObjectRequest()"));
       
   115     iFileSession.Close();
       
   116 
       
   117     delete iResponse;
       
   118     delete iResponseBuffer;
       
   119 
       
   120     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::~CBTSBPPObjectRequest() completed"));
       
   121     }
       
   122 
       
   123 // -----------------------------------------------------------------------------
       
   124 // CBTSBPPObjectRequest::GetResponse
       
   125 // -----------------------------------------------------------------------------
       
   126 //
       
   127 CObexBufObject* CBTSBPPObjectRequest::GetResponse()
       
   128     {
       
   129     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::GetResponse()"));
       
   130     return iResponse;
       
   131     }
       
   132 
       
   133 // -----------------------------------------------------------------------------
       
   134 // CBTSBPPObjectRequest::CheckGetRequestL
       
   135 // -----------------------------------------------------------------------------
       
   136 //
       
   137 void CBTSBPPObjectRequest::CheckGetRequestL()
       
   138     {
       
   139     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckGetRequestL()"));
       
   140 
       
   141     CheckTypeHeaderL();
       
   142     CheckNameHeaderL();
       
   143     CheckAppParamsHeaderL();
       
   144     }
       
   145 
       
   146 // -----------------------------------------------------------------------------
       
   147 // CBTSBPPObjectRequest::CheckTypeHeaderL
       
   148 // -----------------------------------------------------------------------------
       
   149 //
       
   150 void CBTSBPPObjectRequest::CheckTypeHeaderL()
       
   151     {
       
   152     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckTypeHeaderL()"));
       
   153 
       
   154     __ASSERT_DEBUG( iRequest, BTSUPanic( EBTSUPanicNullPointer ) );
       
   155 
       
   156     const TDesC8& typeHeader = iRequest->Type();
       
   157 
       
   158     if ( typeHeader.Length() == 0 )
       
   159         {
       
   160         FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckTypeHeaderL() ERROR, no type header"));
       
   161         User::Leave( KErrNotFound );
       
   162         }
       
   163     else if ( typeHeader.Length() > KBTSUMaxStringLength )
       
   164         {
       
   165         FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckTypeHeaderL() ERROR, type header too long"));
       
   166         User::Leave( KErrTooBig );
       
   167         }
       
   168     else
       
   169         {
       
   170         FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckTypeHeaderL() type header '%S'"), &typeHeader ));
       
   171         // The only supported operation is GetReferencedObjects
       
   172         //
       
   173         if ( typeHeader != KBTSBPPRefObjectOper() )
       
   174             {
       
   175             FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckTypeHeaderL() ERROR, unsupported operation"));
       
   176             User::Leave( KErrNotSupported );
       
   177             }
       
   178         }
       
   179 
       
   180     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckTypeHeaderL() completed"));
       
   181     }
       
   182 
       
   183 // -----------------------------------------------------------------------------
       
   184 // CBTSBPPObjectRequest::CheckNameHeaderL
       
   185 // -----------------------------------------------------------------------------
       
   186 //
       
   187 void CBTSBPPObjectRequest::CheckNameHeaderL()
       
   188     {
       
   189     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckNameHeaderL()"));
       
   190 
       
   191     __ASSERT_DEBUG( iRequest, BTSUPanic( EBTSUPanicNullPointer ) );
       
   192 
       
   193     const TDesC& nameHeader = iRequest->Name();
       
   194 
       
   195     if ( nameHeader.Length() == 0 )
       
   196         {
       
   197         FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckNameHeaderL() ERROR, no name header"));
       
   198         User::Leave( KErrNotFound );
       
   199         }
       
   200     else
       
   201         {
       
   202         FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckNameHeaderL() filename '%S'"), &nameHeader ));
       
   203 
       
   204         // Check are we allowed to send this file
       
   205         //
       
   206         TInt dummy;
       
   207         if ( iObjectList->Find( nameHeader, dummy ) != KBTSUEqualStrings )
       
   208             {
       
   209             FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckNameHeaderL() ERROR, the asked object is not referenced in the document"));
       
   210             User::Leave( KErrPermissionDenied );
       
   211             }
       
   212 
       
   213         iRequestParams.iName = &nameHeader;
       
   214         }
       
   215     }
       
   216 
       
   217 // -----------------------------------------------------------------------------
       
   218 // CBTSBPPObjectRequest::CheckAppParamsHeaderL
       
   219 //
       
   220 // This method expects a Tag-Length-Value format. The method is as defensive 
       
   221 // as possible, for example unknown or illegal values are discarded.
       
   222 // -----------------------------------------------------------------------------
       
   223 //
       
   224 void CBTSBPPObjectRequest::CheckAppParamsHeaderL()
       
   225     {
       
   226     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckAppParamsHeaderL()"));
       
   227 
       
   228     __ASSERT_DEBUG( iRequest, BTSUPanic( EBTSUPanicNullPointer ) );
       
   229 
       
   230     TPtrC8 header( iRequest->AppParam() );    
       
   231 
       
   232     if ( header.Length() == 0 )
       
   233         {
       
   234         FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckAppParamsHeaderL() ERROR, no AppParam header"));
       
   235         User::Leave( KErrNotFound );
       
   236         }
       
   237     else if ( header.Length() < KBTSBPPAppParamLength * 2)
       
   238         {
       
   239         // There has to be at least offset and count -parameters.
       
   240         //
       
   241         FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckAppParamsHeaderL() ERROR, incomplete AppParam header"));
       
   242         User::Leave( KErrArgument );
       
   243         }
       
   244     else
       
   245         {
       
   246         // Parse the header
       
   247         //
       
   248         while( header.Length() >= KBTSBPPAppParamLength )
       
   249             {
       
   250             // Extract tag number and remove it from the header
       
   251             //
       
   252             TInt tagNumber = TBTSUDataConverter::ConvertByteL(
       
   253                 header.Left( KBTSBPPFieldTag ) );
       
   254             header.Set( header.Mid( KBTSBPPFieldTag ) );
       
   255 
       
   256             // Extract value length and remove it from the header
       
   257             //
       
   258             TInt valueLength = TBTSUDataConverter::ConvertByteL( 
       
   259                 header.Left( KBTSBPPFieldLength ) );
       
   260             header.Set( header.Mid( KBTSBPPFieldLength ) );
       
   261 
       
   262             if ( valueLength != KBTSBPPValue )
       
   263                 {
       
   264                 FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckAppParamsHeaderL() WARNING, illegal length %d"), valueLength ));
       
   265                 valueLength = KBTSBPPValue;
       
   266                 // This is an interesting choice of what to do, I would argue that for future compatibility you'll probably want to accept the length
       
   267                 // provided as it might be for a new tag that is not yet published.  (Checking of the size for known tags is handled by the conversion
       
   268                 // functions anyway).
       
   269                 // So, in summary I wouldn't change valueLength from what it is in the payload.  But I've left it in for now in case it was added for
       
   270                 // interoperability reasons with some existing device.
       
   271                 }
       
   272 
       
   273             // Extract value...
       
   274             //
       
   275             switch ( tagNumber )
       
   276                 {
       
   277                 case KBTSBPPTagOffset:
       
   278                     {
       
   279                     iRequestParams.iOffset = 
       
   280                         TBTSUDataConverter::ConvertDataUnsignedL( 
       
   281                         header.Left( valueLength ) );
       
   282 
       
   283                     FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckAppParamsHeaderL() offset '%d'"), iRequestParams.iOffset ));
       
   284                     break;
       
   285                     }
       
   286                 case KBTSBPPTagCount:
       
   287                     {
       
   288                     iRequestParams.iCount = 
       
   289                         TBTSUDataConverter::ConvertDataSignedL( 
       
   290                         header.Left( valueLength ) );
       
   291 
       
   292                     FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckAppParamsHeaderL() count '%d'"), iRequestParams.iCount ));
       
   293                     break;
       
   294                     }
       
   295                 case KBTSBPPTagFileSize:
       
   296                     {
       
   297                     // The value is not interesting, we just need to know whether 
       
   298                     // the parameter was received (and thus requested)
       
   299                     //
       
   300                     iRequestParams.iOffset = KBTSBPPFileSizeRequested;
       
   301                     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::ParseHeadersL() fileSize parameter received"));
       
   302                     break;
       
   303                     }
       
   304 
       
   305                 case KBTSBPPTagJobId:
       
   306                 default:
       
   307                     {
       
   308                     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckAppParamsHeaderL() WARNING, illegal tag"));
       
   309                     break;
       
   310                     }
       
   311                 }
       
   312 
       
   313             // ...and remove it from the header
       
   314             //
       
   315             header.Set( header.Mid( valueLength ) );
       
   316             }
       
   317         }
       
   318 
       
   319     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CheckAppParamsHeaderL() completed"));
       
   320     }
       
   321 
       
   322 // -----------------------------------------------------------------------------
       
   323 // CBTSBPPObjectRequest::ExecuteGetRequestL
       
   324 // -----------------------------------------------------------------------------
       
   325 //
       
   326 void CBTSBPPObjectRequest::ExecuteGetRequestL()
       
   327     {
       
   328     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::ExecuteGetRequestL()"));
       
   329 
       
   330     // If iCount is 0, an empty body will be sent
       
   331     //
       
   332     if ( iRequestParams.iCount != 0 )
       
   333         {
       
   334         ResolveGetRequestL();
       
   335         ReadFileToBufferL();      
       
   336         }
       
   337 
       
   338     CreateResponseObjectL();
       
   339 
       
   340     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::ExecuteGetRequestL() completed"));
       
   341     }
       
   342 
       
   343 // -----------------------------------------------------------------------------
       
   344 // CBTSBPPObjectRequest::ResolveGetRequestL
       
   345 // -----------------------------------------------------------------------------
       
   346 //
       
   347 void CBTSBPPObjectRequest::ResolveGetRequestL()
       
   348     {
       
   349     FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::ResolveGetRequestL()"));
       
   350 
       
   351     // Get the file size
       
   352     //
       
   353     RFile file;
       
   354     TInt size = 0;
       
   355     User::LeaveIfError( file.Open( iFileSession, *iRequestParams.iName, 
       
   356                                    EFileShareReadersOnly | EFileStream ) );
       
   357 
       
   358     TInt error = file.Size( size );
       
   359     
       
   360     if ( error )
       
   361         {
       
   362         FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::ResolveGetRequestL() error %d in getting the size"), error ) );
       
   363         size = KBTSBPPFileSizeUnknown;
       
   364         }
       
   365 
       
   366     file.Close();
       
   367 
       
   368     // Store the file size if it was requested
       
   369     //
       
   370     if ( iRequestParams.iFileSize == KBTSBPPFileSizeRequested )
       
   371         {
       
   372         iRequestParams.iFileSize = size;
       
   373         }
       
   374 
       
   375     // Resolve the actual amount of data that needs to be read.
       
   376     // 
       
   377     TInt dataLeft = size - iRequestParams.iOffset;
       
   378 
       
   379     if ( iRequestParams.iCount == KBTSBPPRestOfTheFileRequested )
       
   380         {
       
   381         if ( size == KBTSBPPFileSizeUnknown )
       
   382             {
       
   383             // The size of the file is unknown, so read as much 
       
   384             // as would fit into the buffer
       
   385             //
       
   386             iRequestParams.iCount = KBTSUDataBufferMaxSize;
       
   387             }        
       
   388         else
       
   389             {
       
   390             // The rest of the file is requested, so correct the count
       
   391             //
       
   392             iRequestParams.iCount = dataLeft;
       
   393             }
       
   394         }
       
   395     else if ( iRequestParams.iCount > dataLeft )
       
   396         {
       
   397         // There is less data left that was requested, so correct the count
       
   398         //
       
   399         iRequestParams.iCount = dataLeft;
       
   400         }
       
   401 
       
   402     if ( iRequestParams.iCount > KBTSUDataBufferMaxSize )
       
   403         {
       
   404         // The requested count is too big
       
   405         //
       
   406         FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::ResolveGetRequestL() iCount too big %d"), iRequestParams.iCount ) );
       
   407         User::Leave( KErrTooBig );
       
   408         }
       
   409 
       
   410     FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::ResolveGetRequestL() completed, requested %d bytes"), iRequestParams.iCount ) );
       
   411     }
       
   412 
       
   413 // -----------------------------------------------------------------------------
       
   414 // CBTSBPPObjectRequest::ReadFileToBufferL
       
   415 // -----------------------------------------------------------------------------
       
   416 //
       
   417 void CBTSBPPObjectRequest::ReadFileToBufferL()
       
   418     {
       
   419     __ASSERT_DEBUG( !iResponseBuffer, BTSUPanic( EBTSUPanicExistingObject ) );
       
   420 
       
   421     // Create a buffer for the object and reserve space according to the request
       
   422     //
       
   423     iResponseBuffer = CBufFlat::NewL( KBTSUDataBufferExpandSize );
       
   424     iResponseBuffer->SetReserveL( iRequestParams.iCount );
       
   425     iResponseBuffer->ResizeL( iRequestParams.iCount );
       
   426 
       
   427     // Open the file
       
   428     //
       
   429     RFile file;
       
   430     User::LeaveIfError( file.Open( iFileSession, *iRequestParams.iName, 
       
   431                                    EFileShareReadersOnly | EFileStream ) );
       
   432     CleanupClosePushL( file );
       
   433 
       
   434     // Create a stream for reading from the file
       
   435     //
       
   436     RFileReadStream readStream( file, iRequestParams.iOffset );
       
   437 
       
   438     // Create a stream for writing into the buffer
       
   439     //
       
   440     RBufWriteStream writeStream( *iResponseBuffer );
       
   441 
       
   442     // Read the data from file to the buffer
       
   443     //
       
   444     readStream.ReadL( writeStream, iRequestParams.iCount );
       
   445 
       
   446     FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::ReadFileToBufferL() space reserved '%d'"), iRequestParams.iCount ));
       
   447     FTRACE(FPrint(_L("[BTSBPP]\t CBTSBPPObjectRequest::ReadFileToBufferL() data read '%d'"), iResponseBuffer->Size() ));
       
   448 
       
   449     CleanupStack::PopAndDestroy(&file);
       
   450     }
       
   451 
       
   452 
       
   453 // -----------------------------------------------------------------------------
       
   454 // CBTSBPPObjectRequest::CreateResponseObjectL
       
   455 // -----------------------------------------------------------------------------
       
   456 //
       
   457 void CBTSBPPObjectRequest::CreateResponseObjectL()
       
   458     {
       
   459     __ASSERT_DEBUG( iResponseBuffer || (iRequestParams.iCount == 0), BTSUPanic( EBTSUPanicNoBufferEvenThoughCountNotZero ) );
       
   460     __ASSERT_DEBUG( !iResponse, BTSUPanic( EBTSUPanicResponseAlreadyPresent ) );
       
   461     
       
   462     // Create the OBEX response object using the buffer already created (or no buffer if appropriate)
       
   463     //
       
   464     iResponse = CObexBufObject::NewL( iResponseBuffer );
       
   465     
       
   466     // Generate FileSize parameter if requested
       
   467     //
       
   468     if ( iRequestParams.iFileSize != KBTSBPPFileSizeNotSet )
       
   469         {
       
   470         FLOG(_L("[BTSBPP]\t CBTSBPPObjectRequest::CreateResponseObjectL() generate file size param"));
       
   471         TBuf8<KBTSBPPAppParamLength> params;
       
   472         params.SetMax();
       
   473         TUint8* ptr = const_cast<TUint8*>(params.Ptr());
       
   474         *ptr++ = KBTSBPPFileSizeTag;
       
   475         *ptr++ = KBTSBPPFileSizeLength;
       
   476         BigEndian::Put32(ptr, *reinterpret_cast<TUint32*>(&iRequestParams.iFileSize)); // reinterpret cast to retain signed nature...
       
   477         iResponse->SetAppParamL( params );
       
   478         }
       
   479     }
       
   480 
       
   481 //  End of File