Fix segfault with remote image download and tidy up 10/42610/5
authorNick Holland <nick.holland@partner.samsung.com>
Wed, 1 Jul 2015 08:17:51 +0000 (09:17 +0100)
committerNick Holland <nick.holland@partner.samsung.com>
Thu, 2 Jul 2015 07:25:33 +0000 (08:25 +0100)
Segfault caused by
When downloading a remote image that does not exist:

curl_easy_getinfo returning -1 for content length.

-1 gets static_cast to size_t == SIZE_MAX

SIZE_MAX passed to Dali::Vector::Reserve() as the capacity

This overflows the vector capacity calculation, ending up with only
15 bytes allocated.
It then seg faults trying to write the vector meta data which is
16 bytes long.

-----------
Tidy up

Removed memory buffer that was created to store the HTTP request header, but was
never used.

Removed all curl code from resource-thread-image.cpp  and made a generic
download file function in a separate file. We can now re-used that function for
other file types.

Added lazy creation of threads. Previously we would always create local and remote threads
for images.

Change-Id: I377e2967ac18b3e115411e370e5b85385ce23632

platform-abstractions/tizen/file.list
platform-abstractions/tizen/resource-loader/network/file-download.cpp [new file with mode: 0755]
platform-abstractions/tizen/resource-loader/network/file-download.h [new file with mode: 0644]
platform-abstractions/tizen/resource-loader/network/http-utils.cpp [new file with mode: 0644]
platform-abstractions/tizen/resource-loader/network/http-utils.h [new file with mode: 0644]
platform-abstractions/tizen/resource-loader/resource-bitmap-requester.cpp
platform-abstractions/tizen/resource-loader/resource-bitmap-requester.h
platform-abstractions/tizen/resource-loader/resource-thread-base.h
platform-abstractions/tizen/resource-loader/resource-thread-image.cpp
platform-abstractions/tizen/resource-loader/resource-thread-image.h

index a8c36a4569d01f2ece523b8a2df240b8230ec7dd..d2d6b3f62f2ad67be72b1ba4a6bee3b06e9c6482 100755 (executable)
@@ -15,6 +15,8 @@ tizen_platform_abstraction_src_files = \
   $(tizen_platform_abstraction_src_dir)/resource-loader/resource-thread-image.cpp \
   $(tizen_platform_abstraction_src_dir)/resource-loader/resource-thread-shader.cpp \
   \
+  $(tizen_platform_abstraction_src_dir)/resource-loader/network/file-download.cpp \
+  $(tizen_platform_abstraction_src_dir)/resource-loader/network/http-utils.cpp \
   \
   $(tizen_platform_abstraction_src_dir)/resource-loader/debug/resource-loader-debug.cpp \
   \
