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