|
1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "BTRegistryDB.h" |
|
17 #include <bluetooth/logger.h> |
|
18 |
|
19 #ifdef __FLOG_ACTIVE |
|
20 _LIT8(KLogComponent, LOG_COMPONENT_BT_MANAGER_SERVER); |
|
21 #endif |
|
22 |
|
23 const TInt KMaxLengthConstraintInitial = 60; // constraint length is initially this |
|
24 const TInt KMaxLengthConstraintIncrement = 60; // - then we extend as necessary by this amount |
|
25 |
|
26 RBTDbQuery::RBTDbQuery() |
|
27 /** |
|
28 Required for non-default constructed RTextBuf |
|
29 **/ |
|
30 { |
|
31 LOG_FUNC |
|
32 } |
|
33 |
|
34 void RBTDbQuery::Close() |
|
35 { |
|
36 LOG_FUNC |
|
37 iQueryBuf.Close(); |
|
38 } |
|
39 |
|
40 const TPtrC RBTDbQuery::QuoteEscapeLC(const TBTDevAddr& aBDAddr) const |
|
41 { |
|
42 LOG_FUNC |
|
43 TBuf<6> wideAddr; // needed to stop implicit converstion back to DevAddr! |
|
44 wideAddr.Copy(aBDAddr.Des()); |
|
45 return QuoteEscapeLC(wideAddr); |
|
46 } |
|
47 |
|
48 const TPtrC RBTDbQuery::QuoteEscapeLC(const TDesC& aDes) const |
|
49 /** |
|
50 Can't search for a string in SQL with a quote (') in un-escaped |
|
51 Escape by putting extra quote in for every quote in the descriptor |
|
52 **/ |
|
53 { |
|
54 LOG_FUNC |
|
55 const TUint16 KEscapeCode = 0x0027; // SQL escape value |
|
56 // maximum size of new descriptor will be twice the original (if it contained all quotes!) |
|
57 HBufC* escaped = HBufC::NewMaxLC(2*aDes.Length()); |
|
58 TPtr escapedPtr= escaped->Des(); |
|
59 |
|
60 TInt i=0; |
|
61 TInt escapedIndex = 0; |
|
62 while (i<aDes.Length()) |
|
63 { |
|
64 const TChar& element = aDes[i++]; // copes with narrow and wide |
|
65 #pragma warning (disable : 4244) // conversion - its ok here |
|
66 escapedPtr[escapedIndex++] = element; |
|
67 #pragma warning (default : 4244) |
|
68 if (element == KEscapeCode) |
|
69 { |
|
70 escapedPtr[escapedIndex++] = KEscapeCode; |
|
71 } |
|
72 } |
|
73 escapedPtr.SetLength(escapedIndex); // bring down from the MaxLength |
|
74 return escapedPtr; // returns ownership of the HBuf via cleanupstack |
|
75 } |
|
76 |
|
77 void RBTDbQuery::FindDeviceL(const TBTDevAddr& aBDAddr) |
|
78 /** |
|
79 Construct a simple SQL query to see if the device is present |
|
80 **/ |
|
81 { |
|
82 LOG_FUNC |
|
83 // this is used to see if the device is in the registry |
|
84 TBuf<KMaxConstraintLen> constraint; |
|
85 |
|
86 constraint.Append(KColName_DeviceAddress); |
|
87 constraint.Append(KSQLEqual); |
|
88 constraint.Append(KSQLQuote); |
|
89 constraint.Append(QuoteEscapeLC(aBDAddr)); |
|
90 constraint.Append(KSQLQuote); |
|
91 |
|
92 iQueryBuf.SetMaxLengthL(constraint.Length() + KSQLSelectAllConstrained().Length() + KDeviceTable().Length()); |
|
93 iQueryBuf.Text().Format(KSQLSelectAllConstrained, &KDeviceTable, &constraint); |
|
94 |
|
95 CleanupStack::PopAndDestroy(1); // address buffer |
|
96 } |
|
97 |
|
98 void RBTDbQuery::FindCommPortL(TUint32 aUnitNumber) |
|
99 /** |
|
100 Construct a SQL query to find the virtual serial port with aUnitNumber |
|
101 **/ |
|
102 { |
|
103 LOG_FUNC |
|
104 TBuf<KMaxConstraintLen> constraint; |
|
105 |
|
106 constraint.Append(KBTCOMMColName_Port); |
|
107 constraint.Append(KSQLEqual); |
|
108 constraint.AppendNum(static_cast<TUint>(aUnitNumber), EDecimal); |
|
109 |
|
110 iQueryBuf.SetMaxLengthL(constraint.Length() + KSQLSelectAllConstrained().Length() + KCSYTable().Length()); |
|
111 iQueryBuf.Text().Format(KSQLSelectAllConstrained, &KCSYTable, &constraint); |
|
112 } |
|
113 |
|
114 void RBTDbQuery::MatchLinkKeyTypeL(TBTLinkKeyType aLinkKeyType) |
|
115 /** |
|
116 Construct a SQL query to find entries that have a link key of a specific type. |
|
117 **/ |
|
118 { |
|
119 LOG_FUNC |
|
120 TBuf<KMaxConstraintLen> constraint; |
|
121 |
|
122 constraint.Append(KDeviceColName_LinkKeyType); |
|
123 constraint.Append(KSQLEqual); |
|
124 constraint.AppendNum(static_cast<TUint>(aLinkKeyType), EDecimal); |
|
125 |
|
126 iQueryBuf.SetMaxLengthL(constraint.Length() + KSQLSelectAllConstrained().Length() + KDeviceTable().Length()); |
|
127 iQueryBuf.Text().Format(KSQLSelectAllConstrained, &KDeviceTable, &constraint); |
|
128 } |
|
129 |
|
130 const TDesC& RBTDbQuery::QueryBuf() const |
|
131 { |
|
132 LOG_FUNC |
|
133 return iQueryBuf.Text(); |
|
134 } |
|
135 |
|
136 TPtrC RBTDbQuery::ConstraintBuf() const |
|
137 { |
|
138 LOG_FUNC |
|
139 TInt index = QueryBuf().Find(KSQLWhere); |
|
140 return (index==KErrNotFound) ? TPtrC() : QueryBuf().Mid(index+KSQLWhere().Length()); |
|
141 } |
|
142 |
|
143 void RBTDbQuery::ExtendForAnotherTokenL(RTextBuf& aSQLBuf, TUint aMask) |
|
144 /** |
|
145 Sees if the token 'AND' is required in a constrained search |
|
146 If so, add into the SQL query |
|
147 If the buffer is getting small, extend it |
|
148 **/ |
|
149 { |
|
150 LOG_FUNC |
|
151 if (aMask) |
|
152 { |
|
153 // need an AND - more constraints follow |
|
154 aSQLBuf.Text().Append(KSQLAnd); |
|
155 //Need to increase the size of the bufferno |
|
156 // RTextBuf::SetMaxLengthL is bad as it closes the textbuf |
|
157 RTextBuf copy; |
|
158 copy.SetMaxLengthL(aSQLBuf.Text().Length()); |
|
159 CleanupClosePushL(copy); |
|
160 copy.Text().Append(aSQLBuf.Text()); |
|
161 aSQLBuf.SetMaxLengthL(aSQLBuf.Text().Length()+KMaxLengthConstraintIncrement); |
|
162 //copy back from the copy to the aSQLBuf |
|
163 aSQLBuf.Text().Append(copy.Text()); |
|
164 CleanupStack::PopAndDestroy(); |
|
165 } |
|
166 // else do nothing - no further constraint to follow |
|
167 } |
|
168 |
|
169 void RBTDbQuery::SearchL(const TBTRegistrySearch& aPattern) |
|
170 /** |
|
171 Converts a search mask into SQL search tokens |
|
172 **/ |
|
173 { |
|
174 LOG_FUNC |
|
175 // do the catch all first - saves time |
|
176 if (aPattern.iSearchMask & TBTRegistrySearch::EAll) |
|
177 { |
|
178 iQueryBuf.SetMaxLengthL(KSQLSelectAll().Length() + KDeviceTable().Length()); |
|
179 iQueryBuf.Text().Format(KSQLSelectAll, &KDeviceTable); |
|
180 return; |
|
181 } |
|
182 |
|
183 // we have a constrained search; formulate the SQL |
|
184 // we use a RTextBuf that can grow as needed (to reduce stack usage) |
|
185 |
|
186 RTextBuf constraintBuf; |
|
187 |
|
188 constraintBuf.SetMaxLengthL(KMaxLengthConstraintInitial); |
|
189 |
|
190 TPtr& constraint = constraintBuf.Text(); |
|
191 |
|
192 TUint toSearch = aPattern.iSearchMask; |
|
193 |
|
194 if (toSearch & TBTRegistrySearch::EAddress) |
|
195 { |
|
196 constraint.Append(KColName_DeviceAddress); |
|
197 constraint.Append(KSQLEqual); |
|
198 constraint.Append(KSQLQuote); |
|
199 constraint.Append(QuoteEscapeLC(aPattern.iDeviceAddress)); |
|
200 constraint.Append(KSQLQuote); |
|
201 CleanupStack::PopAndDestroy(1); // address buffer |
|
202 |
|
203 toSearch &= ~TBTRegistrySearch::EAddress; |
|
204 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
205 } |
|
206 |
|
207 |
|
208 if (toSearch & TBTRegistrySearch::ECoD) |
|
209 { |
|
210 constraint.Append(KDeviceColName_CoD); |
|
211 constraint.Append(KSQLEqual); |
|
212 TUint cod = aPattern.iDeviceClass.DeviceClass(); |
|
213 constraint.AppendNum(cod, EDecimal); |
|
214 |
|
215 toSearch &= ~TBTRegistrySearch::ECoD; |
|
216 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
217 } |
|
218 |
|
219 if (toSearch & TBTRegistrySearch::ECoDMajorDev) |
|
220 { |
|
221 constraint.Append(KDeviceColName_CoD_MajorDev); |
|
222 constraint.Append(KSQLEqual); |
|
223 TUint majDev = aPattern.iDeviceClass.MajorDeviceClass(); |
|
224 constraint.AppendNum(majDev, EDecimal); |
|
225 |
|
226 toSearch &= ~TBTRegistrySearch::ECoDMajorDev; |
|
227 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
228 } |
|
229 |
|
230 if (toSearch & TBTRegistrySearch::ECoDMinorDev) |
|
231 { |
|
232 constraint.Append(KDeviceColName_CoD_MinorDev); |
|
233 constraint.Append(KSQLEqual); |
|
234 TUint minDev = aPattern.iDeviceClass.MinorDeviceClass(); |
|
235 constraint.AppendNum(minDev, EDecimal); |
|
236 |
|
237 toSearch &= ~TBTRegistrySearch::ECoDMinorDev; |
|
238 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
239 } |
|
240 |
|
241 if (toSearch & TBTRegistrySearch::EBTName) |
|
242 { |
|
243 constraint.Append(KDeviceColName_BluetoothName); |
|
244 constraint.Append(KSQLEqual); |
|
245 constraint.Append(KSQLQuote); |
|
246 TBuf<KMaxBluetoothNameLen> widened; |
|
247 widened.Copy(aPattern.iBluetoothName); |
|
248 constraint.Append(QuoteEscapeLC(widened)); |
|
249 constraint.Append(KSQLQuote); |
|
250 CleanupStack::PopAndDestroy(1); //name |
|
251 |
|
252 toSearch &= ~TBTRegistrySearch::EBTName; |
|
253 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
254 } |
|
255 |
|
256 if (toSearch & TBTRegistrySearch::EFriendlyName) |
|
257 { |
|
258 constraint.Append(KDeviceColName_FriendlyName); |
|
259 constraint.Append(KSQLEqual); |
|
260 constraint.Append(KSQLQuote); |
|
261 constraint.Append(QuoteEscapeLC(aPattern.iFriendlyName)); |
|
262 constraint.Append(KSQLQuote); |
|
263 CleanupStack::PopAndDestroy(1); // name |
|
264 |
|
265 toSearch &= ~TBTRegistrySearch::EFriendlyName; |
|
266 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
267 } |
|
268 |
|
269 if (toSearch & TBTRegistrySearch::EProcess) |
|
270 { |
|
271 constraint.Append(KColName_ProcessSID); |
|
272 constraint.Append(KSQLEqual); |
|
273 constraint.AppendNum(MAKE_TUINT64(0,aPattern.iCurrentProcessSID.iUid), EDecimal); |
|
274 |
|
275 toSearch &= ~TBTRegistrySearch::EProcess; |
|
276 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
277 } |
|
278 |
|
279 if (toSearch & TBTRegistrySearch::EBonded) |
|
280 { |
|
281 constraint.Append(KDeviceColName_LinkKey); |
|
282 constraint.Append(KSQLIsNotNull); |
|
283 |
|
284 toSearch &= ~TBTRegistrySearch::EBonded; |
|
285 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
286 } |
|
287 |
|
288 if (toSearch & TBTRegistrySearch::ETrusted) |
|
289 { |
|
290 // check global security for no authorisation AND authentication |
|
291 constraint.Append(KSQLOpenParentheses); |
|
292 constraint.Append(KDeviceColName_GlobalSecSecurity); |
|
293 constraint.Append(KSQLEqual); |
|
294 |
|
295 // we do this here in case TBTDeviceSecurity changes |
|
296 // trusted device = 'NoAuthentication'=No (MUST authenticate!), |
|
297 // 'NoAuthorisation'=Yes |
|
298 // 'Encryption' could be either. |
|
299 // 'Banned' =No (!) |
|
300 |
|
301 TBTDeviceSecurity noEncryption(EFalse, ETrue, EFalse, EFalse); |
|
302 constraint.AppendNum(static_cast<TUint>(noEncryption.SecurityValue())); |
|
303 |
|
304 constraint.Append(KSQLOr); |
|
305 constraint.Append(KDeviceColName_GlobalSecSecurity); |
|
306 constraint.Append(KSQLEqual); |
|
307 |
|
308 TBTDeviceSecurity encryption(EFalse, ETrue, ETrue, EFalse); |
|
309 constraint.AppendNum(static_cast<TUint>(encryption.SecurityValue())); |
|
310 constraint.Append(KSQLCloseParentheses); |
|
311 |
|
312 toSearch &= ~TBTRegistrySearch::ETrusted; |
|
313 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
314 } |
|
315 |
|
316 if (toSearch & TBTRegistrySearch::ELastSeen) |
|
317 { |
|
318 constraint.Append(KDeviceColName_LastSeen); |
|
319 constraint.Append(KSQLGreaterEqual); |
|
320 constraint.AppendNum(aPattern.iLastSeen.Int64()); |
|
321 toSearch &= ~TBTRegistrySearch::ELastSeen; |
|
322 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
323 } |
|
324 |
|
325 if (toSearch & TBTRegistrySearch::ELastUsed) |
|
326 { |
|
327 constraint.Append(KDeviceColName_LastUsed); |
|
328 constraint.Append(KSQLGreaterEqual); |
|
329 constraint.AppendNum(aPattern.iLastUsed.Int64()); |
|
330 toSearch &= ~TBTRegistrySearch::ELastUsed; |
|
331 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
332 } |
|
333 |
|
334 if (toSearch & TBTRegistrySearch::EUiCookie) |
|
335 { |
|
336 constraint.Append(KDeviceColName_UiCookie); |
|
337 constraint.Append(KSQLLike); |
|
338 constraint.Append(KSQLQuote); |
|
339 static const TUint8 KCookieBinaryRepresentationWidth = 32; // 32bits encoded as binary string. |
|
340 TBuf<KCookieBinaryRepresentationWidth> cookiePattern; |
|
341 cookiePattern.NumFixedWidth(aPattern.iUiCookie, EBinary, KCookieBinaryRepresentationWidth); |
|
342 TUint32 shiftedMask = aPattern.iUiCookieMask; |
|
343 for(TInt i=KCookieBinaryRepresentationWidth-1; i>=0; --i) |
|
344 { |
|
345 if(!(shiftedMask&1)) // check the bottom bit (we loop through them all by shifting.) |
|
346 { |
|
347 // bit "i" isn't masked, and so we should ignore it. |
|
348 cookiePattern[i] = '?'; |
|
349 } |
|
350 shiftedMask >>= 1; |
|
351 } |
|
352 constraint.Append(cookiePattern); |
|
353 constraint.Append(KSQLQuote); |
|
354 |
|
355 toSearch &= ~TBTRegistrySearch::EUiCookie; |
|
356 ExtendForAnotherTokenL(constraintBuf, toSearch); |
|
357 } |
|
358 |
|
359 if(toSearch) |
|
360 { |
|
361 // There is an unhandled search attribute that has been provided by the user. |
|
362 // If left the trailing SQL "AND" would trigger the KErrArgument error anyway. |
|
363 User::Leave(KErrArgument); |
|
364 } |
|
365 |
|
366 iQueryBuf.SetMaxLengthL(constraint.Length() + KSQLSelectAllConstrained().Length() + KDeviceTable().Length()); |
|
367 iQueryBuf.Text().Format(KSQLSelectAllConstrained, &KDeviceTable, &constraint); |
|
368 } |
|
369 |