Home | History | Annotate | Download | only in include
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #ifndef PVMF_CPMPLUGIN_PASSTHRU_OMA1_H_INCLUDED
     19 #define PVMF_CPMPLUGIN_PASSTHRU_OMA1_H_INCLUDED
     20 
     21 #ifndef OSCL_BASE_H_INCLUDED
     22 #include "oscl_base.h"
     23 #endif
     24 #ifndef OSCL_TYPES_H_INCLUDED
     25 #include "oscl_types.h"
     26 #endif
     27 #ifndef PVLOGGER_H_INCLUDED
     28 #include "pvlogger.h"
     29 #endif
     30 #ifndef PVMF_NODE_INTERFACE_H_INCLUDED
     31 #include "pvmf_node_interface.h"
     32 #endif
     33 #ifndef PVMF_NODE_UTILS_H_INCLUDED
     34 #include "pvmf_node_utils.h"
     35 #endif
     36 #ifndef OSCL_SCHEDULER_AO_H_INCLUDED
     37 #include "oscl_scheduler_ao.h"
     38 #endif
     39 #ifndef PVMF_CPMPLUGIN_INTERFACE_H_INCLUDED
     40 #include "pvmf_cpmplugin_interface.h"
     41 #endif
     42 #ifndef PVMF_CPMPLUGIN_AUTHORIZATION_INTERFACE_H_INCLUDED
     43 #include "pvmf_cpmplugin_authorization_interface.h"
     44 #endif
     45 #ifndef PVMF_CPMPLUGIN_AUTHENTICATION_INTERFACE_H_INCLUDED
     46 #include "pvmf_cpmplugin_authentication_interface.h"
     47 #endif
     48 #ifndef PVMF_CPMPLUGIN_ACCESS_INTERFACE_FACTORY_H_INCLUDED
     49 #include "pvmf_cpmplugin_access_interface_factory.h"
     50 #endif
     51 #ifndef PVMF_CPMPLUGIN_ACCESS_INTERFACE_H_INCLUDED
     52 #include "pvmf_cpmplugin_access_interface.h"
     53 #endif
     54 #ifndef PVMF_CPMPLUGIN_LICENSE_INTERFACE_H_INCLUDED
     55 #include "pvmf_cpmplugin_license_interface.h"
     56 #endif
     57 #ifndef PVMF_META_DATA_EXTENSION_H_INCLUDED
     58 #include "pvmf_meta_data_extension.h"
     59 #endif
     60 
     61 /**
     62  * Macros for calling PVLogger
     63  */
     64 #define PVMF_CPMPLUGIN_PASSTHRUOMA1_LOGERROR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
     65 #define PVMF_CPMPLUGIN_PASSTHRUOMA1_LOGWARNING(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_WARNING,m);
     66 #define PVMF_CPMPLUGIN_PASSTHRUOMA1_LOGINFOHI(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG,iLogger,PVLOGMSG_INFO,m);
     67 #define PVMF_CPMPLUGIN_PASSTHRUOMA1_LOGINFOMED(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG,iLogger,PVLOGMSG_INFO,m);
     68 #define PVMF_CPMPLUGIN_PASSTHRUOMA1_LOGINFOLOW(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_INFO,m);
     69 #define PVMF_CPMPLUGIN_PASSTHRUOMA1_LOGINFO(m) PVMF_CPMPLUGIN_PASSTHRUOMA1_LOGINFOMED(m)
     70 #define PVMF_CPMPLUGIN_PASSTHRUOMA1_LOGDEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG,iLogger,PVLOGMSG_DEBUG,m);
     71 
     72 #define PVMF_CPM_PASSTHRU_PLUGIN_OMA1_INTERNAL_CMDQ_SIZE 10
     73 //use a #define instead of a typedef here to avoid warnings on some compilers.
     74 #define PVMFCPMPassThruPlugInOMA1CommandBase PVMFGenericNodeCommand<OsclMemAllocator>
     75 
     76 class PVMFCPMPassThruPlugInOMA1Command : public PVMFCPMPassThruPlugInOMA1CommandBase
     77 {
     78     public:
     79         void Construct(PVMFSessionId s,
     80                        int32 cmd,
     81                        OsclAny* aArg1,
     82                        OsclAny* aArg2,
     83                        const OsclAny* aContext)
     84         {
     85             PVMFCPMPassThruPlugInOMA1CommandBase::Construct(s, cmd, aContext);
     86             iParam1 = aArg1;
     87             iParam2 = aArg2;
     88         };
     89 
     90         void Parse(OsclAny*&arg1, OsclAny*&arg2)
     91         {
     92             arg1 = iParam1;
     93             arg2 = iParam2;
     94         };
     95 
     96         void Construct(PVMFSessionId s,
     97                        int32 cmd,
     98                        OsclAny* aArg1,
     99                        OsclAny* aArg2,
    100                        OsclAny* aArg3,
    101                        const OsclAny* aContext)
    102         {
    103             PVMFCPMPassThruPlugInOMA1CommandBase::Construct(s, cmd, aContext);
    104             iParam1 = aArg1;
    105             iParam2 = aArg2;
    106             iParam3 = aArg3;
    107         };
    108 
    109         void Parse(OsclAny*&arg1, OsclAny*&arg2, OsclAny*&arg3)
    110         {
    111             arg1 = iParam1;
    112             arg2 = iParam2;
    113             arg3 = iParam3;
    114         };
    115 
    116         void Construct(PVMFSessionId s,
    117                        int32 cmd,
    118                        OsclAny* aArg1,
    119                        OsclAny* aArg2,
    120                        OsclAny* aArg3,
    121                        OsclAny* aArg4,
    122                        const OsclAny* aContext)
    123         {
    124             PVMFCPMPassThruPlugInOMA1CommandBase::Construct(s, cmd, aContext);
    125             iParam1 = aArg1;
    126             iParam2 = aArg2;
    127             iParam3 = aArg3;
    128             iParam4 = aArg4;
    129         };
    130 
    131         void Parse(OsclAny*&arg1, OsclAny*&arg2, OsclAny*&arg3, OsclAny*&arg4)
    132         {
    133             arg1 = iParam1;
    134             arg2 = iParam2;
    135             arg3 = iParam3;
    136             arg4 = iParam4;
    137         };
    138 };
    139 
    140 typedef PVMFNodeCommandQueue<PVMFCPMPassThruPlugInOMA1Command, OsclMemAllocator> PVMFCPMPassThruPlugInOMA1CmdQ;
    141 
    142 /* Start range for command IDs */
    143 #define PVMF_CPM_PASSTHRU_PLUGIN_OMA1_COMMAND_ID_START 50000
    144 
    145 /*
    146  * IDs for all of the asynchronous plugin commands.
    147  */
    148 enum TPVMFCPMPassThruPlugInOMA1Command
    149 {
    150     PVMF_CPM_PASSTHRU_PLUGIN_OMA1_QUERYUUID = PVMF_GENERIC_NODE_QUERYUUID
    151     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_QUERYINTERFACE = PVMF_GENERIC_NODE_QUERYINTERFACE
    152     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_INIT = PVMF_GENERIC_NODE_COMMAND_LAST
    153     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_RESET
    154     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_AUTHENTICATE
    155     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_AUTHORIZE_USAGE
    156     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_USAGE_COMPLETE
    157     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_GET_LICENSE
    158     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_CANCEL_GET_LICENSE
    159     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_METADATA_KEYS
    160     , PVMF_CPM_PASSTHRU_PLUGIN_OMA1_METADATA_VALUES
    161 };
    162 
    163 class OsclFileHandle;
    164 
    165 /*
    166  * CPM OMA1.0 Plugin
    167  */
    168 
    169 class PVMFCPMPassThruPlugInOMA1 : public OsclActiveObject,
    170         public PVMFCPMPluginInterface,
    171         public PVMFCPMPluginAuthenticationInterface,
    172         public PVMFCPMPluginAuthorizationInterface,
    173         public PVMFCPMPluginAccessInterfaceFactory,
    174         public PVMFCPMPluginLicenseInterface,
    175         public PVMFMetadataExtensionInterface
    176 {
    177     public:
    178         static PVMFCPMPluginInterface* CreatePlugIn(bool aFailAuthorizeUsage = false, bool aCancelAcquireLicense = false,
    179                 bool aSourceInitDataNotSupported = false,
    180                 PVMFCPMContentType aCPMContentType = PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS);
    181         static void DestroyPlugIn(PVMFCPMPluginInterface*);
    182 
    183     public:
    184         /* From PVInterface */
    185         void addRef()
    186         {
    187             ++iExtensionRefCount;
    188         }
    189         void removeRef()
    190         {
    191             --iExtensionRefCount;
    192         }
    193         bool queryInterface(const PVUuid& uuid, PVInterface*& iface);
    194 
    195         /* From PVMFCPMPluginInterface */
    196         OSCL_IMPORT_REF PVMFCommandId QueryUUID(PVMFSessionId aSession,
    197                                                 const PvmfMimeString& aMimeType,
    198                                                 Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    199                                                 bool aExactUuidsOnly = false,
    200                                                 const OsclAny* aContext = NULL);
    201         OSCL_IMPORT_REF PVMFCommandId QueryInterface(PVMFSessionId aSession,
    202                 const PVUuid& aUuid,
    203                 PVInterface*& aInterfacePtr,
    204                 const OsclAny* aContext = NULL);
    205         OSCL_IMPORT_REF PVMFCommandId Init(PVMFSessionId aSession,
    206                                            const OsclAny* aContext = NULL);
    207         OSCL_IMPORT_REF PVMFCommandId Reset(PVMFSessionId aSession,
    208                                             const OsclAny* aContext = NULL);
    209 
    210         OSCL_IMPORT_REF PVMFStatus SetSourceInitializationData(OSCL_wString& aSourceURL,
    211                 PVMFFormatType& aSourceFormat,
    212                 OsclAny* aSourceData);
    213 
    214         OSCL_IMPORT_REF PVMFCPMContentType GetCPMContentType();
    215 
    216 
    217         /* From PVMFCPMPluginAuthenticationInterface */
    218         OSCL_IMPORT_REF PVMFCommandId AuthenticateUser(PVMFSessionId aSessionId,
    219                 OsclAny* aAuthenticationData,
    220                 OsclAny* aContext = NULL);
    221 
    222         /* From PVMFCPMPluginAuthorizationInterface */
    223         OSCL_IMPORT_REF PVMFCommandId AuthorizeUsage(PVMFSessionId aSessionId,
    224                 PvmiKvp& aRequestedUsage,
    225                 PvmiKvp& aApprovedUsage,
    226                 PvmiKvp& aAuthorizationData,
    227                 uint32&  aRequestTimeOutInMS,
    228                 OsclAny* aContext = NULL);
    229 
    230         OSCL_IMPORT_REF PVMFCommandId UsageComplete(PVMFSessionId aSessionId,
    231                 const OsclAny* aContext = NULL);
    232 
    233         /* From PVMFCPMPluginAccessInterfaceFactory */
    234         OSCL_IMPORT_REF PVMFStatus QueryAccessInterfaceUUIDs(Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids);
    235         OSCL_IMPORT_REF PVInterface* CreatePVMFCPMPluginAccessInterface(PVUuid& aUuid);
    236         OSCL_IMPORT_REF void DestroyPVMFCPMPluginAccessInterface(PVUuid& aUuid,
    237                 PVInterface* aPtr);
    238         OSCL_IMPORT_REF void SetStreamReadCapacityObserver(PVMFDataStreamReadCapacityObserver* aObs);
    239 
    240 
    241         /* From PVMFCPMPluginAccessInterfaceFactory */
    242         OSCL_IMPORT_REF PVMFStatus GetLicenseURL(PVMFSessionId aSessionId,
    243                 OSCL_wString& aContentName,
    244                 OSCL_wString& aLicenseURL);
    245         OSCL_IMPORT_REF PVMFStatus GetLicenseURL(PVMFSessionId aSessionId,
    246                 OSCL_String&  aContentName,
    247                 OSCL_String&  aLicenseURL);
    248         OSCL_IMPORT_REF PVMFCommandId GetLicense(PVMFSessionId aSessionId
    249                 , OSCL_wString& aContentName
    250                 , OsclAny* aLicenseData = NULL
    251                                           , uint32 aDataSize = 0
    252                                                                , int32 aTimeoutMsec = (-1)
    253                                                                                       , OsclAny* aContext = NULL);
    254         OSCL_IMPORT_REF PVMFCommandId GetLicense(PVMFSessionId aSessionId
    255                 , OSCL_String&  aContentName
    256                 , OsclAny* aLicenseData = NULL
    257                                           , uint32 aDataSize = 0
    258                                                                , int32 aTimeoutMsec = (-1)
    259                                                                                       , OsclAny* aContext = NULL);
    260         OSCL_IMPORT_REF PVMFCommandId CancelGetLicense(PVMFSessionId aSessionId
    261                 , PVMFCommandId aCmdId
    262                 , OsclAny* aContext = NULL);
    263 
    264         //From PVMFMetadataExtensionInterface
    265         OSCL_IMPORT_REF uint32 GetNumMetadataKeys(char* aQueryKeyString = NULL) ;
    266         OSCL_IMPORT_REF uint32 GetNumMetadataValues(PVMFMetadataList& aKeyList) ;
    267         OSCL_IMPORT_REF PVMFCommandId GetNodeMetadataKeys(PVMFSessionId aSessionId,
    268                 PVMFMetadataList& aKeyList,
    269                 uint32 aStartingKeyIndex,
    270                 int32 aMaxKeyEntries = -1,
    271                 char* aQueryKeyString = NULL,
    272                 const OsclAny* aContextData = NULL) ;
    273         OSCL_IMPORT_REF PVMFCommandId GetNodeMetadataValues(PVMFSessionId aSessionId,
    274                 PVMFMetadataList& aKeyList,
    275                 Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList,
    276                 uint32 aStartingValueIndex,
    277                 int32 aMaxValueEntries = -1,
    278                 const OsclAny* aContextData = NULL) ;
    279         OSCL_IMPORT_REF PVMFStatus ReleaseNodeMetadataKeys(PVMFMetadataList& aKeyList,
    280                 uint32 aStartingKeyIndex,
    281                 uint32 aEndKeyIndex) ;
    282         OSCL_IMPORT_REF PVMFStatus ReleaseNodeMetadataValues(Oscl_Vector<PvmiKvp, OsclMemAllocator>& aValueList,
    283                 uint32 aStartingValueIndex,
    284                 uint32 aEndValueIndex) ;
    285 
    286     private:
    287         /* From PVMFCPMPluginInterface */
    288         void ThreadLogon();
    289         void ThreadLogoff();
    290 
    291         OSCL_IMPORT_REF PVMFCPMPassThruPlugInOMA1(bool aFailAuthorizeUsage = false,
    292                 bool aCancelAcquireLicense = false,
    293                 bool aSourceInitDataNotSupported = false,
    294                 PVMFCPMContentType aCPMContentType = PVMF_CPM_FORMAT_AUTHORIZE_BEFORE_ACCESS,
    295                 int32 aPriority = OsclActiveObject::EPriorityNominal);
    296 
    297         virtual ~PVMFCPMPassThruPlugInOMA1();
    298 
    299         void Run();
    300 
    301         PVMFCPMPassThruPlugInOMA1CmdQ iInputCommands;
    302         PVMFCPMPassThruPlugInOMA1CmdQ iCurrentCommand;
    303         PVMFCommandId QueueCommandL(PVMFCPMPassThruPlugInOMA1Command&);
    304         void MoveCmdToCurrentQueue(PVMFCPMPassThruPlugInOMA1Command& aCmd);
    305         bool ProcessCommand(PVMFCPMPassThruPlugInOMA1Command&);
    306         void CommandComplete(PVMFCPMPassThruPlugInOMA1CmdQ&,
    307                              PVMFCPMPassThruPlugInOMA1Command&,
    308                              PVMFStatus,
    309                              OsclAny* aData = NULL,
    310                              PVUuid* aEventUUID = NULL,
    311                              int32* aEventCode = NULL);
    312 
    313         void DoQueryUuid(PVMFCPMPassThruPlugInOMA1Command&);
    314         void DoQueryInterface(PVMFCPMPassThruPlugInOMA1Command&);
    315         void DoInit(PVMFCPMPassThruPlugInOMA1Command&);
    316         void DoReset(PVMFCPMPassThruPlugInOMA1Command&);
    317         void DoAuthenticate(PVMFCPMPassThruPlugInOMA1Command&);
    318         void DoAuthorizeUsage(PVMFCPMPassThruPlugInOMA1Command&);
    319         void DoUsageComplete(PVMFCPMPassThruPlugInOMA1Command& aCmd);
    320         PVMFStatus DoGetLicense(PVMFCPMPassThruPlugInOMA1Command& aCmd);
    321         void DoCancelGetLicense(PVMFCPMPassThruPlugInOMA1Command& aCmd);
    322         void DoMetadataKeys(PVMFCPMPassThruPlugInOMA1Command& aCmd);
    323         void DoMetadataValues(PVMFCPMPassThruPlugInOMA1Command& aCmd);
    324 
    325         PVLogger* iLogger;
    326         uint32 iExtensionRefCount;
    327 
    328         OSCL_wHeapString<OsclMemAllocator> iFilename;
    329         PVMFFormatType iSourceFormatType;
    330         bool oSourceSet;
    331         OsclFileHandle* iFileHandle;
    332         friend class PVMFCPMPassThruPlugInOMA1DataStreamSyncInterfaceImpl;
    333         bool iFailAuthorizeUsage;
    334         bool iCancelAcquireLicense;
    335         bool iSourceInitDataNotSupported;
    336         PVMFCPMContentType iCPMContentType;
    337         PVMFDataStreamReadCapacityObserver* iDataStreamReadCapacityObserver;
    338 
    339         //metadata related
    340         enum TOMA1Metadata
    341         {
    342             EIsProtectedOMA1
    343             , ELicAvailableOMA1
    344             , ELicTypeOMA1
    345             , EForwardLockOMA1
    346             , ELicLastOMA1 //placeholder.
    347         };
    348         class TOMA1MetadataEntry
    349         {
    350             public:
    351                 TOMA1MetadataEntry(): iValid(false) {}
    352                 bool iValid;
    353                 OSCL_HeapString<OsclMemAllocator> iQuery;//query key string.
    354                 OSCL_HeapString<OsclMemAllocator> iValue;//value string.
    355                 PvmiKvp iKvp;//value kvp.
    356         };
    357         //metadata array.
    358         TOMA1MetadataEntry iMetaData[ELicLastOMA1];
    359         OSCL_HeapString<OsclMemAllocator> iLicType;
    360         void MakeMetadata();
    361 };
    362 
    363 
    364 /*!
    365 ** PVMFCPMPassThruPlugInOMA1DataStreamSyncInterfaceImpl
    366 */
    367 class PVMFCPMPassThruPlugInOMA1DataStreamSyncInterfaceImpl : public PVMIDataStreamSyncInterface
    368 {
    369     public:
    370         // From PVInterface
    371         void addRef() {};
    372 
    373         void removeRef() {};
    374 
    375         OSCL_IMPORT_REF bool queryInterface(const PVUuid& uuid,
    376                                             PVInterface*& iface);
    377 
    378         OSCL_IMPORT_REF
    379         PvmiDataStreamStatus OpenSession(PvmiDataStreamSession& aSessionID,
    380                                          PvmiDataStreamMode aMode,
    381                                          bool nonblocking = false);
    382 
    383         OSCL_IMPORT_REF
    384         PvmiDataStreamStatus CloseSession(PvmiDataStreamSession aSessionID);
    385 
    386         OSCL_IMPORT_REF
    387         PvmiDataStreamRandomAccessType QueryRandomAccessCapability();
    388 
    389         OSCL_IMPORT_REF
    390         PvmiDataStreamStatus QueryReadCapacity(PvmiDataStreamSession aSessionID,
    391                                                uint32& capacity);
    392 
    393         OSCL_IMPORT_REF
    394         PvmiDataStreamCommandId RequestReadCapacityNotification(PvmiDataStreamSession aSessionID,
    395                 PvmiDataStreamObserver& observer,
    396                 uint32 capacity,
    397                 OsclAny* aContextData = NULL);
    398 
    399         OSCL_IMPORT_REF
    400         PvmiDataStreamStatus QueryWriteCapacity(PvmiDataStreamSession aSessionID,
    401                                                 uint32& capacity);
    402 
    403         OSCL_IMPORT_REF
    404         PvmiDataStreamCommandId RequestWriteCapacityNotification(PvmiDataStreamSession aSessionID,
    405                 PvmiDataStreamObserver& observer,
    406                 uint32 capacity,
    407                 OsclAny* aContextData = NULL);
    408 
    409         OSCL_IMPORT_REF
    410         PvmiDataStreamCommandId CancelNotification(PvmiDataStreamSession aSessionID,
    411                 PvmiDataStreamObserver& observer,
    412                 PvmiDataStreamCommandId aID,
    413                 OsclAny* aContextData = NULL);
    414 
    415         OSCL_IMPORT_REF
    416         PvmiDataStreamStatus Read(PvmiDataStreamSession aSessionID,
    417                                   uint8* buffer,
    418                                   uint32 size,
    419                                   uint32& numelements);
    420 
    421         OSCL_IMPORT_REF
    422         PvmiDataStreamStatus Write(PvmiDataStreamSession aSessionID,
    423                                    uint8* buffer,
    424                                    uint32 size,
    425                                    uint32& numelements);
    426 
    427         OSCL_IMPORT_REF
    428         PvmiDataStreamStatus Seek(PvmiDataStreamSession aSessionID,
    429                                   int32 offset,
    430                                   PvmiDataStreamSeekType origin);
    431 
    432         OSCL_IMPORT_REF
    433         uint32 GetCurrentPointerPosition(PvmiDataStreamSession aSessionID) ;
    434 
    435         OSCL_IMPORT_REF
    436         PvmiDataStreamStatus Flush(PvmiDataStreamSession aSessionID);
    437 
    438     private:
    439         friend class PVMFCPMPassThruPlugInOMA1;
    440         PVMFCPMPassThruPlugInOMA1DataStreamSyncInterfaceImpl(PVMFCPMPassThruPlugInOMA1&);
    441         ~PVMFCPMPassThruPlugInOMA1DataStreamSyncInterfaceImpl();
    442 
    443         Oscl_File *iFileObject;
    444         int32 iFileNumBytes;
    445         Oscl_FileServer iFs;
    446         PVMFCPMPassThruPlugInOMA1& iContainer;
    447         PVLogger* iLogger;
    448         PVMFDataStreamReadCapacityObserver* iDataStreamReadCapacityObserver;
    449 };
    450 #endif //PVMF_CPMPLUGIN_OMA1_H_INCLUDED
    451 
    452 
    453