You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by cm...@apache.org on 2008/06/26 16:00:23 UTC

svn commit: r671905 - in /incubator/couchdb/branches/0.8.x: ./ bin/ share/server/ share/www/ share/www/browse/ share/www/script/ src/couchdb/ src/mochiweb/

Author: cmlenz
Date: Thu Jun 26 07:00:22 2008
New Revision: 671905

URL: http://svn.apache.org/viewvc?rev=671905&view=rev
Log:
Ported revisions 668269-670737,670739-671610 from trunk to 0.8.x branch.

Modified:
    incubator/couchdb/branches/0.8.x/   (props changed)
    incubator/couchdb/branches/0.8.x/NEWS
    incubator/couchdb/branches/0.8.x/bin/couchdb.tpl.in
    incubator/couchdb/branches/0.8.x/share/server/main.js
    incubator/couchdb/branches/0.8.x/share/www/browse/database.html
    incubator/couchdb/branches/0.8.x/share/www/browse/document.html
    incubator/couchdb/branches/0.8.x/share/www/browse/index.html
    incubator/couchdb/branches/0.8.x/share/www/couch_tests.html
    incubator/couchdb/branches/0.8.x/share/www/index.html
    incubator/couchdb/branches/0.8.x/share/www/replicator.html
    incubator/couchdb/branches/0.8.x/share/www/script/couch_tests.js
    incubator/couchdb/branches/0.8.x/src/couchdb/couch_httpd.erl
    incubator/couchdb/branches/0.8.x/src/mochiweb/Makefile.am
    incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_html.erl
    incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_request.erl
    incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_socket_server.erl

Propchange: incubator/couchdb/branches/0.8.x/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Thu Jun 26 07:00:22 2008
@@ -1 +1 @@
-/incubator/couchdb/trunk:1-668227,668231-668248
+/incubator/couchdb/trunk:1-668227,668231-668248,668269-670737,670739-671610

Modified: incubator/couchdb/branches/0.8.x/NEWS
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/NEWS?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/NEWS (original)
+++ incubator/couchdb/branches/0.8.x/NEWS Thu Jun 26 07:00:22 2008
@@ -18,7 +18,7 @@
  * Miscellaneous improvements to system integration and portability.
  * Swapped out Erlang's inets HTTP server for the Mochiweb HTTP server.
  * SpiderMonkey is no longer included with CouchDB, but rather treated as an
-   external dependendancy.
+   external dependency.
  * Added bits of awesome.
 
 Please note that there have been many backwards incomatible changes in this

Modified: incubator/couchdb/branches/0.8.x/bin/couchdb.tpl.in
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/bin/couchdb.tpl.in?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/bin/couchdb.tpl.in (original)
+++ incubator/couchdb/branches/0.8.x/bin/couchdb.tpl.in Thu Jun 26 07:00:22 2008
@@ -206,7 +206,7 @@
     command="`%ICU_CONFIG% --invoke` \
         %ERL% $interactive_option -smp auto -sasl errlog_type error \
         -pa %localerlanglibdir%/couch-%version%/ebin \
-            %localerlanglibdir%/mochiweb-r76/ebin \
+            %localerlanglibdir%/mochiweb-r82/ebin \
         -eval \"application:load(inets)\" \
         -eval \"application:load(crypto)\" \
         -eval \"application:load(couch)\" \

Modified: incubator/couchdb/branches/0.8.x/share/server/main.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/share/server/main.js?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/share/server/main.js [utf-8] (original)
+++ incubator/couchdb/branches/0.8.x/share/server/main.js [utf-8] Thu Jun 26 07:00:22 2008
@@ -74,15 +74,13 @@
         // ]
         //
         var doc = cmd[1];
