From bc77c8b78fc55cd68e0eefd96441d22a997c222f Mon Sep 17 00:00:00 2001
From: Nick Draper <nick.draper@stfc.ac.uk>
Date: Fri, 21 Nov 2014 09:53:12 +0000
Subject: [PATCH] re #10549 create DownloadFile and InternetHelper

---
 .../Framework/DataHandling/CMakeLists.txt     |   9 +-
 .../inc/MantidDataHandling/DownloadFile.h     |  67 +++
 .../DataHandling/src/DownloadFile.cpp         |  93 ++++
 .../DataHandling/test/DownloadFileTest.h      | 142 ++++++
 Code/Mantid/Framework/Kernel/CMakeLists.txt   |   3 +
 .../Kernel/inc/MantidKernel/ConfigService.h   |   9 +
 .../Kernel/inc/MantidKernel/Exception.h       |  25 ++
 .../Kernel/inc/MantidKernel/InternetHelper.h  |  92 ++++
 .../Framework/Kernel/src/ConfigService.cpp    |  35 +-
 .../Mantid/Framework/Kernel/src/Exception.cpp |  51 +++
 .../Framework/Kernel/src/InternetHelper.cpp   | 403 ++++++++++++++++++
 .../Kernel/test/InternetHelperTest.h          | 125 ++++++
 .../src/ScriptRepositoryImpl.cpp              |   2 +-
 .../source/algorithms/DownloadFile-v1.rst     |  73 ++++
 14 files changed, 1123 insertions(+), 6 deletions(-)
 create mode 100644 Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/DownloadFile.h
 create mode 100644 Code/Mantid/Framework/DataHandling/src/DownloadFile.cpp
 create mode 100644 Code/Mantid/Framework/DataHandling/test/DownloadFileTest.h
 create mode 100644 Code/Mantid/Framework/Kernel/inc/MantidKernel/InternetHelper.h
 create mode 100644 Code/Mantid/Framework/Kernel/src/InternetHelper.cpp
 create mode 100644 Code/Mantid/Framework/Kernel/test/InternetHelperTest.h
 create mode 100644 Code/Mantid/docs/source/algorithms/DownloadFile-v1.rst

diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt
index 5df27be94a9..0bbf2bc35bf 100644
--- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt
+++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt
@@ -10,6 +10,7 @@ set ( SRC_FILES
 	src/DefineGaugeVolume.cpp
 	src/DeleteTableRows.cpp
 	src/DetermineChunking.cpp
+	src/DownloadFile.cpp
 	src/ExtractMonitorWorkspace.cpp
 	src/FilterEventsByLogValuePreNexus.cpp
 	src/FindDetectorsInShape.cpp
@@ -126,10 +127,9 @@ set ( SRC_FILES
 	src/SaveMask.cpp
 	src/SaveNISTDAT.cpp
 	src/SaveNXSPE.cpp
+	src/SaveNXTomo.cpp
 	src/SaveNexus.cpp
 	src/SaveNexusProcessed.cpp
-	src/SaveNXTomo.cpp
-	src/SaveParameterFile.cpp
 	src/SavePAR.cpp
 	src/SavePDFGui.cpp
 	src/SavePHX.cpp
@@ -156,6 +156,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/DefineGaugeVolume.h
 	inc/MantidDataHandling/DeleteTableRows.h
 	inc/MantidDataHandling/DetermineChunking.h
+	inc/MantidDataHandling/DownloadFile.h
 	inc/MantidDataHandling/ExtractMonitorWorkspace.h
 	inc/MantidDataHandling/FilterEventsByLogValuePreNexus.h
 	inc/MantidDataHandling/FindDetectorsInShape.h
@@ -267,10 +268,9 @@ set ( INC_FILES
 	inc/MantidDataHandling/SaveMask.h
 	inc/MantidDataHandling/SaveNISTDAT.h
 	inc/MantidDataHandling/SaveNXSPE.h
+	inc/MantidDataHandling/SaveNXTomo.h
 	inc/MantidDataHandling/SaveNexus.h
 	inc/MantidDataHandling/SaveNexusProcessed.h
-	inc/MantidDataHandling/SaveNXTomo.h
-	inc/MantidDataHandling/SaveParameterFile.h
 	inc/MantidDataHandling/SavePAR.h
 	inc/MantidDataHandling/SavePDFGui.h
 	inc/MantidDataHandling/SavePHX.h
@@ -301,6 +301,7 @@ set ( TEST_FILES
 	DefineGaugeVolumeTest.h
 	DeleteTableRowsTest.h
 	DetermineChunkingTest.h
+	DownloadFileTest.h
 	ExtractMonitorWorkspaceTest.h
 	FilterEventsByLogValuePreNexusTest.h
 	FindDetectorsInShapeTest.h
diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/DownloadFile.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/DownloadFile.h
new file mode 100644
index 00000000000..43063c68806
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/DownloadFile.h
@@ -0,0 +1,67 @@
+#ifndef MANTID_DATAHANDLING_DOWNLOADFILE_H_
+#define MANTID_DATAHANDLING_DOWNLOADFILE_H_
+
+#include "MantidKernel/System.h"
+#include "MantidAPI/Algorithm.h"
+
+namespace Mantid
+{
+
+namespace Kernel
+{
+  //forward Declaration
+  class InternetHelper;
+}
+
+namespace DataHandling
+{
+
+  /** DownloadFile : Downloads a file from a url to the file system
+
+    Copyright &copy; 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://github.com/mantidproject/mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+  */
+  class DLLExport DownloadFile  : public API::Algorithm
+  {
+  public:
+    DownloadFile();
+    virtual ~DownloadFile();
+    
+    virtual const std::string name() const;
+    virtual int version() const;
+    virtual const std::string category() const;
+    virtual const std::string summary() const;
+
+  protected:
+    Kernel::InternetHelper* m_internetHelper;
+
+  private:
+    void init();
+    void exec();
+
+
+
+  };
+
+
+} // namespace DataHandling
+} // namespace Mantid
+
+#endif  /* MANTID_DATAHANDLING_DOWNLOADFILE_H_ */
\ No newline at end of file
diff --git a/Code/Mantid/Framework/DataHandling/src/DownloadFile.cpp b/Code/Mantid/Framework/DataHandling/src/DownloadFile.cpp
new file mode 100644
index 00000000000..37c0c322ad3
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/src/DownloadFile.cpp
@@ -0,0 +1,93 @@
+#include "MantidDataHandling/DownloadFile.h"
+#include "MantidKernel/InternetHelper.h"
+#include "MantidKernel/ListValidator.h"
+#include "MantidKernel/MandatoryValidator.h"
+#include "MantidAPI/FileProperty.h"
+
+#include "Poco/URI.h"
+
+#include "boost/make_shared.hpp"
+#include "boost/algorithm/string/predicate.hpp"
+
+#include <string>
+#include <stdexcept>
+
+namespace Mantid
+{
+namespace DataHandling
+{
+  
+  using Mantid::Kernel::Direction;
+  using Mantid::Kernel::MandatoryValidator;
+  using Mantid::Kernel::StringListValidator;
+  using Mantid::API::WorkspaceProperty;
+  using Mantid::API::FileProperty;
+
+  // Register the algorithm into the AlgorithmFactory
+  DECLARE_ALGORITHM(DownloadFile)
+
+
+
+  //----------------------------------------------------------------------------------------------
+  /** Constructor
+   */
+  DownloadFile::DownloadFile():m_internetHelper(new Kernel::InternetHelper())
+  {
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** Destructor
+   */
+  DownloadFile::~DownloadFile()
+  {
+    delete m_internetHelper;
+  }
+
+
+  //----------------------------------------------------------------------------------------------
+
+  /// Algorithms name for identification. @see Algorithm::name
+  const std::string DownloadFile::name() const { return "DownloadFile"; }
+
+  /// Algorithm's version for identification. @see Algorithm::version
+  int DownloadFile::version() const { return 1;}
+
+  /// Algorithm's category for identification. @see Algorithm::category
+  const std::string DownloadFile::category() const { return "DataHandling";}
+
+  /// Algorithm's summary for use in the GUI and help. @see Algorithm::summary
+  const std::string DownloadFile::summary() const { return "Downloads a file from a url to the file system";}
+
+
+  //----------------------------------------------------------------------------------------------
+  /** Initialize the algorithm's properties.
+   */
+  void DownloadFile::init()
+  {
+    declareProperty("Address", "",   boost::make_shared<MandatoryValidator<std::string> >(),
+        "The address of the network resource to download. This should start http:// or https:// .", Direction::InOut);
+    declareProperty(new FileProperty("Filename", "", FileProperty::Save),
+		    "The filename to save the download to.");
+  }
+
+  //----------------------------------------------------------------------------------------------
+  /** Execute the algorithm.
+   */
+  void DownloadFile::exec()
+  {
+    std::string address = getProperty("Address");
+    if ((!boost::starts_with(address,"http://")) && (!boost::starts_with(address,"https://")))
+    {
+      address = "http://" + address;
+      g_log.information("Address must start http:// or https://, http has been assumed to continue: " + address);
+    }
+    std::string filename = getProperty("Filename");
+
+    Poco::URI url(address);
+    m_internetHelper->downloadFile(url.toString(),filename);
+    setProperty("Address",address);
+  }
+
+
+} // namespace DataHandling
+} // namespace Mantid
\ No newline at end of file
diff --git a/Code/Mantid/Framework/DataHandling/test/DownloadFileTest.h b/Code/Mantid/Framework/DataHandling/test/DownloadFileTest.h
new file mode 100644
index 00000000000..1c04536f737
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/test/DownloadFileTest.h
@@ -0,0 +1,142 @@
+#ifndef MANTID_DATAHANDLING_DOWNLOADFILETEST_H_
+#define MANTID_DATAHANDLING_DOWNLOADFILETEST_H_
+
+#include <cxxtest/TestSuite.h>
+
+#include "MantidDataHandling/DownloadFile.h"
+#include "MantidKernel/InternetHelper.h"
+
+#include <Poco/TemporaryFile.h>
+
+
+#include <fstream>
+#include <sstream>
+
+using Mantid::Kernel::InternetHelper;
+using Mantid::DataHandling::DownloadFile;
+using namespace Mantid::Kernel;
+using namespace Mantid::API;
+
+
+namespace
+{
+  /**
+   * Mock out the internet calls of this helper
+   */
+  class MockedInternetHelper : public InternetHelper
+  {
+  protected:
+    virtual int sendHTTPSRequest(const std::string& url, 
+                          std::ostream& responseStream,
+                          const StringToStringMap& headers = StringToStringMap())
+    {
+      responseStream << "HTTPS request succeeded";
+      return 200;
+    }
+    virtual int sendHTTPRequest(const std::string& url, 
+                              std::ostream& responseStream,
+                              const StringToStringMap& headers = StringToStringMap())
+    {
+      responseStream << "HTTP request succeeded";
+      return 200;
+    }
+  };
+
+    /**
+   * Mock out the internet calls of this algorithm
+   */
+  class MockedDownloadFile : public DownloadFile
+  {
+  public:
+    MockedDownloadFile::MockedDownloadFile()
+    {
+      delete m_internetHelper;
+      m_internetHelper = new MockedInternetHelper();
+    }
+  };
+}
+
+
+class DownloadFileTest : public CxxTest::TestSuite
+{
+public:
+  // This pair of boilerplate methods prevent the suite being created statically
+  // This means the constructor isn't called when running other tests
+  static DownloadFileTest *createSuite() { return new DownloadFileTest(); }
+  static void destroySuite( DownloadFileTest *suite ) { delete suite; }
+
+
+  void test_Init()
+  {
+    DownloadFile alg;
+    TS_ASSERT_THROWS_NOTHING( alg.initialize() )
+    TS_ASSERT( alg.isInitialized() )
+  }
+
+  void test_Bad_Address()
+  {
+    MockedInternetHelper internetHelper;
+    std::string url = "www.google.com";
+    Poco::TemporaryFile tmpFile;
+    exec_alg(url,tmpFile.path(), "http://" + url);
+  }
+
+  void exec_alg(std::string address, std::string filename, std::string newAddress = "")
+  {
+    MockedDownloadFile alg;
+    TS_ASSERT_THROWS_NOTHING( alg.initialize() )
+    TS_ASSERT( alg.isInitialized() )
+    TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Address", address) );
+    TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", filename) );
+    TS_ASSERT_THROWS_NOTHING( alg.execute(); );
+    TS_ASSERT( alg.isExecuted() );
+    if (newAddress.size() > 0)
+    {
+      TS_ASSERT_EQUALS(newAddress, alg.getPropertyValue("Address") );
+    }
+  }
+  
+  void test_DownloadFile_HTTP()
+  {
+    MockedInternetHelper internetHelper;
+    std::string url = "http://www.google.com";
+    Poco::TemporaryFile tmpFile;
+    exec_alg(url,tmpFile.path());
+    TSM_ASSERT("File has not been created.",tmpFile.exists()); 
+    TSM_ASSERT("File is not a file.",tmpFile.isFile()); 
+    std::fstream fs;
+    TS_ASSERT_THROWS_NOTHING (fs.open (tmpFile.path(), std::fstream::in ));
+    
+    TSM_ASSERT("Cannot open file.",fs.is_open()); 
+    
+    std::stringstream ss;
+    ss << fs.rdbuf();//read the file
+    fs.close();
+
+    TS_ASSERT_EQUALS ("HTTP request succeeded", ss.str());
+  }
+
+  void test_DownloadFile_HTTPS()
+  {
+    MockedInternetHelper internetHelper;
+    std::string httpsUrl = "https://api.github.com/repos/mantidproject/mantid/contents";
+    Poco::TemporaryFile tmpFile;
+    exec_alg(httpsUrl,tmpFile.path());
+    TSM_ASSERT("File has not been created.",tmpFile.exists()); 
+    TSM_ASSERT("File is not a file.",tmpFile.isFile()); 
+    std::fstream fs;
+    TS_ASSERT_THROWS_NOTHING (fs.open (tmpFile.path(), std::fstream::in ));
+    
+    TSM_ASSERT("Cannot open file.",fs.is_open()); 
+    
+    std::stringstream ss;
+    ss << fs.rdbuf();//read the file
+    fs.close();
+
+    TS_ASSERT_EQUALS ("HTTPS request succeeded", ss.str());
+  }
+
+};
+
+
+#endif /* MANTID_DATAHANDLING_DOWNLOADFILETEST_H_ */
\ No newline at end of file
diff --git a/Code/Mantid/Framework/Kernel/CMakeLists.txt b/Code/Mantid/Framework/Kernel/CMakeLists.txt
index c76df1829da..897b0ac8c7c 100644
--- a/Code/Mantid/Framework/Kernel/CMakeLists.txt
+++ b/Code/Mantid/Framework/Kernel/CMakeLists.txt
@@ -32,6 +32,7 @@ set ( SRC_FILES
 	src/IPropertyManager.cpp
 	src/ISaveable.cpp
 	src/InstrumentInfo.cpp
+	src/InternetHelper.cpp
 	src/Interpolation.cpp
 	src/LibraryManager.cpp
 	src/LibraryWrapper.cpp
@@ -160,6 +161,7 @@ set ( INC_FILES
 	inc/MantidKernel/IValidator.h
 	inc/MantidKernel/Instantiator.h
 	inc/MantidKernel/InstrumentInfo.h
+	inc/MantidKernel/InternetHelper.h
 	inc/MantidKernel/Interpolation.h
 	inc/MantidKernel/LibraryManager.h
 	inc/MantidKernel/LibraryWrapper.h
@@ -284,6 +286,7 @@ set ( TEST_FILES
 	ISaveableTest.h
 	IValidatorTest.h
 	InstrumentInfoTest.h
+	InternetHelperTest.h
 	InterpolationTest.h
 	ListValidatorTest.h
 	LogFilterTest.h
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/ConfigService.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/ConfigService.h
index 498154a9719..baa5a86715f 100644
--- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/ConfigService.h
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/ConfigService.h
@@ -6,6 +6,7 @@
 //----------------------------------------------------------------------
 #include "MantidKernel/DllConfig.h"
 #include "MantidKernel/SingletonHolder.h"
+#include "MantidKernel/ProxyInfo.h"
 #include <vector>
 #include <map>
 #include <set>
@@ -227,6 +228,8 @@ namespace Mantid
       /// Quick check to determine if vates has been installed.
       bool quickVatesCheck() const;
 
+      Kernel::ProxyInfo& getProxy(const std::string& url);
+
     private:
       friend struct Mantid::Kernel::CreateUsingNew<ConfigServiceImpl>;
       /// Handles distribution of Poco signals.
@@ -307,6 +310,12 @@ namespace Mantid
       std::vector<FacilityInfo*> m_facilities;
       /// Define a flag value for a removed property
       const std::string m_removedFlag;
+
+      ///local cache of proxy details
+      Kernel::ProxyInfo m_proxyInfo;
+      ///wether the proxy has been populated yet
+      bool m_isProxySet;
+
     };
 
     /// Forward declaration of a specialisation of SingletonHolder for AlgorithmFactoryImpl (needed for dllexport/dllimport) and a typedef for it.
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Exception.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Exception.h
index 3717fdc5220..677f3be39ff 100644
--- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/Exception.h
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/Exception.h
@@ -345,6 +345,31 @@ class MANTID_KERNEL_DLL OpenGLError: public std::runtime_error
     const char* what() const throw();
   };
 
+  /** Exception thrown when error occurs accessing an internet resource
+   *
+   *  @author Nick Draper, Tessella
+   *  @date 13/11/2013
+   */
+  class MANTID_KERNEL_DLL
+  InternetError : public std::runtime_error
+  {
+  private:
+    /// The message returned by what()
+    std::string outMessage;
+    int m_errorCode; ///< The message reported by what()
+
+  public:
+    InternetError(const std::string& message, const int& errorCode = 0);
+    InternetError(const InternetError&);
+    ~InternetError() throw() {}
+
+    InternetError & operator=(const InternetError &);
+
+    /// Overloaded reporting method
+    const char* what() const throw();
+    const int& errorCode() const;
+  };
+
 } //namespace Exception
 } // namespace Kernel
 } // namespace Mantid
diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/InternetHelper.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/InternetHelper.h
new file mode 100644
index 00000000000..b5ad080f184
--- /dev/null
+++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/InternetHelper.h
@@ -0,0 +1,92 @@
+#ifndef MANTID_KERNEL_InternetHelper_H_
+#define MANTID_KERNEL_InternetHelper_H_
+
+#include "MantidKernel/System.h"
+#include "MantidKernel/DllConfig.h"
+#include "MantidKernel/ProxyInfo.h"
+
+#include <map>
+
+namespace Poco
+{
+  namespace Net
+  {
+    //forward declaration
+    class HTTPResponse;
+  }
+}
+
+
+namespace Mantid
+{
+namespace Kernel
+{
+  //forward declaration
+  class Logger;
+
+  /** InternetHelper : A helper class for supporting access to resources through HTTP and HTTPS
+
+    Copyright &copy; 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://github.com/mantidproject/mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+  */
+  class MANTID_KERNEL_DLL InternetHelper
+  {
+  public:
+    InternetHelper();
+    InternetHelper(const Kernel::ProxyInfo& proxy);
+    virtual ~InternetHelper();
+
+    // Convenience typedef
+    typedef std::map<std::string, std::string> StringToStringMap;
+
+    virtual int downloadFile(const std::string& urlFile, const std::string& localFilePath = "",
+                              const StringToStringMap& headers = StringToStringMap());
+    virtual int sendRequest(const std::string& url, 
+                              std::ostream& responseStream,
+                              const StringToStringMap& headers = StringToStringMap());
+
+    Kernel::ProxyInfo& getProxy(const std::string& url);
+    void clearProxy();
+    void setProxy(const Kernel::ProxyInfo& proxy);
+
+    void setTimeout(int seconds);
+
+  protected:
+    virtual int sendHTTPSRequest(const std::string& url, 
+                              std::ostream& responseStream,
+                              const StringToStringMap& headers = StringToStringMap());    
+    virtual int sendHTTPRequest(const std::string& url, 
+                              std::ostream& responseStream,
+                              const StringToStringMap& headers = StringToStringMap());
+    virtual int processErrorStates(const Poco::Net::HTTPResponse& res, std::istream & rs,const std::string& url);
+  private:
+
+    Kernel::ProxyInfo m_proxyInfo;
+    bool m_isProxySet;
+    int m_timeout;
+  };
+
+
+} // namespace Kernel
+} // namespace Mantid
+
+#endif  /* MANTID_KERNEL_InternetHelper_H_ */
+
+
diff --git a/Code/Mantid/Framework/Kernel/src/ConfigService.cpp b/Code/Mantid/Framework/Kernel/src/ConfigService.cpp
index f81d562cb7a..2f0dd6417d8 100644
--- a/Code/Mantid/Framework/Kernel/src/ConfigService.cpp
+++ b/Code/Mantid/Framework/Kernel/src/ConfigService.cpp
@@ -11,6 +11,7 @@
 #include "MantidKernel/StdoutChannel.h"
 #include "MantidKernel/Exception.h"
 #include "MantidKernel/FacilityInfo.h"
+#include "MantidKernel/NetworkProxy.h"
 
 #include <Poco/Util/LoggingConfigurator.h>
 #include <Poco/Util/SystemConfiguration.h>
@@ -27,6 +28,7 @@
 #include <Poco/Environment.h>
 #include <Poco/Process.h>
 #include <Poco/String.h>
+#include <Poco/URI.h>
 #ifdef _WIN32
   #pragma warning( disable: 4250 )
 #endif
@@ -182,7 +184,8 @@ ConfigServiceImpl::ConfigServiceImpl() :
 #else
   m_user_properties_file_name("Mantid.user.properties"),
 #endif
-  m_DataSearchDirs(), m_UserSearchDirs(), m_InstrumentDirs(), m_instr_prefixes(), m_removedFlag("@@REMOVED@@")
+  m_DataSearchDirs(), m_UserSearchDirs(), m_InstrumentDirs(), m_instr_prefixes(), m_removedFlag("@@REMOVED@@"),
+  m_proxyInfo(),m_isProxySet(false)
 {
   //getting at system details
   m_pSysConfig = new WrappedObject<Poco::Util::SystemConfiguration> ;
@@ -2021,6 +2024,36 @@ bool ConfigServiceImpl::quickVatesCheck() const
   return found;
 }
 
+/*
+Gets the system proxy information
+@url A url to match the proxy to
+@return the proxy information.
+*/
+Kernel::ProxyInfo& ConfigServiceImpl::getProxy(const std::string& url)
+{
+  if (!m_isProxySet)
+  {  
+    //set the proxy
+    //first check if the proxy is defined in the properties file
+    std::string proxyHost;
+    int proxyPort;
+    if ((getValue("proxy.host",proxyHost) == 1) && (getValue("proxy.port",proxyPort) == 1))
+    {
+      //set it from the config values
+      m_proxyInfo = ProxyInfo(proxyHost,proxyPort,true);
+    }
+    else
+    {
+      //get the system proxy
+      Poco::URI uri(url);
+      Mantid::Kernel::NetworkProxy proxyHelper;
+      m_proxyInfo = proxyHelper.getHttpProxy(uri.toString());
+    }      
+    m_isProxySet = true;
+  }
+  return m_proxyInfo;
+}
+
 /// \cond TEMPLATE
 template DLLExport int ConfigServiceImpl::getValue(const std::string&, double&);
 template DLLExport int ConfigServiceImpl::getValue(const std::string&, std::string&);
diff --git a/Code/Mantid/Framework/Kernel/src/Exception.cpp b/Code/Mantid/Framework/Kernel/src/Exception.cpp
index d5330df3d98..f2784d76054 100644
--- a/Code/Mantid/Framework/Kernel/src/Exception.cpp
+++ b/Code/Mantid/Framework/Kernel/src/Exception.cpp
@@ -378,6 +378,57 @@ const char* NullPointerException::what() const throw()
   return outMessage.c_str();
 }
 
+//-------------------------
+// InternetError Error class
+//-------------------------
+
+/**
+  Constructor
+  @param message :: The error message
+  @param errorCode :: The HTTP error code if available
+*/
+InternetError::InternetError(const std::string& message, const int& errorCode) :
+  std::runtime_error(message)
+{
+  std::stringstream cx;
+  cx << "InternetError: ";
+  if (errorCode!=0)
+  {
+    cx << "[" << errorCode << "] ";
+  } 
+  cx << message;
+  outMessage = cx.str();
+  m_errorCode = errorCode;
+}
+
+/**
+  Copy Constructor
+  @param A :: IndexError to copy
+*/
+InternetError::InternetError(const InternetError& A) :
+  std::runtime_error(A)
+{}
+
+/**
+  Writes out the range and limits
+  @return the error string
+*/
+const char* InternetError::what() const throw()
+{
+  return outMessage.c_str();
+}
+
+/**
+  Writes out the range and limits
+  @return the error string
+*/
+const int& InternetError::errorCode() const
+{
+  return m_errorCode;
+}
+
+
+
 } // namespace Exception
 } // namespace Kernel
 } // namespace Mantid
