/**
 * Fetch an HTTP url to a local file.
 **/

var http = require("http")
  , url = require("url")
  , sys = require("sys")
  , fs = require("fs")
  , get = require("./get")
  , set = require("./set")
  , log = require("./log")

module.exports = function fetch (remote, local, headers, cb) {
  if (!cb) {
    cb = headers
    headers = {}
  }
  log(remote+" to "+local, "fetch")
  headers.host = url.parse(remote).hostname
  fs.open(local, process.O_CREAT | process.O_WRONLY | process.O_TRUNC, 0755,
    function (er, fd) {
      if (er) return cb(er, fd)
      fetchAndWrite(remote, fd, headers, cb)
    }
  )
}

function fetchAndWrite (remote, fd, headers, maxRedirects, redirects, cb) {
  // log("fetchAndWrite "+sys.inspect(Array.prototype.slice.call(arguments, 0)))

  if (!cb) {
    cb = redirects
    redirects = 0
  }
  if (!cb) {
    cb = maxRedirects
    maxRedirects = 10
  }
  if (!cb) throw new Error("No callback provided")
  log(remote, "fetch")
  remote = url.parse(remote)
  set(headers, "host", remote.hostname)
  remote.path = remote.pathname+(remote.search||"")+(remote.hash||"")
  var https = (remote.protocol === "https:")
  http
    .createClient(remote.port || (https ? 443 : 80), remote.hostname, https)
    .request("GET", (remote.pathname||"/")+(remote.search||"")+(remote.hash||""), headers)
    .addListener("response", function (response) {
      // handle redirects.
      var loc = get(response.headers, "location")
      if (Math.floor(response.statusCode / 100) === 3
          && loc && loc !== remote.href && redirects < maxRedirects) {
        // This is a laughably naïve way to handle this situation.
        // @TODO: Really need a full curl or wget style module that would
        // do all this kind of stuff for us.
        var cookie = get(response.headers, "Set-Cookie")
        if (cookie) {
          cookie = cookie.split(";").shift()
          set(headers, "Cookie", cookie)
        }
        log(response.statusCode, "fetch")
        return fetchAndWrite(loc, fd, headers, maxRedirects, redirects + 1, cb)
      }
      if (response.statusCode !== 200) {
        return cb(new Error(response.statusCode + " " +
                  (sys.inspect(response.headers).replace(/\s+/, ' '))))
      }
      response.setBodyEncoding("binary")
      var written = 0
      response.addListener("data", function (chunk) {
        // write the chunk...
        log((written += chunk.length) + " bytes", "fetch")
        fs.write(fd, chunk, "binary", function (er) { if (er) cb(er) })
      })
      response.addListener("error", cb)
      response.addListener("end", function () {
        log("finished", "fetch")
        fs.close(fd, cb)
      })
    })
    .end()
}

@@ -221,16 +221,54 @@
 %22./log%22)
+%0A  , Buffer = require(%22buffer%22).Buffer
 %0A%0Amodule
@@ -574,25 +574,104 @@
 er) 
-return cb(er, fd)
+%7B%0A        return cb(new Error(%0A          %22Failed to create %22+local+%22: %22+er.message, fd))%0A      %7D
 %0A   
@@ -2353,24 +2353,27 @@
      %7D%0A     
+ //
  response.se
@@ -2396,16 +2396,16 @@
 inary%22)%0A
-
       va
@@ -2553,32 +2553,196 @@
 ytes%22, %22fetch%22)%0A
+        if (chunk instanceof Buffer) %7B%0A          fs.write(fd, chunk, 0, chunk.length, null%0A                  , function (er) %7B if (er) cb(er) %7D)%0A        %7D else %7B%0A  
         fs.write
@@ -2762,16 +2762,41 @@
 binary%22,
+ null%0A                  ,
  functio
@@ -2818,24 +2818,34 @@
 ) cb(er) %7D)%0A
+        %7D%0A
       %7D)%0A   

Use the Buffer-based API for file writing. It's better.