-        seal(doc); // seal to prevent map functions from changing doc
+        recursivelySeal(doc); // seal to prevent map functions from changing doc
         var buf = [];
         for (var i = 0; i < funs.length; i++) {
           map_results = [];
           try {
             funs[i](doc);
-            buf.push(map_results.filter(function(pair) {
-              return pair[0] !== undefined && pair[1] !== undefined;
-            }));
+            buf.push(toJSON(map_results));
           } catch (err) {
             if (err == "fatal_error") {
               // Only if it's a "fatal_error" do we exit. What's a fatal error?
@@ -96,10 +94,10 @@
                   reason: "function raised fatal exception"};
             }
             print(toJSON({log: "function raised exception (" + err + ")"}));
-            buf.push([]);
+            buf.push("[]");
           }
         }
-        print(toJSON(buf));
+        print("[" + buf.join(", ") + "]");
         break;
 
       case "rereduce":
@@ -170,9 +168,18 @@
   }
 }
 
+function recursivelySeal(obj) {
+  seal(obj);
+  for (var propname in obj) {
+    if (typeof doc[propname] == "object") {
+      recursivelySeal(doc[propname]);
+    }
+  }
+}
+
 function toJSON(val) {
   if (typeof(val) == "undefined") {
-    throw {error:"bad_value", reason:"Cannot encode 'undefined' value as JSON"};
+    throw "Cannot encode 'undefined' value as JSON";
   }
   var subs = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f',
               '\r': '\\r', '"' : '\\"', '\\': '\\\\'};

Modified: incubator/couchdb/branches/0.8.x/share/www/browse/database.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/share/www/browse/database.html?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/share/www/browse/database.html [utf-8] (original)
+++ incubator/couchdb/branches/0.8.x/share/www/browse/database.html [utf-8] Thu Jun 26 07:00:22 2008
@@ -17,16 +17,16 @@
   <head>
     <title>Browse Database</title>
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-    <link rel="stylesheet" href="../style/layout.css?0.8.0a" type="text/css">
+    <link rel="stylesheet" href="../style/layout.css?0.8.0" type="text/css">
     <script src="../script/json2.js"></script>
     <script src="../script/jquery.js?1.2.6"></script>