diff --git a/Code/Mantid/Framework/Kernel/src/InternetHelper.cpp b/Code/Mantid/Framework/Kernel/src/InternetHelper.cpp
new file mode 100644
index 00000000000..96c699176c5
--- /dev/null
+++ b/Code/Mantid/Framework/Kernel/src/InternetHelper.cpp
@@ -0,0 +1,403 @@
+#include "MantidKernel/InternetHelper.h"
+#include "MantidKernel/ConfigService.h"
+#include "MantidKernel/DateAndTime.h"
+#include "MantidKernel/Exception.h"
+#include "MantidKernel/Logger.h"
+
+// Poco
+#include <Poco/Net/AcceptCertificateHandler.h>
+#include <Poco/Net/NetException.h>
+#include <Poco/Net/HTTPRequest.h>
+#include <Poco/Net/HTTPResponse.h>
+#include <Poco/Net/HTTPSClientSession.h>
+#include <Poco/Net/PrivateKeyPassphraseHandler.h>
+#include <Poco/Net/SecureStreamSocket.h>
+#include <Poco/Net/SSLManager.h>
+#include <Poco/StreamCopier.h>
+#include <Poco/TemporaryFile.h>
+#include <Poco/URI.h>
+// Visual Studio complains with the inclusion of Poco/FileStream
+// disabling this warning.
+#if defined(_WIN32) || defined(_WIN64)
+#pragma warning( push )
+#pragma warning( disable : 4250 )
+ #include <Poco/FileStream.h>
+ #include <Poco/NullStream.h>
+ #include <Winhttp.h>
+#pragma warning( pop )
+#else
+ #include <Poco/FileStream.h>
+ #include <Poco/NullStream.h>
+ #include <stdlib.h>
+#endif
+
+// std
+#include <fstream>
+
+namespace Mantid
+{
+namespace Kernel
+{
+
+using namespace Poco::Net;
+
+namespace 
+{ 
+  // anonymous namespace for some utility functions
+
+  /// static Logger object
+  Logger g_log("InternetHelper");
+}
+
+//----------------------------------------------------------------------------------------------
+/** Constructor
+*/
+InternetHelper::InternetHelper() : m_proxyInfo(), m_isProxySet(false),m_timeout(30)
+{
+}
+
+//----------------------------------------------------------------------------------------------
+/** Constructor
+*/
+InternetHelper::InternetHelper(const Kernel::ProxyInfo& proxy) : m_proxyInfo(proxy), m_isProxySet(true),m_timeout(30)
+{
+}
+
+//----------------------------------------------------------------------------------------------
+/** Destructor
+*/
+InternetHelper::~InternetHelper()
+{
+}
+
+/** Performs a request using http or https depending on the url
+* @param url the address to the network resource
+* @param responseStream The stream to fill with the reply on success
+* @param headers [optional] : A key value pair map of any additional headers to include in the request.
+**/
+int InternetHelper::sendRequest(const std::string& url, 
+                    std::ostream& responseStream,
+                    const StringToStringMap& headers)
+{
+  Poco::URI uri(url);
+  if ((uri.getScheme() == "https") || (uri.getPort() ==443))
+  {
+    return sendHTTPSRequest(url,responseStream,headers);
+  }
+  else
+  {
+    return sendHTTPRequest(url,responseStream,headers);
+  }
+
+}
+
+/** Performs a request using http
+* @param url the address to the network resource
+* @param responseStream The stream to fill with the reply on success
+* @param headers [optional] : A key value pair map of any additional headers to include in the request.
+**/
+int InternetHelper::sendHTTPRequest(const std::string& url, 
+                            std::ostream& responseStream,
+                            const StringToStringMap& headers)
+{
+  int retStatus = 0;
+  g_log.debug() << "SendingRequest : " << url  << std::endl;
+
+  Poco::URI uri(url);
+  //Configure Poco HTTP Client Session
+  try
+  {
+    Poco::Net::HTTPClientSession session(uri.getHost(), uri.getPort());
+    session.setTimeout(Poco::Timespan(m_timeout, 0)); // m_timeout seconds
+
+    // configure proxy
+    if (!getProxy(url).emptyProxy())
+    {
+      session.setProxyHost(getProxy(url).host());
+      session.setProxyPort(static_cast<Poco::UInt16>(getProxy(url).port()));
+    }
+
+    Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, uri.getPathAndQuery(),
+        Poco::Net::HTTPMessage::HTTP_1_1);
+
+    session.sendRequest(request);
+
+    HTTPResponse res;
+    std::istream & rs = session.receiveResponse(res);
+    retStatus = res.getStatus();
+    g_log.debug() << "Answer from web: " << res.getStatus() << " "
+                  << res.getReason() << std::endl;
+    
+    if (res.getStatus() == HTTPResponse::HTTP_OK)
+    {
+      Poco::StreamCopier::copyStream(rs, responseStream);
+      return res.getStatus();
+    }  
+    else if ((retStatus == HTTPResponse::HTTP_FOUND) ||  
+      (retStatus == HTTPResponse::HTTP_MOVED_PERMANENTLY) ||
+      (retStatus == HTTPResponse::HTTP_TEMPORARY_REDIRECT) ||
+      (retStatus == HTTPResponse::HTTP_SEE_OTHER))
+    {
+      //extract the new location
+      std::string newLocation = res.get("location","");
+      if (newLocation != "")
+      {
+        return sendRequest(newLocation,responseStream,headers);
+      }
+    }
+    else
+    {
+      retStatus = processErrorStates(res,rs,url);
+    }
+
+  } catch (HostNotFoundException & ex)
+  {
+    // this exception occurs when the pc is not connected to the internet
+    std::stringstream info;
+    info << "Failed to download " << url << " because there is no connection to the host "
+      << ex.message() << ".\nHint: Check your connection following this link: <a href=\""
+      << url << "\">" << url << "</a> ";
+    throw Exception::InternetError(info.str() + ex.displayText());
+
+  } catch (Poco::Exception & ex)
+  {
+    throw Exception::InternetError("Connection and request failed " + ex.displayText());
+  }
+  return retStatus;
+}
+
+/** Performs a request using https
+* @param url the address to the network resource
+* @param responseStream The stream to fill with the reply on success
+* @param headers [optional] : A key value pair map of any additional headers to include in the request.
+**/
+int InternetHelper::sendHTTPSRequest(const std::string& url, 
+                            std::ostream& responseStream,
+                            const StringToStringMap& headers)
+{
+  int retStatus = 0;
+  g_log.debug() << "SendingRequest : " << url  << std::endl;
+
+  Poco::URI uri(url);
+  try {
+    // initialize ssl
+    Poco::SharedPtr<InvalidCertificateHandler> certificateHandler = \
+      new AcceptCertificateHandler(true);
+    // Currently do not use any means of authentication. This should be updated IDS has signed certificate.
+    const Context::Ptr context = \
+      new Context(Context::CLIENT_USE, "", "", "", Context::VERIFY_NONE);
+    // Create a singleton for holding the default context.
+    // e.g. any future requests to publish are made to this certificate and context.
+    SSLManager::instance().initializeClient(NULL, certificateHandler, context);
+    // Create the session
+    HTTPSClientSession session(uri.getHost(), static_cast<Poco::UInt16>(uri.getPort()));
+    session.setTimeout(Poco::Timespan(m_timeout, 0)); // m_timeout seconds
+
+    if (!getProxy(url).emptyProxy())
+    {
+      session.setProxyHost(getProxy(url).host());
+      session.setProxyPort(static_cast<Poco::UInt16>(getProxy(url).port()));
+    }
+
+    // create a request
+    HTTPRequest req(HTTPRequest::HTTP_GET, uri.getPathAndQuery(),
+                    HTTPMessage::HTTP_1_1);
+    req.set("User-Agent","MANTID");
+    for (auto itHeaders = headers.begin(); itHeaders != headers.end(); ++itHeaders)
+    {
+      req.set(itHeaders->first,itHeaders->second);
+    }
+    session.sendRequest(req);
+
+    HTTPResponse res;
+    std::istream & rs = session.receiveResponse(res);
+    retStatus = res.getStatus();
+    g_log.debug() << "Answer from web: " << res.getStatus() << " "
+                  << res.getReason() << std::endl;
+        
+    if (res.getStatus() == HTTPResponse::HTTP_OK)
+    {
+      Poco::StreamCopier::copyStream(rs, responseStream);
+      return res.getStatus();
+    }  
+    else if ((retStatus == HTTPResponse::HTTP_FOUND) ||  
+      (retStatus == HTTPResponse::HTTP_MOVED_PERMANENTLY) ||
+      (retStatus == HTTPResponse::HTTP_TEMPORARY_REDIRECT) ||
+      (retStatus == HTTPResponse::HTTP_SEE_OTHER))
+    {
+      //extract the new location
+      std::string newLocation = res.get("location","");
+      if (newLocation != "")
+      {
+        return sendRequest(newLocation,responseStream,headers);
+      }
+    }
+    else
+    {
+      retStatus = processErrorStates(res,rs,url);
+    }
+  } 
+  catch (HostNotFoundException & ex)
+  {
+    // this exception occurs when the pc is not connected to the internet
+    std::stringstream info;
+    info << "Failed to download " << url << " because there is no connection to the host "
+      << ex.message() << ".\nHint: Check your connection following this link: <a href=\""
+      << url << "\">" << url << "</a> ";
+    throw Exception::InternetError(info.str() + ex.displayText());
+
+  } catch (Poco::Exception & ex)
+  {
+    throw Exception::InternetError("Connection and request failed " + ex.displayText());
+  }
+  return retStatus;
+}
+
+/** Gets proxy details for a system and a url.
+@param url : The url to be called
+*/
+Kernel::ProxyInfo& InternetHelper::getProxy(const std::string& url)
+{
+  //set the proxy
+  if (!m_isProxySet)
+  {  
+    setProxy(ConfigService::Instance().getProxy(url));
+  }
+  return m_proxyInfo;
+}
+
+/** Clears cached proxy details.
+*/
+void InternetHelper::clearProxy()
+{
+  m_isProxySet = false;
+}
+
+/** sets the proxy details.
+@param proxy the proxy information to use
+*/
+void InternetHelper::setProxy(const Kernel::ProxyInfo& proxy)
+{
+  m_proxyInfo = proxy;
+  m_isProxySet = true;
+}
+
+/** Process any HTTP errors states.
+
+@param res : The http response
+@param rs : The iutput stream from the response
+@param url : The url originally called
+
+@exception Mantid::Kernel::Exception::InternetError : Coded for the failure state.
+*/
+int InternetHelper::processErrorStates(const Poco::Net::HTTPResponse& res, std::istream & rs,const std::string& url)
+{
+  int retStatus = res.getStatus();
+  g_log.debug() << "Answer from web: " << res.getStatus() << " "
+                << res.getReason() << std::endl;
+        
+  //get github api rate limit information if available;
+  int rateLimitRemaining;
+  DateAndTime rateLimitReset;
+  try 
+  {
+    rateLimitRemaining = boost::lexical_cast<int>( res.get("X-RateLimit-Remaining","-1") );
+    rateLimitReset.set_from_time_t(boost::lexical_cast<int>( res.get("X-RateLimit-Reset","0")));
+  }
+  catch( boost::bad_lexical_cast const& ) 
+  {
+    rateLimitRemaining = -1;
+  }
+
+  if (retStatus == HTTPResponse::HTTP_OK)
+  {
+    throw Exception::InternetError("Response was ok, processing should never have entered processErrorStates",retStatus);
+  }
+  else if (retStatus == HTTPResponse::HTTP_FOUND)
+  {
+    throw Exception::InternetError("Response was HTTP_FOUND, processing should never have entered processErrorStates",retStatus);
+  }  
+  else if (retStatus == HTTPResponse::HTTP_MOVED_PERMANENTLY)
+  {
+    throw Exception::InternetError("Response was HTTP_MOVED_PERMANENTLY, processing should never have entered processErrorStates",retStatus);
+  }
+  else if (retStatus == HTTPResponse::HTTP_NOT_MODIFIED)
+  {
+    throw Exception::InternetError("Not modified since provided date" + 
+                                    rateLimitReset.toSimpleString(),retStatus);
+  }        
+  else if ((retStatus == HTTPResponse::HTTP_FORBIDDEN) && (rateLimitRemaining == 0))
+  {
+    throw Exception::InternetError("The Github API rate limit has been reached, try again after " + 
+                                    rateLimitReset.toSimpleString(),retStatus);
+  }
+  else
+  {
+    std::stringstream info;
+    std::stringstream ss;
+    Poco::StreamCopier::copyStream(rs, ss);
+    if (retStatus == HTTPResponse::HTTP_NOT_FOUND)
+      info << "Failed to download " << url
+      << " with the link " << "<a href=\"" << url
+      << "\">.\n" << "Hint. Check that link is correct</a>";
+    else
+    {
+      // show the error
+      info << res.getReason();
+      info << ss.str();
+    }
+    throw Exception::InternetError(info.str() + ss.str(),retStatus);
+  }
+
+}
+
+
+/** Download a url and fetch it inside the local path given.
+
+@param urlFile: Define a valid URL for the file to be downloaded. Eventually, it may give
+any valid https path. For example:
+
+url_file = "http://www.google.com"
+
+url_file = "https://mantidweb/repository/README.md"
+
+The result is to connect to the http server, and request the path given.
+
+The answer, will be inserted at the local_file_path.
+
+@param localFilePath : Provide the destination of the file downloaded at the url_file.
+
+@param headers [optional] : A key value pair map of any additional headers to include in the request.
+
+@exception Mantid::Kernel::Exception::InternetError : For any unexpected behaviour.
+*/
+int InternetHelper::downloadFile(const std::string & urlFile,
+  const std::string & localFilePath,
+  const StringToStringMap & headers)
+{
+  int retStatus = 0;
+  g_log.debug() << "DownloadFile : " << urlFile << " to file: " << localFilePath << std::endl;
+
+  Poco::TemporaryFile tempFile;
+  Poco::FileStream tempFileStream(tempFile.path());
+  retStatus = sendRequest(urlFile,tempFileStream,headers);
+  tempFileStream.close();
+
+  //if there have been no errors move it to the final location, and turn off automatic deletion.
+  tempFile.moveTo(localFilePath);
+  tempFile.keep();
+
+  return retStatus;
+}
+
+/** Sets the timeout in seconds
+* @param seconds The value in seconds for the timeout
+**/
+void InternetHelper::setTimeout(int seconds)
+{
+  m_timeout = seconds;
+}
+
+
+} // namespace Kernel
+} // namespace Mantid
\ No newline at end of file
diff --git a/Code/Mantid/Framework/Kernel/test/InternetHelperTest.h b/Code/Mantid/Framework/Kernel/test/InternetHelperTest.h
new file mode 100644
index 00000000000..209129f9b0f
--- /dev/null
+++ b/Code/Mantid/Framework/Kernel/test/InternetHelperTest.h
@@ -0,0 +1,125 @@
+#ifndef MANTID_KERNEL_INTERNETSERVICETEST_H_
+#define MANTID_KERNEL_INTERNETSERVICETEST_H_
+
+#include <cxxtest/TestSuite.h>
+
+#include "MantidKernel/InternetHelper.h"
+#include "MantidKernel/ConfigService.h"
+#include "MantidKernel/NetworkProxy.h"
+#include "MantidKernel/ProxyInfo.h"
+
+#include <Poco/TemporaryFile.h>
+
+
+#include <fstream>
+#include <sstream>
+
+using Mantid::Kernel::InternetHelper;
+using namespace Mantid::Kernel;
+
+
+
+namespace
+{
+  /**
+   * Mock out the internet calls of this algorithm
+   */
+  class MockedInternetHelper : public InternetHelper
+  {
+  protected:
+    virtual int sendHTTPSRequest(const std::string& url, 
+                          std::ostream& responseStream,
+                          const StringToStringMap& headers = StringToStringMap())
+    {
+      responseStream << "HTTPS request succeeded";
+      return 200;
+    }
+    virtual int sendHTTPRequest(const std::string& url, 
+                              std::ostream& responseStream,
+                              const StringToStringMap& headers = StringToStringMap())
+    {
+      responseStream << "HTTP request succeeded";
+      return 200;
+    }
+  };
+}
+
+
+class InternetHelperTest : public CxxTest::TestSuite
+{
+public:
+  // This pair of boilerplate methods prevent the suite being created statically
+  // This means the constructor isn't called when running other tests
+  static InternetHelperTest *createSuite() { return new InternetHelperTest(); }
+  static void destroySuite( InternetHelperTest *suite ) { delete suite; }
+
+  
+  void test_sendRequest_HTTP()
+  {
+    MockedInternetHelper internetHelper;
+    std::string url = "http://www.google.com";
+
+    std::stringstream ss;
+    int response;
+    TS_ASSERT_THROWS_NOTHING (response = internetHelper.sendRequest(url, ss);)
+    TS_ASSERT_EQUALS (200, response);
+    TS_ASSERT_EQUALS ("HTTP request succeeded", ss.str());
+  }
+
+  void test_sendRequest_HTTPS()
+  {
+    MockedInternetHelper internetHelper;
+    std::string httpsUrl = "https://api.github.com/repos/mantidproject/mantid/contents";
+    
+    std::stringstream ss;
+    int response;
+    TS_ASSERT_THROWS_NOTHING (response = internetHelper.sendRequest(httpsUrl, ss);)
+    TS_ASSERT_EQUALS (200, response);
+    TS_ASSERT_EQUALS ("HTTPS request succeeded", ss.str());
+  }
+
+  void test_DownloadFile_HTTP()
+  {
+    MockedInternetHelper internetHelper;
+    std::string url = "http://www.google.com";
+    Poco::TemporaryFile tmpFile;
+    int response = internetHelper.downloadFile(url,tmpFile.path());
+    TSM_ASSERT("File has not been created.",tmpFile.exists()); 
+    TSM_ASSERT("File is not a file.",tmpFile.isFile()); 
+    std::fstream fs;
+    TS_ASSERT_THROWS_NOTHING (fs.open (tmpFile.path(), std::fstream::in ));
+    
+    TSM_ASSERT("Cannot open file.",fs.is_open()); 
+    
+    std::stringstream ss;
+    ss << fs.rdbuf();//read the file
+    fs.close();
+
+    TS_ASSERT_EQUALS ("HTTP request succeeded", ss.str());
+  }
+
+  void test_DownloadFile_HTTPS()
+  {
+    MockedInternetHelper internetHelper;
+    std::string httpsUrl = "https://api.github.com/repos/mantidproject/mantid/contents";
+    Poco::TemporaryFile tmpFile;
+    int response = internetHelper.downloadFile(httpsUrl,tmpFile.path());
+    TSM_ASSERT("File has not been created.",tmpFile.exists()); 
+    TSM_ASSERT("File is not a file.",tmpFile.isFile()); 
+    std::fstream fs;
+    TS_ASSERT_THROWS_NOTHING (fs.open (tmpFile.path(), std::fstream::in ));
+    
+    TSM_ASSERT("Cannot open file.",fs.is_open()); 
+    
+    std::stringstream ss;
+    ss << fs.rdbuf();//read the file
+    fs.close();
+
+    TS_ASSERT_EQUALS ("HTTPS request succeeded", ss.str());
+  }
+
+
+};
+
+
+#endif /* MANTID_KERNEL_INTERNETSERVICETEST_H_ */
\ No newline at end of file
diff --git a/Code/Mantid/Framework/ScriptRepository/src/ScriptRepositoryImpl.cpp b/Code/Mantid/Framework/ScriptRepository/src/ScriptRepositoryImpl.cpp
index 94e44bbca25..3d4501caddb 100644
--- a/Code/Mantid/Framework/ScriptRepository/src/ScriptRepositoryImpl.cpp
+++ b/Code/Mantid/Framework/ScriptRepository/src/ScriptRepositoryImpl.cpp
@@ -833,7 +833,6 @@ namespace Mantid
         // inserting the file
         FilePartSource * m_file = new FilePartSource(absolute_path);
         form.addPart("file", m_file);
