sl@0
|
1 |
/*
|
sl@0
|
2 |
* Copyright (c) 2003-2010 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
3 |
* All rights reserved.
|
sl@0
|
4 |
* This component and the accompanying materials are made available
|
sl@0
|
5 |
* under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
6 |
* which accompanies this distribution, and is available
|
sl@0
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
8 |
*
|
sl@0
|
9 |
* Initial Contributors:
|
sl@0
|
10 |
* Nokia Corporation - initial contribution.
|
sl@0
|
11 |
*
|
sl@0
|
12 |
* Contributors:
|
sl@0
|
13 |
*
|
sl@0
|
14 |
* Description:
|
sl@0
|
15 |
*
|
sl@0
|
16 |
*/
|
sl@0
|
17 |
|
sl@0
|
18 |
|
sl@0
|
19 |
#include <s32file.h>
|
sl@0
|
20 |
#include <ecom/ecom.h>
|
sl@0
|
21 |
#include <ecom/implementationproxy.h>
|
sl@0
|
22 |
|
sl@0
|
23 |
#include "resolver.h"
|
sl@0
|
24 |
#include "mimetypemapping.h"
|
sl@0
|
25 |
#include "CafApaRecognizer.h"
|
sl@0
|
26 |
|
sl@0
|
27 |
using namespace ContentAccess;
|
sl@0
|
28 |
|
sl@0
|
29 |
|
sl@0
|
30 |
CApaCafRecognizer* CApaCafRecognizer::NewL()
|
sl@0
|
31 |
{
|
sl@0
|
32 |
CApaCafRecognizer* self;
|
sl@0
|
33 |
self = new (ELeave) CApaCafRecognizer();
|
sl@0
|
34 |
CleanupStack::PushL(self);
|
sl@0
|
35 |
self->ConstructL();
|
sl@0
|
36 |
CleanupStack::Pop(self);
|
sl@0
|
37 |
return self;
|
sl@0
|
38 |
}
|
sl@0
|
39 |
|
sl@0
|
40 |
void CApaCafRecognizer::ConstructL()
|
sl@0
|
41 |
{
|
sl@0
|
42 |
iResolver = CAgentResolver::NewL(ETrue);
|
sl@0
|
43 |
SetupContentTypesL();
|
sl@0
|
44 |
}
|
sl@0
|
45 |
|
sl@0
|
46 |
CApaCafRecognizer::CApaCafRecognizer() :
|
sl@0
|
47 |
CApaDataRecognizerType(KUidCafApaRecognizer, CApaDataRecognizerType::ELow)
|
sl@0
|
48 |
{
|
sl@0
|
49 |
// Assume initially we don't recognize any data types (ie. no agents)
|
sl@0
|
50 |
iCountDataTypes = 0;
|
sl@0
|
51 |
}
|
sl@0
|
52 |
|
sl@0
|
53 |
CApaCafRecognizer::~CApaCafRecognizer()
|
sl@0
|
54 |
{
|
sl@0
|
55 |
iContentTypes.ResetAndDestroy();
|
sl@0
|
56 |
delete iResolver;
|
sl@0
|
57 |
}
|
sl@0
|
58 |
|
sl@0
|
59 |
void CApaCafRecognizer::SetupContentTypesL()
|
sl@0
|
60 |
{
|
sl@0
|
61 |
// Construct the array used to map content types to our drm mime types
|
sl@0
|
62 |
CMimeTypeMapping* mimeType;
|
sl@0
|
63 |
|
sl@0
|
64 |
// The RecCaf configuration file is just a list of content mime types
|
sl@0
|
65 |
// CApaCafRecognizer expects each mime type to be on a separate line
|
sl@0
|
66 |
// The configuration file is stored in the Apparc server's private directory.
|
sl@0
|
67 |
// This should be ok since the recognizer is run in the apparc servers process
|
sl@0
|
68 |
|
sl@0
|
69 |
// ROM file
|
sl@0
|
70 |
_LIT(KRomConfigurationFile, "Z:\\private\\10003A3F\\RecCaf\\RecCafMimeTypes.txt");
|
sl@0
|
71 |
|
sl@0
|
72 |
// System drive file
|
sl@0
|
73 |
_LIT(KConfigurationFile, "_:\\private\\10003A3F\\RecCaf\\RecCafMimeTypes.txt");
|
sl@0
|
74 |
TBuf<47> sysDriveConfigFile(KConfigurationFile);
|
sl@0
|
75 |
sysDriveConfigFile[0] = 'A' + static_cast<TInt>(RFs::GetSystemDrive());
|
sl@0
|
76 |
|
sl@0
|
77 |
RFs fs;
|
sl@0
|
78 |
User::LeaveIfError(fs.Connect());
|
sl@0
|
79 |
CleanupClosePushL(fs);
|
sl@0
|
80 |
|
sl@0
|
81 |
RFile file;
|
sl@0
|
82 |
TInt result = file.Open(fs, sysDriveConfigFile, EFileRead | EFileStream | EFileShareAny);
|
sl@0
|
83 |
if (result != KErrNone)
|
sl@0
|
84 |
{
|
sl@0
|
85 |
result = file.Open(fs, KRomConfigurationFile(), EFileRead | EFileStream | EFileShareAny);
|
sl@0
|
86 |
}
|
sl@0
|
87 |
|
sl@0
|
88 |
if (result == KErrNone)
|
sl@0
|
89 |
{
|
sl@0
|
90 |
CleanupClosePushL(file);
|
sl@0
|
91 |
|
sl@0
|
92 |
// create file stream
|
sl@0
|
93 |
RFileReadStream inputFileStream(file);
|
sl@0
|
94 |
CleanupClosePushL(inputFileStream);
|
sl@0
|
95 |
|
sl@0
|
96 |
TBuf8 <KMaxDataTypeLength> buf;
|
sl@0
|
97 |
|
sl@0
|
98 |
do
|
sl@0
|
99 |
{
|
sl@0
|
100 |
// Read a content mime type from the file
|
sl@0
|
101 |
result = ReadLine(inputFileStream, buf);
|
sl@0
|
102 |
|
sl@0
|
103 |
if (result == KErrNone || result == KErrEof)
|
sl@0
|
104 |
{
|
sl@0
|
105 |
// Add a new entry into the array of mime types
|
sl@0
|
106 |
if (buf.Length())
|
sl@0
|
107 |
{
|
sl@0
|
108 |
// force to lower case to ensure that chosen lower case scheme for mime
|
sl@0
|
109 |
// types is maintained
|
sl@0
|
110 |
buf.LowerCase();
|
sl@0
|
111 |
mimeType = CMimeTypeMapping::NewL(buf);
|
sl@0
|
112 |
CleanupStack::PushL(mimeType);
|
sl@0
|
113 |
User::LeaveIfError(iContentTypes.Append(mimeType));
|
sl@0
|
114 |
CleanupStack::Pop(mimeType);
|
sl@0
|
115 |
}
|
sl@0
|
116 |
}
|
sl@0
|
117 |
else
|
sl@0
|
118 |
{
|
sl@0
|
119 |
// Encountered an error reading the file
|
sl@0
|
120 |
// don't know how to recover so leave
|
sl@0
|
121 |
iContentTypes.ResetAndDestroy();
|
sl@0
|
122 |
User::Leave(result);
|
sl@0
|
123 |
}
|
sl@0
|
124 |
} while (result != KErrEof);
|
sl@0
|
125 |
|
sl@0
|
126 |
CleanupStack::PopAndDestroy(2, &file); // inputFileStream, file
|
sl@0
|
127 |
}
|
sl@0
|
128 |
|
sl@0
|
129 |
CleanupStack::PopAndDestroy(&fs);
|
sl@0
|
130 |
|
sl@0
|
131 |
// Add multiple content object file mime type
|
sl@0
|
132 |
_LIT8(KApplicationXCafStr, "application/x-caf");
|
sl@0
|
133 |
mimeType = CMimeTypeMapping::NewL(KApplicationXCafStr());
|
sl@0
|
134 |
CleanupStack::PushL(mimeType);
|
sl@0
|
135 |
User::LeaveIfError(iContentTypes.Append(mimeType));
|
sl@0
|
136 |
CleanupStack::Pop(mimeType);
|
sl@0
|
137 |
|
sl@0
|
138 |
|
sl@0
|
139 |
// Add supplier Mime types
|
sl@0
|
140 |
// otherwise nobody will recognize unprocessed files
|
sl@0
|
141 |
// that could be churned through the CAF Supplier API
|
sl@0
|
142 |
// The resolver ensures that its supplier mime types are lower case
|
sl@0
|
143 |
for(TInt index = 0; index < iResolver->SupplierMimeTypes().Count(); index++)
|
sl@0
|
144 |
{
|
sl@0
|
145 |
mimeType = CMimeTypeMapping::NewL(iResolver->SupplierMimeTypes()[index],
|
sl@0
|
146 |
iResolver->SupplierMimeTypes()[index]);
|
sl@0
|
147 |
CleanupStack::PushL(mimeType);
|
sl@0
|
148 |
User::LeaveIfError(iContentTypes.Append(mimeType));
|
sl@0
|
149 |
CleanupStack::Pop(mimeType);
|
sl@0
|
150 |
}
|
sl@0
|
151 |
|
sl@0
|
152 |
iCountDataTypes = iContentTypes.Count();
|
sl@0
|
153 |
}
|
sl@0
|
154 |
|
sl@0
|
155 |
TInt CApaCafRecognizer::ReadLine(RFileReadStream& aInStream, TDes8& aBuffer)
|
sl@0
|
156 |
{
|
sl@0
|
157 |
const TChar KCarriageReturn = '\r';
|
sl@0
|
158 |
const TChar KLineFeed = '\n';
|
sl@0
|
159 |
|
sl@0
|
160 |
// Clear the buffer
|
sl@0
|
161 |
aBuffer.SetLength(0);
|
sl@0
|
162 |
|
sl@0
|
163 |
// Read line upto linefeed delimiter
|
sl@0
|
164 |
TRAPD(err, aInStream.ReadL(aBuffer, KLineFeed));
|
sl@0
|
165 |
TInt length = aBuffer.Length();
|
sl@0
|
166 |
|
sl@0
|
167 |
// assume all lines must end in CRLF and do not
|
sl@0
|
168 |
// allow blank lines. So length must be at least 2 for
|
sl@0
|
169 |
// the CRLF characters
|
sl@0
|
170 |
if(length < 3)
|
sl@0
|
171 |
{
|
sl@0
|
172 |
err = KErrEof;
|
sl@0
|
173 |
}
|
sl@0
|
174 |
if (err == KErrNone)
|
sl@0
|
175 |
{
|
sl@0
|
176 |
// remove line feed and any carriage return
|
sl@0
|
177 |
if (aBuffer[length - 1] == KLineFeed)
|
sl@0
|
178 |
{
|
sl@0
|
179 |
--length;
|
sl@0
|
180 |
}
|
sl@0
|
181 |
if (aBuffer[length - 1] == KCarriageReturn)
|
sl@0
|
182 |
{
|
sl@0
|
183 |
--length;
|
sl@0
|
184 |
}
|
sl@0
|
185 |
aBuffer.SetLength(length);
|
sl@0
|
186 |
}
|
sl@0
|
187 |
return err;
|
sl@0
|
188 |
}
|
sl@0
|
189 |
|
sl@0
|
190 |
|
sl@0
|
191 |
TUint CApaCafRecognizer::PreferredBufSize()
|
sl@0
|
192 |
{
|
sl@0
|
193 |
// Ask all of the agents if they have a preferred buffer size for calls to DoRecognizeL()
|
sl@0
|
194 |
return iResolver->PreferredBufferSize();
|
sl@0
|
195 |
}
|
sl@0
|
196 |
|
sl@0
|
197 |
TDataType CApaCafRecognizer::SupportedDataTypeL(TInt aIndex) const
|
sl@0
|
198 |
{
|
sl@0
|
199 |
// leave if an out of range aIndex is supplied
|
sl@0
|
200 |
if (aIndex < 0 || aIndex >= iContentTypes.Count())
|
sl@0
|
201 |
{
|
sl@0
|
202 |
User::Leave(KErrArgument);
|
sl@0
|
203 |
}
|
sl@0
|
204 |
|
sl@0
|
205 |
return TDataType(iContentTypes[aIndex]->CafMimeType());
|
sl@0
|
206 |
}
|
sl@0
|
207 |
|
sl@0
|
208 |
void CApaCafRecognizer::DoRecognizeL(const TDesC& aName, const TDesC8& aBuffer)
|
sl@0
|
209 |
{
|
sl@0
|
210 |
TBuf8 <KMaxDataTypeLength> FileMimeType;
|
sl@0
|
211 |
TBuf8 <KMaxDataTypeLength> ContentMimeType;
|
sl@0
|
212 |
|
sl@0
|
213 |
// Need to start by assuming we don't recognize the file
|
sl@0
|
214 |
iConfidence = ENotRecognized;
|
sl@0
|
215 |
|
sl@0
|
216 |
TBool isRecognized = EFalse;
|
sl@0
|
217 |
|
sl@0
|
218 |
// If aName is prepended with 2 colons (::), then it is not valid, and we need to
|
sl@0
|
219 |
// derive it from the file handle. Otherwise, we assume that aName is valid
|
sl@0
|
220 |
if (aName.Match(_L("::*")) == KErrNotFound)
|
sl@0
|
221 |
{
|
sl@0
|
222 |
isRecognized = iResolver->DoRecognizeL(aName, aBuffer, FileMimeType, ContentMimeType);
|
sl@0
|
223 |
}
|
sl@0
|
224 |
// aName is not a valid URI/filename and a file handle must be used. This is marked
|
sl@0
|
225 |
// by two colons at the start of aName.
|
sl@0
|
226 |
// We need to get the actual file name from the file handle.
|
sl@0
|
227 |
else
|
sl@0
|
228 |
{
|
sl@0
|
229 |
RFile* fileHandle = CApaCafRecognizer::FilePassedByHandleL();
|
sl@0
|
230 |
|
sl@0
|
231 |
if( fileHandle == NULL )
|
sl@0
|
232 |
{
|
sl@0
|
233 |
return;
|
sl@0
|
234 |
}
|
sl@0
|
235 |
|
sl@0
|
236 |
TBuf<KMaxDataTypeLength> fileName;
|
sl@0
|
237 |
User::LeaveIfError(fileHandle->Name(fileName));
|
sl@0
|
238 |
isRecognized = iResolver->DoRecognizeL(fileName, aBuffer, FileMimeType, ContentMimeType);
|
sl@0
|
239 |
}
|
sl@0
|
240 |
|
sl@0
|
241 |
if (isRecognized == EFalse)
|
sl@0
|
242 |
{
|
sl@0
|
243 |
return;
|
sl@0
|
244 |
}
|
sl@0
|
245 |
|
sl@0
|
246 |
|
sl@0
|
247 |
// If there is no content type but the file is recognized it is assumed
|
sl@0
|
248 |
// to be a file that can be processed through the supplier interface
|
sl@0
|
249 |
|
sl@0
|
250 |
// dummy object for comparison in match function
|
sl@0
|
251 |
CMimeTypeMapping* mimeTypeMapping = (ContentMimeType.Length() == 0) ?
|
sl@0
|
252 |
CMimeTypeMapping::NewL(FileMimeType) :
|
sl@0
|
253 |
CMimeTypeMapping::NewL(ContentMimeType);
|
sl@0
|
254 |
|
sl@0
|
255 |
|
sl@0
|
256 |
// check that the content mime type is one of the ones we
|
sl@0
|
257 |
// told Apparc we can recognize in the beginning
|
sl@0
|
258 |
// The mime type should always be found as the file has been recognised.
|
sl@0
|
259 |
// If not it is because an agent, when recognising the file, has set a mime type not in its supplier list.
|
sl@0
|
260 |
// Mime types are always forced to lower case therefore this match can be case sensitive.
|
sl@0
|
261 |
TInt index = iContentTypes.Find(mimeTypeMapping, CMimeTypeMapping::ContentMimeTypeMatch);
|
sl@0
|
262 |
if (index != KErrNotFound)
|
sl@0
|
263 |
{
|
sl@0
|
264 |
iDataType = TDataType(iContentTypes[index]->CafMimeType());
|
sl@0
|
265 |
iConfidence=ECertain;
|
sl@0
|
266 |
}
|
sl@0
|
267 |
|
sl@0
|
268 |
delete mimeTypeMapping;
|
sl@0
|
269 |
}
|
sl@0
|
270 |
|
sl@0
|
271 |
const TImplementationProxy ImplementationTable[] =
|
sl@0
|
272 |
{
|
sl@0
|
273 |
IMPLEMENTATION_PROXY_ENTRY(0x102031E9, CApaCafRecognizer::NewL)
|
sl@0
|
274 |
};
|
sl@0
|
275 |
|
sl@0
|
276 |
EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
|
sl@0
|
277 |
{
|
sl@0
|
278 |
aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
|
sl@0
|
279 |
return ImplementationTable;
|
sl@0
|
280 |
}
|
sl@0
|
281 |
|
sl@0
|
282 |
|