b790eff7218742d221e19d7631538e975b813ea3
[framework/osp/net.git] / src / http / FNetHttp_HttpCommon.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FNetHttp_HttpCommon.cpp
20  * @brief               This file implement the common macro or function used by internal module.
21  */
22
23 #include <unique_ptr.h>
24 #include <pthread.h>
25 #include <FBaseString.h>
26 #include <FBaseByteBuffer.h>
27 #include <FBaseUtil.h>
28 #include <FBaseRtMutex.h>
29 #include <FBaseRtMutexGuard.h>
30 #include <FBaseCol.h>
31 #include <FAppApp.h>
32 #include <FBaseSysLog.h>
33 #include <FBase_StringConverter.h>
34 #include <FApp_AppInfo.h>
35 #include <FIoDirectory.h>
36 #include "FNetHttp_HttpCommon.h"
37 #include "FNetHttp_HttpTransactionEvent.h"
38
39 using namespace std;
40 using namespace Tizen::Base;
41 using namespace Tizen::Base::Runtime;
42 using namespace Tizen::Base::Utility;
43 using namespace Tizen::Base::Collection;
44 using namespace Tizen::App;
45 using namespace Tizen::Io;
46
47 namespace Tizen { namespace Net { namespace Http
48 {
49
50 extern const wchar_t _HTTP_USERAGENT_HEADER_NAME[] = L"User-Agent";
51
52 extern const wchar_t _HTTP_CONTENT_LENGTH_HEADER_NAME[] = L"Content-Length";
53
54 extern const wchar_t _HTTP_CONTENT_TYPE_HEADER_NAME[] = L"Content-Type";
55
56 extern const wchar_t _HTTP_TRANSFER_ENCODING_HEADER_NAME[] = L"Transfer-Encoding";
57
58 extern const wchar_t _HTTP_EXPECT_HEADER_NAME[] = L"Expect";
59
60 extern const wchar_t _HTTP_SET_COOKIE_HEADER_NAME[] = L"Set-Cookie";
61
62 extern const wchar_t _HTTP_PROXY_AUTHENTICATE_HEADER_NAME[] = L"Proxy-Authenticate";
63
64 extern const wchar_t _HTTP_WWW_AUTHENTICATE_HEADER_NAME[] = L"WWW-Authenticate";
65
66 extern const wchar_t _HTTP_CHUNKED_HEADER_VALUE[] = L"chunked";
67
68 extern const wchar_t _HTTP_PROTOCOL_SCHEME[] = L"http://";
69
70 extern const wchar_t _HTTPS_PROTOCOL_SCHEME[] = L"https://";
71
72 extern const wchar_t _HTTP_DEFAULT_BODY_CHARSET[] = L"ISO-8859-1";
73
74 extern const wchar_t _MULTI_PART_FORM_DATA_PREFIX[] = L"multipart/form-data; boundary=";
75
76 extern const wchar_t _HTTP_STRING_PART_DEFAULT_CHARSET[] = L"ISO-8859-1";
77
78 extern const wchar_t _HTTP_FILE_PART_DEFAULT_CHARSET[] = L"";
79
80 extern const wchar_t _HTTP_MULTI_PART_BOUNDARY_CHARACTER_SET[] = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
81
82 extern const wchar_t _HTTP_SET_COOKIE_DELIMITER[] = L";";
83
84 extern const wchar_t _HTTP_SET_COOKIE_FLAG_DELIMITER[] = L"=";
85
86 extern const wchar_t _HTTP_COOKIE_COMMENT_NAME[] = L"Comment";
87
88 extern const wchar_t _HTTP_COOKIE_COMMENTURL_NAME[] = L"CommentURL";
89
90 extern const wchar_t _HTTP_COOKIE_DISCARD_NAME[] = L"Discard";
91
92 extern const wchar_t _HTTP_COOKIE_EXPIRES_NAME[] = L"Expires";
93
94 extern const wchar_t _HTTP_COOKIE_DOMAIN_NAME[] = L"Domain";
95
96 extern const wchar_t _HTTP_COOKIE_MAX_AGE_NAME[] = L"Max-Age";
97
98 extern const wchar_t _HTTP_COOKIE_PATH_NAME[] = L"Path";
99
100 extern const wchar_t _HTTP_COOKIE_PORT_NAME[] = L"Port";
101
102 extern const wchar_t _HTTP_COOKIE_SECURE_NAME[] = L"Secure";
103
104 extern const wchar_t _HTTP_COOKIE_VERSION_NAME[] = L"Version";
105
106 extern const wchar_t _HTTP_COOKIE_HTTP_ONLY[] = L"HttpOnly";
107
108 extern const wchar_t _HTTP_CARRIAGE_RETURN_LINE_FEED[] = L"\r\n";
109
110 extern const wchar_t _CURL_COOKIE_HTTP_ONLY_PREFIX[] = L"#HttpOnly_";
111
112 extern const wchar_t _HTTP_COOKIE_FILE[] = L"data/cookies.txt";
113
114 static const char* NetHttpTransactionEventTypesToString[] =
115 {
116         "_HTTP_TRANSACTION_EVENT_TYPE_UNDEFINED", "_HTTP_TRANSACTION_EVENT_TYPE_HEADER_COMPLETED",
117         "_HTTP_TRANSACTION_EVENT_TYPE_READY_TO_READ", "_HTTP_TRANSACTION_EVENT_TYPE_READY_TO_WRITE",
118         "_HTTP_TRANSACTION_EVENT_TYPE_COMPLETD", "_HTTP_TRANSACTION_EVENT_TYPE_ABORTED",
119         "_HTTP_TRANSACTION_EVENT_TYPE_CERT_VERIFICATION_REQUIRED", "_HTTP_TRANSACTION_EVENT_TYPE_UPLOAD_PROGRESS",
120         "_HTTP_TRANSACTION_EVENT_TYPE_DOWNLOAD_PROGRESS"
121 };
122
123 static const char* NetHttpCertificateVerificationFlagToString[] =
124 {
125         "HTTP_CV_FLAG_AUTOMATIC",
126         "HTTP_CV_FLAG_MANUAL",
127         "HTTP_CV_FLAG_IGNORED"
128 };
129
130 const char*
131 _HttpUtility::ConvertHttpTransactionEventTypeToString(_HttpTransactionEventType type)
132 {
133         return NetHttpTransactionEventTypesToString[type];
134 }
135
136 const char*
137 _HttpUtility::ConvertNetHttpCertificateVerificationFlagToString(NetHttpCertificateVerificationFlag flag)
138 {
139         return NetHttpCertificateVerificationFlagToString[flag];
140 }
141
142 void
143 _HttpUtility::PrintCurlMultiErrorCode(CURLMcode code)
144 {
145         const char* pErrorMessage = null;
146         switch (code)
147         {
148                 case CURLM_CALL_MULTI_PERFORM:
149                         pErrorMessage = "CURLM_CALL_MULTI_PERFORM";
150                         break;
151                 case CURLM_BAD_HANDLE:
152                         pErrorMessage = "CURLM_BAD_HANDLE";
153                         break;
154                 case CURLM_BAD_EASY_HANDLE:
155                         pErrorMessage = "CURLM_BAD_EASY_HANDLE";
156                         break;
157                 case CURLM_OUT_OF_MEMORY:
158                         pErrorMessage = "CURLM_OUT_OF_MEMORY";
159                         break;
160                 case CURLM_INTERNAL_ERROR:
161                         pErrorMessage = "CURLM_INTERNAL_ERROR";
162                         break;
163                 case CURLM_BAD_SOCKET:
164                         pErrorMessage = "CURLM_BAD_SOCKET";
165                         break;
166                 case CURLM_UNKNOWN_OPTION:
167                         pErrorMessage = "CURLM_UNKNOWN_OPTION";
168                         break;
169                 case CURLM_LAST:
170                         pErrorMessage = "CURLM_LAST";
171                         break;
172                 default:
173                         pErrorMessage = "CURLM_UNKNOWN_ERROR";
174                         break;
175         }
176
177         SysLog(NID_NET_HTTP, "CURLMcode(%d): %s", code, pErrorMessage);
178 }
179
180 result
181 _HttpUtility::ConvertErrorCode(CURLcode code)
182 {
183         result r = E_SUCCESS;
184         switch (code)
185         {
186                 case CURLE_OK:
187                         r = E_SUCCESS;
188                         break;
189
190                 case CURLE_COULDNT_CONNECT:                 // 7
191                         r = E_HOST_UNREACHABLE;
192                         break;
193
194                 case CURLE_READ_ERROR:                      // 26 - couldn't open/read from file
195                         r = E_NOT_RESPONDING;
196                         break;
197
198                 case CURLE_OPERATION_TIMEDOUT:              // 28 - the timeout time was reached
199                         r = E_TIMEOUT;
200                         break;
201
202                 case CURLE_SSL_CONNECT_ERROR:               // 35 - wrong when connecting with SSL
203                         r = E_CONNECTION_RESET;
204                         break;
205
206                 case CURLE_ABORTED_BY_CALLBACK:             // 42 - aborted by callback.
207                         r = E_OPERATION_CANCELED;
208                         break;
209
210                 case CURLE_BAD_CONTENT_ENCODING:            // 61 - Unrecognized transfer encoding
211                         r = E_INVALID_CONTENT;
212                         break;
213
214                 case CURLE_OUT_OF_MEMORY:                   // 27  Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error instead of a memory allocation error if CURL_DOES_CONVERSIONS is defined
215                         r = E_OUT_OF_MEMORY;
216                         break;
217
218                 case CURLE_UNSUPPORTED_PROTOCOL:            // 1
219                 case CURLE_URL_MALFORMAT:                   // 3
220                 case CURLE_COULDNT_RESOLVE_PROXY:           // 5
221                 case CURLE_COULDNT_RESOLVE_HOST:            // 6
222                 case CURLE_REMOTE_ACCESS_DENIED:            // 9 a service was denied by the server due to lack of access - when login fails this is not returned.
223                 case CURLE_PARTIAL_FILE:                    // 18
224                 case CURLE_QUOTE_ERROR:                     // 21 - quote command failure
225                 case CURLE_HTTP_RETURNED_ERROR:             // 22
226                 case CURLE_WRITE_ERROR:                     // 23
227                 case CURLE_UPLOAD_FAILED:                   // 25 - failed upload "command"
228                 case CURLE_RANGE_ERROR:                     // 33 - RANGE "command" didn't work
229                 case CURLE_HTTP_POST_ERROR:                 // 34
230                 case CURLE_BAD_DOWNLOAD_RESUME:             // 36 - couldn't resume download
231                 case CURLE_FILE_COULDNT_READ_FILE:          // 37
232                 case CURLE_FUNCTION_NOT_FOUND:              // 41
233                 case CURLE_BAD_FUNCTION_ARGUMENT:           // 43
234                 case CURLE_INTERFACE_FAILED:                // 45 - CURLOPT_INTERFACE failed
235                 case CURLE_TOO_MANY_REDIRECTS:              // 47 - catch endless re-direct loops
236                 case CURLE_GOT_NOTHING:                     // 52 - when this is a specific error
237                 case CURLE_SEND_ERROR:                      // 55 - failed sending network data
238                 case CURLE_RECV_ERROR:                      // 56 - failure in receiving network data
239                 case CURLE_PEER_FAILED_VERIFICATION:        // 51 - peer's certificate or fingerprint wasn't verified fine
240                 case CURLE_SSL_CERTPROBLEM:                 // 58 - problem with the local certificate
241                 case CURLE_SSL_CIPHER:                      // 59 - couldn't use specified cipher
242                 case CURLE_SSL_CACERT:                      // 60 - problem with the CA cert (path?)
243                 case CURLE_SSL_ISSUER_ERROR:                // 83 - Issuer check failed.  (Added in 7.19.0)
244                 case CURLE_SSL_CRL_BADFILE:                 // 82 - could not load CRL file, missing or wrong format (Added in 7.19.0)
245                 case CURLE_SSL_CACERT_BADFILE:              // 77 - could not load CACERT file, missing or wrong format
246                 case CURLE_FILESIZE_EXCEEDED:               // 63 - Maximum file size exceeded
247                 case CURLE_SEND_FAIL_REWIND:                // 65 - Sending the data requires a rewind that failed
248                 case CURLE_SSL_ENGINE_INITFAILED:           // 66 - failed to initialise ENGINE
249                 case CURLE_LOGIN_DENIED:                    // 67 - user, password or similar was not accepted and we failed to login
250                 case CURLE_REMOTE_DISK_FULL:                // 70 - out of disk space on server
251                 case CURLE_REMOTE_FILE_EXISTS:              // 73 - File already exists
252                 case CURLE_CONV_FAILED:                     // 75 - conversion failed
253                 case CURLE_CONV_REQD:                       // 76 - caller must register conversion callbacks using curl_easy_setopt options  CURLOPT_CONV_FROM_NETWORK_FUNCTION,  CURLOPT_CONV_TO_NETWORK_FUNCTION, and CURLOPT_CONV_FROM_UTF8_FUNCTION
254                 case CURLE_REMOTE_FILE_NOT_FOUND:           // 78 - remote file not found
255                 case CURLE_AGAIN:                           // 81 - socket is not ready for send/recv,  wait till it's ready and try again (Added in 7.18.2)
256                 case CURLE_CHUNK_FAILED:                    // 88 - chunk callback reported error
257                 case CURL_LAST:                             // never use!
258                         r = E_IO;
259                         break;
260
261                 case CURLE_SSL_ENGINE_NOTFOUND:             // 53 - SSL crypto engine not found
262                 case CURLE_SSL_ENGINE_SETFAILED:            // 54 - can not set SSL crypto engine as default
263                 case CURLE_SSL_SHUTDOWN_FAILED:             // 80 - Failed to shut down the SSL connection
264                         r = E_SYSTEM;
265                         break;
266
267                 default:
268                         r = E_UNKNOWN;
269                         break;
270         }
271                 SysLog(NID_NET_HTTP, "Converter Error Code(CURLE(%d) => OSP result(%lu: %s)", code, r, GetErrorMessage(r));
272                 return r;
273 }
274
275 bool
276 _HttpUtility::IsSslError(CURLcode code)
277 {
278         bool isSSLError = false;
279         switch (code)
280         {
281                 case CURLE_SSL_CONNECT_ERROR:
282                 case CURLE_PEER_FAILED_VERIFICATION: // 51 - peer's certificate or fingerprint wasn't verified fine
283                 case CURLE_SSL_CERTPROBLEM: // 58 - problem with the local certificate
284                 case CURLE_SSL_CIPHER: // 59 - couldn't use specified cipher
285                 case CURLE_SSL_CACERT: // 60 - problem with the CA cert (path?)
286                 case CURLE_SSL_ISSUER_ERROR: // 83 - Issuer check failed.  (Added in 7.19.0)
287                 case CURLE_SSL_CRL_BADFILE: // 82 - could not load CRL file, missing or wrong format (Added in 7.19.0)
288                 case CURLE_SSL_CACERT_BADFILE: // 77 - could not load CACERT file, missing or wrong format
289                         isSSLError = true;
290                         break;
291                 default:
292                         isSSLError = false;
293                         break;
294         }
295
296         return isSSLError;
297 }
298
299 result
300 _HttpUtility::AddHeaderByteBufferToBuffer(ByteBuffer **ppSrcBuffer, const ByteBuffer & destBuffer)
301 {
302         result r = E_SUCCESS;
303
304         r = AddByteBufferToBuffer(ppSrcBuffer, destBuffer, _HTTP_DEFAULT_HEADER_SIZE);
305         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "Propagating.");
306
307         return r;
308 }
309
310 result
311 _HttpUtility::AddHeaderBytesToBuffer(ByteBuffer **ppSrcBuffer, const byte *pDestBytes, int destBytesSize)
312 {
313         result r = E_SUCCESS;
314
315         r = AddBytesToBuffer(ppSrcBuffer, pDestBytes, destBytesSize, _HTTP_DEFAULT_HEADER_SIZE);
316         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "Propagating.");
317
318         return r;
319 }
320
321 result
322 _HttpUtility::AddByteBufferToBuffer(ByteBuffer **ppSrcBuffer, const ByteBuffer & destBuffer, int defaultExtendedSize)
323 {
324         result r = E_SUCCESS;
325
326         r = AddBytesToBuffer(ppSrcBuffer, destBuffer.GetPointer(), destBuffer.GetRemaining(), defaultExtendedSize);
327         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, r, "Propagating.");
328
329         return r;
330 }
331
332 result
333 _HttpUtility::AddBytesToBuffer(ByteBuffer **ppSrcBuffer, const byte *pDestBytes, int destBytesSize, int defaultExtendedSize)
334 {
335         result r = E_SUCCESS;
336         ByteBuffer* pBuffer = null;
337         int srcBufferRemainSize = 0;
338
339         SysTryReturnResult(NID_NET_HTTP, ppSrcBuffer != null && *ppSrcBuffer != null,
340                                    E_SYSTEM, "Input buffer is invalid.");
341
342         //creates the new buffer.
343         srcBufferRemainSize = (*ppSrcBuffer)->GetRemaining();
344         if (srcBufferRemainSize >= destBytesSize)
345         {
346                 r = (*ppSrcBuffer)->SetArray(pDestBytes, 0, destBytesSize);
347                 SysTryCatch(NID_NET_HTTP, r == E_SUCCESS, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
348                                         "[E_OUT_OF_MEMORY] Memory allocation failed.");
349
350         }
351         else
352         {
353                 (*ppSrcBuffer)->Flip();
354                 srcBufferRemainSize = (*ppSrcBuffer)->GetRemaining();
355                 int newBufferSize = srcBufferRemainSize + destBytesSize + defaultExtendedSize;
356
357                 pBuffer = new (std::nothrow) ByteBuffer();
358                 r = pBuffer->Construct(newBufferSize);
359                 SysTryCatch(NID_NET_HTTP, r == E_SUCCESS, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
360                                         "[E_OUT_OF_MEMORY] Memory allocation failed.");
361
362                 r = pBuffer->CopyFrom((** ppSrcBuffer));
363                 SysTryCatch(NID_NET_HTTP, r == E_SUCCESS, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
364                                         "[E_OUT_OF_MEMORY] Memory allocation failed.");
365
366                 r = pBuffer->SetArray(pDestBytes, 0, destBytesSize);
367                 SysTryCatch(NID_NET_HTTP, r == E_SUCCESS, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY,
368                                         "[E_OUT_OF_MEMORY] Memory allocation failed.");
369
370                 SysLog(NID_NET_HTTP, "Creates a new ByteBuffer(%d): ppSrcBuffer(%d), pDestBytes(%d).", newBufferSize,
371                                 srcBufferRemainSize, destBytesSize);
372
373                 delete *ppSrcBuffer;
374                 *ppSrcBuffer = pBuffer;
375         }
376
377         return r;
378
379 CATCH:
380
381         delete pBuffer;
382         return r;
383 }
384
385 bool _HttpUtility::__initialized = false;
386 Mutex* _HttpUtility::__pHttpMutex = null;
387 IList* _HttpUtility::__pSslCertList = null;
388
389 void
390 _HttpUtility::DestroyHttp(void)
391 {
392         delete __pHttpMutex;
393         delete __pSslCertList;
394         __initialized = false;
395
396         SysLog(NID_NET_HTTP, "Called DestroyHttp.");
397 }
398
399 void
400 _HttpUtility::InitializeHttpOnce(void)
401 {
402         result r = E_SUCCESS;
403
404         unique_ptr<Mutex> pMutex(new (std::nothrow)Mutex());
405         SysTryReturnVoidResult(NID_NET_HTTP, pMutex != null, E_OUT_OF_MEMORY,
406                         "[E_OUT_OF_MEMORY] Memory allocation failed.");
407
408         r = pMutex->Create();
409         SysTryReturnVoidResult(NID_NET_HTTP, r == E_SUCCESS, r,
410                         "[%s] Propagating.", GetErrorMessage(r));
411
412         SysLog(NID_NET_HTTP, "Created the mutex.");
413
414         unique_ptr<IList> pSslCertList(new (std::nothrow)LinkedList());
415         SysTryReturnVoidResult(NID_NET_HTTP, pSslCertList != null, E_OUT_OF_MEMORY,
416                         "[E_OUT_OF_MEMORY] Memory allocation failed.");
417
418         CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
419         SysTryReturnVoidResult(NID_NET_HTTP, code == CURLE_OK, E_SYSTEM, "[E_SYSTEM] Failed to call curl_global_init()");
420
421         SysLog(NID_NET_HTTP, "Called curl_global_init()");
422
423         __pHttpMutex = pMutex.release();
424         __pSslCertList = pSslCertList.release();
425         __initialized = true;
426
427         SysLog(NID_NET_HTTP, "Allocated the LinkedList.");
428
429         //std::atexit(DestroyHttp);
430 }
431
432 void
433 _HttpUtility::InitializeHttp(void)
434 {
435         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
436
437         if (!__initialized)
438         {
439                 ClearLastResult();
440                 SysLog(NID_NET_HTTP, "Initializing HTTP.");
441                 pthread_once(&onceBlock, InitializeHttpOnce);
442                 result r = GetLastResult();
443                 if (IsFailed(r))
444                 {
445                         onceBlock = PTHREAD_ONCE_INIT;
446                         SysLogException(NID_NET_HTTP, r, "[%s] Failed to initialize HTTP.", GetErrorMessage(r));
447                         return;
448                 }
449
450                 SysLog(NID_NET_HTTP, "Initialized HTTP.");
451         }
452         else
453         {
454                 SysLog(NID_NET_HTTP, "HTTP is already initialized.");
455         }
456 }
457
458 Mutex*
459 _HttpUtility::GetHttpMutex(void)
460 {
461         SysAssertf(__pHttpMutex != null, "pHttpMutex is null.");
462         return __pHttpMutex;
463 }
464
465 IList*
466 _HttpUtility::GetSslCertList(void)
467 {
468         SysAssertf(__pSslCertList != null, "pSSLCertList is null.");
469         return __pSslCertList;
470 }
471
472 result
473 _HttpUtility::SetSslCertInfo(_HttpSslInfo & sslInfo)
474 {
475         result r = E_SUCCESS;
476
477         IList* pServerCertList = GetSslCertList();
478         Mutex* pHttpMutex = GetHttpMutex();
479
480         MutexGuard locked(*pHttpMutex);
481         SysTryReturnResult(NID_NET_HTTP, locked.IsLocked(), E_SYSTEM,
482                         "Failed to lock mutex.");
483
484         r = pServerCertList->Add(sslInfo);
485         SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS, E_OUT_OF_MEMORY,
486                         "Memory allocation failed.");
487
488         return r;
489 }
490
491 _HttpSslInfo*
492 _HttpUtility::GetSslCertInfo(int socketFd)
493 {
494         ClearLastResult();
495
496         IList* pServerCertList = GetSslCertList();
497         Mutex* pHttpMutex = GetHttpMutex();
498         _HttpSslInfo* pSSLInfo = null;
499
500         MutexGuard locked(*pHttpMutex);
501         SysTryReturn(NID_NET_HTTP, locked.IsLocked(), null, E_SYSTEM,
502                         "[E_SYSTEM] Failed to lock mutex.");
503
504         unique_ptr<IEnumerator> pEnum(pServerCertList->GetEnumeratorN());
505         SysTryReturn(NID_NET_HTTP, pEnum != null, null, E_OUT_OF_MEMORY,
506                                 "[E_OUT_OF_MEMORY] Memory allocation failed.");
507
508         while (pEnum->MoveNext() == E_SUCCESS)
509         {
510                 pSSLInfo = dynamic_cast< _HttpSslInfo* >(pEnum->GetCurrent());
511                 SysTryReturn(NID_NET_HTTP, pSSLInfo != null, null, E_OUT_OF_MEMORY,
512                                         "[E_OUT_OF_MEMORY] Memory allocation failed.");
513
514                 if (pSSLInfo->GetSocketFd() == socketFd)
515                 {
516                         SysLog(NID_NET_HTTP, "Found the same server cert.");
517                         return pSSLInfo;
518                 }
519         }
520
521         return null;
522 }
523
524 result
525 _HttpUtility::RemoveSslCertInfo(_HttpSslInfo & sslInfo)
526 {
527         ClearLastResult();
528         result r = E_SUCCESS;
529         Mutex* pHttpMutex = GetHttpMutex();
530         IList *pServerCertList = GetSslCertList();
531
532         MutexGuard locked(*pHttpMutex);
533         SysTryReturnResult(NID_NET_HTTP, locked.IsLocked(), E_SYSTEM,
534                         "Failed to lock mutex.");
535
536         pServerCertList->Remove(sslInfo, true);
537
538         return r;
539 }
540
541 bool
542 _HttpUtility::HasProtocolScheme(const Tizen::Base::String & host)
543 {
544         result r = E_SUCCESS;
545         int indexOfDelimiter = -1;
546
547         //Check if the prefix of hostAddr includes "http://".
548         r = host.IndexOf(_HTTP_PROTOCOL_SCHEME, 0, indexOfDelimiter);
549         if (r == E_OBJ_NOT_FOUND)
550         {
551                 //Check if the prefix of hostAddr includes "https://".
552                 r = host.IndexOf(_HTTPS_PROTOCOL_SCHEME, 0, indexOfDelimiter);
553                 if (r == E_OBJ_NOT_FOUND)
554                 {
555                         return false;
556                 }
557         }
558
559         return true;
560 }
561
562 String
563 _HttpUtility::GetProtocolScheme(const String & host)
564 {
565         result r = E_SUCCESS;
566         String scheme;
567         Uri hostUri;
568
569         r = hostUri.SetUri(host);
570         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, L"", E_INVALID_ARG,
571                          "[E_INVALID_ARG] Failed to set uri");
572         scheme = hostUri.GetScheme();
573         scheme += L"://";
574
575         return scheme;
576 }
577
578 bool
579 _HttpUtility::CompareHost(const Tizen::Base::String & host0, const Tizen::Base::String & host1)
580 {
581         result r = E_SUCCESS;
582         Uri hostUri0;
583         Uri hostUri1;
584
585         r = hostUri0.SetUri(host0);
586         r = TransExceptionsExclusive(r, E_INVALID_ARG, E_OUT_OF_MEMORY);
587         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, false, r,
588                          "[%s] Failed to set uri.", GetErrorMessage(r));
589
590         r = hostUri1.SetUri(host1);
591         r = TransExceptionsExclusive(r, E_INVALID_ARG, E_OUT_OF_MEMORY);
592         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, false, r,
593                          "[%s] Failed to set uri", GetErrorMessage(r));
594
595         String scheme0 = hostUri0.GetScheme();
596         String scheme1 = hostUri1.GetScheme();
597
598         if(!scheme0.Equals(scheme1, false))
599         {
600                 SetLastResult(E_INVALID_ARG);
601                 return false;
602         }
603
604         String hostPart0 = hostUri0.GetHost();
605         String hostPart1 = hostUri1.GetHost();
606
607         if(!hostPart0.Equals(hostPart1, false))
608         {
609                 SetLastResult(E_INVALID_ARG);
610                 return false;
611         }
612
613         int port0 = hostUri0.GetPort();
614         int port1 = hostUri1.GetPort();
615
616         port0 = (port0 == -1) ? _HTTP_DEFAULT_PORT : port0;
617         port1 = (port1 == -1) ? _HTTP_DEFAULT_PORT : port1;
618
619         if(port0 != port1)
620         {
621                 SetLastResult(E_INVALID_ARG);
622                 return false;
623         }
624
625         return true;
626 }
627
628 String
629 _HttpUtility::GetCookieFilePath(void)
630 {
631         result r = E_SUCCESS;
632
633         String filePath = Tizen::App::App::GetInstance()->GetAppRootPath();
634         r = filePath.Append(_HTTP_COOKIE_FILE);
635         SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, L"", r,
636                          "[%s] Propagating.", GetErrorMessage(r));
637
638         SysLog(NID_NET_HTTP, "Cookie Path: %ls", filePath.GetPointer());
639
640         return filePath;
641 }
642
643 NetHttpAuthScheme
644 _HttpUtility::GetHttpAuthScheme(bool isProxyAuth, long  curlAuthScheme)
645 {
646         NetHttpAuthScheme authScheme = NET_HTTP_AUTH_NONE;
647         if(isProxyAuth)
648         {
649                 switch (curlAuthScheme)
650                 {
651                         case _CURL_HTTP_AUTH_NONE:
652                                 authScheme = NET_HTTP_AUTH_NONE;
653                                 break;
654                         case _CURL_HTTP_AUTH_BASIC:
655                                 authScheme = NET_HTTP_AUTH_PROXY_BASIC;
656                                 break;
657                         case _CURL_HTTP_AUTH_DIGEST:
658                                 authScheme = NET_HTTP_AUTH_PROXY_MD5;
659                                 break;
660                         case _CURL_HTTP_AUTH_NTLM:
661                                 authScheme = NET_HTTP_AUTH_PROXY_NTLM;
662                                 break;
663                         default:
664                                 authScheme = NET_HTTP_AUTH_NONE;
665                                 break;
666                 }
667         }
668         else
669         {
670                 switch (curlAuthScheme)
671                 {
672                         case _CURL_HTTP_AUTH_NONE:
673                                 authScheme = NET_HTTP_AUTH_NONE;
674                                 break;
675                         case _CURL_HTTP_AUTH_BASIC:
676                                 authScheme = NET_HTTP_AUTH_WWW_BASIC;
677                                 break;
678                         case _CURL_HTTP_AUTH_DIGEST:
679                                 authScheme = NET_HTTP_AUTH_WWW_MD5;
680                                 break;
681                         case _CURL_HTTP_AUTH_NTLM:
682                                 authScheme = NET_HTTP_AUTH_WWW_NTLM;
683                                 break;
684                         case _CURL_HTTP_AUTH_GSSNEGOTIATE:
685                                 authScheme = NET_HTTP_AUTH_WWW_NEGOTIATE;
686                                 break;
687                         default:
688                                 authScheme = NET_HTTP_AUTH_NONE;
689                                 break;
690                 }
691         }
692
693         return authScheme;
694 }
695
696 long
697 _HttpUtility::GetHttpCurlAuthScheme(NetHttpAuthScheme httpAuthScheme)
698 {
699         long curlScheme = _CURL_HTTP_AUTH_NONE;
700         switch (httpAuthScheme)
701         {
702                 case NET_HTTP_AUTH_PROXY_BASIC:
703                 case NET_HTTP_AUTH_WWW_BASIC:
704                         curlScheme = _CURL_HTTP_AUTH_BASIC;
705                         break;
706                 case NET_HTTP_AUTH_PROXY_MD5:
707                 case NET_HTTP_AUTH_WWW_MD5:
708                         curlScheme = _CURL_HTTP_AUTH_DIGEST;
709                         break;
710                 case NET_HTTP_AUTH_PROXY_NTLM:
711                 case NET_HTTP_AUTH_WWW_NTLM:
712                         curlScheme = _CURL_HTTP_AUTH_NTLM;
713                         break;
714                 case NET_HTTP_AUTH_WWW_NEGOTIATE:
715                         curlScheme = _CURL_HTTP_AUTH_GSSNEGOTIATE;
716                         break;
717                 default:
718                         curlScheme = _CURL_HTTP_AUTH_NONE;
719                         break;
720         }
721
722         return curlScheme;
723 }
724
725 static const char* NetHttpAuthSchemeTypesToString[] =
726 {
727         "NET_HTTP_AUTH_NONE", "NET_HTTP_AUTH_PROXY_BASIC",
728         "NET_HTTP_AUTH_PROXY_MD5", "NET_HTTP_AUTH_WWW_BASIC",
729         "NET_HTTP_AUTH_WWW_MD5", "NET_HTTP_AUTH_PROXY_NTLM",
730         "", "NET_HTTP_AUTH_WWW_NTLM",
731         "NET_HTTP_AUTH_WWW_NEGOTIATE"
732 };
733
734 const char*
735 _HttpUtility::GetHttpAuthSchemeByString(NetHttpAuthScheme type)
736 {
737         return NetHttpAuthSchemeTypesToString[type];
738 }
739
740 _HttpSslInfo::_HttpSslInfo(int socketFd, int depth, const String & serverCert, const String & errorMessage)
741 {
742         __socketFd = socketFd;
743         __depth = depth;
744         __serverCert = serverCert;
745         __errorMessage = errorMessage;
746         __pHttpTransactionEvent = null;
747         __flag = HTTP_CV_FLAG_AUTOMATIC;
748 }
749
750 _HttpSslInfo::_HttpSslInfo(int socketFd, _HttpTransactionEvent* pHttpTransactionEvent)
751 {
752         __socketFd = socketFd;
753         __depth = -1;
754         __pHttpTransactionEvent = pHttpTransactionEvent;
755         __flag = HTTP_CV_FLAG_MANUAL;
756 }
757
758 _HttpSslInfo::~_HttpSslInfo()
759 {
760 }
761
762 int
763 _HttpSslInfo::GetDepth() const
764 {
765         return __depth;
766 }
767
768 String
769 _HttpSslInfo::GetErrorMessage() const
770 {
771         return __errorMessage;
772 }
773
774 String
775 _HttpSslInfo::GetServerCert() const
776 {
777         return __serverCert;
778 }
779
780 int
781 _HttpSslInfo::GetSocketFd() const
782 {
783         return __socketFd;
784 }
785
786 _HttpTransactionEvent*
787 _HttpSslInfo::GetHttpTransactionEvent(void) const
788 {
789         return __pHttpTransactionEvent;
790 }
791
792 NetHttpCertificateVerificationFlag
793 _HttpSslInfo::GetCertificateVerificationFlag(void) const
794 {
795         return __flag;
796 }
797
798 } } } // Tizen::Net::Http