-        form.prepareSubmit(req);
 
         // get the size of everything
         std::stringstream sst;
@@ -844,6 +843,7 @@ namespace Mantid
         // set the size
         req.setContentLength((int) sst.str().size());
 
+        form.prepareSubmit(req);
         std::ostream& ostr = session.sendRequest(req);
         // send the request.
         ostr << sst.str();
diff --git a/Code/Mantid/docs/source/algorithms/DownloadFile-v1.rst b/Code/Mantid/docs/source/algorithms/DownloadFile-v1.rst
new file mode 100644
index 00000000000..5f0407d72a2
--- /dev/null
+++ b/Code/Mantid/docs/source/algorithms/DownloadFile-v1.rst
@@ -0,0 +1,73 @@
+
+.. algorithm::
+
+.. summary::
+
+.. alias::
+
+.. properties::
+
+Description
+-----------
+
+This is a simple algorithm that will download the contents of a url address to a file.
+It can support http:// and https:// based urls, and if the method is not supplied then http:// will be assumed.
+For example: If the address is www.mantidproject.org, then this will be adjusted to http://www.mantidproject.org.
+
+
+Usage
+-----
+
+**Example - http**
+
+.. testcode:: DownloadFileHttp
+
+    #import the os path libraries for directory functions
+    import os
+
+    #Create an absolute path by joining the proposed filename to a directory
+    #os.path.expanduser("~") used in this case returns the home directory of the current user
+    savefile = os.path.join(os.path.expanduser("~"), "DownloadedFile.txt")
+
+    DownloadFile("http://www.mantidproject.org", savefile)
+
+    print "File Exists:", os.path.exists(savefile)
+
+.. testcleanup:: DownloadFileHttp
+
+    os.remove(savefile)
+
+Output:
+
+.. testoutput:: DownloadFileHttp
+
+    File Exists: True
+
+
+**Example - https**
+
+.. testcode:: DownloadFileHttps
+
+    #import the os path libraries for directory functions
+    import os
+
+    #Create an absolute path by joining the proposed filename to a directory
+    #os.path.expanduser("~") used in this case returns the home directory of the current user
+    savefile = os.path.join(os.path.expanduser("~"), "DownloadedFile.txt")
+
+    DownloadFile("https://raw.githubusercontent.com/mantidproject/mantid/master/README.md", savefile)
+
+    print "File Exists:", os.path.exists(savefile)
+
+.. testcleanup:: DownloadFileHttps
+
+    os.remove(savefile)
+
+Output:
+
+.. testoutput:: DownloadFileHttps
+
+    File Exists: True
+
+.. categories::
+
-- 
GitLab