diff --git a/platform-abstractions/tizen/resource-loader/network/file-download.cpp b/platform-abstractions/tizen/resource-loader/network/file-download.cpp
new file mode 100755 (executable)
index 0000000..9f91eb6
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// HEADER
+#include "file-download.h"
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <curl/curl.h>
+
+// INTERNAL INCLUDES
+#include "portable/file-closer.h"
+
+
+using namespace Dali::Integration;
+
+namespace Dali
+{
+
+namespace TizenPlatform
+{
+
+namespace // unnamed namespace
+{
+
+const int CONNECTION_TIMEOUT_SECONDS( 30L );
+const long VERBOSE_MODE = 0L;                // 0 == off, 1 == on
+const long CLOSE_CONNECTION_ON_ERROR = 1L;   // 0 == off, 1 == on
+const long EXCLUDE_HEADER = 0L;
+const long INCLUDE_HEADER = 1L;
+const long INCLUDE_BODY = 0L;
+const long EXCLUDE_BODY = 1L;
+
+void ConfigureCurlOptions( CURL* curl_handle, const std::string& url )
+{
+  curl_easy_setopt( curl_handle, CURLOPT_URL, url.c_str() );
+  curl_easy_setopt( curl_handle, CURLOPT_VERBOSE, VERBOSE_MODE );
+
+  // CURLOPT_FAILONERROR is not fail-safe especially when authentication is involved ( see manual )
+  curl_easy_setopt( curl_handle, CURLOPT_FAILONERROR, CLOSE_CONNECTION_ON_ERROR );
+  curl_easy_setopt( curl_handle, CURLOPT_CONNECTTIMEOUT, CONNECTION_TIMEOUT_SECONDS );
+  curl_easy_setopt( curl_handle, CURLOPT_HEADER, INCLUDE_HEADER );
+  curl_easy_setopt( curl_handle, CURLOPT_NOBODY, EXCLUDE_BODY );
+}
+
+// Without a write function or a buffer (file descriptor) to write to, curl will pump out
+// header/body contents to stdout
+size_t DummyWrite(char *ptr, size_t size, size_t nmemb, void *userdata)
+{
+  return size * nmemb;
+}
+
+
+bool DownloadFile( CURL* curl_handle,
+                   const std::string& url,
+                   Dali::Vector<uint8_t>& dataBuffer,
+                   size_t& dataSize,
+                   size_t maximumAllowedSizeBytes )
+{
+  CURLcode res( CURLE_OK );
+  double size(0);
+
+  // setup curl to download just the header so we can extract the content length
+  ConfigureCurlOptions( curl_handle, url );
+
+  curl_easy_setopt( curl_handle, CURLOPT_WRITEFUNCTION, DummyWrite);
+
+  // perform the request to get the header
+  res = curl_easy_perform( curl_handle );
+
+  if( res != CURLE_OK)
+  {
+    DALI_LOG_WARNING( "Failed to download http header for \"%s\" with error code %d\n", url.c_str(), res );
+    return false;
+  }
+
+  // get the content length, -1 == size is not known
+  curl_easy_getinfo( curl_handle,CURLINFO_CONTENT_LENGTH_DOWNLOAD , &size );
+
+  if( size < 1 )
+  {
+    DALI_LOG_WARNING( "Header missing content length \"%s\" \n", url.c_str() );
+    return false;
+  }
+  if( size >= maximumAllowedSizeBytes )
+  {
+    DALI_LOG_WARNING( "File content length %f > max allowed %zu \"%s\" \n", size, maximumAllowedSizeBytes, url.c_str() );
+    return false;
+  }
+
+  dataSize = static_cast<size_t>( size );
+
+  dataBuffer.Resize( dataSize );
+
+  // create
+  Dali::Internal::Platform::FileCloser fileCloser( static_cast<void*>(&dataBuffer[0]), dataSize, "wb" );
+  FILE* dataBufferFilePointer = fileCloser.GetFile();
+  if( NULL != dataBufferFilePointer )
+  {
+    // we only want the body which contains the file data
+    curl_easy_setopt( curl_handle, CURLOPT_HEADER, EXCLUDE_HEADER );
+    curl_easy_setopt( curl_handle, CURLOPT_NOBODY, INCLUDE_BODY );
+
+    // disable the write callback, and get curl to write directly into our data buffer
+    curl_easy_setopt( curl_handle, CURLOPT_WRITEFUNCTION, NULL );
+    curl_easy_setopt( curl_handle, CURLOPT_WRITEDATA, dataBufferFilePointer );
+
+    // synchronous request of the body data
+    res = curl_easy_perform( curl_handle );
+
+    if( CURLE_OK != res )
+    {
+      DALI_LOG_WARNING( "Failed to download image file \"%s\" with error code %d\n", url.c_str(), res );
+      return false;
+    }
+  }
+  return true;
+}
+} // unnamed namespace
+
+
+
+bool Network::DownloadRemoteFileIntoMemory( const std::string& url,
+                                            Dali::Vector<uint8_t>& dataBuffer,
+                                            size_t& dataSize,
+                                            size_t maximumAllowedSizeBytes )
+{
+  if( url.empty() )
+  {
+    DALI_LOG_WARNING("empty url requested \n");
+    return false;
+  }
+
+  // start a libcurl easy session, this internally calls curl_global_init, if we ever have more than one download
+  // thread we need to explicity call curl_global_init() on startup from a single thread.
+
+  CURL* curl_handle = curl_easy_init();
+
+  bool result = DownloadFile( curl_handle, url, dataBuffer,  dataSize, maximumAllowedSizeBytes);
+
+  // clean up session
+  curl_easy_cleanup( curl_handle );
+
+  return result;
+}
+
+
+} // namespace TizenPlatform
+
+} // namespace Dali
diff --git a/platform-abstractions/tizen/resource-loader/network/file-download.h b/platform-abstractions/tizen/resource-loader/network/file-download.h
new file mode 100644 (file)
index 0000000..0d31953
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __DALI_TIZEN_PLATFORM_NETWORK_FILE_DOWNLOAD_H__
+#define __DALI_TIZEN_PLATFORM_NETWORK_FILE_DOWNLOAD_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <string>
+#include <stdint.h> // uint8
+
+namespace Dali
+{
+
+namespace TizenPlatform
+{
+
+namespace Network
+{
+
+/**
+ * Download a requested file into a memory buffer.
+ * Threading notes: This function can be called from multiple threads, however l
+ * we must explicitly call curl_global_init() from a single thread before using curl
+ * as the global function calls are not thread safe.
+ *
+ * @param[in] url The requested file url
+ * @param[out] dataBuffer  A memory buffer object to be written with downloaded file data.
+ * @param[out] dataSize  The size of the memory buffer.
+ * @param[in] maximumAllowedSize The maxmimum allowed file size in bytes to download. E.g. for an Image file this may be 50 MB
+ * @return true on success, false on failure
+ *
+ */
+bool DownloadRemoteFileIntoMemory( const std::string& url,
+                                   Dali::Vector<uint8_t>& dataBuffer,
+                                   size_t& dataSize,
+                                   size_t maximumAllowedSizeBytes );
+
+} // namespace Network
+
+} // namespace TizenPlatform
+
+} // namespace Dali
+
+#endif // __DALI_TIZEN_PLATFORM_RESOURCE_THREAD_IMAGE_H__
diff --git a/platform-abstractions/tizen/resource-loader/network/http-utils.cpp b/platform-abstractions/tizen/resource-loader/network/http-utils.cpp
new file mode 100644 (file)
index 0000000..517dfbd
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "http-utils.h"
+
+// EXTERNAL INCLUDES
+#include <cstring>
+
+namespace Dali
+{
+
+namespace TizenPlatform
+{
+
+namespace
+{
+const unsigned int MIN_HTTP_URL_LENGTH = 12; // assume we have a least http://xx/yy
+const char HTTP_URL[] = "http://";
+const char HTTPS_URL[] = "https://";
+}
+
+bool Network::IsHttpUrl( const std::string& path )
+{
+ if( path.size() <= MIN_HTTP_URL_LENGTH )
+ {
+   return false;
+ }
+
+ if( ( strncasecmp( path.c_str(), HTTP_URL,  sizeof(HTTP_URL)  -1 ) == 0 )  ||
+     ( strncasecmp( path.c_str(), HTTPS_URL, sizeof(HTTPS_URL) -1 ) == 0 ) )
+ {
+   return true;
+ }
+
+ return false;
+}
+
+} // TizenPlatform
+
+} // Dali
diff --git a/platform-abstractions/tizen/resource-loader/network/http-utils.h b/platform-abstractions/tizen/resource-loader/network/http-utils.h
new file mode 100644 (file)
index 0000000..e7d225c
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __DALI_TIZEN_PLATFORM_NETWORK_UTILS_H__
+#define __DALI_TIZEN_PLATFORM_NETWORK_UTILS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <string>
+
+namespace Dali
+{
+
+namespace TizenPlatform
+{
+
+namespace Network
+{
+
+/**
+ * @brief Tests if a string starts with either http:// or https://
+ * @param[in] path string
+ * @return true if the path is a http url
+ */
+bool IsHttpUrl( const std::string& path );
+
+} // Network
+
+} // namespace TizenPlatform
+
+} // namespace Dali
+
+#endif // __DALI_TIZEN_PLATFORM_NETWORK_UTILS_H__
index ff33ec96c4ab0d5cbd22a5ff67829fb0844fbf39..b838e33e81eaea4c5a8190dde12bc7fb6e2a1bc5 100644 (file)
  *
  */
 
