1 /* |
|
2 * Copyright (c) 2003 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 "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: CXcapHttpResponse |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 // INCLUDE FILES |
|
22 #include <XdmErrors.h> |
|
23 #include "XdmCredentials.h" |
|
24 #include "XcapHttpRequest.h" |
|
25 #include "XcapHttpResponse.h" |
|
26 #include "XcapHttpTransport.h" |
|
27 #include "XcapHttpAuthManager.h" |
|
28 |
|
29 const TUint KMaxRetryCount = 3; |
|
30 |
|
31 // ================= MEMBER FUNCTIONS ======================= |
|
32 // |
|
33 |
|
34 |
|
35 // ---------------------------------------------------------- |
|
36 // CXcapHttpResponse::CXcapHttpResponse |
|
37 // |
|
38 // ---------------------------------------------------------- |
|
39 // |
|
40 CXcapHttpResponse::CXcapHttpResponse( CXcapHttpRequest* aHttpRequest, |
|
41 CXcapHttpTransport& aTransportMain ) : |
|
42 iAuthPending( EFalse ), |
|
43 iHttpRequest( aHttpRequest ), |
|
44 iTransportMain( aTransportMain ), |
|
45 iAuthManager( iHttpRequest->AuthManager() ) |
|
46 { |
|
47 } |
|
48 |
|
49 // ---------------------------------------------------- |
|
50 // CXcapHttpResponse::NewL |
|
51 // |
|
52 // ---------------------------------------------------- |
|
53 // |
|
54 CXcapHttpResponse* CXcapHttpResponse::NewL( CXcapHttpRequest* aHttpRequest, |
|
55 CXcapHttpTransport& aTransportMain ) |
|
56 { |
|
57 CXcapHttpResponse* self = new ( ELeave ) CXcapHttpResponse( aHttpRequest, aTransportMain ); |
|
58 CleanupStack::PushL( self ); |
|
59 self->ConstructL(); |
|
60 CleanupStack::Pop(); //self |
|
61 return self; |
|
62 } |
|
63 |
|
64 // ---------------------------------------------------- |
|
65 // CXcapHttpResponse::ConstructL |
|
66 // |
|
67 // ---------------------------------------------------- |
|
68 // |
|
69 void CXcapHttpResponse::ConstructL() |
|
70 { |
|
71 } |
|
72 |
|
73 // ---------------------------------------------------- |
|
74 // CXcapHttpResponse::~CXcapHttpResponse() |
|
75 // Destructor |
|
76 // ---------------------------------------------------- |
|
77 // |
|
78 CXcapHttpResponse::~CXcapHttpResponse() |
|
79 { |
|
80 } |
|
81 |
|
82 // ---------------------------------------------------- |
|
83 // CXcapHttpResponse::MHFRunL |
|
84 // |
|
85 // ---------------------------------------------------- |
|
86 // |
|
87 void CXcapHttpResponse::MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent ) |
|
88 { |
|
89 TInt status = aTransaction.Response().StatusCode(); |
|
90 #ifdef _DEBUG |
|
91 iTransportMain.WriteToLog( _L8( "CXcapHttpResponse::MHFRunL()" ) ); |
|
92 iTransportMain.WriteToLog( _L8( " HTTP status: %d" ), status ); |
|
93 iTransportMain.WriteToLog( _L8( " Event status: %d" ), aEvent.iStatus ); |
|
94 iTransportMain.WriteToLog( _L8( " TransID: %d " ), aTransaction.Id() ); |
|
95 #endif |
|
96 switch( aEvent.iStatus ) |
|
97 { |
|
98 case THTTPEvent::EGotResponseHeaders: |
|
99 #ifdef _DEBUG |
|
100 DumpHeadersL( aTransaction.Response().GetHeaderCollection(), aTransaction.Id() ); |
|
101 //DumpHeadersL( aTransaction.Request().GetHeaderCollection(), aTransaction.Id() ); |
|
102 #endif |
|
103 TInt authType; |
|
104 if( IsUnauthRequest( aTransaction, authType ) ) |
|
105 { |
|
106 // If server keeps on sending 401 resposenses. Will stop |
|
107 // sending new requests after 3 trys. |
|
108 if ( KMaxRetryCount == iUnauthRequestCounter ) |
|
109 { |
|
110 #ifdef _DEBUG |
|
111 iTransportMain.WriteToLog( |
|
112 _L8( " Max retry count. Stop sending auth requests to server." ) ); |
|
113 #endif |
|
114 iHttpRequest->FinaliseRequestL( KErrCancel ); |
|
115 aTransaction.Cancel(); |
|
116 } |
|
117 //We only support Digest => If Basic is defined, stop. |
|
118 else if( iAuthManager.ParseHeaderL( aTransaction, authType ) ) |
|
119 { |
|
120 iHttpRequest->ResendWithAuthL( authType ); |
|
121 iAuthPending = ETrue; |
|
122 } |
|
123 else |
|
124 { |
|
125 #ifdef _DEBUG |
|
126 iTransportMain.WriteToLog( _L8( " Basic authentication not supported" ) ); |
|
127 #endif |
|
128 iHttpRequest->FinaliseRequestL( KXcapErrorAuthentication ); |
|
129 aTransaction.Cancel(); |
|
130 } |
|
131 } |
|
132 else if( iAuthPending && ( status != 401 && status != 403 ) ) |
|
133 { |
|
134 iAuthPending = EFalse; |
|
135 iAuthManager.SetAuthorized( ETrue ); |
|
136 } |
|
137 else if( !CheckAuthInfoHeaderL( aTransaction.Response().GetHeaderCollection() ) ) |
|
138 { |
|
139 //This means that something was wrong with the Authentication-Info header |
|
140 //the server returned. Do not take any chances here, but stop. |
|
141 #ifdef _DEBUG |
|
142 iTransportMain.WriteToLog( _L8( " Something's wrong with Authentication-Info => STOP" ) ); |
|
143 #endif |
|
144 iHttpRequest->FinaliseRequestL( KXcapErrorAuthentication ); |
|
145 aTransaction.Cancel(); |
|
146 } |
|
147 break; |
|
148 case THTTPEvent::EGotResponseBodyData: |
|
149 #ifdef _DEBUG |
|
150 iTransportMain.WriteToLog( _L8( "MHFRunL() - A body part received" ) ); |
|
151 #endif |
|
152 HandleReceivedBodyDataL( aTransaction ); |
|
153 break; |
|
154 case THTTPEvent::EResponseComplete: |
|
155 #ifdef _DEBUG |
|
156 iTransportMain.WriteToLog( _L8( " * Transaction complete") ); |
|
157 #endif |
|
158 break; |
|
159 case THTTPEvent::ESucceeded: |
|
160 #ifdef _DEBUG |
|
161 iTransportMain.WriteToLog( _L8( " * Transaction succeeded") ); |
|
162 #endif |
|
163 iHttpRequest->FinaliseRequestL( KErrNone ); |
|
164 break; |
|
165 case THTTPEvent::EFailed: |
|
166 { |
|
167 TInt completion = aEvent.iStatus < 0 ? aEvent.iStatus : KErrNone; |
|
168 #ifdef _DEBUG |
|
169 iTransportMain.WriteToLog( _L8( " * Transaction failed - Completion: %d"), completion ); |
|
170 #endif |
|
171 iHttpRequest->FinaliseRequestL( completion ); |
|
172 } |
|
173 break; |
|
174 case THTTPEvent::ERedirectedPermanently: |
|
175 break; |
|
176 case THTTPEvent::ERedirectedTemporarily: |
|
177 break; |
|
178 default: |
|
179 { |
|
180 if( aEvent.iStatus < KErrNone ) |
|
181 { |
|
182 #ifdef _DEBUG |
|
183 iTransportMain.WriteToLog( _L8( " * Transaction failed, stop" ) ); |
|
184 #endif |
|
185 iHttpRequest->FinaliseRequestL( aEvent.iStatus ); |
|
186 } |
|
187 else |
|
188 { |
|
189 #ifdef _DEBUG |
|
190 iTransportMain.WriteToLog( _L8( " * Unknown status, stop" ) ); |
|
191 #endif |
|
192 iHttpRequest->FinaliseRequestL( KErrUnknown ); |
|
193 } |
|
194 } |
|
195 break; |
|
196 } |
|
197 } |
|
198 |
|
199 // ---------------------------------------------------------- |
|
200 // CXcapHttpAuthManager::CheckAuthInfoHeaderL |
|
201 // |
|
202 // ---------------------------------------------------------- |
|
203 // |
|
204 TBool CXcapHttpResponse::CheckAuthInfoHeaderL( RHTTPHeaders aHeaders ) |
|
205 { |
|
206 #ifdef _DEBUG |
|
207 iTransportMain.WriteToLog( _L8( "CXcapHttpResponse::CheckAuthInfoHeaderL()" ) ); |
|
208 #endif |
|
209 THTTPHdrVal fieldVal; |
|
210 TBool authOk = ETrue; |
|
211 TPtrC8 rawData( _L8( "" ) ); |
|
212 RStringPool spool = iHttpRequest->Session().StringPool(); |
|
213 RStringF authInfo = spool.OpenFStringL( TPtrC8( KAuthInfoParamArray[ENfoAuthInfo] ) ); |
|
214 CleanupClosePushL( authInfo ); |
|
215 RStringF prxAuthInfo = spool.OpenFStringL( TPtrC8( KAuthInfoParamArray[ENfoPrxAuthInfo] ) ); |
|
216 CleanupClosePushL( prxAuthInfo ); |
|
217 if( aHeaders.GetRawField( authInfo, rawData ) == KErrNone || |
|
218 aHeaders.GetRawField( prxAuthInfo, rawData ) == KErrNone ) |
|
219 { |
|
220 TInt length = 0; |
|
221 HBufC8* tempCopy = rawData.AllocLC(); |
|
222 TPtr8 modDesc( tempCopy->Des() ); |
|
223 while( authOk && modDesc.Length() > 0 ) |
|
224 { |
|
225 TPtrC8 value; |
|
226 TAuthInfoParam name = ( TAuthInfoParam )-1; |
|
227 if( ParseAuthInfoParam( length, name, value, modDesc ) ) |
|
228 authOk = iAuthManager.ConsumeAuthInfoParamL( name, value ); |
|
229 modDesc.Delete( 0, length ); |
|
230 modDesc.TrimLeft(); |
|
231 } |
|
232 CleanupStack::PopAndDestroy(); //tempCopy |
|
233 } |
|
234 CleanupStack::PopAndDestroy( 2 ); //prxAuthInfo, authInfo |
|
235 return authOk; |
|
236 } |
|
237 |
|
238 // ---------------------------------------------------------- |
|
239 // CXcapHttpAuthManager::ParseAuthInfoParam |
|
240 // |
|
241 // ---------------------------------------------------------- |
|
242 // |
|
243 TBool CXcapHttpResponse::ParseAuthInfoParam( TInt& aLength, TAuthInfoParam& aName, TPtrC8& aValue, TPtr8& aParam ) |
|
244 { |
|
245 TBool found = EFalse; |
|
246 TInt delim = aParam.Locate( ',' ); |
|
247 TPtrC8 param( delim > 0 ? aParam.Left( delim ) : aParam ); |
|
248 TInt index = param.Locate( '=' ); |
|
249 if( index > 0 ) |
|
250 { |
|
251 TPtrC8 name( param.Left( index ) ); |
|
252 TPtrC8 value( param.Mid( index + 1 ) ); |
|
253 const TInt count = sizeof( KAuthInfoParamArray ) / sizeof( KAuthInfoParamArray[0] ); |
|
254 for( TInt i = 0;!found && i < count;i++ ) |
|
255 { |
|
256 if( name.CompareF( TPtrC8( KAuthInfoParamArray[i] ) ) == 0 ) |
|
257 { |
|
258 aValue.Set( value ); |
|
259 aName = ( TAuthInfoParam )i; |
|
260 found = ETrue; |
|
261 } |
|
262 } |
|
263 } |
|
264 aLength = delim > 0 ? delim + 1 : aParam.Length(); |
|
265 return found; |
|
266 } |
|
267 |
|
268 |
|
269 // ---------------------------------------------------------- |
|
270 // CXcapHttpResponse::IsUnauthRequest |
|
271 // |
|
272 // ---------------------------------------------------------- |
|
273 // |
|
274 TBool CXcapHttpResponse::IsUnauthRequest( RHTTPTransaction aTransaction, TInt& aAuthType ) |
|
275 { |
|
276 iUnauthRequestCounter++; |
|
277 TInt status = aTransaction.Response().StatusCode(); |
|
278 switch( status ) |
|
279 { |
|
280 case 401: //Normal authentication |
|
281 aAuthType = 401; |
|
282 return ETrue; |
|
283 case 407: //Proxy authentication |
|
284 aAuthType = 407; |
|
285 return ETrue; |
|
286 default: |
|
287 return EFalse; |
|
288 } |
|
289 } |
|
290 |
|
291 // ---------------------------------------------------------- |
|
292 // CXcapHttpResponse::HandleReceivedBodyDataL |
|
293 // |
|
294 // ---------------------------------------------------------- |
|
295 // |
|
296 TBool CXcapHttpResponse::HandleReceivedBodyDataL( const RHTTPTransaction aTransaction ) |
|
297 { |
|
298 #ifdef _DEBUG |
|
299 iTransportMain.WriteToLog( _L8( "CXcapHttpResponse::HandleReceivedBodyDataL()") ); |
|
300 #endif |
|
301 TPtrC8 bodyData; |
|
302 MHTTPDataSupplier* respBody = aTransaction.Response().Body(); |
|
303 TBool lastChunk = respBody->GetNextDataPart( bodyData ); |
|
304 iHttpRequest->AppendDataL( bodyData ); |
|
305 respBody->ReleaseData(); |
|
306 return lastChunk; |
|
307 } |
|
308 |
|
309 // ---------------------------------------------------------- |
|
310 // CImpsHttpTransactionSender::ContentLengthL |
|
311 // |
|
312 // ---------------------------------------------------------- |
|
313 // |
|
314 TInt CXcapHttpResponse::ContentLengthL() const |
|
315 { |
|
316 TInt retVal = KMaxTInt; |
|
317 THTTPHdrVal fieldValue; |
|
318 _LIT8( KContentLength, "Content-Length" ); |
|
319 RHTTPHeaders headers = ResponseHeaderCollection(); |
|
320 RStringPool stringPool = iHttpRequest->Session().StringPool(); |
|
321 RStringF lengthString = stringPool.OpenFStringL( KContentLength ); |
|
322 headers.GetField( lengthString, 0, fieldValue ); |
|
323 lengthString.Close(); |
|
324 if( fieldValue.Type() == THTTPHdrVal::KTIntVal ) |
|
325 retVal = fieldValue.Int(); |
|
326 return retVal; |
|
327 } |
|
328 |
|
329 // ---------------------------------------------------- |
|
330 // CXcapHttpResponse::HeaderCollection |
|
331 // |
|
332 // ---------------------------------------------------- |
|
333 // |
|
334 RHTTPHeaders CXcapHttpResponse::ResponseHeaderCollection() const |
|
335 { |
|
336 return iHttpRequest->Transaction().Response().GetHeaderCollection(); |
|
337 } |
|
338 |
|
339 // ---------------------------------------------------- |
|
340 // CXcapHttpResponse::HeaderCollection |
|
341 // |
|
342 // ---------------------------------------------------- |
|
343 // |
|
344 RHTTPHeaders CXcapHttpResponse::RequestHeaderCollection() const |
|
345 { |
|
346 return iHttpRequest->Transaction().Request().GetHeaderCollection(); |
|
347 } |
|
348 |
|
349 // ---------------------------------------------------- |
|
350 // CXcapHttpResponse::MHFRunError |
|
351 // HTTP Stack callback interface |
|
352 // ---------------------------------------------------- |
|
353 // |
|
354 TInt CXcapHttpResponse::MHFRunError( TInt /*aInt*/, RHTTPTransaction /*aTransaction*/, |
|
355 const THTTPEvent& /*aEvent*/ ) |
|
356 { |
|
357 return KErrNone; |
|
358 } |
|
359 |
|
360 #ifdef _DEBUG |
|
361 // ---------------------------------------------------- |
|
362 // CXcapHttpResponse::DumpHeadersL |
|
363 // |
|
364 // ---------------------------------------------------- |
|
365 // |
|
366 void CXcapHttpResponse::DumpHeadersL( RHTTPHeaders aHeaders, TInt aId ) |
|
367 { |
|
368 iTransportMain.WriteToLog( _L( "--------------------") ); |
|
369 iTransportMain.WriteToLog( _L( "Headers of the transaction %d: "), aId ); |
|
370 RStringPool strP = iHttpRequest->Session().StringPool(); |
|
371 THTTPHdrFieldIter it = aHeaders.Fields(); |
|
372 TBuf<KMaxHeaderNameLen> fieldName16; |
|
373 TBuf<KMaxHeaderValueLen> fieldVal16; |
|
374 |
|
375 while( it.AtEnd() == EFalse ) |
|
376 { |
|
377 RStringTokenF fieldName = it(); |
|
378 RStringF fieldNameStr = strP.StringF( fieldName ); |
|
379 THTTPHdrVal fieldVal; |
|
380 if( aHeaders.GetField( fieldNameStr, 0, fieldVal ) == KErrNone ) |
|
381 { |
|
382 const TDesC8& fieldNameDesC = fieldNameStr.DesC(); |
|
383 fieldName16.Copy( fieldNameDesC.Left( KMaxHeaderNameLen ) ); |
|
384 switch( fieldVal.Type() ) |
|
385 { |
|
386 case THTTPHdrVal::KTIntVal: |
|
387 iTransportMain.WriteToLog( _L("%S: %d"), &fieldName16, fieldVal.Int() ); |
|
388 break; |
|
389 case THTTPHdrVal::KStrFVal: |
|
390 { |
|
391 RStringF fieldValStr = strP.StringF( fieldVal.StrF() ); |
|
392 const TDesC8& fieldValDesC = fieldValStr.DesC(); |
|
393 fieldVal16.Copy( fieldValDesC.Left( KMaxHeaderValueLen ) ); |
|
394 iTransportMain.WriteToLog( _L( "%S: %S" ), &fieldName16, &fieldVal16 ); |
|
395 } |
|
396 break; |
|
397 case THTTPHdrVal::KStrVal: |
|
398 { |
|
399 RString fieldValStr = strP.String(fieldVal.Str()); |
|
400 const TDesC8& fieldValDesC = fieldValStr.DesC(); |
|
401 fieldVal16.Copy( fieldValDesC.Left( KMaxHeaderValueLen ) ); |
|
402 iTransportMain.WriteToLog( _L( "%S: %S" ), &fieldName16, &fieldVal16 ); |
|
403 } |
|
404 break; |
|
405 case THTTPHdrVal::KDateVal: |
|
406 { |
|
407 TDateTime date = fieldVal.DateTime(); |
|
408 TBuf<40> dateTimeString; |
|
409 TTime t(date); |
|
410 t.FormatL( dateTimeString,KTransportDateFormat ); |
|
411 iTransportMain.WriteToLog( _L( "%S: %S" ), &fieldName16, &dateTimeString ); |
|
412 } |
|
413 break; |
|
414 default: |
|
415 iTransportMain.WriteToLog( _L( "%S: <unrecognised value type>" ), &fieldName16 ); |
|
416 break; |
|
417 } |
|
418 // Display realm for WWW-Authenticate header |
|
419 RStringF wwwAuth = strP.StringF( HTTP::EWWWAuthenticate, RHTTPSession::GetTable() ); |
|
420 if( fieldNameStr == wwwAuth ) |
|
421 { |
|
422 // check the auth scheme is 'basic' |
|
423 RStringF basic = strP.StringF( HTTP::EBasic,RHTTPSession::GetTable() ); |
|
424 RStringF realm = strP.StringF( HTTP::ERealm,RHTTPSession::GetTable() ); |
|
425 THTTPHdrVal realmVal; |
|
426 if ( (fieldVal.StrF() == basic ) && |
|
427 ( !aHeaders.GetParam(wwwAuth, realm, realmVal) ) ) |
|
428 { |
|
429 RStringF realmValStr = strP.StringF( realmVal.StrF() ); |
|
430 fieldVal16.Copy( realmValStr.DesC() ); |
|
431 iTransportMain.WriteToLog( _L( "Realm is: %S" ), &fieldVal16 ); |
|
432 } |
|
433 } |
|
434 } |
|
435 ++it; |
|
436 } |
|
437 iTransportMain.WriteToLog( _L( "--------------------") ); |
|
438 } |
|
439 #endif |
|
440 |
|
441 // End of File |
|
442 |
|