module PhusionPassenger::Utils::Download

def download_with_curl(logger, url, output, options)

def download_with_curl(logger, url, output, options)
  command = ["curl", "-f", "-L", "-o", output]
  if options[:show_progress]
    command << "-#"
  else
    command << "-s"
    command << "-S"
  end
  if options[:cacert]
    command << "--cacert"
    command << options[:cacert]
  end
  if options[:connect_timeout]
    command << "--connect-timeout"
    command << options[:connect_timeout].to_s
  end
  if options[:idle_timeout]
    command << "--speed-time"
    command << options[:idle_timeout].to_s
    command << "--speed-limit"
    command << "1"
  end
  if options[:total_timeout]
    command << "--max-time"
    command << options[:total_timeout].to_s
  end
  command << url
  command_str = Shellwords.join(command)
  logger.info("Invoking: #{command_str}")
  if options[:show_progress]
    # If curl errors out we don't want it to display 'curl: ' prefixes,
    # so we parse its output.
    begin
      io = IO.popen("#{command_str} 2>&1", "r")
    rescue SystemCallError => e
      logger.error("Could not invoke curl: #{e}")
      return false
    end
    begin
      non_empty_line_encountered = false
      while !io.eof?
        # We split on "\r" because progress bar lines do not contain "\n".
        data = io.gets("\r")
        data = remove_curl_output_prefix(data)
        # If an error occurs then the first few lines may be empty.
        # Skip those.
        if !non_empty_line_encountered && data =~ /\A\n+/
          data.gsub!(/\A\n+/, '')
        end
        non_empty_line_encountered = true
        STDERR.write(data)
        STDERR.flush
      end
    ensure
      io.close
    end
    result = $?.exitstatus == 0
  else
    begin
      output = `#{command_str} 2>&1`
    rescue SystemCallError => e
      logger.error("Could not invoke curl: #{e}")
      return false
    end
    result = $?.exitstatus == 0
    if !result
      output = remove_curl_output_prefix(output)
      output.chomp!
      logger.error("Could not download #{url}: #{output}")
    end
  end
  return result
end