+// CLASS HEADER
 #include "resource-bitmap-requester.h"
+
+// EXTERNAL INCLUDES
 #include <dali/integration-api/resource-cache.h>
 
+// INTERNAL INCLUDES
+#include "network/file-download.h"
+#include "network/http-utils.h"
+
 using namespace Dali::Integration;
 
 namespace Dali
 {
 namespace TizenPlatform
 {
+namespace
+{
+enum ResourceScheme
+{
+  FILE_SYSTEM_RESOURCE,
+  NETWORK_RESOURCE
+};
+}// unnamed namespace
 
 ResourceBitmapRequester::ResourceBitmapRequester( ResourceLoader& resourceLoader )
-: ResourceRequesterBase( resourceLoader )
+: ResourceRequesterBase( resourceLoader ),
+  mThreadImageLocal( NULL ),
+  mThreadImageRemote( NULL )
 {
-  mThreadImageLocal  = new ResourceThreadImage( resourceLoader, false );
-  mThreadImageRemote  = new ResourceThreadImage( resourceLoader, true );
 }
 
 ResourceBitmapRequester::~ResourceBitmapRequester()
@@ -40,61 +55,79 @@ ResourceBitmapRequester::~ResourceBitmapRequester()
 
 void ResourceBitmapRequester::Pause()
 {
-  mThreadImageLocal->Pause();
-  mThreadImageRemote->Pause();
+  if( mThreadImageLocal )
+  {
+    mThreadImageLocal->Pause();
+  }
+  if( mThreadImageRemote )
+  {
+    mThreadImageRemote->Pause();
+  }
 }
 
 void ResourceBitmapRequester::Resume()
 {
-  mThreadImageLocal->Resume();
-  mThreadImageRemote->Resume();
+  if( mThreadImageLocal )
+  {
+    mThreadImageLocal->Resume();
+  }
+  if( mThreadImageRemote )
+  {
+    mThreadImageRemote->Resume();
+  }
 }
 
 void ResourceBitmapRequester::LoadResource( Integration::ResourceRequest& request )
 {
   DALI_ASSERT_DEBUG( (0 != dynamic_cast<BitmapResourceType*>(request.GetType())) && "Only requsts for bitmap resources can ever be routed to ResourceBitmapRequester.\n");
   BitmapResourceType* resType = static_cast<BitmapResourceType*>(request.GetType());
-  if( resType )
+  if( !resType )
   {
-    // Work out what thread to decode / load the image on:
-    ResourceThreadBase* const localImageThread = mThreadImageLocal;
-    ResourceThreadBase* const remoteImageThread = mThreadImageRemote;
-    ResourceThreadBase* workerThread;
-
-    // Work out if the resource is in memory, a file, or in a remote server:
-    ResourceThreadBase::RequestType requestType;
-    if( request.GetResource().Get() )
+    return;
+  }
+
+  // Work out what thread to decode / load the image on:
+  ResourceScheme scheme( FILE_SYSTEM_RESOURCE );
+
+  // Work out if the resource is in memory, a file, or in a remote server:
+  ResourceThreadBase::RequestType requestType;
+
+  // if resource exists already, then it just needs decoding
+  if( request.GetResource().Get() )
+  {
+    requestType = ResourceThreadBase::RequestDecode;
+  }
+  else
+  {
+    const std::string& resourcePath = request.GetPath();
+    if( Network::IsHttpUrl( resourcePath) )
     {
-      requestType = ResourceThreadBase::RequestDecode;
-      workerThread = localImageThread;
+      requestType = ResourceThreadBase::RequestDownload;
+      scheme = NETWORK_RESOURCE;
     }
     else
     {
-      const std::string& resourcePath = request.GetPath();
-      if( strncasecmp( resourcePath.c_str(), "http", 4 ) == 0 )
-      {
-        if( resourcePath.size() > 4 &&
-            ( strncasecmp( &resourcePath.c_str()[4], "://", 3 ) == 0 ||
-              strncasecmp( &resourcePath.c_str()[4], "s://", 4) == 0 ) )
-        {
-          requestType = ResourceThreadBase::RequestDownload;
-          workerThread = remoteImageThread;
-        }
-        else
-        {
-          requestType = ResourceThreadBase::RequestLoad;
-          workerThread = localImageThread;
-        }
-      }
-      else
-      {
-        requestType = ResourceThreadBase::RequestLoad;
-        workerThread = localImageThread;
-      }
+      requestType = ResourceThreadBase::RequestLoad;
     }
+  }
 
-    // Dispatch the job to the right thread:
-    workerThread->AddRequest( request, requestType );
+  // Dispatch the job to the right thread
+  // lazily create the thread
+  if( scheme ==  FILE_SYSTEM_RESOURCE )
+  {
+    if( !mThreadImageLocal )
+    {
+      mThreadImageLocal = new ResourceThreadImage( mResourceLoader );
+    }
+    mThreadImageLocal->AddRequest( request, requestType );
+  }
+  else
+  {
+    if( !mThreadImageRemote )
+    {
+      mThreadImageRemote = new ResourceThreadImage( mResourceLoader );
+    }
+    mThreadImageRemote->AddRequest( request, requestType );
   }
 }
 
@@ -111,8 +144,14 @@ void ResourceBitmapRequester::SaveResource(const Integration::ResourceRequest& r
 
 void ResourceBitmapRequester::CancelLoad(Integration::ResourceId id, Integration::ResourceTypeId typeId)
 {
-  mThreadImageLocal->CancelRequest(id);
-  mThreadImageRemote->CancelRequest(id);
+  if( mThreadImageLocal )
+  {
+    mThreadImageLocal->CancelRequest(id);
+  }
+  if( mThreadImageRemote )
+  {
+    mThreadImageRemote->CancelRequest(id);
+  }
 }
 
 } // TizenPlatform
index d5a4bb7722bff30e08fff358e6009f032216f450..218f26ed247fccaaf26e81ac5baac545f9a4ad18 100644 (file)
@@ -73,7 +73,7 @@ public:
    */
   virtual void CancelLoad(Integration::ResourceId id, Integration::ResourceTypeId typeId);
 
-protected:
+private:
   ResourceThreadImage*          mThreadImageLocal;      ///< Image loader thread object to load images in local machine
   ResourceThreadImage*          mThreadImageRemote;     ///< Image loader thread object to download images in remote http server
 };
index 3034c86a1f22e9cfb712a5126004bba6f1bfc907..b4499fbc2fc4ffae21f05cc6d0e8fbb438e49c25 100644 (file)
@@ -48,7 +48,7 @@ public:
   {
     /** Pull a resource out of the platform's file system. */
     RequestLoad,
-    /** Pull a resource over http protocol. */
+    /** Pull a resource from the network. */
     RequestDownload,
     /** Pull a resource out of a memory buffer. */
     RequestDecode,
index 3062265c14618c56be6607b7ba88501aa31e3244..5838721dec7312b822d5c10c01319333ca1db014 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
+// CLASS HEADER
 #include "resource-thread-image.h"
+
+// EXTERNAL INCLUDES
 #include <dali/devel-api/common/ref-counted-dali-vector.h>
 #include <dali/integration-api/bitmap.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/resource-cache.h>
 #include <dali/integration-api/resource-types.h>
-#include <curl/curl.h>
+
+// INTERNAL INCLUDES
 #include "portable/file-closer.h"
 #include "image-loaders/image-loader.h"
+#include "network/file-download.h"
 
 using namespace Dali::Integration;
 
-namespace
-{
-const int CONNECTION_TIMEOUT( 30 );
-}
-
 namespace Dali
 {
 
 namespace TizenPlatform
 {
 
-ResourceThreadImage::ResourceThreadImage(ResourceLoader& resourceLoader, bool forRemoteImage)
+namespace
+{
+
+// limit maximum image down load size to 50 MB
+const size_t MAXIMUM_DOWNLOAD_IMAGE_SIZE  = 50 * 1024 * 1024 ;
+}
+
+ResourceThreadImage::ResourceThreadImage(ResourceLoader& resourceLoader)
 : ResourceThreadBase(resourceLoader)
 {
 }
@@ -104,87 +111,13 @@ void ResourceThreadImage::Save(const Integration::ResourceRequest& request)
 
 bool ResourceThreadImage::DownloadRemoteImageIntoMemory(const Integration::ResourceRequest& request, Dali::Vector<uint8_t>& dataBuffer, size_t& dataSize)
 {
-  bool succeeded = true;
-  CURLcode cresult;
-
-  CURL* curl_handle = curl_easy_init();
-  curl_easy_setopt( curl_handle, CURLOPT_VERBOSE, 0 );
-  curl_easy_setopt( curl_handle, CURLOPT_URL, request.GetPath().c_str() );
-  curl_easy_setopt( curl_handle, CURLOPT_FAILONERROR, 1 );
-  curl_easy_setopt( curl_handle, CURLOPT_CONNECTTIMEOUT, CONNECTION_TIMEOUT );
-
-  // Download header first to get data size
-  char* headerBytes = NULL;
-  size_t headerSize = 0;
-  FILE* header_fp = open_memstream( &headerBytes, &headerSize );
-  double size;
-
-  if( NULL != header_fp)
-  {
-    curl_easy_setopt( curl_handle, CURLOPT_HEADER, 1 );
-    curl_easy_setopt( curl_handle, CURLOPT_NOBODY, 1 );
-    curl_easy_setopt( curl_handle, CURLOPT_WRITEDATA, header_fp );
-
-    cresult = curl_easy_perform( curl_handle );
-    if( cresult == CURLE_OK )
-    {
-      curl_easy_getinfo( curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &size );
-    }
-    else
-    {
-      DALI_LOG_WARNING( "Failed to download http header for \"%s\" with error code %d\n", request.GetPath().c_str(), cresult );
-      succeeded = false;
-    }
-
-    fclose( header_fp );
-  }
-  else
-  {
-    succeeded = false;
-  }
-
-  if( NULL != headerBytes )
-  {
-    free( headerBytes );
-  }
-
-  if( succeeded )
-  {
-    // Download file data
-    dataSize = static_cast<size_t>( size );
-    dataBuffer.Reserve( dataSize );
-    dataBuffer.Resize( dataSize );
-
-    Dali::Internal::Platform::FileCloser fileCloser( static_cast<void*>(&dataBuffer[0]), dataSize, "wb" );
-    FILE* data_fp = fileCloser.GetFile();
-    if( NULL != data_fp )
-    {
-      curl_easy_setopt( curl_handle, CURLOPT_HEADER, 0 );
-      curl_easy_setopt( curl_handle, CURLOPT_NOBODY, 0 );
-      curl_easy_setopt( curl_handle, CURLOPT_WRITEDATA, data_fp );
-
-      cresult = curl_easy_perform( curl_handle );
-      if( CURLE_OK != cresult )
-      {
-        DALI_LOG_WARNING( "Failed to download image file \"%s\" with error code %d\n", request.GetPath().c_str(), cresult );
-        succeeded = false;
-      }
-    }
-    else
-    {
-      succeeded = false;
-    }
-  }
-
-  curl_easy_cleanup( curl_handle );
-
-  if( !succeeded )
+  bool ok = Network::DownloadRemoteFileIntoMemory( request.GetPath(), dataBuffer,  dataSize, MAXIMUM_DOWNLOAD_IMAGE_SIZE );
+  if( !ok )
   {
     FailedResource resource(request.GetId(), FailureUnknown);
     mResourceLoader.AddFailedLoad(resource);
   }
-
-  return succeeded;
+  return ok;
 }
 
 void ResourceThreadImage::LoadImageFromLocalFile(const Integration::ResourceRequest& request)
index d2a1b9f6fb48f10f703bfbc2dfe1ced72dfb8bdd..91d518838eefce1316578cfd6520f5da21926c82 100644 (file)
@@ -2,7 +2,7 @@
 #define __DALI_TIZEN_PLATFORM_RESOURCE_THREAD_IMAGE_H__
 
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  *
  */
-
+// EXTERNAL INCLUDES
 #include <dali/integration-api/resource-cache.h>
 #include <dali/integration-api/resource-types.h>
+
+// INTERNAL INCLUDES
 #include "resource-thread-base.h"
 
 namespace Dali
@@ -35,7 +37,7 @@ public:
    * Constructor
    * @param[in] resourceLoader A reference to the ResourceLoader
    */
-  ResourceThreadImage(ResourceLoader& resourceLoader, bool forRemoteImage);
+  ResourceThreadImage( ResourceLoader& resourceLoader );
 
   /**
    * Destructor