14 * Description: Implement the operation: SetObjectPropList |
14 * Description: Implement the operation: SetObjectPropList |
15 * |
15 * |
16 */ |
16 */ |
17 |
17 |
18 |
18 |
19 #include <mtp/mmtpdataproviderframework.h> |
|
20 #include <mtp/cmtptypeobjectproplist.h> |
19 #include <mtp/cmtptypeobjectproplist.h> |
21 #include <mtp/mmtpobjectmgr.h> |
20 #include <mtp/mmtpobjectmgr.h> |
22 #include <mtp/cmtptypestring.h> |
21 #include <mtp/cmtptypestring.h> |
23 #include <mtp/cmtptypearray.h> |
22 #include <mtp/cmtptypearray.h> |
24 |
23 |
25 #include "csetobjectproplist.h" |
24 #include "csetobjectproplist.h" |
26 #include "cmmmtpdpmetadataaccesswrapper.h" |
25 #include "cmmmtpdpmetadataaccesswrapper.h" |
27 #include "mmmtpdputility.h" |
26 #include "mmmtpdputility.h" |
28 #include "mmmtpdplogger.h" |
27 #include "mmmtpdplogger.h" |
29 #include "mmmtpdpconfig.h" |
28 #include "mmmtpdpconfig.h" |
30 |
29 #include "cpropertysettingutility.h" |
31 // ----------------------------------------------------------------------------- |
30 |
32 // CSetObjectPropList::NewL |
31 // ----------------------------------------------------------------------------- |
|
32 // CSendObject::NewL |
33 // Two-phase construction method |
33 // Two-phase construction method |
34 // ----------------------------------------------------------------------------- |
34 // ----------------------------------------------------------------------------- |
35 // |
35 // |
36 //EXPORT_C MMmRequestProcessor* CSetObjectPropList::NewL( MMTPDataProviderFramework& aFramework, |
36 EXPORT_C MMmRequestProcessor* CSetObjectPropList::NewL( MMTPDataProviderFramework& aFramework, |
37 // MMTPConnection& aConnection, |
37 MMTPConnection& aConnection, |
38 // CMmMtpDpMetadataAccessWrapper& aWrapper ) |
38 MMmMtpDpConfig& aDpConfig ) |
39 // { |
39 { |
40 // CSetObjectPropList* self = new ( ELeave ) CSetObjectPropList( aFramework, |
40 CSetObjectPropList* self = new ( ELeave ) CSetObjectPropList( aFramework, aConnection, aDpConfig ); |
41 // aConnection, |
41 |
42 // aWrapper ); |
42 CleanupStack::PushL(self); |
43 // CleanupStack::PushL( self ); |
43 self->ConstructL(); |
44 // self->ConstructL(); |
44 CleanupStack::Pop(self); |
45 // CleanupStack::Pop( self ); |
45 |
46 // return self; |
46 return self; |
47 // } |
47 } |
48 |
48 |
49 // ----------------------------------------------------------------------------- |
49 // ----------------------------------------------------------------------------- |
50 // CSetObjectPropList::CSetObjectPropList |
50 // CSetObjectPropList::CSetObjectPropList |
51 // Standard c++ constructor |
51 // Standard c++ constructor |
52 // ----------------------------------------------------------------------------- |
52 // ----------------------------------------------------------------------------- |
53 // |
53 // |
54 EXPORT_C CSetObjectPropList::CSetObjectPropList( MMTPDataProviderFramework& aFramework, |
54 CSetObjectPropList::CSetObjectPropList( MMTPDataProviderFramework& aFramework, |
55 MMTPConnection& aConnection, |
55 MMTPConnection& aConnection, |
56 MMmMtpDpConfig& aDpConfig ) : |
56 MMmMtpDpConfig& aDpConfig ) : |
57 CRequestProcessor( aFramework, aConnection, 0, NULL), |
57 CRequestProcessor( aFramework, aConnection, 0, NULL), |
58 iObjectMgr( aFramework.ObjectMgr() ), |
58 iObjectMgr( aFramework.ObjectMgr() ), |
59 iFs( aFramework.Fs() ), |
59 iFs( aFramework.Fs() ), |
60 iDpConfig( aDpConfig ), |
60 iDpConfig( aDpConfig ), |
61 iUnprocessedIndex ( 0 ) |
61 iUnprocessedIndex ( 0 ) |
62 { |
62 { |
63 PRINT( _L( "Operation: SetObjectPropList(0x9806)" ) ); |
63 PRINT( _L( "Operation: SetObjectPropList(0x9806)" ) ); |
64 } |
64 } |
65 |
65 |
66 // ----------------------------------------------------------------------------- |
66 // ----------------------------------------------------------------------------- |
67 // CSetObjectPropList::ConstructL |
67 // CSetObjectPropList::ConstructL |
68 // 2nd Phase Constructor |
68 // 2nd Phase Constructor |
69 // ----------------------------------------------------------------------------- |
69 // ----------------------------------------------------------------------------- |
70 // |
70 // |
71 EXPORT_C void CSetObjectPropList::ConstructL() |
71 void CSetObjectPropList::ConstructL() |
72 { |
72 { |
73 CActiveScheduler::Add( this ); |
73 CActiveScheduler::Add( this ); |
74 |
74 |
75 iPropertyList = CMTPTypeObjectPropList::NewL(); |
75 iPropertyList = CMTPTypeObjectPropList::NewL(); |
76 SetPSStatus(); |
76 SetPSStatus(); |
83 // |
83 // |
84 EXPORT_C CSetObjectPropList::~CSetObjectPropList() |
84 EXPORT_C CSetObjectPropList::~CSetObjectPropList() |
85 { |
85 { |
86 Cancel(); |
86 Cancel(); |
87 delete iPropertyList; |
87 delete iPropertyList; |
|
88 } |
|
89 |
|
90 // ----------------------------------------------------------------------------- |
|
91 // CSetObjectPropList::CheckRequestL |
|
92 // |
|
93 // ----------------------------------------------------------------------------- |
|
94 // |
|
95 EXPORT_C TMTPResponseCode CSetObjectPropList::CheckRequestL() |
|
96 { |
|
97 PRINT( _L( "MM MTP => CSetObjectPropList::CheckRequestL" ) ); |
|
98 |
|
99 TMTPResponseCode result = CRequestProcessor::CheckRequestL(); |
|
100 if ( result == EMTPRespCodeObjectWriteProtected ) |
|
101 { |
|
102 // Return AccessDenied for P4S pass rate, instead of EMTPRespCodeObjectWriteProtected |
|
103 result = EMTPRespCodeAccessDenied; |
|
104 } |
|
105 |
|
106 PRINT( _L( "MM MTP <= CSetObjectPropList::CheckRequestL" ) ); |
|
107 return result; |
88 } |
108 } |
89 |
109 |
90 // ----------------------------------------------------------------------------- |
110 // ----------------------------------------------------------------------------- |
91 // CSetObjectPropList::ServiceL |
111 // CSetObjectPropList::ServiceL |
92 // SetObjectPropList request handler |
112 // SetObjectPropList request handler |
130 // ----------------------------------------------------------------------------- |
150 // ----------------------------------------------------------------------------- |
131 // CSetObjectPropList::SetObjectPropListL |
151 // CSetObjectPropList::SetObjectPropListL |
132 // Set object proplist |
152 // Set object proplist |
133 // ----------------------------------------------------------------------------- |
153 // ----------------------------------------------------------------------------- |
134 // |
154 // |
135 TMTPResponseCode CSetObjectPropList::SetObjectPropListL( |
155 TMTPResponseCode CSetObjectPropList::SetObjectPropListL( const CMTPTypeObjectPropListElement& aPropListElement ) |
136 const CMTPTypeObjectPropListElement& aPropListElement ) |
|
137 { |
156 { |
138 PRINT( _L( "MM MTP => CSetObjectPropList::SetObjectPropListL" ) ); |
157 PRINT( _L( "MM MTP => CSetObjectPropList::SetObjectPropListL" ) ); |
139 |
158 |
140 TMTPTypeUint16 protectionStatus( EMTPProtectionNoProtection ); |
|
141 TMTPResponseCode responseCode( EMTPRespCodeOK ); |
159 TMTPResponseCode responseCode( EMTPRespCodeOK ); |
142 |
160 |
143 TUint32 handle = aPropListElement.Uint32L( CMTPTypeObjectPropListElement::EObjectHandle ); |
161 TUint32 handle = aPropListElement.Uint32L( CMTPTypeObjectPropListElement::EObjectHandle ); |
144 TUint16 propertyCode = aPropListElement.Uint16L( CMTPTypeObjectPropListElement::EPropertyCode ); |
162 TUint16 propertyCode = aPropListElement.Uint16L( CMTPTypeObjectPropListElement::EPropertyCode ); |
145 TUint16 dataType = aPropListElement.Uint16L( CMTPTypeObjectPropListElement::EDatatype ); |
163 TUint16 dataType = aPropListElement.Uint16L( CMTPTypeObjectPropListElement::EDatatype ); |
146 PRINT3( _L( "MM MTP <> handle = 0x%x, propertyCode = 0x%x, dataType = 0x%x" ), |
164 PRINT3( _L( "MM MTP <> handle = 0x%x, propertyCode = 0x%x, dataType = 0x%x" ), |
147 handle, propertyCode, dataType ); |
165 handle, |
|
166 propertyCode, |
|
167 dataType ); |
148 |
168 |
149 responseCode = MmMtpDpUtility::CheckPropType( propertyCode, dataType ); |
169 responseCode = MmMtpDpUtility::CheckPropType( propertyCode, dataType ); |
150 PRINT1( _L( "MM MTP <> CheckPropType response code is 0x%x" ), responseCode ); |
170 PRINT1( _L( "MM MTP <> CheckPropType response code is 0x%x" ), responseCode ); |
|
171 |
151 if( responseCode != EMTPRespCodeOK ) |
172 if( responseCode != EMTPRespCodeOK ) |
152 return responseCode; |
173 return responseCode; |
153 |
174 |
154 if ( iFramework.ObjectMgr().ObjectOwnerId( handle ) |
175 if ( iFramework.ObjectMgr().ObjectOwnerId( handle ) |
155 == iFramework.DataProviderId() ) |
176 == iFramework.DataProviderId() ) |
156 { |
177 { |
157 PRINT( _L( "MM MTP => CSetObjectPropList::SetObjectPropListL enter" ) ); |
178 PRINT( _L( "MM MTP => CSetObjectPropList::SetObjectPropListL enter" ) ); |
|
179 |
158 CMTPObjectMetaData* object = CMTPObjectMetaData::NewLC(); // + object |
180 CMTPObjectMetaData* object = CMTPObjectMetaData::NewLC(); // + object |
159 iFramework.ObjectMgr().ObjectL( handle, *object ); |
181 iFramework.ObjectMgr().ObjectL( handle, *object ); |
160 |
182 |
161 if ( protectionStatus.Value() != EMTPProtectionNoProtection ) |
183 // Check the file attribution first. If it is Read-Only, nothing should be set into db which is inlined with P4S cases. |
|
184 TUint16 protectionStatus = EMTPProtectionNoProtection; |
|
185 protectionStatus = MmMtpDpUtility::GetProtectionStatusL( iFs, object->DesC( CMTPObjectMetaData::ESuid ) ); |
|
186 if ( protectionStatus != EMTPProtectionNoProtection ) |
162 { |
187 { |
163 //for some reason, P4S expects Access Denied response instead of write protected |
188 // NOTE: P4S expects AccessDenied response instead of ObjectWriteProtected |
164 return EMTPRespCodeAccessDenied; // EMTPRespCodeObjectWriteProtected; |
189 return EMTPRespCodeAccessDenied; // EMTPRespCodeObjectWriteProtected; |
165 } |
190 } |
166 |
191 |
167 switch ( propertyCode ) |
192 switch ( propertyCode ) |
168 { |
193 { |
170 case EMTPObjectPropCodeObjectFormat: |
195 case EMTPObjectPropCodeObjectFormat: |
171 case EMTPObjectPropCodeProtectionStatus: |
196 case EMTPObjectPropCodeProtectionStatus: |
172 case EMTPObjectPropCodeObjectSize: |
197 case EMTPObjectPropCodeObjectSize: |
173 case EMTPObjectPropCodeParentObject: |
198 case EMTPObjectPropCodeParentObject: |
174 case EMTPObjectPropCodePersistentUniqueObjectIdentifier: |
199 case EMTPObjectPropCodePersistentUniqueObjectIdentifier: |
175 case EMTPObjectPropCodeNonConsumable: |
|
176 case EMTPObjectPropCodeDateAdded: |
200 case EMTPObjectPropCodeDateAdded: |
177 case EMTPObjectPropCodeDateCreated: |
201 case EMTPObjectPropCodeDateCreated: |
178 case EMTPObjectPropCodeDateModified: |
202 case EMTPObjectPropCodeDateModified: |
179 { |
203 { |
180 responseCode = EMTPRespCodeAccessDenied; |
204 responseCode = EMTPRespCodeAccessDenied; |
181 } |
205 } |
182 break; |
206 break; |
183 |
207 |
|
208 case EMTPObjectPropCodeNonConsumable: |
|
209 object->SetUint( CMTPObjectMetaData::ENonConsumable, |
|
210 aPropListElement.Uint8L( CMTPTypeObjectPropListElement::EValue ) ); |
|
211 // TODO: need to reconsider, |
|
212 // if propList comprise both non-consumable and objectFileName, |
|
213 // ModifyObjectL would be called twice, need to investigate if it won't affect |
|
214 // performance |
|
215 iFramework.ObjectMgr().ModifyObjectL( *object ); |
|
216 break; |
|
217 |
184 case EMTPObjectPropCodeObjectFileName: |
218 case EMTPObjectPropCodeObjectFileName: |
185 { |
219 { |
186 TPtrC suid( object->DesC( CMTPObjectMetaData::ESuid ) ); |
220 TPtrC suid( object->DesC( CMTPObjectMetaData::ESuid ) ); |
187 TBuf<KMaxFileName> newSuid( aPropListElement.StringL( |
221 TPtrC ptr( aPropListElement.StringL( CMTPTypeObjectPropListElement::EValue ) ); |
188 CMTPTypeObjectPropListElement::EValue ) ); |
222 if ( KMaxFileName < ptr.Length() ) |
189 TInt err = KErrNone; |
223 responseCode = EMTPRespCodeInvalidDataset; |
190 err = MmMtpDpUtility::UpdateObjectFileName( iFramework.Fs(), suid, newSuid ); |
224 else |
191 PRINT1( _L( "MM MTP <> Update object file name err = %d" ), err ); |
|
192 if ( KErrOverflow == err ) // full path name is too long |
|
193 { |
225 { |
194 responseCode = EMTPRespCodeInvalidDataset; |
226 TFileName newSuid( ptr ); |
195 } |
227 TInt err = MmMtpDpUtility::UpdateObjectFileName( iFramework.Fs(), suid, newSuid ); |
196 else if ( ( KErrNone == err ) || ( KErrAlreadyExists == err ) ) |
228 PRINT1( _L( "MM MTP <> Update object file name err = %d" ), err ); |
197 { |
229 if ( KErrOverflow == err ) // full path name is too long |
198 TRAP( err, iDpConfig.GetWrapperL().RenameObjectL( suid, newSuid ) ); //Update MPX DB |
|
199 PRINT1( _L( "MM MTP <> Rename Object err = %d" ), err ); |
|
200 // it is ok if file is not found in DB, following S60 solution |
|
201 if ( KErrNotFound == err ) |
|
202 { |
230 { |
203 TRAP( err, iDpConfig.GetWrapperL().AddObjectL( newSuid ) ); |
231 responseCode = EMTPRespCodeInvalidDataset; |
204 PRINT1( _L( "MM MTP <> Add Object err = %d" ), err ); |
|
205 } |
232 } |
206 |
233 else if ( KErrNone == err ) // TODO: ( KErrAlreadyExists == err ) |
207 if ( KErrNone == err ) |
|
208 { |
234 { |
|
235 TRAP( err, iDpConfig.GetWrapperL().RenameObjectL( *object, newSuid ) ); //Update MPX DB |
|
236 |
|
237 PRINT1( _L( "MM MTP <> Rename MPX object file name err = %d" ), err ); |
|
238 // it is ok if file is not found in DB, following S60 solution |
|
239 if ( KErrNotFound == err ) |
|
240 { |
|
241 TRAP( err, iDpConfig.GetWrapperL().AddObjectL( *object ) ); |
|
242 PRINT1( _L( "MM MTP <> Add MPX object file name err = %d" ), err ); |
|
243 } |
|
244 |
209 object->SetDesCL( CMTPObjectMetaData::ESuid, newSuid ); |
245 object->SetDesCL( CMTPObjectMetaData::ESuid, newSuid ); |
210 iFramework.ObjectMgr().ModifyObjectL( *object ); |
246 iFramework.ObjectMgr().ModifyObjectL( *object ); |
211 } |
247 } |
212 else |
248 else |
213 { |
249 { |
216 } |
252 } |
217 } |
253 } |
218 break; |
254 break; |
219 |
255 |
220 case EMTPObjectPropCodeName: |
256 case EMTPObjectPropCodeName: |
|
257 case EMTPObjectPropCodeAlbumArtist: |
221 { |
258 { |
222 CMTPTypeString* stringData = CMTPTypeString::NewLC( |
259 CMTPTypeString* stringData = CMTPTypeString::NewLC( |
223 aPropListElement.StringL( |
260 aPropListElement.StringL( CMTPTypeObjectPropListElement::EValue ) );// + stringData |
224 CMTPTypeObjectPropListElement::EValue ) );// + stringData |
261 |
225 |
262 responseCode = iDpConfig.PropSettingUtility()->SetMetaDataToWrapper( iDpConfig, |
226 responseCode = ServiceMetaDataToWrapperL( propertyCode, |
263 propertyCode, |
227 *stringData, *object ); |
264 *stringData, |
|
265 *object ); |
228 |
266 |
229 CleanupStack::PopAndDestroy( stringData );// - stringData |
267 CleanupStack::PopAndDestroy( stringData );// - stringData |
230 } |
268 } |
231 break; |
269 break; |
232 |
270 |
233 default: |
271 default: |
234 { |
272 { |
235 /*// trap and handle with response code here, so correct fail index should report |
273 responseCode = iDpConfig.PropSettingUtility()->SetSpecificObjectPropertyL( iDpConfig, |
236 TRAPD( err, responseCode = ServiceSpecificObjectPropertyL( propertyCode, *object, aPropListElement ) ); |
274 propertyCode, |
237 PRINT1( _L("MM MTP <> CSetObjectPropList::SetObjectPropListL, ServiceSpecificObjectPropertyL, err = %d"), err ); |
275 *object, |
238 |
|
239 if ( err == KErrNotSupported ) |
|
240 { |
|
241 responseCode = EMTPRespCodeAccessDenied; |
|
242 }*/ |
|
243 responseCode = ServiceSpecificObjectPropertyL( propertyCode, *object, |
|
244 aPropListElement ); |
276 aPropListElement ); |
245 } |
277 } |
246 break; |
278 break; |
247 } |
279 } |
248 |
280 |
259 // ----------------------------------------------------------------------------- |
291 // ----------------------------------------------------------------------------- |
260 // |
292 // |
261 EXPORT_C TBool CSetObjectPropList::HasDataphase() const |
293 EXPORT_C TBool CSetObjectPropList::HasDataphase() const |
262 { |
294 { |
263 return ETrue; |
295 return ETrue; |
264 } |
|
265 |
|
266 // ----------------------------------------------------------------------------- |
|
267 // CSetObjectPropList::ServiceMetaDataToWrapperL |
|
268 // |
|
269 // ----------------------------------------------------------------------------- |
|
270 // |
|
271 EXPORT_C TMTPResponseCode CSetObjectPropList::ServiceMetaDataToWrapperL( |
|
272 const TUint16 aPropCode, |
|
273 MMTPType& aNewData, |
|
274 const CMTPObjectMetaData& aObjectMetaData ) |
|
275 { |
|
276 TMTPResponseCode resCode = EMTPRespCodeOK; |
|
277 |
|
278 TRAPD( err, iDpConfig.GetWrapperL().SetObjectMetadataValueL( aPropCode, |
|
279 aNewData, |
|
280 aObjectMetaData ) ); |
|
281 |
|
282 PRINT1( _L("MM MTP <> CSetObjectPropList::ServiceMetaDataToWrapperL err = %d"), err); |
|
283 |
|
284 if ( err == KErrNone ) |
|
285 { |
|
286 resCode = EMTPRespCodeOK; |
|
287 } |
|
288 else if ( err == KErrTooBig ) |
|
289 // according to the codes of S60 |
|
290 { |
|
291 resCode = EMTPRespCodeInvalidDataset; |
|
292 } |
|
293 else if ( err == KErrPermissionDenied ) |
|
294 { |
|
295 resCode = EMTPRespCodeAccessDenied; |
|
296 } |
|
297 else if ( err == KErrNotFound ) |
|
298 { |
|
299 if( MmMtpDpUtility::HasMetadata( aObjectMetaData.Uint( CMTPObjectMetaData::EFormatCode ) ) ) |
|
300 SendResponseL( EMTPRespCodeAccessDenied ); |
|
301 } |
|
302 else |
|
303 { |
|
304 // add new virtual call to see if the above condition can be handle probably |
|
305 err = HandleSpecificWrapperError( err, aObjectMetaData ); |
|
306 |
|
307 if ( err != KErrNone ) |
|
308 resCode = EMTPRespCodeGeneralError; |
|
309 } |
|
310 |
|
311 PRINT1( _L( "MM MTP <= CSetObjectPropList::ServiceMetaDataToWrapperL resCode = 0x%x" ), resCode ); |
|
312 |
|
313 return resCode; |
|
314 } |
296 } |
315 |
297 |
316 // ----------------------------------------------------------------------------- |
298 // ----------------------------------------------------------------------------- |
317 // CSetObjectPropList::RunL |
299 // CSetObjectPropList::RunL |
318 // |
300 // |