-    <script src="../script/jquery.cookies.js?0.8.0a"></script>
-    <script src="../script/jquery.couch.js?0.8.0a"></script>
-    <script src="../script/jquery.dialog.js?0.8.0a"></script>
-    <script src="../script/jquery.resizer.js?0.8.0a"></script>
-    <script src="../script/jquery.suggest.js?0.8.0a"></script>
-    <script src="../script/browse.js?0.8.0a"></script>
-    <script src="../script/pprint.js?0.8.0a"></script>
+    <script src="../script/jquery.cookies.js?0.8.0"></script>
+    <script src="../script/jquery.couch.js?0.8.0"></script>
+    <script src="../script/jquery.dialog.js?0.8.0"></script>
+    <script src="../script/jquery.resizer.js?0.8.0"></script>
+    <script src="../script/jquery.suggest.js?0.8.0"></script>
+    <script src="../script/browse.js?0.8.0"></script>
+    <script src="../script/pprint.js?0.8.0"></script>
     <script>
       var page = new CouchDatabasePage();
       if (window != parent) {

Modified: incubator/couchdb/branches/0.8.x/share/www/browse/document.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/share/www/browse/document.html?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/share/www/browse/document.html [utf-8] (original)
+++ incubator/couchdb/branches/0.8.x/share/www/browse/document.html [utf-8] Thu Jun 26 07:00:22 2008
@@ -17,15 +17,15 @@
   <head>
     <title>View Document</title>
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-    <link rel="stylesheet" href="../style/layout.css?0.8.0a" type="text/css">
+    <link rel="stylesheet" href="../style/layout.css?0.8.0" type="text/css">
     <script src="../script/json2.js"></script>
     <script src="../script/jquery.js?1.2.6"></script>
-    <script src="../script/jquery.cookies.js?0.8.0a"></script>
-    <script src="../script/jquery.couch.js?0.8.0a"></script>
-    <script src="../script/jquery.dialog.js?0.8.0a"></script>
-    <script src="../script/jquery.resizer.js?0.8.0a"></script>
-    <script src="../script/browse.js?0.8.0a"></script>
-    <script src="../script/pprint.js?0.8.0a"></script>
+    <script src="../script/jquery.cookies.js?0.8.0"></script>
+    <script src="../script/jquery.couch.js?0.8.0"></script>
+    <script src="../script/jquery.dialog.js?0.8.0"></script>
+    <script src="../script/jquery.resizer.js?0.8.0"></script>
+    <script src="../script/browse.js?0.8.0"></script>
+    <script src="../script/pprint.js?0.8.0"></script>
     <script>
       var page = new CouchDocumentPage();
       if (window != parent) {

Modified: incubator/couchdb/branches/0.8.x/share/www/browse/index.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/share/www/browse/index.html?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/share/www/browse/index.html [utf-8] (original)
+++ incubator/couchdb/branches/0.8.x/share/www/browse/index.html [utf-8] Thu Jun 26 07:00:22 2008
@@ -17,14 +17,14 @@
   <head>
     <title>Welcome</title>
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-    <link rel="stylesheet" href="../style/layout.css?0.8.0a" type="text/css">
+    <link rel="stylesheet" href="../style/layout.css?0.8.0" type="text/css">
     <script src="../script/json2.js"></script>
     <script src="../script/jquery.js?1.2.6"></script>
-    <script src="../script/jquery.cookies.js?0.8.0a"></script>
-    <script src="../script/jquery.couch.js?0.8.0a"></script>
-    <script src="../script/jquery.dialog.js?0.8.0a"></script>
-    <script src="../script/browse.js?0.8.0a"></script>
-    <script src="../script/pprint.js?0.8.0a"></script>
+    <script src="../script/jquery.cookies.js?0.8.0"></script>
+    <script src="../script/jquery.couch.js?0.8.0"></script>
+    <script src="../script/jquery.dialog.js?0.8.0"></script>
+    <script src="../script/browse.js?0.8.0"></script>
+    <script src="../script/pprint.js?0.8.0"></script>
     <script>
       var page = new CouchIndexPage();
       $(document).ready(function() {

Modified: incubator/couchdb/branches/0.8.x/share/www/couch_tests.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/share/www/couch_tests.html?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/share/www/couch_tests.html [utf-8] (original)
+++ incubator/couchdb/branches/0.8.x/share/www/couch_tests.html [utf-8] Thu Jun 26 07:00:22 2008
@@ -17,11 +17,11 @@
   <head>
     <title>Test Suite</title>
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-    <link rel="stylesheet" href="style/layout.css?0.8.0a" type="text/css">
+    <link rel="stylesheet" href="style/layout.css?0.8.0" type="text/css">
     <script src="script/json2.js"></script>
     <script src="script/jquery.js?1.2.6"></script>
-    <script src="script/couch.js?0.8.0a"></script>
-    <script src="script/pprint.js?0.8.0a"></script>
+    <script src="script/couch.js?0.8.0"></script>
+    <script src="script/pprint.js?0.8.0"></script>
     <script>
       $(document).ready(function() {
         $("#toolbar button.load").click(function() {

Modified: incubator/couchdb/branches/0.8.x/share/www/index.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/share/www/index.html?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/share/www/index.html [utf-8] (original)
+++ incubator/couchdb/branches/0.8.x/share/www/index.html [utf-8] Thu Jun 26 07:00:22 2008
@@ -17,7 +17,7 @@
   <head>
     <title>Apache CouchDB: Futon Utility Client</title>
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-    <link rel="stylesheet" href="style/layout.css?0.8.0a" type="text/css">
+    <link rel="stylesheet" href="style/layout.css?0.8.0" type="text/css">
     <style type="text/css">
       html { height: 100%; overflow: hidden; }
       body { background: #fff url(image/bg.png) 100% 0 repeat-y;
@@ -28,7 +28,7 @@
     </style>
     <script src="script/json2.js"></script>
     <script src="script/jquery.js?1.2.6"></script>
-    <script src="script/jquery.couch.js?0.8.0a"></script>
+    <script src="script/jquery.couch.js?0.8.0"></script>
     <script>
       function updateDatabaseList() {
         var list = $("#dbs").empty();

Modified: incubator/couchdb/branches/0.8.x/share/www/replicator.html
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/share/www/replicator.html?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/share/www/replicator.html [utf-8] (original)
+++ incubator/couchdb/branches/0.8.x/share/www/replicator.html [utf-8] Thu Jun 26 07:00:22 2008
@@ -17,11 +17,11 @@
   <head>
     <title>Replicator</title>
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-    <link rel="stylesheet" href="style/layout.css?0.8.0a" type="text/css">
+    <link rel="stylesheet" href="style/layout.css?0.8.0" type="text/css">
     <script src="script/json2.js"></script>
     <script src="script/jquery.js?1.2.6"></script>
-    <script src="script/jquery.couch.js?0.8.0a"></script>
-    <script src="script/pprint.js?0.8.0a"></script>
+    <script src="script/jquery.couch.js?0.8.0"></script>
+    <script src="script/pprint.js?0.8.0"></script>
     <script>
       $(document).ready(function() {
         if (window !== parent) parent.updateNavigation();

Modified: incubator/couchdb/branches/0.8.x/share/www/script/couch_tests.js
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/share/www/script/couch_tests.js?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/share/www/script/couch_tests.js [utf-8] (original)
+++ incubator/couchdb/branches/0.8.x/share/www/script/couch_tests.js [utf-8] Thu Jun 26 07:00:22 2008
@@ -58,7 +58,7 @@
     // create a map function that selects all documents whose "a" member
     // has a value of 4, and then returns the document's b value.
     var mapFunction = function(doc){
-      if(doc.a==4)
+      if (doc.a==4)
         emit(null, doc.b);
     };
 
@@ -328,7 +328,12 @@
       T(equals(results.rows[1], {key:["a","b"],value:20*i}));
       T(equals(results.rows[2], {key:["a", "b", "c"],value:10*i}));
       T(equals(results.rows[3], {key:["a", "b", "d"],value:10*i}));
-      
+
+      // test to make sure group reduce and count params provide valid json
+      var results = db.query(map, reduce, {group: true, count: 2});
+      T(equals(results.rows[0], {key: ["a"], value: 20*i}));
+      T(equals(results.rows.length, 2));
+
       //group by the first element in the key array
       var results = db.query(map, reduce, {group_level:1});
       T(equals(results.rows[0], {key:["a"],value:70*i}));
@@ -769,6 +774,38 @@
     T(results.rows[0].value[0] == conflictRev);
   },
 
+  view_errors: function(debug) {
+    var db = new CouchDB("test_suite_db");
+    db.deleteDb();
+    db.createDb();
+    if (debug) debugger;
+
+    var doc = {integer: 1, string: "1", array: [1, 2, 3]};
+    T(db.save(doc).ok);
+
+    // emitting a key value that is undefined should result in that row not
+    // being included in the view results
+    var results = db.query(function(doc) {
+      emit(doc.undef, null);
+    });
+    T(results.total_rows == 0);
+
+    // if a view function throws an exception, its results are not included in
+    // the view index, but the view does not itself raise an error
+    var results = db.query(function(doc) {
+      doc.undef(); // throws an error
+    });
+    T(results.total_rows == 0);
+
+    // if a view function includes an undefined value in the emitted key or
+    // value, an error is logged and the result is not included in the view
+    // index, and the view itself does not raise an error
+    var results = db.query(function(doc) {
+      emit([doc._id, doc.undef], null);
+    });
+    T(results.total_rows == 0);
+  },
+
   view_pagination: function(debug) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
@@ -871,12 +908,18 @@
     db.createDb();
     if (debug) debugger;
 
-    var docs = makeDocs(1, 2);
-    T(db.bulkSave(docs).ok);
+    var doc = {integer: 1, string: "1", array: [1, 2, 3]};
+    T(db.save(doc).ok);
 
     // make sure that attempting to change the document throws an error
     var results = db.query(function(doc) {
-      doc._id = "foo";
+      doc.integer = 2;
+      emit(null, doc);
+    });
+    T(results.total_rows == 0);
+
+    var results = db.query(function(doc) {
+      doc.array[0] = 0;
       emit(null, doc);
     });
     T(results.total_rows == 0);

Modified: incubator/couchdb/branches/0.8.x/src/couchdb/couch_httpd.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/src/couchdb/couch_httpd.erl?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/src/couchdb/couch_httpd.erl (original)
+++ incubator/couchdb/branches/0.8.x/src/couchdb/couch_httpd.erl Thu Jun 26 07:00:22 2008
@@ -98,9 +98,11 @@
         "/_restart" ->
             handle_restart_request(Req, Method);
         "/_utils" ->
-            {ok, Req:respond({301, [{"Location", "/_utils/"}], <<>>})};
+            {ok, Req:respond({301, [
+                {"Location", "/_utils/"}
+            ] ++ server_header(), <<>>})};
         "/_utils/" ++ PathInfo ->
-            {ok, Req:serve_file(PathInfo, DocumentRoot)};
+            {ok, Req:serve_file(PathInfo, DocumentRoot, server_header())};
         "/_" ++ _Path ->
             throw({not_found, unknown_private_path});
         "/favicon.ico" ->
@@ -463,7 +465,7 @@
         fun(_Key, _Red, {AccSeparator,AccSkip,AccCount}) when AccSkip > 0 ->
             {ok, {AccSeparator,AccSkip-1,AccCount}};
         (_Key, _Red, {AccSeparator,0,AccCount}) when AccCount == 0 ->
-            {stop,{AccSeparator,0,AccCount}};
+            {ok, {AccSeparator,0,AccCount}};
         (_Key, Red, {AccSeparator,0,AccCount}) when GroupLevel == 0 ->
             Json = lists:flatten(cjson:encode({obj, [{key, null}, {value, Red}]})),
             Resp:write_chunk(AccSeparator ++ Json),
@@ -613,9 +615,10 @@
             throw({not_found, missing});
         {Type, Bin} ->
             Resp = Req:respond({200, [
-                {"content-type", Type},
-                {"content-length", integer_to_list(couch_doc:bin_size(Bin))}
-            ], chunked}),
+                {"Cache-Control", "must-revalidate"},
+                {"Content-Type", Type},
+                {"Content-Length", integer_to_list(couch_doc:bin_size(Bin))}
+            ] ++ server_header(), chunked}),
             couch_doc:bin_foldl(Bin,
                 fun(BinSegment, []) ->
                     ok = Resp:write_chunk(BinSegment),
@@ -899,11 +902,11 @@
     {500, error, Error}.
 
 send_error(Req, {method_not_allowed, Methods}) ->
-    {ok, Req:respond({405, [{"Allow", Methods}], <<>>})};
+    {ok, Req:respond({405, [{"Allow", Methods}] ++ server_header(), <<>>})};
 send_error(Req, {modified, Etag}) ->
-    {ok, Req:respond({412, [{"Etag", Etag}], <<>>})};
+    {ok, Req:respond({412, [{"Etag", Etag}] ++ server_header(), <<>>})};
 send_error(Req, {not_modified, Etag}) ->
-    {ok, Req:respond({304, [{"Etag", Etag}], <<>>})};
+    {ok, Req:respond({304, [{"Etag", Etag}] ++ server_header(), <<>>})};
 send_error(Req, Error) ->
     {Code, Json} = error_to_json(Error),
     ?LOG_INFO("HTTP Error (code ~w): ~p", [Code, Error]),
@@ -919,18 +922,23 @@
     send_json(Req, Code, [], Value).
 
 send_json(Req, Code, Headers, Value) ->
-    ContentType = negotiate_content_type(Req),
+    DefaultHeaders = [
+        {"Content-Type", negotiate_content_type(Req)},
+        {"Cache-Control", "must-revalidate"}
+    ] ++ server_header(),
     Body = cjson:encode(Value),
-    Resp = Req:respond({Code, [{"Content-Type", ContentType}] ++ Headers,
-                        Body}),
+    Resp = Req:respond({Code, DefaultHeaders ++ Headers, Body}),
     {ok, Resp}.
 
 start_json_response(Req, Code) ->
     start_json_response(Req, Code, []).
 
 start_json_response(Req, Code, Headers) ->
-    ContentType = negotiate_content_type(Req),
-    Req:respond({Code, [{"Content-Type", ContentType}] ++ Headers, chunked}).
+    DefaultHeaders = [
+        {"Content-Type", negotiate_content_type(Req)},
+        {"Cache-Control", "must-revalidate"}
+    ] ++ server_header(),
+    Req:respond({Code, DefaultHeaders ++ Headers, chunked}).
 
 end_json_response(Resp) ->
     Resp:write_chunk(""),
@@ -949,3 +957,7 @@
         true  -> "application/json";
         false -> "text/plain;charset=utf-8"
     end.
+
+server_header() ->
+    [{"Server", "CouchDB/" ++ couch_server:get_version() ++
+                " (Erlang OTP/" ++ erlang:system_info(otp_release) ++ ")"}].

Modified: incubator/couchdb/branches/0.8.x/src/mochiweb/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/src/mochiweb/Makefile.am?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/src/mochiweb/Makefile.am (original)
+++ incubator/couchdb/branches/0.8.x/src/mochiweb/Makefile.am Thu Jun 26 07:00:22 2008
@@ -10,7 +10,7 @@
 ## License for the specific language governing permissions and limitations under
 ## the License.
 
-mochiwebebindir = $(localerlanglibdir)/mochiweb-r76/ebin
+mochiwebebindir = $(localerlanglibdir)/mochiweb-r82/ebin
 
 mochiweb_file_collection = \
     mochifmt.erl \

Modified: incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_html.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_html.erl?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_html.erl (original)
+++ incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_html.erl Thu Jun 26 07:00:22 2008
@@ -101,7 +101,7 @@
 to_html(Tokens) when is_list(Tokens) ->
     to_html(Tokens, []).
 
-%% @spec escape(string() | binary()) -> string()
+%% @spec escape(string() | atom() | binary()) -> binary()
 %% @doc Escape a string such that it's safe for HTML (amp; lt; gt;).
 escape(B) when is_binary(B) ->
     escape(binary_to_list(B), []);
@@ -110,7 +110,7 @@
 escape(S) when is_list(S) ->
     escape(S, []).
 
-%% @spec escape_attr(S::string()) -> string()
+%% @spec escape_attr(string() | binary() | atom() | integer() | float()) -> binary()
 %% @doc Escape a string such that it's safe for HTML attrs
 %%      (amp; lt; gt; quot;).
 escape_attr(B) when is_binary(B) ->

Modified: incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_request.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_request.erl?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_request.erl (original)
+++ incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_request.erl Thu Jun 26 07:00:22 2008
@@ -15,11 +15,11 @@
 -export([send/1, recv/1, recv/2, recv_body/0, recv_body/1]).
 -export([start_response/1, start_response_length/1, start_raw_response/1]).
 -export([respond/1, ok/1]).
--export([not_found/0]).
+-export([not_found/0, not_found/1]).
 -export([parse_post/0, parse_qs/0]).
 -export([should_close/0, cleanup/0]).
 -export([parse_cookie/0, get_cookie_value/1]).
--export([serve_file/2]).
+-export([serve_file/2, serve_file/3]).
 -export([test/0]).
 
 -define(SAVE_QS, mochiweb_request_qs).
@@ -276,9 +276,16 @@
     Response.
 
 %% @spec not_found() -> response()
-%% @doc respond({404, [{"Content-Type", "text/plain"}], "Not found."}).
+%% @doc Alias for <code>not_found([])</code>.
 not_found() ->
-    respond({404, [{"Content-Type", "text/plain"}], <<"Not found.">>}).
+    not_found([]).
+
+%% @spec not_found(ExtraHeaders) -> response()
+%% @doc Alias for <code>respond({404, [{"Content-Type", "text/plain"}
+%% | ExtraHeaders], &lt;&lt;"Not found."&gt;&gt;})</code>.
+not_found(ExtraHeaders) ->
+    respond({404, [{"Content-Type", "text/plain"} | ExtraHeaders],
+             <<"Not found.">>}).
 
 %% @spec ok({value(), iodata()} | {value(), ioheaders(), iodata() | {file, IoDevice}}) ->
 %%           response()
@@ -326,7 +333,9 @@
         %% unread data left on the socket, can't safely continue
         orelse (DidNotRecv
                 andalso get_header_value("content-length") =/= undefined
-                andalso list_to_integer(get_header_value("content-length")) > 0).
+                andalso list_to_integer(get_header_value("content-length")) > 0)
+        orelse (DidNotRecv
+                andalso get_header_value("transfer-encoding") =:= "chunked").
 
 %% @spec cleanup() -> ok
 %% @doc Clean up any junk in the process dictionary, required before continuing
@@ -455,9 +464,14 @@
 %% @spec serve_file(Path, DocRoot) -> Response
 %% @doc Serve a file relative to DocRoot.
 serve_file(Path, DocRoot) ->
+    serve_file(Path, DocRoot, []).
+
+%% @spec serve_file(Path, DocRoot, ExtraHeaders) -> Response
+%% @doc Serve a file relative to DocRoot.
+serve_file(Path, DocRoot, ExtraHeaders) ->
     case mochiweb_util:safe_relative_path(Path) of
         undefined ->
-            not_found();
+            not_found(ExtraHeaders);
         RelPath ->
             FullPath = filename:join([DocRoot, RelPath]),
             File = case filelib:is_dir(FullPath) of
@@ -471,20 +485,23 @@
                     LastModified = httpd_util:rfc1123_date(FileInfo#file_info.mtime),
                     case get_header_value("if-modified-since") of
                         LastModified ->
-                            respond({304, [], ""});
+                            respond({304, ExtraHeaders, ""});
                         _ ->
                             case file:open(File, [raw, binary]) of
                                 {ok, IoDevice} ->
                                     ContentType = mochiweb_util:guess_mime(File),
-                                    Res = ok({ContentType, [{"last-modified", LastModified}], {file, IoDevice}}),
+                                    Res = ok({ContentType,
+                                              [{"last-modified", LastModified}
+                                               | ExtraHeaders],
+                                              {file, IoDevice}}),
                                     file:close(IoDevice),
                                     Res;
                                 _ ->
-                                    not_found()
+                                    not_found(ExtraHeaders)
                             end
                     end;
                 {error, _} ->
-                    not_found()
+                    not_found(ExtraHeaders)
             end
     end.
 

Modified: incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_socket_server.erl
URL: http://svn.apache.org/viewvc/incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_socket_server.erl?rev=671905&r1=671904&r2=671905&view=diff
==============================================================================
--- incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_socket_server.erl (original)
+++ incubator/couchdb/branches/0.8.x/src/mochiweb/mochiweb_socket_server.erl Thu Jun 26 07:00:22 2008
@@ -96,6 +96,14 @@
             gen_server:start_link(Name, ?MODULE, State, [])
     end.
 
+ipv6_supported() ->
+    case (catch inet:getaddr("localhost", inet6)) of
+        {ok, _Addr} ->
+            true;
+        {error, _} ->
+            false
+    end.
+
 init(State=#mochiweb_socket_server{ip=Ip, port=Port, backlog=Backlog}) ->
     process_flag(trap_exit, true),
     BaseOpts = [binary, 
@@ -106,11 +114,16 @@
                 {active, false},
                 {nodelay, true}],
     Opts = case Ip of
-               any ->
-                   BaseOpts;
-               Ip ->
-                   [{ip, Ip} | BaseOpts]
-           end,
+        any ->
+            case ipv6_supported() of % IPv4, and IPv6 if supported
+                true -> [inet, inet6 | BaseOpts];
+                _ -> BaseOpts
+            end;
+        {_, _, _, _} -> % IPv4
+            [inet, {ip, Ip} | BaseOpts];
+        {_, _, _, _, _, _, _, _} -> % IPv6
+            [inet6, {ip, Ip} | BaseOpts]
+    end,
     case gen_tcp_listen(Port, Opts, State) of
         {stop, eacces} ->
             case Port < 1024 of