Merge lp:~jderose/ubuntu/saucy/couchdb/1.4.0 into lp:ubuntu/saucy/couchdb

Proposed by Chad Miller
Status: Merged
Merge reported by: Robie Basak
Merged at revision: not available
Proposed branch: lp:~jderose/ubuntu/saucy/couchdb/1.4.0
Merge into: lp:ubuntu/saucy/couchdb
Diff against target: 173949 lines (+110026/-36696)
496 files modified
.pc/applied-patches (+0/-8)
.pc/couchdb_own_rundir.patch/etc/init/couchdb.tpl.in (+0/-156)
.pc/couchdb_sighup.patch/bin/couchdb.tpl.in (+0/-335)
.pc/force-reload.patch/etc/init/couchdb.tpl.in (+0/-156)
.pc/improve_parsing_of_mochiweb_relative_paths.patch/src/mochiweb/mochiweb_util.erl (+0/-973)
.pc/improve_script_url_validation.patch/share/www/script/couch_test_runner.js (+0/-472)
.pc/include_a_comment_before_jsonp_output.patch/src/couchdb/couch_httpd.erl (+0/-1081)
.pc/logrotate_as_couchdb.patch/etc/logrotate.d/couchdb.tpl.in (+0/-9)
.pc/wait_for_couchdb_stop.patch/etc/init/couchdb.tpl.in (+0/-157)
AUTHORS (+6/-0)
BUGS (+5/-3)
CHANGES (+0/-874)
DEVELOPERS (+128/-22)
INSTALL (+171/-35)
INSTALL.Unix (+80/-44)
INSTALL.Windows (+72/-21)
LICENSE (+489/-12)
Makefile.am (+63/-59)
Makefile.in (+329/-188)
NEWS (+0/-418)
NOTICE (+98/-10)
README (+0/-83)
README.rst (+95/-0)
THANKS (+55/-4)
acinclude.m4 (+1/-1)
aclocal.m4 (+962/-140)
bin/Makefile.am (+59/-30)
bin/Makefile.in (+212/-140)
bin/couch-config.tpl.in (+1/-1)
bin/couchdb.1 (+2/-2)
bin/couchdb.bat.tpl.in (+1/-1)
bin/couchdb.tpl.in (+34/-5)
build-aux/config.guess (+343/-293)
build-aux/config.sub (+294/-103)
build-aux/depcomp (+207/-83)
build-aux/dist-error (+28/-0)
build-aux/install-sh (+141/-121)
build-aux/ltmain.sh (+1640/-749)
build-aux/missing (+29/-65)
build-aux/sphinx-build (+67/-0)
build-aux/sphinx-touch (+24/-0)
config.h.in (+48/-7)
configure (+8546/-8152)
configure.ac (+356/-214)
debian/README.Debian (+0/-26)
debian/README.source (+0/-20)
debian/changelog (+41/-0)
debian/compat (+1/-1)
debian/control (+39/-19)
debian/couchdb-bin.install (+4/-1)
debian/couchdb-bin.postrm (+0/-16)
debian/couchdb-common.install (+3/-0)
debian/couchdb.install (+0/-2)
debian/couchdb.lintian-overrides (+2/-1)
debian/couchdb.postinst (+6/-0)
debian/couchdb.postrm (+0/-5)
debian/couchdb.upstart (+19/-0)
debian/patches/couchdb_own_rundir.patch (+0/-20)
debian/patches/couchdb_sighup.patch (+0/-22)
debian/patches/force-reload.patch (+0/-21)
debian/patches/improve_parsing_of_mochiweb_relative_paths.patch (+0/-40)
debian/patches/improve_script_url_validation.patch (+0/-26)
debian/patches/include_a_comment_before_jsonp_output.patch (+0/-20)
debian/patches/logrotate_as_couchdb.patch (+0/-16)
debian/patches/series (+0/-8)
debian/patches/wait_for_couchdb_stop.patch (+0/-30)
debian/rules (+20/-51)
debian/watch (+1/-1)
etc/Makefile.in (+218/-96)
etc/couchdb/Makefile.am (+10/-3)
etc/couchdb/Makefile.in (+122/-40)
etc/couchdb/default.ini.tpl.in (+55/-12)
etc/couchdb/local.ini (+13/-4)
etc/default/Makefile.in (+76/-24)
etc/init/Makefile.in (+76/-24)
etc/init/couchdb.tpl.in (+6/-15)
etc/launchd/Makefile.in (+76/-24)
etc/logrotate.d/Makefile.in (+76/-24)
etc/logrotate.d/couchdb.tpl.in (+0/-2)
etc/windows/Makefile.in (+76/-24)
etc/windows/couchdb.iss.tpl (+8/-4)
license.skip (+59/-36)
m4/ac_check_curl.m4 (+0/-69)
m4/ac_check_icu.m4 (+0/-74)
m4/libtool.m4 (+762/-355)
m4/ltversion.m4 (+6/-6)
m4/pkg.m4 (+0/-157)
share/Makefile.am (+20/-1)
share/Makefile.in (+408/-100)
share/doc/Makefile.am (+14/-0)
share/doc/Makefile.in (+644/-0)
share/doc/build/Makefile.am (+329/-0)
share/doc/build/Makefile.in (+752/-0)
share/doc/build/html/_sources/api-basics.txt (+463/-0)
share/doc/build/html/_sources/api/authn.txt (+41/-0)
share/doc/build/html/_sources/api/configuration.txt (+297/-0)
share/doc/build/html/_sources/api/database.txt (+1471/-0)
share/doc/build/html/_sources/api/design.txt (+1264/-0)
share/doc/build/html/_sources/api/documents.txt (+973/-0)
share/doc/build/html/_sources/api/local.txt (+169/-0)
share/doc/build/html/_sources/api/misc.txt (+867/-0)
share/doc/build/html/_sources/api/reference.txt (+42/-0)
share/doc/build/html/_sources/changelog.txt (+1489/-0)
share/doc/build/html/_sources/changes.txt (+227/-0)
share/doc/build/html/_sources/config_reference.txt (+330/-0)
share/doc/build/html/_sources/configuring.txt (+629/-0)
share/doc/build/html/_sources/contributing.txt (+167/-0)
share/doc/build/html/_sources/ddocs.txt (+751/-0)
share/doc/build/html/_sources/index.txt (+46/-0)
share/doc/build/html/_sources/intro.txt (+309/-0)
share/doc/build/html/_sources/json-structure.txt (+825/-0)
share/doc/build/html/_sources/query-servers.txt (+436/-0)
share/doc/build/html/_sources/replication.txt (+95/-0)
share/doc/build/html/_sources/replicator.txt (+383/-0)
share/doc/build/html/_static/basic.css (+540/-0)
share/doc/build/html/_static/default.css (+256/-0)
share/doc/build/html/_static/doctools.js (+247/-0)
share/doc/build/html/_static/jquery.js (+154/-0)
share/doc/build/html/_static/pygments.css (+62/-0)
share/doc/build/html/_static/rtd.css (+795/-0)
share/doc/build/html/_static/searchtools.js (+560/-0)
share/doc/build/html/_static/sidebar.js (+151/-0)
share/doc/build/html/_static/underscore.js (+23/-0)
share/doc/build/html/_static/websupport.js (+808/-0)
share/doc/build/html/api-basics.html (+556/-0)
share/doc/build/html/api/authn.html (+222/-0)
share/doc/build/html/api/configuration.html (+467/-0)
share/doc/build/html/api/database.html (+1646/-0)
share/doc/build/html/api/design.html (+1384/-0)
share/doc/build/html/api/documents.html (+1136/-0)
share/doc/build/html/api/local.html (+363/-0)
share/doc/build/html/api/misc.html (+1222/-0)
share/doc/build/html/api/reference.html (+273/-0)
share/doc/build/html/changelog.html (+2043/-0)
share/doc/build/html/changes.html (+414/-0)
share/doc/build/html/config_reference.html (+743/-0)
share/doc/build/html/configuring.html (+682/-0)
share/doc/build/html/ddocs.html (+976/-0)
share/doc/build/html/genindex.html (+360/-0)
share/doc/build/html/index.html (+316/-0)
share/doc/build/html/intro.html (+423/-0)
share/doc/build/html/json-structure.html (+1278/-0)
share/doc/build/html/query-servers.html (+739/-0)
share/doc/build/html/replication.html (+247/-0)
share/doc/build/html/replicator.html (+503/-0)
share/doc/build/html/search.html (+177/-0)
share/doc/build/html/searchindex.js (+1/-0)
share/doc/build/texinfo/CouchDB.info (+16106/-0)
share/doc/src/api-basics.rst (+463/-0)
share/doc/src/api/authn.rst (+41/-0)
share/doc/src/api/configuration.rst (+297/-0)
share/doc/src/api/database.rst (+1471/-0)
share/doc/src/api/design.rst (+1264/-0)
share/doc/src/api/documents.rst (+973/-0)
share/doc/src/api/local.rst (+169/-0)
share/doc/src/api/misc.rst (+867/-0)
share/doc/src/api/reference.rst (+42/-0)
share/doc/src/changelog.rst (+1489/-0)
share/doc/src/changes.rst (+227/-0)
share/doc/src/conf.py (+88/-0)
share/doc/src/config_reference.rst (+330/-0)
share/doc/src/configuring.rst (+629/-0)
share/doc/src/contributing.rst (+167/-0)
share/doc/src/ddocs.rst (+751/-0)
share/doc/src/index.rst (+46/-0)
share/doc/src/intro.rst (+309/-0)
share/doc/src/json-structure.rst (+825/-0)
share/doc/src/query-servers.rst (+436/-0)
share/doc/src/replication.rst (+95/-0)
share/doc/src/replicator.rst (+383/-0)
share/doc/static/rtd.css (+795/-0)
share/doc/templates/help.html (+24/-0)
share/doc/templates/searchbox.html (+31/-0)
share/doc/templates/utilities.html (+22/-0)
share/server/filter.js (+1/-1)
share/server/loop.js (+5/-3)
share/server/render.js (+17/-5)
share/server/util.js (+18/-9)
share/server/validate.js (+4/-1)
share/server/views.js (+2/-1)
share/www/_sidebar.html (+7/-6)
share/www/config.html (+5/-5)
share/www/couch_tests.html (+6/-6)
share/www/custom_test.html (+7/-7)
share/www/database.html (+14/-11)
share/www/dialog/_delete_database.html (+4/-2)
share/www/document.html (+9/-9)
share/www/index.html (+6/-6)
share/www/replicator.html (+4/-4)
share/www/script/couch.js (+52/-5)
share/www/script/couch_test_runner.js (+3/-1)
share/www/script/couch_tests.js (+18/-1)
share/www/script/futon.browse.js (+46/-6)
share/www/script/futon.js (+30/-0)
share/www/script/jquery.couch.js (+10/-6)
share/www/script/jquery.js (+5655/-5164)
share/www/script/jquery.suggest.js (+0/-2)
share/www/script/replicator_db_inc.js (+96/-0)
share/www/script/test/attachment_names.js (+0/-2)
share/www/script/test/attachment_ranges.js (+5/-0)
share/www/script/test/attachments.js (+27/-0)
share/www/script/test/attachments_multipart.js (+32/-29)
share/www/script/test/changes.js (+139/-44)
share/www/script/test/config.js (+49/-1)
share/www/script/test/content_negotiation.js (+2/-2)
share/www/script/test/cookie_auth.js (+25/-20)
share/www/script/test/etags_views.js (+2/-2)
share/www/script/test/form_submit.js (+0/-1)
share/www/script/test/list_views.js (+37/-0)
share/www/script/test/oauth.js (+2/-1)
share/www/script/test/reader_acl.js (+7/-0)
share/www/script/test/replication.js (+11/-0)
share/www/script/test/replicator_db.js (+0/-1547)
share/www/script/test/replicator_db_bad_rep_id.js (+77/-0)
share/www/script/test/replicator_db_by_doc_id.js (+99/-0)
share/www/script/test/replicator_db_compact_rep_db.js (+119/-0)
share/www/script/test/replicator_db_continuous.js (+137/-0)
share/www/script/test/replicator_db_credential_delegation.js (+149/-0)
share/www/script/test/replicator_db_field_validation.js (+178/-0)
share/www/script/test/replicator_db_filtered.js (+105/-0)
share/www/script/test/replicator_db_identical.js (+87/-0)
share/www/script/test/replicator_db_identical_continuous.js (+132/-0)
share/www/script/test/replicator_db_invalid_filter.js (+115/-0)
share/www/script/test/replicator_db_security.js (+12/-8)
share/www/script/test/replicator_db_simple.js (+114/-0)
share/www/script/test/replicator_db_successive.js (+127/-0)
share/www/script/test/replicator_db_survives.js (+126/-0)
share/www/script/test/replicator_db_swap_rep_db.js (+170/-0)
share/www/script/test/replicator_db_update_security.js (+92/-0)
share/www/script/test/replicator_db_user_ctx.js (+272/-0)
share/www/script/test/replicator_db_write_auth.js (+102/-0)
share/www/script/test/rev_stemming.js (+3/-0)
share/www/script/test/rewrite.js (+173/-119)
share/www/script/test/security_validation.js (+2/-2)
share/www/script/test/show_documents.js (+2/-2)
share/www/script/test/update_documents.js (+56/-2)
share/www/script/test/users_db.js (+38/-0)
share/www/script/test/users_db_security.js (+111/-9)
share/www/script/test/utf8.js (+1/-0)
share/www/script/test/uuids.js (+26/-1)
share/www/script/test/view_compaction.js (+10/-10)
share/www/script/test/view_multi_key_all_docs.js (+4/-0)
share/www/script/test/view_multi_key_design.js (+4/-0)
share/www/script/test/view_multi_key_temp.js (+3/-0)
share/www/session.html (+6/-6)
share/www/spec/run.html (+1/-0)
share/www/status.html (+4/-4)
share/www/style/layout.css (+4/-0)
share/www/verify_install.html (+8/-7)
src/Makefile.am (+12/-1)
src/Makefile.in (+163/-59)
src/couch_dbupdates/Makefile.am (+33/-0)
src/couch_dbupdates/Makefile.in (+519/-0)
src/couch_dbupdates/src/couch_dbupdates.app.src (+11/-0)
src/couch_dbupdates/src/couch_dbupdates.erl (+46/-0)
src/couch_dbupdates/src/couch_dbupdates_httpd.erl (+69/-0)
src/couch_index/Makefile.am (+40/-0)
src/couch_index/Makefile.in (+525/-0)
src/couch_index/src/couch_index.app.src (+22/-0)
src/couch_index/src/couch_index.erl (+340/-0)
src/couch_index/src/couch_index_api.erl (+54/-0)
src/couch_index/src/couch_index_compactor.erl (+114/-0)
src/couch_index/src/couch_index_server.erl (+201/-0)
src/couch_index/src/couch_index_updater.erl (+200/-0)
src/couch_index/src/couch_index_util.erl (+78/-0)
src/couch_mrview/Makefile.am (+73/-0)
src/couch_mrview/Makefile.in (+582/-0)
src/couch_mrview/include/couch_mrview.hrl (+80/-0)
src/couch_mrview/src/couch_mrview.app.src (+28/-0)
src/couch_mrview/src/couch_mrview.erl (+387/-0)
src/couch_mrview/src/couch_mrview_cleanup.erl (+47/-0)
src/couch_mrview/src/couch_mrview_compactor.erl (+178/-0)
src/couch_mrview/src/couch_mrview_http.erl (+378/-0)
src/couch_mrview/src/couch_mrview_index.erl (+162/-0)
src/couch_mrview/src/couch_mrview_show.erl (+368/-0)
src/couch_mrview/src/couch_mrview_test_util.erl (+91/-0)
src/couch_mrview/src/couch_mrview_updater.erl (+282/-0)
src/couch_mrview/src/couch_mrview_util.erl (+802/-0)
src/couch_mrview/test/01-load.t (+34/-0)
src/couch_mrview/test/02-map-views.t (+131/-0)
src/couch_mrview/test/03-red-views.t (+78/-0)
src/couch_mrview/test/04-index-info.t (+54/-0)
src/couch_mrview/test/05-collation.t (+163/-0)
src/couch_mrview/test/06-all-docs.t (+127/-0)
src/couch_mrview/test/07-compact-swap.t (+57/-0)
src/couch_replicator/Makefile.am (+77/-0)
src/couch_replicator/Makefile.in (+586/-0)
src/couch_replicator/src/couch_replicator.app.src (+33/-0)
src/couch_replicator/src/couch_replicator.erl (+955/-0)
src/couch_replicator/src/couch_replicator.hrl (+30/-0)
src/couch_replicator/src/couch_replicator_api_wrap.erl (+780/-0)
src/couch_replicator/src/couch_replicator_api_wrap.hrl (+36/-0)
src/couch_replicator/src/couch_replicator_httpc.erl (+297/-0)
src/couch_replicator/src/couch_replicator_httpc_pool.erl (+138/-0)
src/couch_replicator/src/couch_replicator_httpd.erl (+66/-0)
src/couch_replicator/src/couch_replicator_job_sup.erl (+31/-0)
src/couch_replicator/src/couch_replicator_js_functions.hrl (+151/-0)
src/couch_replicator/src/couch_replicator_manager.erl (+703/-0)
src/couch_replicator/src/couch_replicator_notifier.erl (+57/-0)
src/couch_replicator/src/couch_replicator_utils.erl (+388/-0)
src/couch_replicator/src/couch_replicator_worker.erl (+515/-0)
src/couch_replicator/test/01-load.t (+37/-0)
src/couch_replicator/test/02-httpc-pool.t (+250/-0)
src/couch_replicator/test/03-replication-compact.t (+488/-0)
src/couch_replicator/test/04-replication-large-atts.t (+267/-0)
src/couch_replicator/test/05-replication-many-leaves.t (+294/-0)
src/couch_replicator/test/06-doc-missing-stubs.t (+304/-0)
src/couchdb/Makefile.am (+10/-39)
src/couchdb/Makefile.in (+210/-120)
src/couchdb/couch.app.tpl.in (+1/-3)
src/couchdb/couch_api_wrap.erl (+0/-779)
src/couchdb/couch_api_wrap.hrl (+0/-36)
src/couchdb/couch_api_wrap_httpc.erl (+0/-286)
src/couchdb/couch_app.erl (+1/-1)
src/couchdb/couch_auth_cache.erl (+25/-10)
src/couchdb/couch_changes.erl (+19/-7)
src/couchdb/couch_compaction_daemon.erl (+9/-10)
src/couchdb/couch_config.erl (+2/-2)
src/couchdb/couch_config_writer.erl (+1/-1)
src/couchdb/couch_db.erl (+47/-25)
src/couchdb/couch_db.hrl (+13/-29)
src/couchdb/couch_db_update_notifier.erl (+11/-2)
src/couchdb/couch_db_updater.erl (+19/-17)
src/couchdb/couch_doc.erl (+64/-10)
src/couchdb/couch_ejson_compare.erl (+12/-1)
src/couchdb/couch_file.erl (+27/-3)
src/couchdb/couch_httpc_pool.erl (+0/-138)
src/couchdb/couch_httpd.erl (+122/-90)
src/couchdb/couch_httpd_auth.erl (+31/-19)
src/couchdb/couch_httpd_cors.erl (+349/-0)
src/couchdb/couch_httpd_db.erl (+118/-280)
src/couchdb/couch_httpd_external.erl (+11/-7)
src/couchdb/couch_httpd_misc_handlers.erl (+77/-13)
src/couchdb/couch_httpd_oauth.erl (+10/-9)
src/couchdb/couch_httpd_replicator.erl (+0/-66)
src/couchdb/couch_httpd_rewrite.erl (+18/-5)
src/couchdb/couch_httpd_show.erl (+0/-407)
src/couchdb/couch_httpd_vhost.erl (+34/-26)
src/couchdb/couch_httpd_view.erl (+0/-777)
src/couchdb/couch_js_functions.hrl (+11/-142)
src/couchdb/couch_log.erl (+61/-10)
src/couchdb/couch_os_daemons.erl (+11/-1)
src/couchdb/couch_os_process.erl (+1/-1)
src/couchdb/couch_passwords.erl (+119/-0)
src/couchdb/couch_primary_sup.erl (+3/-3)
src/couchdb/couch_rep_sup.erl (+0/-31)
src/couchdb/couch_replication_manager.erl (+0/-694)
src/couchdb/couch_replication_notifier.erl (+0/-57)
src/couchdb/couch_replicator.erl (+0/-952)
src/couchdb/couch_replicator.hrl (+0/-30)
src/couchdb/couch_replicator_utils.erl (+0/-382)
src/couchdb/couch_replicator_worker.erl (+0/-515)
src/couchdb/couch_server.erl (+55/-30)
src/couchdb/couch_stream.erl (+13/-8)
src/couchdb/couch_users_db.erl (+27/-9)
src/couchdb/couch_util.erl (+61/-8)
src/couchdb/couch_uuids.erl (+9/-1)
src/couchdb/couch_view.erl (+0/-437)
src/couchdb/couch_view_compactor.erl (+0/-152)
src/couchdb/couch_view_group.erl (+0/-699)
src/couchdb/couch_view_updater.erl (+0/-283)
src/couchdb/couch_work_queue.erl (+1/-1)
src/couchdb/priv/Makefile.am (+43/-13)
src/couchdb/priv/Makefile.in (+313/-215)
src/couchdb/priv/couch_ejson_compare/couch_ejson_compare.c (+11/-10)
src/couchdb/priv/couch_js/help.h (+4/-2)
src/couchdb/priv/couch_js/http.c (+63/-3)
src/couchdb/priv/couch_js/http.h (+3/-0)
src/couchdb/priv/couch_js/sm170.c (+50/-30)
src/couchdb/priv/couch_js/sm180.c (+50/-30)
src/couchdb/priv/couch_js/sm185.c (+58/-28)
src/couchdb/priv/couch_js/util.c (+79/-37)
src/couchdb/priv/couch_js/util.h (+6/-4)
src/couchdb/priv/couchjs.1 (+8/-4)
src/ejson/Makefile.in (+183/-98)
src/ejson/ejson.erl (+2/-0)
src/ejson/yajl/yajl_encode.c (+7/-0)
src/erlang-oauth/Makefile.am (+2/-13)
src/erlang-oauth/Makefile.in (+114/-49)
src/erlang-oauth/oauth.erl (+276/-68)
src/erlang-oauth/oauth_hmac_sha1.erl (+0/-11)
src/erlang-oauth/oauth_http.erl (+0/-22)
src/erlang-oauth/oauth_plaintext.erl (+0/-10)
src/erlang-oauth/oauth_rsa_sha1.erl (+0/-30)
src/erlang-oauth/oauth_unix.erl (+0/-16)
src/erlang-oauth/oauth_uri.erl (+0/-100)
src/etap/Makefile.am (+2/-18)
src/etap/Makefile.in (+114/-54)
src/etap/etap.erl (+273/-76)
src/etap/etap_application.erl (+0/-72)
src/etap/etap_can.erl (+0/-79)
src/etap/etap_exception.erl (+0/-66)
src/etap/etap_process.erl (+0/-42)
src/etap/etap_report.erl (+0/-343)
src/etap/etap_request.erl (+0/-89)
src/etap/etap_string.erl (+0/-47)
src/etap/etap_web.erl (+0/-65)
src/ibrowse/Makefile.in (+112/-36)
src/ibrowse/ibrowse.app.in (+4/-10)
src/ibrowse/ibrowse.erl (+158/-92)
src/ibrowse/ibrowse_http_client.erl (+175/-109)
src/ibrowse/ibrowse_lb.erl (+54/-37)
src/ibrowse/ibrowse_lib.erl (+62/-12)
src/ibrowse/ibrowse_test.erl (+122/-10)
src/mochiweb/Makefile.am (+0/-1)
src/mochiweb/Makefile.in (+112/-37)
src/mochiweb/mochifmt.erl (+1/-1)
src/mochiweb/mochifmt_records.erl (+10/-6)
src/mochiweb/mochifmt_std.erl (+12/-9)
src/mochiweb/mochiglobal.erl (+2/-2)
src/mochiweb/mochihex.erl (+1/-4)
src/mochiweb/mochijson.erl (+1/-3)
src/mochiweb/mochijson2.erl (+52/-12)
src/mochiweb/mochilists.erl (+1/-1)
src/mochiweb/mochilogfile2.erl (+1/-1)
src/mochiweb/mochinum.erl (+1/-1)
src/mochiweb/mochitemp.erl (+2/-1)
src/mochiweb/mochiutf8.erl (+4/-3)
src/mochiweb/mochiweb.app.in (+5/-28)
src/mochiweb/mochiweb.app.src (+0/-9)
src/mochiweb/mochiweb.erl (+19/-27)
src/mochiweb/mochiweb_acceptor.erl (+7/-4)
src/mochiweb/mochiweb_charref.erl (+2131/-256)
src/mochiweb/mochiweb_cookies.erl (+29/-7)
src/mochiweb/mochiweb_cover.erl (+1/-1)
src/mochiweb/mochiweb_echo.erl (+9/-6)
src/mochiweb/mochiweb_headers.erl (+125/-4)
src/mochiweb/mochiweb_html.erl (+100/-32)
src/mochiweb/mochiweb_http.erl (+41/-67)
src/mochiweb/mochiweb_io.erl (+1/-4)
src/mochiweb/mochiweb_mime.erl (+360/-39)
src/mochiweb/mochiweb_multipart.erl (+73/-25)
src/mochiweb/mochiweb_request.erl (+299/-192)
src/mochiweb/mochiweb_request_tests.erl (+120/-1)
src/mochiweb/mochiweb_response.erl (+27/-19)
src/mochiweb/mochiweb_socket.erl (+7/-8)
src/mochiweb/mochiweb_socket_server.erl (+33/-47)
src/mochiweb/mochiweb_util.erl (+11/-5)
src/mochiweb/reloader.erl (+2/-2)
src/snappy/Makefile.am (+3/-3)
src/snappy/Makefile.in (+168/-83)
src/snappy/google-snappy/config.h.in (+33/-38)
src/snappy/google-snappy/snappy-sinksource.cc (+0/-1)
src/snappy/google-snappy/snappy-sinksource.h (+1/-0)
src/snappy/google-snappy/snappy-stubs-internal.h (+99/-5)
src/snappy/google-snappy/snappy.cc (+152/-62)
src/snappy/google-snappy/snappy.h (+2/-2)
src/snappy/snappy.app.in (+1/-1)
test/Makefile.am (+1/-0)
test/Makefile.in (+151/-58)
test/bench/Makefile.in (+76/-24)
test/etap/001-load.t (+2/-17)
test/etap/020-btree-basics.t (+2/-2)
test/etap/040-util.t (+2/-2)
test/etap/041-uuid-gen-id.ini (+20/-0)
test/etap/041-uuid-gen.t (+31/-2)
test/etap/050-stream.t (+4/-4)
test/etap/072-cleanup.t (+3/-3)
test/etap/073-changes.t (+1/-1)
test/etap/074-doc-update-conflicts.t (+218/-0)
test/etap/075-auth-cache.t (+3/-1)
test/etap/076-file-compression.t (+7/-6)
test/etap/077-couch-db-fast-db-delete-create.t (+61/-0)
test/etap/080-config-get-set.t (+1/-1)
test/etap/083-config-no-files.t (+0/-2)
test/etap/090-task-status.t (+0/-3)
test/etap/120-stats-collect.t (+7/-7)
test/etap/140-attachment-comp.t (+4/-1)
test/etap/160-vhosts.t (+12/-31)
test/etap/200-view-group-no-db-leaks.t (+21/-49)
test/etap/201-view-group-shutdown.t (+9/-19)
test/etap/220-compaction-daemon.t (+19/-21)
test/etap/230-httpc-pool.t (+0/-250)
test/etap/230-pbkfd2.t (+38/-0)
test/etap/231-cors.t (+449/-0)
test/etap/240-replication-compact.t (+0/-488)
test/etap/241-replication-large-atts.t (+0/-267)
test/etap/242-replication-many-leaves.t (+0/-294)
test/etap/243-doc-missing-stubs.t (+0/-304)
test/etap/250-upgrade-legacy-view-files.t (+168/-0)
test/etap/Makefile.am (+19/-9)
test/etap/Makefile.in (+130/-61)
test/etap/random_port.ini (+0/-19)
test/etap/run.tpl (+16/-11)
test/etap/test_util.erl.in (+25/-3)
test/javascript/Makefile.am (+2/-0)
test/javascript/Makefile.in (+78/-24)
test/javascript/cli_runner.js (+34/-39)
test/javascript/couch_http.js (+16/-5)
test/javascript/run.tpl (+91/-12)
test/javascript/test_setup.js (+89/-0)
test/random_port.ini (+19/-0)
test/view_server/Makefile.in (+76/-24)
utils/Makefile.am (+1/-1)
utils/Makefile.in (+77/-25)
var/Makefile.in (+76/-25)
To merge this branch: bzr merge lp:~jderose/ubuntu/saucy/couchdb/1.4.0
Reviewer Review Type Date Requested Status
Andrew Starr-Bochicchio (community) Approve
Chad Miller (community) Approve
Jason Gerard DeRose (community) Needs Resubmitting
Ubuntu branches Pending
Review via email: mp+182725@code.launchpad.net
To post a comment you must log in.
114. By Jason Gerard DeRose

merge-upstream 1.4.0 (no change from 1.4.0-rc.1)

Revision history for this message
Chad Miller (cmiller) wrote :

So nice. $ bzr diff -r72.. debian/

1)
+XSBC-Original-Maintainer: Jason Gerard DeRose <email address hidden>
This should be whoever owned the package in the previous packaging, which usually means the Debian maintainer, but can sometimes be the previous person in Ubuntu. It shouldn't be whoever's in the changelog.

2)
-case $1 in
- configure)
- if dpkg --compare-versions "$2" lt-nl 1.2.0-2ubuntu1; then
Should you be dropping this? Someone could go from 1.1 to 1.4.

3)
-get-orig-source:
- uscan --force-download --rename --download-version=$(DEB_UPSTREAM_VERSION) --destdir .
This rule can be useful. In fact, I'd update it so that it uses the most recent standard: Rule should be
"get-packaged-orig-source", and it inherits ORIG_PACKAGE and ORIG_VERSION as Make/environment variables, so it should download orig sources, clean them up, and make a tarball in the current dir that extracts correctly (tar xf ORIG_PACKAGE+"_"+ORIG_SOURCE+".orig.tar.gz" -> "./"+ORIG_PACKAGE+"-"+ORIG_VERSION). This assumes you know where the official tarball or sources will be at release.

review: Needs Fixing
115. By Jason Gerard DeRose

Fixed up changelog

116. By Jason Gerard DeRose

oops, revert XSBC-Original-Maintainer to Laszlo Boszormenyi (GCS) <email address hidden>

117. By Jason Gerard DeRose

oops, we still need couchdb-bin.postinst

118. By Jason Gerard DeRose

Updated debian/watch file to use current http://www.apache.org/dist/couchdb/source/ location

119. By Jason Gerard DeRose

Added a get-packaged-orig-source rule

120. By Jason Gerard DeRose

Updated changelog with a few last bits

Revision history for this message
Jason Gerard DeRose (jderose) wrote :

Thanks, Chad!

So I've got those 3 things fixed, and I also fixed the debian/watch file, which wasn't pointing to the current download location.

I also got word from the CouchDB folks that the 1.4.0 release is now golden (no change from 1.4.0-rc.1), so I updated the version in the changelog to reflect this (note the 1.4.0 release announcement hasn't been made yet).

review: Needs Resubmitting
Revision history for this message
Jason Gerard DeRose (jderose) wrote :

Oh, one more thing, something about UDD or quilt caused two conflicts when you try to merge this into lp:ubuntu/saucy/couchdb:

conflicts:
  Text conflict in bin/couchdb.tpl.in
  Text conflict in etc/init/couchdb.tpl.in

They can be correctly resolved with:

bzr resolve --all --take-other

Revision history for this message
Chad Miller (cmiller) wrote :

Okay. In the future, Jason, I think the quilt state directory '.pc' should be added to bzr's ignores list. Not important now.

review: Approve
Revision history for this message
Chad Miller (cmiller) wrote :

Jason, another wishlist thing to add in the future is "autopkgtests", so we can detect breakage between couchdb--erlang, and maybe novacut--c--e one day.

Revision history for this message
Chad Miller (cmiller) wrote :

Jason, also pay attention to lintian messages. Fix these "E" at least for next upload. Maybe you can ignore the init.d ones, assuming you Depend on upstart.

W: couchdb-common: debian-changelog-line-too-long line 14
W: couchdb-common: embedded-javascript-library usr/share/couchdb/www/docs/_static/jquery.js
W: couchdb-common: embedded-javascript-library usr/share/couchdb/www/docs/_static/underscore.js
W: couchdb-common: embedded-javascript-library usr/share/couchdb/www/script/jquery.form.js
W: couchdb-common: embedded-javascript-library usr/share/couchdb/www/script/jquery.js
W: couchdb-common: executable-not-elf-or-script usr/share/couchdb/server/main.js
W: couchdb-common: executable-not-elf-or-script usr/share/couchdb/server/main-coffee.js
W: couchdb-bin: debian-changelog-line-too-long line 14
W: couchdb-bin: virtual-package-depends-without-real-package-depends depends: erlang-abi-15.b
E: couchdb-bin: package-contains-info-dir-file usr/share/info/dir.gz
W: couchdb-bin: binary-without-manpage usr/bin/couch-config
E: couchdb-bin: non-empty-dependency_libs-in-la-file usr/lib/i386-linux-gnu/couchdb/erlang/lib/couch-1.4.0/priv/lib/couch_ejson_compare.la
E: couchdb-bin: non-empty-dependency_libs-in-la-file usr/lib/i386-linux-gnu/couchdb/erlang/lib/couch-1.4.0/priv/lib/couch_icu_driver.la
E: couchdb-bin: non-empty-dependency_libs-in-la-file usr/lib/i386-linux-gnu/couchdb/erlang/lib/ejson-0.1.0/priv/ejson.la
E: couchdb-bin: non-empty-dependency_libs-in-la-file usr/lib/i386-linux-gnu/couchdb/erlang/lib/snappy-1.0.5/priv/snappy_nif.la
W: couchdb: debian-changelog-line-too-long line 14
E: couchdb: postrm-does-not-call-updaterc.d-for-init.d-script etc/init.d/couchdb
W: couchdb: init.d-script-not-marked-as-conffile etc/init.d/couchdb
E: couchdb: init.d-script-not-included-in-package etc/init.d/couchdb

121. By Jason Gerard DeRose

Fix linian non-empty-dependency_libs-in-la-file warnings

122. By Jason Gerard DeRose

Fix lintian debian-changelog-line-too-long warning

123. By Jason Gerard DeRose

Oops, didn't mean to commit with --disable-tests

Revision history for this message
Jason Gerard DeRose (jderose) wrote :

Chad,

So you don't need to keep .pc under version control for UDD any more?

Yeah, I'm keen adding some autopkgtests goodness. It would be good to test couchdb as a reverse dependency whenever erlang is updated, and testing the novacut components as a reverse dependency whenever couchdb is updated would also be awesome. Although these days couchdb has quite extensive unit tests that get run during the builds, so at least we're not completely lacking it automatic test coverage in the present. Could be much better though.

So I fixed the non-empty-dependency_libs-in-la-file lintian errors, and also fixed the debian-changelog-line-too-long warning.

Out of curiosity, how are you running lintian? When I run it, I'm not seeing the package-contains-info-dir-file error, for some reason.

Thanks again for all your help!

Revision history for this message
Jason Gerard DeRose (jderose) wrote :

Oh, and the last two lintian errors seem to be spurious, just the result of lintian not groking upstart:
https://bugs.launchpad.net/ubuntu/+source/lintian/+bug/1030195

Revision history for this message
Chad Miller (cmiller) wrote :

Jason, quilt state files in .pc/ should never be in Bazaar version control. Only the results of using quilt, a set of patch files in debian/, should be in Bazaar version control.

I'm running lintian as the automatic step at the end of "bzr builddeb", on Saucy.

Revision history for this message
Andrew Starr-Bochicchio (andrewsomething) :
review: Approve
Revision history for this message
Robie Basak (racb) wrote :

This is uploaded now, so closing out this MP.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file '.pc/applied-patches'
2--- .pc/applied-patches 2013-01-18 22:04:32 +0000
3+++ .pc/applied-patches 1970-01-01 00:00:00 +0000
4@@ -1,8 +0,0 @@
5-force-reload.patch
6-couchdb_own_rundir.patch
7-logrotate_as_couchdb.patch
8-couchdb_sighup.patch
9-wait_for_couchdb_stop.patch
10-improve_parsing_of_mochiweb_relative_paths.patch
11-improve_script_url_validation.patch
12-include_a_comment_before_jsonp_output.patch
13
14=== removed directory '.pc/couchdb_own_rundir.patch'
15=== removed directory '.pc/couchdb_own_rundir.patch/etc'
16=== removed directory '.pc/couchdb_own_rundir.patch/etc/init'
17=== removed file '.pc/couchdb_own_rundir.patch/etc/init/couchdb.tpl.in'
18--- .pc/couchdb_own_rundir.patch/etc/init/couchdb.tpl.in 2012-07-19 20:13:25 +0000
19+++ .pc/couchdb_own_rundir.patch/etc/init/couchdb.tpl.in 1970-01-01 00:00:00 +0000
20@@ -1,156 +0,0 @@
21-#!/bin/sh -e
22-
23-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
24-# use this file except in compliance with the License. You may obtain a copy of
25-# the License at
26-#
27-# http://www.apache.org/licenses/LICENSE-2.0
28-#
29-# Unless required by applicable law or agreed to in writing, software
30-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
31-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
32-# License for the specific language governing permissions and limitations under
33-# the License.
34-
35-### BEGIN INIT INFO
36-# Provides: couchdb
37-# Required-Start: $local_fs $remote_fs
38-# Required-Stop: $local_fs $remote_fs
39-# Default-Start: 2 3 4 5
40-# Default-Stop: 0 1 6
41-# Short-Description: Apache CouchDB init script
42-# Description: Apache CouchDB init script for the database server.
43-### END INIT INFO
44-
45-SCRIPT_OK=0
46-SCRIPT_ERROR=1
47-
48-DESCRIPTION="database server"
49-NAME=couchdb
50-SCRIPT_NAME=`basename $0`
51-COUCHDB=%bindir%/%couchdb_command_name%
52-CONFIGURATION_FILE=%sysconfdir%/default/couchdb
53-RUN_DIR=%localstaterundir%
54-LSB_LIBRARY=/lib/lsb/init-functions
55-
56-if test ! -x $COUCHDB; then
57- exit $SCRIPT_ERROR
58-fi
59-
60-if test -r $CONFIGURATION_FILE; then
61- . $CONFIGURATION_FILE
62-fi
63-
64-log_daemon_msg () {
65- # Dummy function to be replaced by LSB library.
66-
67- echo $@
68-}
69-
70-log_end_msg () {
71- # Dummy function to be replaced by LSB library.
72-
73- if test "$1" != "0"; then
74- echo "Error with $DESCRIPTION: $NAME"
75- fi
76- return $1
77-}
78-
79-if test -r $LSB_LIBRARY; then
80- . $LSB_LIBRARY
81-fi
82-
83-run_command () {
84- command="$1"
85- if test -n "$COUCHDB_OPTIONS"; then
86- command="$command $COUCHDB_OPTIONS"
87- fi
88- if test -n "$COUCHDB_USER"; then
89- if su $COUCHDB_USER -c "$command"; then
90- return $SCRIPT_OK
91- else
92- return $SCRIPT_ERROR
93- fi
94- else
95- if $command; then
96- return $SCRIPT_OK
97- else
98- return $SCRIPT_ERROR
99- fi
100- fi
101-}
102-
103-start_couchdb () {
104- # Start Apache CouchDB as a background process.
105-
106- mkdir -p "$RUN_DIR"
107- command="$COUCHDB -b"
108- if test -n "$COUCHDB_STDOUT_FILE"; then
109- command="$command -o $COUCHDB_STDOUT_FILE"
110- fi
111- if test -n "$COUCHDB_STDERR_FILE"; then
112- command="$command -e $COUCHDB_STDERR_FILE"
113- fi
114- if test -n "$COUCHDB_RESPAWN_TIMEOUT"; then
115- command="$command -r $COUCHDB_RESPAWN_TIMEOUT"
116- fi
117- run_command "$command" > /dev/null
118-}
119-
120-stop_couchdb () {
121- # Stop the running Apache CouchDB process.
122-
123- run_command "$COUCHDB -d" > /dev/null
124-}
125-
126-display_status () {
127- # Display the status of the running Apache CouchDB process.
128-
129- run_command "$COUCHDB -s"
130-}
131-
132-parse_script_option_list () {
133- # Parse arguments passed to the script and take appropriate action.
134-
135- case "$1" in
136- start)
137- log_daemon_msg "Starting $DESCRIPTION" $NAME
138- if start_couchdb; then
139- log_end_msg $SCRIPT_OK
140- else
141- log_end_msg $SCRIPT_ERROR
142- fi
143- ;;
144- stop)
145- log_daemon_msg "Stopping $DESCRIPTION" $NAME
146- if stop_couchdb; then
147- log_end_msg $SCRIPT_OK
148- else
149- log_end_msg $SCRIPT_ERROR
150- fi
151- ;;
152- restart|force-reload)
153- log_daemon_msg "Restarting $DESCRIPTION" $NAME
154- if stop_couchdb; then
155- if start_couchdb; then
156- log_end_msg $SCRIPT_OK
157- else
158- log_end_msg $SCRIPT_ERROR
159- fi
160- else
161- log_end_msg $SCRIPT_ERROR
162- fi
163- ;;
164- status)
165- display_status
166- ;;
167- *)
168- cat << EOF >&2
169-Usage: $SCRIPT_NAME {start|stop|restart|force-reload|status}
170-EOF
171- exit $SCRIPT_ERROR
172- ;;
173- esac
174-}
175-
176-parse_script_option_list $@
177
178=== removed directory '.pc/couchdb_sighup.patch'
179=== removed directory '.pc/couchdb_sighup.patch/bin'
180=== removed file '.pc/couchdb_sighup.patch/bin/couchdb.tpl.in'
181--- .pc/couchdb_sighup.patch/bin/couchdb.tpl.in 2012-11-18 12:24:24 +0000
182+++ .pc/couchdb_sighup.patch/bin/couchdb.tpl.in 1970-01-01 00:00:00 +0000
183@@ -1,335 +0,0 @@
184-#! /bin/sh -e
185-
186-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
187-# use this file except in compliance with the License. You may obtain a copy of
188-# the License at
189-#
190-# http://www.apache.org/licenses/LICENSE-2.0
191-#
192-# Unless required by applicable law or agreed to in writing, software
193-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
194-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
195-# License for the specific language governing permissions and limitations under
196-# the License.
197-
198-BACKGROUND=false
199-DEFAULT_CONFIG_DIR=%localconfdir%/default.d
200-DEFAULT_CONFIG_FILE=%localconfdir%/%defaultini%
201-ERL_OS_MON_OPTIONS="-os_mon \
202- start_memsup false \
203- start_cpu_sup false \
204- disk_space_check_interval 1 \
205- disk_almost_full_threshold 1"
206-ERL_START_OPTIONS="$ERL_OS_MON_OPTIONS -sasl errlog_type error +K true +A 4"
207-HEART_BEAT_TIMEOUT=11
208-HEART_COMMAND="%bindir%/%couchdb_command_name% -k"
209-INTERACTIVE=false
210-KILL=false
211-LOCAL_CONFIG_DIR=%localconfdir%/local.d
212-LOCAL_CONFIG_FILE=%localconfdir%/%localini%
213-PID_FILE=%localstatedir%/run/couchdb/couchdb.pid
214-RECURSED=false
215-RESET_CONFIG=true
216-RESPAWN_TIMEOUT=0
217-SCRIPT_ERROR=1
218-SCRIPT_OK=0
219-SHUTDOWN=false
220-STDERR_FILE=couchdb.stderr
221-STDOUT_FILE=couchdb.stdout
222-
223-print_arguments=""
224-start_arguments=""
225-background_start_arguments=""
226-
227-basename=`basename $0`
228-
229-display_version () {
230- cat << EOF
231-$basename - %package_name% %version%
232-
233-Licensed under the Apache License, Version 2.0 (the "License"); you may not use
234-this file except in compliance with the License. You may obtain a copy of the
235-License at
236-
237- http://www.apache.org/licenses/LICENSE-2.0
238-
239-Unless required by applicable law or agreed to in writing, software distributed
240-under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
241-CONDITIONS OF ANY KIND, either express or implied. See the License for the
242-specific language governing permissions and limitations under the License.
243-
244-EOF
245-}
246-
247-display_help () {
248- cat << EOF
249-Usage: $basename [OPTION]
250-
251-The $basename command runs the %package_name% server.
252-
253-Erlang is called with:
254-
255- $ERL_START_OPTIONS
256-
257-Erlang inherits the environment of this command.
258-
259-You can override these options using the environment:
260-
261- ERL_AFLAGS, ERL_FLAGS, ERL_ZFLAGS
262-
263-See erl(1) for more information about the environment variables.
264-
265-The exit status is 0 for success or 1 for failure.
266-
267-Options:
268-
269- -h display a short help message and exit
270- -V display version information and exit
271- -a FILE add configuration FILE to chain
272- -A DIR add configuration DIR to chain
273- -n reset configuration file chain (including system default)
274- -c print configuration file chain and exit
275- -i use the interactive Erlang shell
276- -b spawn as a background process
277- -p FILE set the background PID FILE (overrides system default)
278- -r SECONDS respawn background process after SECONDS (defaults to no respawn)
279- -o FILE redirect background stdout to FILE (defaults to $STDOUT_FILE)
280- -e FILE redirect background stderr to FILE (defaults to $STDERR_FILE)
281- -s display the status of the background process
282- -k kill the background process, will respawn if needed
283- -d shutdown the background process
284-
285-Report bugs at <%bug_uri%>.
286-EOF
287-}
288-
289-display_error () {
290- if test -n "$1"; then
291- echo $1 >&2
292- fi
293- echo >&2
294- echo "Try \`"$basename" -h' for more information." >&2
295- false
296-}
297-
298-_get_pid () {
299- if test -f $PID_FILE; then
300- PID=`cat $PID_FILE`
301- fi
302- echo $PID
303-}
304-
305-_add_config_file () {
306- if test -z "$print_arguments"; then
307- print_arguments="$1"
308- else
309- print_arguments="`cat <<EOF
310-$print_arguments
311-$1
312-EOF
313-`"
314- fi
315- start_arguments="$start_arguments $1"
316- background_start_arguments="$background_start_arguments -a $1"
317-}
318-
319-_add_config_dir () {
320- for file in "$1"/*.ini; do
321- if [ -r "$file" ]; then
322- _add_config_file "$file"
323- fi
324- done
325-}
326-
327-_load_config () {
328- _add_config_file "$DEFAULT_CONFIG_FILE"
329- _add_config_dir "$DEFAULT_CONFIG_DIR"
330- _add_config_file "$LOCAL_CONFIG_FILE"
331- _add_config_dir "$LOCAL_CONFIG_DIR"
332-}
333-
334-_reset_config () {
335- print_arguments=""
336- start_arguments=""
337- background_start_arguments="-n"
338-}
339-
340-_print_config () {
341- cat <<EOF
342-$print_arguments
343-EOF
344-}
345-
346-check_status () {
347- PID=`_get_pid`
348- if test -n "$PID"; then
349- if kill -0 $PID 2> /dev/null; then
350- echo "Apache CouchDB is running as process $PID, time to relax."
351- return $SCRIPT_OK
352- else
353- echo >&2 << EOF
354-Apache CouchDB is not running but a stale PID file exists: $PID_FILE
355-EOF
356- fi
357- else
358- echo "Apache CouchDB is not running." >&2
359- fi
360- return $SCRIPT_ERROR
361-}
362-
363-check_environment () {
364- if test "$BACKGROUND" != "true"; then
365- return
366- fi
367- touch $PID_FILE 2> /dev/null || true
368- touch $STDOUT_FILE 2> /dev/null || true
369- touch $STDERR_FILE 2> /dev/null || true
370- message_prefix="Apache CouchDB needs write permission on the"
371- if test ! -w $PID_FILE; then
372- echo "$message_prefix PID file: $PID_FILE" >&2
373- false
374- fi
375- if test ! -w $STDOUT_FILE; then
376- echo "$message_prefix STDOUT file: $STDOUT_FILE" >&2
377- false
378- fi
379- if test ! -w $STDERR_FILE; then
380- echo "$message_prefix STDERR file: $STDERR_FILE" >&2
381- false
382- fi
383- message_prefix="Apache CouchDB needs a regular"
384- if test `echo 2> /dev/null >> $PID_FILE; echo $?` -gt 0; then
385- echo "$message_prefix PID file: $PID_FILE" >&2
386- false
387- fi
388- if test `echo 2> /dev/null >> $STDOUT_FILE; echo $?` -gt 0; then
389- echo "$message_prefix STDOUT file: $STDOUT_FILE" >&2
390- false
391- fi
392- if test `echo 2> /dev/null >> $STDERR_FILE; echo $?` -gt 0; then
393- echo "$message_prefix STDERR file: $STDERR_FILE" >&2
394- false
395- fi
396-}
397-
398-start_couchdb () {
399- if test ! "$RECURSED" = "true"; then
400- if check_status 2> /dev/null; then
401- exit
402- fi
403- check_environment
404- fi
405- interactive_option="+Bd -noinput"
406- if test "$INTERACTIVE" = "true"; then
407- interactive_option=""
408- fi
409- if test "$BACKGROUND" = "true"; then
410- touch $PID_FILE
411- interactive_option="+Bd -noinput"
412- fi
413- command="%ERL% $interactive_option $ERL_START_OPTIONS \
414- -env ERL_LIBS %localerlanglibdir% -couch_ini $start_arguments -s couch"
415- if test "$BACKGROUND" = "true" -a "$RECURSED" = "false"; then
416- $0 $background_start_arguments -b -r $RESPAWN_TIMEOUT -p $PID_FILE \
417- -o $STDOUT_FILE -e $STDERR_FILE -R &
418- echo "Apache CouchDB has started, time to relax."
419- else
420- if test "$RECURSED" = "true"; then
421- while true; do
422- export HEART_COMMAND
423- export HEART_BEAT_TIMEOUT
424- `eval $command -pidfile $PID_FILE -heart \
425- >> $STDOUT_FILE 2>> $STDERR_FILE` || true
426- PID=`_get_pid`
427- if test -n "$PID"; then
428- if kill -0 $PID 2> /dev/null; then
429- return $SCRIPT_ERROR
430- fi
431- else
432- return $SCRIPT_OK
433- fi
434- if test "$RESPAWN_TIMEOUT" = "0"; then
435- return $SCRIPT_OK
436- fi
437- if test "$RESPAWN_TIMEOUT" != "1"; then
438- plural_ending="s"
439- fi
440- cat << EOF
441-Apache CouchDB crashed, restarting in $RESPAWN_TIMEOUT second$plural_ending.
442-EOF
443- sleep $RESPAWN_TIMEOUT
444- done
445- else
446- eval exec $command
447- fi
448- fi
449-}
450-
451-stop_couchdb () {
452- PID=`_get_pid`
453- if test -n "$PID"; then
454- if test "$1" = "false"; then
455- echo > $PID_FILE
456- fi
457- if kill -0 $PID 2> /dev/null; then
458- if kill -1 $PID 2> /dev/null; then
459- if test "$1" = "false"; then
460- echo "Apache CouchDB has been shutdown."
461- else
462- echo "Apache CouchDB has been killed."
463- fi
464- return $SCRIPT_OK
465- else
466- echo "Apache CouchDB could not be killed." >&2
467- return $SCRIPT_ERROR
468- fi
469- if test "$1" = "false"; then
470- echo "Stale PID file exists but Apache CouchDB is not running."
471- else
472- echo "Stale PID file existed but Apache CouchDB is not running."
473- fi
474- fi
475- else
476- echo "Apache CouchDB is not running."
477- fi
478-}
479-
480-parse_script_option_list () {
481- _load_config
482- set +e
483- options=`getopt hVa:A:ncibp:r:Ro:e:skd $@`
484- if test ! $? -eq 0; then
485- display_error
486- fi
487- set -e
488- eval set -- $options
489- while [ $# -gt 0 ]; do
490- case "$1" in
491- -h) shift; display_help; exit;;
492- -V) shift; display_version; exit;;
493- -a) shift; _add_config_file "$1"; shift;;
494- -A) shift; _add_config_dir "$1"; shift;;
495- -n) shift; _reset_config;;
496- -c) shift; _print_config; exit;;
497- -i) shift; INTERACTIVE=true;;
498- -b) shift; BACKGROUND=true;;
499- -r) shift; RESPAWN_TIMEOUT=$1; shift;;
500- -R) shift; RECURSED=true;;
501- -p) shift; PID_FILE=$1; shift;;
502- -o) shift; STDOUT_FILE=$1; shift;;
503- -e) shift; STDERR_FILE=$1; shift;;
504- -s) shift; check_status; exit;;
505- -k) shift; KILL=true;;
506- -d) shift; SHUTDOWN=true;;
507- --) shift; break;;
508- *) display_error "Unknown option: $1" >&2;;
509- esac
510- done
511- if test "$KILL" = "true" -o "$SHUTDOWN" = "true"; then
512- stop_couchdb $KILL
513- else
514- start_couchdb
515- fi
516-}
517-
518-parse_script_option_list $@
519
520=== removed directory '.pc/force-reload.patch'
521=== removed directory '.pc/force-reload.patch/etc'
522=== removed directory '.pc/force-reload.patch/etc/init'
523=== removed file '.pc/force-reload.patch/etc/init/couchdb.tpl.in'
524--- .pc/force-reload.patch/etc/init/couchdb.tpl.in 2012-04-10 21:14:05 +0000
525+++ .pc/force-reload.patch/etc/init/couchdb.tpl.in 1970-01-01 00:00:00 +0000
526@@ -1,156 +0,0 @@
527-#!/bin/sh -e
528-
529-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
530-# use this file except in compliance with the License. You may obtain a copy of
531-# the License at
532-#
533-# http://www.apache.org/licenses/LICENSE-2.0
534-#
535-# Unless required by applicable law or agreed to in writing, software
536-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
537-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
538-# License for the specific language governing permissions and limitations under
539-# the License.
540-
541-### BEGIN INIT INFO
542-# Provides: couchdb
543-# Required-Start: $local_fs $remote_fs
544-# Required-Stop: $local_fs $remote_fs
545-# Default-Start: 2 3 4 5
546-# Default-Stop: 0 1 6
547-# Short-Description: Apache CouchDB init script
548-# Description: Apache CouchDB init script for the database server.
549-### END INIT INFO
550-
551-SCRIPT_OK=0
552-SCRIPT_ERROR=1
553-
554-DESCRIPTION="database server"
555-NAME=couchdb
556-SCRIPT_NAME=`basename $0`
557-COUCHDB=%bindir%/%couchdb_command_name%
558-CONFIGURATION_FILE=%sysconfdir%/default/couchdb
559-RUN_DIR=%localstaterundir%
560-LSB_LIBRARY=/lib/lsb/init-functions
561-
562-if test ! -x $COUCHDB; then
563- exit $SCRIPT_ERROR
564-fi
565-
566-if test -r $CONFIGURATION_FILE; then
567- . $CONFIGURATION_FILE
568-fi
569-
570-log_daemon_msg () {
571- # Dummy function to be replaced by LSB library.
572-
573- echo $@
574-}
575-
576-log_end_msg () {
577- # Dummy function to be replaced by LSB library.
578-
579- if test "$1" != "0"; then
580- echo "Error with $DESCRIPTION: $NAME"
581- fi
582- return $1
583-}
584-
585-if test -r $LSB_LIBRARY; then
586- . $LSB_LIBRARY
587-fi
588-
589-run_command () {
590- command="$1"
591- if test -n "$COUCHDB_OPTIONS"; then
592- command="$command $COUCHDB_OPTIONS"
593- fi
594- if test -n "$COUCHDB_USER"; then
595- if su $COUCHDB_USER -c "$command"; then
596- return $SCRIPT_OK
597- else
598- return $SCRIPT_ERROR
599- fi
600- else
601- if $command; then
602- return $SCRIPT_OK
603- else
604- return $SCRIPT_ERROR
605- fi
606- fi
607-}
608-
609-start_couchdb () {
610- # Start Apache CouchDB as a background process.
611-
612- mkdir -p "$RUN_DIR"
613- command="$COUCHDB -b"
614- if test -n "$COUCHDB_STDOUT_FILE"; then
615- command="$command -o $COUCHDB_STDOUT_FILE"
616- fi
617- if test -n "$COUCHDB_STDERR_FILE"; then
618- command="$command -e $COUCHDB_STDERR_FILE"
619- fi
620- if test -n "$COUCHDB_RESPAWN_TIMEOUT"; then
621- command="$command -r $COUCHDB_RESPAWN_TIMEOUT"
622- fi
623- run_command "$command" > /dev/null
624-}
625-
626-stop_couchdb () {
627- # Stop the running Apache CouchDB process.
628-
629- run_command "$COUCHDB -d" > /dev/null
630-}
631-
632-display_status () {
633- # Display the status of the running Apache CouchDB process.
634-
635- run_command "$COUCHDB -s"
636-}
637-
638-parse_script_option_list () {
639- # Parse arguments passed to the script and take appropriate action.
640-
641- case "$1" in
642- start)
643- log_daemon_msg "Starting $DESCRIPTION" $NAME
644- if start_couchdb; then
645- log_end_msg $SCRIPT_OK
646- else
647- log_end_msg $SCRIPT_ERROR
648- fi
649- ;;
650- stop)
651- log_daemon_msg "Stopping $DESCRIPTION" $NAME
652- if stop_couchdb; then
653- log_end_msg $SCRIPT_OK
654- else
655- log_end_msg $SCRIPT_ERROR
656- fi
657- ;;
658- restart)
659- log_daemon_msg "Restarting $DESCRIPTION" $NAME
660- if stop_couchdb; then
661- if start_couchdb; then
662- log_end_msg $SCRIPT_OK
663- else
664- log_end_msg $SCRIPT_ERROR
665- fi
666- else
667- log_end_msg $SCRIPT_ERROR
668- fi
669- ;;
670- status)
671- display_status
672- ;;
673- *)
674- cat << EOF >&2
675-Usage: $SCRIPT_NAME {start|stop|restart|status}
676-EOF
677- exit $SCRIPT_ERROR
678- ;;
679- esac
680-}
681-
682-parse_script_option_list $@
683
684=== removed directory '.pc/improve_parsing_of_mochiweb_relative_paths.patch'
685=== removed directory '.pc/improve_parsing_of_mochiweb_relative_paths.patch/src'
686=== removed directory '.pc/improve_parsing_of_mochiweb_relative_paths.patch/src/mochiweb'
687=== removed file '.pc/improve_parsing_of_mochiweb_relative_paths.patch/src/mochiweb/mochiweb_util.erl'
688--- .pc/improve_parsing_of_mochiweb_relative_paths.patch/src/mochiweb/mochiweb_util.erl 2013-01-18 22:04:32 +0000
689+++ .pc/improve_parsing_of_mochiweb_relative_paths.patch/src/mochiweb/mochiweb_util.erl 1970-01-01 00:00:00 +0000
690@@ -1,973 +0,0 @@
691-%% @author Bob Ippolito <bob@mochimedia.com>
692-%% @copyright 2007 Mochi Media, Inc.
693-
694-%% @doc Utilities for parsing and quoting.
695-
696--module(mochiweb_util).
697--author('bob@mochimedia.com').
698--export([join/2, quote_plus/1, urlencode/1, parse_qs/1, unquote/1]).
699--export([path_split/1]).
700--export([urlsplit/1, urlsplit_path/1, urlunsplit/1, urlunsplit_path/1]).
701--export([guess_mime/1, parse_header/1]).
702--export([shell_quote/1, cmd/1, cmd_string/1, cmd_port/2, cmd_status/1]).
703--export([record_to_proplist/2, record_to_proplist/3]).
704--export([safe_relative_path/1, partition/2]).
705--export([parse_qvalues/1, pick_accepted_encodings/3]).
706--export([make_io/1]).
707-
708--define(PERCENT, 37). % $\%
709--define(FULLSTOP, 46). % $\.
710--define(IS_HEX(C), ((C >= $0 andalso C =< $9) orelse
711- (C >= $a andalso C =< $f) orelse
712- (C >= $A andalso C =< $F))).
713--define(QS_SAFE(C), ((C >= $a andalso C =< $z) orelse
714- (C >= $A andalso C =< $Z) orelse
715- (C >= $0 andalso C =< $9) orelse
716- (C =:= ?FULLSTOP orelse C =:= $- orelse C =:= $~ orelse
717- C =:= $_))).
718-
719-hexdigit(C) when C < 10 -> $0 + C;
720-hexdigit(C) when C < 16 -> $A + (C - 10).
721-
722-unhexdigit(C) when C >= $0, C =< $9 -> C - $0;
723-unhexdigit(C) when C >= $a, C =< $f -> C - $a + 10;
724-unhexdigit(C) when C >= $A, C =< $F -> C - $A + 10.
725-
726-%% @spec partition(String, Sep) -> {String, [], []} | {Prefix, Sep, Postfix}
727-%% @doc Inspired by Python 2.5's str.partition:
728-%% partition("foo/bar", "/") = {"foo", "/", "bar"},
729-%% partition("foo", "/") = {"foo", "", ""}.
730-partition(String, Sep) ->
731- case partition(String, Sep, []) of
732- undefined ->
733- {String, "", ""};
734- Result ->
735- Result
736- end.
737-
738-partition("", _Sep, _Acc) ->
739- undefined;
740-partition(S, Sep, Acc) ->
741- case partition2(S, Sep) of
742- undefined ->
743- [C | Rest] = S,
744- partition(Rest, Sep, [C | Acc]);
745- Rest ->
746- {lists:reverse(Acc), Sep, Rest}
747- end.
748-
749-partition2(Rest, "") ->
750- Rest;
751-partition2([C | R1], [C | R2]) ->
752- partition2(R1, R2);
753-partition2(_S, _Sep) ->
754- undefined.
755-
756-
757-
758-%% @spec safe_relative_path(string()) -> string() | undefined
759-%% @doc Return the reduced version of a relative path or undefined if it
760-%% is not safe. safe relative paths can be joined with an absolute path
761-%% and will result in a subdirectory of the absolute path.
762-safe_relative_path("/" ++ _) ->
763- undefined;
764-safe_relative_path(P) ->
765- safe_relative_path(P, []).
766-
767-safe_relative_path("", Acc) ->
768- case Acc of
769- [] ->
770- "";
771- _ ->
772- string:join(lists:reverse(Acc), "/")
773- end;
774-safe_relative_path(P, Acc) ->
775- case partition(P, "/") of
776- {"", "/", _} ->
777- %% /foo or foo//bar
778- undefined;
779- {"..", _, _} when Acc =:= [] ->
780- undefined;
781- {"..", _, Rest} ->
782- safe_relative_path(Rest, tl(Acc));
783- {Part, "/", ""} ->
784- safe_relative_path("", ["", Part | Acc]);
785- {Part, _, Rest} ->
786- safe_relative_path(Rest, [Part | Acc])
787- end.
788-
789-%% @spec shell_quote(string()) -> string()
790-%% @doc Quote a string according to UNIX shell quoting rules, returns a string
791-%% surrounded by double quotes.
792-shell_quote(L) ->
793- shell_quote(L, [$\"]).
794-
795-%% @spec cmd_port([string()], Options) -> port()
796-%% @doc open_port({spawn, mochiweb_util:cmd_string(Argv)}, Options).
797-cmd_port(Argv, Options) ->
798- open_port({spawn, cmd_string(Argv)}, Options).
799-
800-%% @spec cmd([string()]) -> string()
801-%% @doc os:cmd(cmd_string(Argv)).
802-cmd(Argv) ->
803- os:cmd(cmd_string(Argv)).
804-
805-%% @spec cmd_string([string()]) -> string()
806-%% @doc Create a shell quoted command string from a list of arguments.
807-cmd_string(Argv) ->
808- string:join([shell_quote(X) || X <- Argv], " ").
809-
810-%% @spec cmd_status([string()]) -> {ExitStatus::integer(), Stdout::binary()}
811-%% @doc Accumulate the output and exit status from the given application, will be
812-%% spawned with cmd_port/2.
813-cmd_status(Argv) ->
814- Port = cmd_port(Argv, [exit_status, stderr_to_stdout,
815- use_stdio, binary]),
816- try cmd_loop(Port, [])
817- after catch port_close(Port)
818- end.
819-
820-%% @spec cmd_loop(port(), list()) -> {ExitStatus::integer(), Stdout::binary()}
821-%% @doc Accumulate the output and exit status from a port.
822-cmd_loop(Port, Acc) ->
823- receive
824- {Port, {exit_status, Status}} ->
825- {Status, iolist_to_binary(lists:reverse(Acc))};
826- {Port, {data, Data}} ->
827- cmd_loop(Port, [Data | Acc])
828- end.
829-
830-%% @spec join([iolist()], iolist()) -> iolist()
831-%% @doc Join a list of strings or binaries together with the given separator
832-%% string or char or binary. The output is flattened, but may be an
833-%% iolist() instead of a string() if any of the inputs are binary().
834-join([], _Separator) ->
835- [];
836-join([S], _Separator) ->
837- lists:flatten(S);
838-join(Strings, Separator) ->
839- lists:flatten(revjoin(lists:reverse(Strings), Separator, [])).
840-
841-revjoin([], _Separator, Acc) ->
842- Acc;
843-revjoin([S | Rest], Separator, []) ->
844- revjoin(Rest, Separator, [S]);
845-revjoin([S | Rest], Separator, Acc) ->
846- revjoin(Rest, Separator, [S, Separator | Acc]).
847-
848-%% @spec quote_plus(atom() | integer() | float() | string() | binary()) -> string()
849-%% @doc URL safe encoding of the given term.
850-quote_plus(Atom) when is_atom(Atom) ->
851- quote_plus(atom_to_list(Atom));
852-quote_plus(Int) when is_integer(Int) ->
853- quote_plus(integer_to_list(Int));
854-quote_plus(Binary) when is_binary(Binary) ->
855- quote_plus(binary_to_list(Binary));
856-quote_plus(Float) when is_float(Float) ->
857- quote_plus(mochinum:digits(Float));
858-quote_plus(String) ->
859- quote_plus(String, []).
860-
861-quote_plus([], Acc) ->
862- lists:reverse(Acc);
863-quote_plus([C | Rest], Acc) when ?QS_SAFE(C) ->
864- quote_plus(Rest, [C | Acc]);
865-quote_plus([$\s | Rest], Acc) ->
866- quote_plus(Rest, [$+ | Acc]);
867-quote_plus([C | Rest], Acc) ->
868- <<Hi:4, Lo:4>> = <<C>>,
869- quote_plus(Rest, [hexdigit(Lo), hexdigit(Hi), ?PERCENT | Acc]).
870-
871-%% @spec urlencode([{Key, Value}]) -> string()
872-%% @doc URL encode the property list.
873-urlencode(Props) ->
874- Pairs = lists:foldr(
875- fun ({K, V}, Acc) ->
876- [quote_plus(K) ++ "=" ++ quote_plus(V) | Acc]
877- end, [], Props),
878- string:join(Pairs, "&").
879-
880-%% @spec parse_qs(string() | binary()) -> [{Key, Value}]
881-%% @doc Parse a query string or application/x-www-form-urlencoded.
882-parse_qs(Binary) when is_binary(Binary) ->
883- parse_qs(binary_to_list(Binary));
884-parse_qs(String) ->
885- parse_qs(String, []).
886-
887-parse_qs([], Acc) ->
888- lists:reverse(Acc);
889-parse_qs(String, Acc) ->
890- {Key, Rest} = parse_qs_key(String),
891- {Value, Rest1} = parse_qs_value(Rest),
892- parse_qs(Rest1, [{Key, Value} | Acc]).
893-
894-parse_qs_key(String) ->
895- parse_qs_key(String, []).
896-
897-parse_qs_key([], Acc) ->
898- {qs_revdecode(Acc), ""};
899-parse_qs_key([$= | Rest], Acc) ->
900- {qs_revdecode(Acc), Rest};
901-parse_qs_key(Rest=[$; | _], Acc) ->
902- {qs_revdecode(Acc), Rest};
903-parse_qs_key(Rest=[$& | _], Acc) ->
904- {qs_revdecode(Acc), Rest};
905-parse_qs_key([C | Rest], Acc) ->
906- parse_qs_key(Rest, [C | Acc]).
907-
908-parse_qs_value(String) ->
909- parse_qs_value(String, []).
910-
911-parse_qs_value([], Acc) ->
912- {qs_revdecode(Acc), ""};
913-parse_qs_value([$; | Rest], Acc) ->
914- {qs_revdecode(Acc), Rest};
915-parse_qs_value([$& | Rest], Acc) ->
916- {qs_revdecode(Acc), Rest};
917-parse_qs_value([C | Rest], Acc) ->
918- parse_qs_value(Rest, [C | Acc]).
919-
920-%% @spec unquote(string() | binary()) -> string()
921-%% @doc Unquote a URL encoded string.
922-unquote(Binary) when is_binary(Binary) ->
923- unquote(binary_to_list(Binary));
924-unquote(String) ->
925- qs_revdecode(lists:reverse(String)).
926-
927-qs_revdecode(S) ->
928- qs_revdecode(S, []).
929-
930-qs_revdecode([], Acc) ->
931- Acc;
932-qs_revdecode([$+ | Rest], Acc) ->
933- qs_revdecode(Rest, [$\s | Acc]);
934-qs_revdecode([Lo, Hi, ?PERCENT | Rest], Acc) when ?IS_HEX(Lo), ?IS_HEX(Hi) ->
935- qs_revdecode(Rest, [(unhexdigit(Lo) bor (unhexdigit(Hi) bsl 4)) | Acc]);
936-qs_revdecode([C | Rest], Acc) ->
937- qs_revdecode(Rest, [C | Acc]).
938-
939-%% @spec urlsplit(Url) -> {Scheme, Netloc, Path, Query, Fragment}
940-%% @doc Return a 5-tuple, does not expand % escapes. Only supports HTTP style
941-%% URLs.
942-urlsplit(Url) ->
943- {Scheme, Url1} = urlsplit_scheme(Url),
944- {Netloc, Url2} = urlsplit_netloc(Url1),
945- {Path, Query, Fragment} = urlsplit_path(Url2),
946- {Scheme, Netloc, Path, Query, Fragment}.
947-
948-urlsplit_scheme(Url) ->
949- case urlsplit_scheme(Url, []) of
950- no_scheme ->
951- {"", Url};
952- Res ->
953- Res
954- end.
955-
956-urlsplit_scheme([C | Rest], Acc) when ((C >= $a andalso C =< $z) orelse
957- (C >= $A andalso C =< $Z) orelse
958- (C >= $0 andalso C =< $9) orelse
959- C =:= $+ orelse C =:= $- orelse
960- C =:= $.) ->
961- urlsplit_scheme(Rest, [C | Acc]);
962-urlsplit_scheme([$: | Rest], Acc=[_ | _]) ->
963- {string:to_lower(lists:reverse(Acc)), Rest};
964-urlsplit_scheme(_Rest, _Acc) ->
965- no_scheme.
966-
967-urlsplit_netloc("//" ++ Rest) ->
968- urlsplit_netloc(Rest, []);
969-urlsplit_netloc(Path) ->
970- {"", Path}.
971-
972-urlsplit_netloc("", Acc) ->
973- {lists:reverse(Acc), ""};
974-urlsplit_netloc(Rest=[C | _], Acc) when C =:= $/; C =:= $?; C =:= $# ->
975- {lists:reverse(Acc), Rest};
976-urlsplit_netloc([C | Rest], Acc) ->
977- urlsplit_netloc(Rest, [C | Acc]).
978-
979-
980-%% @spec path_split(string()) -> {Part, Rest}
981-%% @doc Split a path starting from the left, as in URL traversal.
982-%% path_split("foo/bar") = {"foo", "bar"},
983-%% path_split("/foo/bar") = {"", "foo/bar"}.
984-path_split(S) ->
985- path_split(S, []).
986-
987-path_split("", Acc) ->
988- {lists:reverse(Acc), ""};
989-path_split("/" ++ Rest, Acc) ->
990- {lists:reverse(Acc), Rest};
991-path_split([C | Rest], Acc) ->
992- path_split(Rest, [C | Acc]).
993-
994-
995-%% @spec urlunsplit({Scheme, Netloc, Path, Query, Fragment}) -> string()
996-%% @doc Assemble a URL from the 5-tuple. Path must be absolute.
997-urlunsplit({Scheme, Netloc, Path, Query, Fragment}) ->
998- lists:flatten([case Scheme of "" -> ""; _ -> [Scheme, "://"] end,
999- Netloc,
1000- urlunsplit_path({Path, Query, Fragment})]).
1001-
1002-%% @spec urlunsplit_path({Path, Query, Fragment}) -> string()
1003-%% @doc Assemble a URL path from the 3-tuple.
1004-urlunsplit_path({Path, Query, Fragment}) ->
1005- lists:flatten([Path,
1006- case Query of "" -> ""; _ -> [$? | Query] end,
1007- case Fragment of "" -> ""; _ -> [$# | Fragment] end]).
1008-
1009-%% @spec urlsplit_path(Url) -> {Path, Query, Fragment}
1010-%% @doc Return a 3-tuple, does not expand % escapes. Only supports HTTP style
1011-%% paths.
1012-urlsplit_path(Path) ->
1013- urlsplit_path(Path, []).
1014-
1015-urlsplit_path("", Acc) ->
1016- {lists:reverse(Acc), "", ""};
1017-urlsplit_path("?" ++ Rest, Acc) ->
1018- {Query, Fragment} = urlsplit_query(Rest),
1019- {lists:reverse(Acc), Query, Fragment};
1020-urlsplit_path("#" ++ Rest, Acc) ->
1021- {lists:reverse(Acc), "", Rest};
1022-urlsplit_path([C | Rest], Acc) ->
1023- urlsplit_path(Rest, [C | Acc]).
1024-
1025-urlsplit_query(Query) ->
1026- urlsplit_query(Query, []).
1027-
1028-urlsplit_query("", Acc) ->
1029- {lists:reverse(Acc), ""};
1030-urlsplit_query("#" ++ Rest, Acc) ->
1031- {lists:reverse(Acc), Rest};
1032-urlsplit_query([C | Rest], Acc) ->
1033- urlsplit_query(Rest, [C | Acc]).
1034-
1035-%% @spec guess_mime(string()) -> string()
1036-%% @doc Guess the mime type of a file by the extension of its filename.
1037-guess_mime(File) ->
1038- case mochiweb_mime:from_extension(filename:extension(File)) of
1039- undefined ->
1040- "text/plain";
1041- Mime ->
1042- Mime
1043- end.
1044-
1045-%% @spec parse_header(string()) -> {Type, [{K, V}]}
1046-%% @doc Parse a Content-Type like header, return the main Content-Type
1047-%% and a property list of options.
1048-parse_header(String) ->
1049- %% TODO: This is exactly as broken as Python's cgi module.
1050- %% Should parse properly like mochiweb_cookies.
1051- [Type | Parts] = [string:strip(S) || S <- string:tokens(String, ";")],
1052- F = fun (S, Acc) ->
1053- case lists:splitwith(fun (C) -> C =/= $= end, S) of
1054- {"", _} ->
1055- %% Skip anything with no name
1056- Acc;
1057- {_, ""} ->
1058- %% Skip anything with no value
1059- Acc;
1060- {Name, [$\= | Value]} ->
1061- [{string:to_lower(string:strip(Name)),
1062- unquote_header(string:strip(Value))} | Acc]
1063- end
1064- end,
1065- {string:to_lower(Type),
1066- lists:foldr(F, [], Parts)}.
1067-
1068-unquote_header("\"" ++ Rest) ->
1069- unquote_header(Rest, []);
1070-unquote_header(S) ->
1071- S.
1072-
1073-unquote_header("", Acc) ->
1074- lists:reverse(Acc);
1075-unquote_header("\"", Acc) ->
1076- lists:reverse(Acc);
1077-unquote_header([$\\, C | Rest], Acc) ->
1078- unquote_header(Rest, [C | Acc]);
1079-unquote_header([C | Rest], Acc) ->
1080- unquote_header(Rest, [C | Acc]).
1081-
1082-%% @spec record_to_proplist(Record, Fields) -> proplist()
1083-%% @doc calls record_to_proplist/3 with a default TypeKey of '__record'
1084-record_to_proplist(Record, Fields) ->
1085- record_to_proplist(Record, Fields, '__record').
1086-
1087-%% @spec record_to_proplist(Record, Fields, TypeKey) -> proplist()
1088-%% @doc Return a proplist of the given Record with each field in the
1089-%% Fields list set as a key with the corresponding value in the Record.
1090-%% TypeKey is the key that is used to store the record type
1091-%% Fields should be obtained by calling record_info(fields, record_type)
1092-%% where record_type is the record type of Record
1093-record_to_proplist(Record, Fields, TypeKey)
1094- when tuple_size(Record) - 1 =:= length(Fields) ->
1095- lists:zip([TypeKey | Fields], tuple_to_list(Record)).
1096-
1097-
1098-shell_quote([], Acc) ->
1099- lists:reverse([$\" | Acc]);
1100-shell_quote([C | Rest], Acc) when C =:= $\" orelse C =:= $\` orelse
1101- C =:= $\\ orelse C =:= $\$ ->
1102- shell_quote(Rest, [C, $\\ | Acc]);
1103-shell_quote([C | Rest], Acc) ->
1104- shell_quote(Rest, [C | Acc]).
1105-
1106-%% @spec parse_qvalues(string()) -> [qvalue()] | invalid_qvalue_string
1107-%% @type qvalue() = {media_type() | encoding() , float()}.
1108-%% @type media_type() = string().
1109-%% @type encoding() = string().
1110-%%
1111-%% @doc Parses a list (given as a string) of elements with Q values associated
1112-%% to them. Elements are separated by commas and each element is separated
1113-%% from its Q value by a semicolon. Q values are optional but when missing
1114-%% the value of an element is considered as 1.0. A Q value is always in the
1115-%% range [0.0, 1.0]. A Q value list is used for example as the value of the
1116-%% HTTP "Accept" and "Accept-Encoding" headers.
1117-%%
1118-%% Q values are described in section 2.9 of the RFC 2616 (HTTP 1.1).
1119-%%
1120-%% Example:
1121-%%
1122-%% parse_qvalues("gzip; q=0.5, deflate, identity;q=0.0") ->
1123-%% [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 0.0}]
1124-%%
1125-parse_qvalues(QValuesStr) ->
1126- try
1127- lists:map(
1128- fun(Pair) ->
1129- [Type | Params] = string:tokens(Pair, ";"),
1130- NormParams = normalize_media_params(Params),
1131- {Q, NonQParams} = extract_q(NormParams),
1132- {string:join([string:strip(Type) | NonQParams], ";"), Q}
1133- end,
1134- string:tokens(string:to_lower(QValuesStr), ",")
1135- )
1136- catch
1137- _Type:_Error ->
1138- invalid_qvalue_string
1139- end.
1140-
1141-normalize_media_params(Params) ->
1142- {ok, Re} = re:compile("\\s"),
1143- normalize_media_params(Re, Params, []).
1144-
1145-normalize_media_params(_Re, [], Acc) ->
1146- lists:reverse(Acc);
1147-normalize_media_params(Re, [Param | Rest], Acc) ->
1148- NormParam = re:replace(Param, Re, "", [global, {return, list}]),
1149- normalize_media_params(Re, Rest, [NormParam | Acc]).
1150-
1151-extract_q(NormParams) ->
1152- {ok, KVRe} = re:compile("^([^=]+)=([^=]+)$"),
1153- {ok, QRe} = re:compile("^((?:0|1)(?:\\.\\d{1,3})?)$"),
1154- extract_q(KVRe, QRe, NormParams, []).
1155-
1156-extract_q(_KVRe, _QRe, [], Acc) ->
1157- {1.0, lists:reverse(Acc)};
1158-extract_q(KVRe, QRe, [Param | Rest], Acc) ->
1159- case re:run(Param, KVRe, [{capture, [1, 2], list}]) of
1160- {match, [Name, Value]} ->
1161- case Name of
1162- "q" ->
1163- {match, [Q]} = re:run(Value, QRe, [{capture, [1], list}]),
1164- QVal = case Q of
1165- "0" ->
1166- 0.0;
1167- "1" ->
1168- 1.0;
1169- Else ->
1170- list_to_float(Else)
1171- end,
1172- case QVal < 0.0 orelse QVal > 1.0 of
1173- false ->
1174- {QVal, lists:reverse(Acc) ++ Rest}
1175- end;
1176- _ ->
1177- extract_q(KVRe, QRe, Rest, [Param | Acc])
1178- end
1179- end.
1180-
1181-%% @spec pick_accepted_encodings([qvalue()], [encoding()], encoding()) ->
1182-%% [encoding()]
1183-%%
1184-%% @doc Determines which encodings specified in the given Q values list are
1185-%% valid according to a list of supported encodings and a default encoding.
1186-%%
1187-%% The returned list of encodings is sorted, descendingly, according to the
1188-%% Q values of the given list. The last element of this list is the given
1189-%% default encoding unless this encoding is explicitily or implicitily
1190-%% marked with a Q value of 0.0 in the given Q values list.
1191-%% Note: encodings with the same Q value are kept in the same order as
1192-%% found in the input Q values list.
1193-%%
1194-%% This encoding picking process is described in section 14.3 of the
1195-%% RFC 2616 (HTTP 1.1).
1196-%%
1197-%% Example:
1198-%%
1199-%% pick_accepted_encodings(
1200-%% [{"gzip", 0.5}, {"deflate", 1.0}],
1201-%% ["gzip", "identity"],
1202-%% "identity"
1203-%% ) ->
1204-%% ["gzip", "identity"]
1205-%%
1206-pick_accepted_encodings(AcceptedEncs, SupportedEncs, DefaultEnc) ->
1207- SortedQList = lists:reverse(
1208- lists:sort(fun({_, Q1}, {_, Q2}) -> Q1 < Q2 end, AcceptedEncs)
1209- ),
1210- {Accepted, Refused} = lists:foldr(
1211- fun({E, Q}, {A, R}) ->
1212- case Q > 0.0 of
1213- true ->
1214- {[E | A], R};
1215- false ->
1216- {A, [E | R]}
1217- end
1218- end,
1219- {[], []},
1220- SortedQList
1221- ),
1222- Refused1 = lists:foldr(
1223- fun(Enc, Acc) ->
1224- case Enc of
1225- "*" ->
1226- lists:subtract(SupportedEncs, Accepted) ++ Acc;
1227- _ ->
1228- [Enc | Acc]
1229- end
1230- end,
1231- [],
1232- Refused
1233- ),
1234- Accepted1 = lists:foldr(
1235- fun(Enc, Acc) ->
1236- case Enc of
1237- "*" ->
1238- lists:subtract(SupportedEncs, Accepted ++ Refused1) ++ Acc;
1239- _ ->
1240- [Enc | Acc]
1241- end
1242- end,
1243- [],
1244- Accepted
1245- ),
1246- Accepted2 = case lists:member(DefaultEnc, Accepted1) of
1247- true ->
1248- Accepted1;
1249- false ->
1250- Accepted1 ++ [DefaultEnc]
1251- end,
1252- [E || E <- Accepted2, lists:member(E, SupportedEncs),
1253- not lists:member(E, Refused1)].
1254-
1255-make_io(Atom) when is_atom(Atom) ->
1256- atom_to_list(Atom);
1257-make_io(Integer) when is_integer(Integer) ->
1258- integer_to_list(Integer);
1259-make_io(Io) when is_list(Io); is_binary(Io) ->
1260- Io.
1261-
1262-%%
1263-%% Tests
1264-%%
1265--include_lib("eunit/include/eunit.hrl").
1266--ifdef(TEST).
1267-
1268-make_io_test() ->
1269- ?assertEqual(
1270- <<"atom">>,
1271- iolist_to_binary(make_io(atom))),
1272- ?assertEqual(
1273- <<"20">>,
1274- iolist_to_binary(make_io(20))),
1275- ?assertEqual(
1276- <<"list">>,
1277- iolist_to_binary(make_io("list"))),
1278- ?assertEqual(
1279- <<"binary">>,
1280- iolist_to_binary(make_io(<<"binary">>))),
1281- ok.
1282-
1283--record(test_record, {field1=f1, field2=f2}).
1284-record_to_proplist_test() ->
1285- ?assertEqual(
1286- [{'__record', test_record},
1287- {field1, f1},
1288- {field2, f2}],
1289- record_to_proplist(#test_record{}, record_info(fields, test_record))),
1290- ?assertEqual(
1291- [{'typekey', test_record},
1292- {field1, f1},
1293- {field2, f2}],
1294- record_to_proplist(#test_record{},
1295- record_info(fields, test_record),
1296- typekey)),
1297- ok.
1298-
1299-shell_quote_test() ->
1300- ?assertEqual(
1301- "\"foo \\$bar\\\"\\`' baz\"",
1302- shell_quote("foo $bar\"`' baz")),
1303- ok.
1304-
1305-cmd_port_test_spool(Port, Acc) ->
1306- receive
1307- {Port, eof} ->
1308- Acc;
1309- {Port, {data, {eol, Data}}} ->
1310- cmd_port_test_spool(Port, ["\n", Data | Acc]);
1311- {Port, Unknown} ->
1312- throw({unknown, Unknown})
1313- after 1000 ->
1314- throw(timeout)
1315- end.
1316-
1317-cmd_port_test() ->
1318- Port = cmd_port(["echo", "$bling$ `word`!"],
1319- [eof, stream, {line, 4096}]),
1320- Res = try lists:append(lists:reverse(cmd_port_test_spool(Port, [])))
1321- after catch port_close(Port)
1322- end,
1323- self() ! {Port, wtf},
1324- try cmd_port_test_spool(Port, [])
1325- catch throw:{unknown, wtf} -> ok
1326- end,
1327- try cmd_port_test_spool(Port, [])
1328- catch throw:timeout -> ok
1329- end,
1330- ?assertEqual(
1331- "$bling$ `word`!\n",
1332- Res).
1333-
1334-cmd_test() ->
1335- ?assertEqual(
1336- "$bling$ `word`!\n",
1337- cmd(["echo", "$bling$ `word`!"])),
1338- ok.
1339-
1340-cmd_string_test() ->
1341- ?assertEqual(
1342- "\"echo\" \"\\$bling\\$ \\`word\\`!\"",
1343- cmd_string(["echo", "$bling$ `word`!"])),
1344- ok.
1345-
1346-cmd_status_test() ->
1347- ?assertEqual(
1348- {0, <<"$bling$ `word`!\n">>},
1349- cmd_status(["echo", "$bling$ `word`!"])),
1350- ok.
1351-
1352-
1353-parse_header_test() ->
1354- ?assertEqual(
1355- {"multipart/form-data", [{"boundary", "AaB03x"}]},
1356- parse_header("multipart/form-data; boundary=AaB03x")),
1357- %% This tests (currently) intentionally broken behavior
1358- ?assertEqual(
1359- {"multipart/form-data",
1360- [{"b", ""},
1361- {"cgi", "is"},
1362- {"broken", "true\"e"}]},
1363- parse_header("multipart/form-data;b=;cgi=\"i\\s;broken=true\"e;=z;z")),
1364- ok.
1365-
1366-guess_mime_test() ->
1367- "text/plain" = guess_mime(""),
1368- "text/plain" = guess_mime(".text"),
1369- "application/zip" = guess_mime(".zip"),
1370- "application/zip" = guess_mime("x.zip"),
1371- "text/html" = guess_mime("x.html"),
1372- "application/xhtml+xml" = guess_mime("x.xhtml"),
1373- ok.
1374-
1375-path_split_test() ->
1376- {"", "foo/bar"} = path_split("/foo/bar"),
1377- {"foo", "bar"} = path_split("foo/bar"),
1378- {"bar", ""} = path_split("bar"),
1379- ok.
1380-
1381-urlsplit_test() ->
1382- {"", "", "/foo", "", "bar?baz"} = urlsplit("/foo#bar?baz"),
1383- {"http", "host:port", "/foo", "", "bar?baz"} =
1384- urlsplit("http://host:port/foo#bar?baz"),
1385- {"http", "host", "", "", ""} = urlsplit("http://host"),
1386- {"", "", "/wiki/Category:Fruit", "", ""} =
1387- urlsplit("/wiki/Category:Fruit"),
1388- ok.
1389-
1390-urlsplit_path_test() ->
1391- {"/foo/bar", "", ""} = urlsplit_path("/foo/bar"),
1392- {"/foo", "baz", ""} = urlsplit_path("/foo?baz"),
1393- {"/foo", "", "bar?baz"} = urlsplit_path("/foo#bar?baz"),
1394- {"/foo", "", "bar?baz#wibble"} = urlsplit_path("/foo#bar?baz#wibble"),
1395- {"/foo", "bar", "baz"} = urlsplit_path("/foo?bar#baz"),
1396- {"/foo", "bar?baz", "baz"} = urlsplit_path("/foo?bar?baz#baz"),
1397- ok.
1398-
1399-urlunsplit_test() ->
1400- "/foo#bar?baz" = urlunsplit({"", "", "/foo", "", "bar?baz"}),
1401- "http://host:port/foo#bar?baz" =
1402- urlunsplit({"http", "host:port", "/foo", "", "bar?baz"}),
1403- ok.
1404-
1405-urlunsplit_path_test() ->
1406- "/foo/bar" = urlunsplit_path({"/foo/bar", "", ""}),
1407- "/foo?baz" = urlunsplit_path({"/foo", "baz", ""}),
1408- "/foo#bar?baz" = urlunsplit_path({"/foo", "", "bar?baz"}),
1409- "/foo#bar?baz#wibble" = urlunsplit_path({"/foo", "", "bar?baz#wibble"}),
1410- "/foo?bar#baz" = urlunsplit_path({"/foo", "bar", "baz"}),
1411- "/foo?bar?baz#baz" = urlunsplit_path({"/foo", "bar?baz", "baz"}),
1412- ok.
1413-
1414-join_test() ->
1415- ?assertEqual("foo,bar,baz",
1416- join(["foo", "bar", "baz"], $,)),
1417- ?assertEqual("foo,bar,baz",
1418- join(["foo", "bar", "baz"], ",")),
1419- ?assertEqual("foo bar",
1420- join([["foo", " bar"]], ",")),
1421- ?assertEqual("foo bar,baz",
1422- join([["foo", " bar"], "baz"], ",")),
1423- ?assertEqual("foo",
1424- join(["foo"], ",")),
1425- ?assertEqual("foobarbaz",
1426- join(["foo", "bar", "baz"], "")),
1427- ?assertEqual("foo" ++ [<<>>] ++ "bar" ++ [<<>>] ++ "baz",
1428- join(["foo", "bar", "baz"], <<>>)),
1429- ?assertEqual("foobar" ++ [<<"baz">>],
1430- join(["foo", "bar", <<"baz">>], "")),
1431- ?assertEqual("",
1432- join([], "any")),
1433- ok.
1434-
1435-quote_plus_test() ->
1436- "foo" = quote_plus(foo),
1437- "1" = quote_plus(1),
1438- "1.1" = quote_plus(1.1),
1439- "foo" = quote_plus("foo"),
1440- "foo+bar" = quote_plus("foo bar"),
1441- "foo%0A" = quote_plus("foo\n"),
1442- "foo%0A" = quote_plus("foo\n"),
1443- "foo%3B%26%3D" = quote_plus("foo;&="),
1444- "foo%3B%26%3D" = quote_plus(<<"foo;&=">>),
1445- ok.
1446-
1447-unquote_test() ->
1448- ?assertEqual("foo bar",
1449- unquote("foo+bar")),
1450- ?assertEqual("foo bar",
1451- unquote("foo%20bar")),
1452- ?assertEqual("foo\r\n",
1453- unquote("foo%0D%0A")),
1454- ?assertEqual("foo\r\n",
1455- unquote(<<"foo%0D%0A">>)),
1456- ok.
1457-
1458-urlencode_test() ->
1459- "foo=bar&baz=wibble+%0D%0A&z=1" = urlencode([{foo, "bar"},
1460- {"baz", "wibble \r\n"},
1461- {z, 1}]),
1462- ok.
1463-
1464-parse_qs_test() ->
1465- ?assertEqual(
1466- [{"foo", "bar"}, {"baz", "wibble \r\n"}, {"z", "1"}],
1467- parse_qs("foo=bar&baz=wibble+%0D%0a&z=1")),
1468- ?assertEqual(
1469- [{"", "bar"}, {"baz", "wibble \r\n"}, {"z", ""}],
1470- parse_qs("=bar&baz=wibble+%0D%0a&z=")),
1471- ?assertEqual(
1472- [{"foo", "bar"}, {"baz", "wibble \r\n"}, {"z", "1"}],
1473- parse_qs(<<"foo=bar&baz=wibble+%0D%0a&z=1">>)),
1474- ?assertEqual(
1475- [],
1476- parse_qs("")),
1477- ?assertEqual(
1478- [{"foo", ""}, {"bar", ""}, {"baz", ""}],
1479- parse_qs("foo;bar&baz")),
1480- ok.
1481-
1482-partition_test() ->
1483- {"foo", "", ""} = partition("foo", "/"),
1484- {"foo", "/", "bar"} = partition("foo/bar", "/"),
1485- {"foo", "/", ""} = partition("foo/", "/"),
1486- {"", "/", "bar"} = partition("/bar", "/"),
1487- {"f", "oo/ba", "r"} = partition("foo/bar", "oo/ba"),
1488- ok.
1489-
1490-safe_relative_path_test() ->
1491- "foo" = safe_relative_path("foo"),
1492- "foo/" = safe_relative_path("foo/"),
1493- "foo" = safe_relative_path("foo/bar/.."),
1494- "bar" = safe_relative_path("foo/../bar"),
1495- "bar/" = safe_relative_path("foo/../bar/"),
1496- "" = safe_relative_path("foo/.."),
1497- "" = safe_relative_path("foo/../"),
1498- undefined = safe_relative_path("/foo"),
1499- undefined = safe_relative_path("../foo"),
1500- undefined = safe_relative_path("foo/../.."),
1501- undefined = safe_relative_path("foo//"),
1502- ok.
1503-
1504-parse_qvalues_test() ->
1505- [] = parse_qvalues(""),
1506- [{"identity", 0.0}] = parse_qvalues("identity;q=0"),
1507- [{"identity", 0.0}] = parse_qvalues("identity ;q=0"),
1508- [{"identity", 0.0}] = parse_qvalues(" identity; q =0 "),
1509- [{"identity", 0.0}] = parse_qvalues("identity ; q = 0"),
1510- [{"identity", 0.0}] = parse_qvalues("identity ; q= 0.0"),
1511- [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues(
1512- "gzip,deflate,identity;q=0.0"
1513- ),
1514- [{"deflate", 1.0}, {"gzip", 1.0}, {"identity", 0.0}] = parse_qvalues(
1515- "deflate,gzip,identity;q=0.0"
1516- ),
1517- [{"gzip", 1.0}, {"deflate", 1.0}, {"gzip", 1.0}, {"identity", 0.0}] =
1518- parse_qvalues("gzip,deflate,gzip,identity;q=0"),
1519- [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues(
1520- "gzip, deflate , identity; q=0.0"
1521- ),
1522- [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues(
1523- "gzip; q=1, deflate;q=1.0, identity;q=0.0"
1524- ),
1525- [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues(
1526- "gzip; q=0.5, deflate;q=1.0, identity;q=0"
1527- ),
1528- [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 0.0}] = parse_qvalues(
1529- "gzip; q=0.5, deflate , identity;q=0.0"
1530- ),
1531- [{"gzip", 0.5}, {"deflate", 0.8}, {"identity", 0.0}] = parse_qvalues(
1532- "gzip; q=0.5, deflate;q=0.8, identity;q=0.0"
1533- ),
1534- [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 1.0}] = parse_qvalues(
1535- "gzip; q=0.5,deflate,identity"
1536- ),
1537- [{"gzip", 0.5}, {"deflate", 1.0}, {"identity", 1.0}, {"identity", 1.0}] =
1538- parse_qvalues("gzip; q=0.5,deflate,identity, identity "),
1539- [{"text/html;level=1", 1.0}, {"text/plain", 0.5}] =
1540- parse_qvalues("text/html;level=1, text/plain;q=0.5"),
1541- [{"text/html;level=1", 0.3}, {"text/plain", 1.0}] =
1542- parse_qvalues("text/html;level=1;q=0.3, text/plain"),
1543- [{"text/html;level=1", 0.3}, {"text/plain", 1.0}] =
1544- parse_qvalues("text/html; level = 1; q = 0.3, text/plain"),
1545- [{"text/html;level=1", 0.3}, {"text/plain", 1.0}] =
1546- parse_qvalues("text/html;q=0.3;level=1, text/plain"),
1547- invalid_qvalue_string = parse_qvalues("gzip; q=1.1, deflate"),
1548- invalid_qvalue_string = parse_qvalues("gzip; q=0.5, deflate;q=2"),
1549- invalid_qvalue_string = parse_qvalues("gzip, deflate;q=AB"),
1550- invalid_qvalue_string = parse_qvalues("gzip; q=2.1, deflate"),
1551- invalid_qvalue_string = parse_qvalues("gzip; q=0.1234, deflate"),
1552- invalid_qvalue_string = parse_qvalues("text/html;level=1;q=0.3, text/html;level"),
1553- ok.
1554-
1555-pick_accepted_encodings_test() ->
1556- ["identity"] = pick_accepted_encodings(
1557- [],
1558- ["gzip", "identity"],
1559- "identity"
1560- ),
1561- ["gzip", "identity"] = pick_accepted_encodings(
1562- [{"gzip", 1.0}],
1563- ["gzip", "identity"],
1564- "identity"
1565- ),
1566- ["identity"] = pick_accepted_encodings(
1567- [{"gzip", 0.0}],
1568- ["gzip", "identity"],
1569- "identity"
1570- ),
1571- ["gzip", "identity"] = pick_accepted_encodings(
1572- [{"gzip", 1.0}, {"deflate", 1.0}],
1573- ["gzip", "identity"],
1574- "identity"
1575- ),
1576- ["gzip", "identity"] = pick_accepted_encodings(
1577- [{"gzip", 0.5}, {"deflate", 1.0}],
1578- ["gzip", "identity"],
1579- "identity"
1580- ),
1581- ["identity"] = pick_accepted_encodings(
1582- [{"gzip", 0.0}, {"deflate", 0.0}],
1583- ["gzip", "identity"],
1584- "identity"
1585- ),
1586- ["gzip"] = pick_accepted_encodings(
1587- [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}],
1588- ["gzip", "identity"],
1589- "identity"
1590- ),
1591- ["gzip", "deflate", "identity"] = pick_accepted_encodings(
1592- [{"gzip", 1.0}, {"deflate", 1.0}],
1593- ["gzip", "deflate", "identity"],
1594- "identity"
1595- ),
1596- ["gzip", "deflate"] = pick_accepted_encodings(
1597- [{"gzip", 1.0}, {"deflate", 1.0}, {"identity", 0.0}],
1598- ["gzip", "deflate", "identity"],
1599- "identity"
1600- ),
1601- ["deflate", "gzip", "identity"] = pick_accepted_encodings(
1602- [{"gzip", 0.2}, {"deflate", 1.0}],
1603- ["gzip", "deflate", "identity"],
1604- "identity"
1605- ),
1606- ["deflate", "deflate", "gzip", "identity"] = pick_accepted_encodings(
1607- [{"gzip", 0.2}, {"deflate", 1.0}, {"deflate", 1.0}],
1608- ["gzip", "deflate", "identity"],
1609- "identity"
1610- ),
1611- ["deflate", "gzip", "gzip", "identity"] = pick_accepted_encodings(
1612- [{"gzip", 0.2}, {"deflate", 1.0}, {"gzip", 1.0}],
1613- ["gzip", "deflate", "identity"],
1614- "identity"
1615- ),
1616- ["gzip", "deflate", "gzip", "identity"] = pick_accepted_encodings(
1617- [{"gzip", 0.2}, {"deflate", 0.9}, {"gzip", 1.0}],
1618- ["gzip", "deflate", "identity"],
1619- "identity"
1620- ),
1621- [] = pick_accepted_encodings(
1622- [{"*", 0.0}],
1623- ["gzip", "deflate", "identity"],
1624- "identity"
1625- ),
1626- ["gzip", "deflate", "identity"] = pick_accepted_encodings(
1627- [{"*", 1.0}],
1628- ["gzip", "deflate", "identity"],
1629- "identity"
1630- ),
1631- ["gzip", "deflate", "identity"] = pick_accepted_encodings(
1632- [{"*", 0.6}],
1633- ["gzip", "deflate", "identity"],
1634- "identity"
1635- ),
1636- ["gzip"] = pick_accepted_encodings(
1637- [{"gzip", 1.0}, {"*", 0.0}],
1638- ["gzip", "deflate", "identity"],
1639- "identity"
1640- ),
1641- ["gzip", "deflate"] = pick_accepted_encodings(
1642- [{"gzip", 1.0}, {"deflate", 0.6}, {"*", 0.0}],
1643- ["gzip", "deflate", "identity"],
1644- "identity"
1645- ),
1646- ["deflate", "gzip"] = pick_accepted_encodings(
1647- [{"gzip", 0.5}, {"deflate", 1.0}, {"*", 0.0}],
1648- ["gzip", "deflate", "identity"],
1649- "identity"
1650- ),
1651- ["gzip", "identity"] = pick_accepted_encodings(
1652- [{"deflate", 0.0}, {"*", 1.0}],
1653- ["gzip", "deflate", "identity"],
1654- "identity"
1655- ),
1656- ["gzip", "identity"] = pick_accepted_encodings(
1657- [{"*", 1.0}, {"deflate", 0.0}],
1658- ["gzip", "deflate", "identity"],
1659- "identity"
1660- ),
1661- ok.
1662-
1663--endif.
1664
1665=== removed directory '.pc/improve_script_url_validation.patch'
1666=== removed directory '.pc/improve_script_url_validation.patch/share'
1667=== removed directory '.pc/improve_script_url_validation.patch/share/www'
1668=== removed directory '.pc/improve_script_url_validation.patch/share/www/script'
1669=== removed file '.pc/improve_script_url_validation.patch/share/www/script/couch_test_runner.js'
1670--- .pc/improve_script_url_validation.patch/share/www/script/couch_test_runner.js 2013-01-18 22:04:32 +0000
1671+++ .pc/improve_script_url_validation.patch/share/www/script/couch_test_runner.js 1970-01-01 00:00:00 +0000
1672@@ -1,472 +0,0 @@
1673-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
1674-// use this file except in compliance with the License. You may obtain a copy of
1675-// the License at
1676-//
1677-// http://www.apache.org/licenses/LICENSE-2.0
1678-//
1679-// Unless required by applicable law or agreed to in writing, software
1680-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1681-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1682-// License for the specific language governing permissions and limitations under
1683-// the License.
1684-
1685-// *********************** Test Framework of Sorts ************************* //
1686-
1687-
1688-function loadScript(url) {
1689- // disallow loading remote URLs
1690- if((url.substr(0, 7) == "http://")
1691- || (url.substr(0, 2) == "//")
1692- || (url.substr(0, 5) == "data:")
1693- || (url.substr(0, 11) == "javascript:")) {
1694- throw "Not loading remote test scripts";
1695- }
1696- if (typeof document != "undefined") document.write('<script src="'+url+'"></script>');
1697-};
1698-
1699-function patchTest(fun) {
1700- var source = fun.toString();
1701- var output = "";
1702- var i = 0;
1703- var testMarker = "T(";
1704- while (i < source.length) {
1705- var testStart = source.indexOf(testMarker, i);
1706- if (testStart == -1) {
1707- output = output + source.substring(i, source.length);
1708- break;
1709- }
1710- var testEnd = source.indexOf(");", testStart);
1711- var testCode = source.substring(testStart + testMarker.length, testEnd);
1712- output += source.substring(i, testStart) + "T(" + testCode + "," + JSON.stringify(testCode);
1713- i = testEnd;
1714- }
1715- try {
1716- return eval("(" + output + ")");
1717- } catch (e) {
1718- return null;
1719- }
1720-}
1721-
1722-function runAllTests() {
1723- var rows = $("#tests tbody.content tr");
1724- $("td", rows).text("");
1725- $("td.status", rows).removeClass("error").removeClass("failure").removeClass("success").text("not run");
1726- var offset = 0;
1727- function runNext() {
1728- if (offset < rows.length) {
1729- var row = rows.get(offset);
1730- runTest($("th button", row).get(0), function() {
1731- offset += 1;
1732- setTimeout(runNext, 100);
1733- }, false, true);
1734- } else {
1735- saveTestReport();
1736- }
1737- }
1738- runNext();
1739-}
1740-
1741-var numFailures = 0;
1742-var currentRow = null;
1743-
1744-function runTest(button, callback, debug, noSave) {
1745-
1746- // offer to save admins
1747- if (currentRow != null) {
1748- alert("Can not run multiple tests simultaneously.");
1749- return;
1750- }
1751- var row = currentRow = $(button).parents("tr").get(0);
1752- $("td.status", row).removeClass("error").removeClass("failure").removeClass("success");
1753- $("td", row).text("");
1754- $("#toolbar li.current").text("Running: "+row.id);
1755- var testFun = couchTests[row.id];
1756- function run() {
1757- numFailures = 0;
1758- var start = new Date().getTime();
1759- try {
1760- if (debug == undefined || !debug) {
1761- testFun = patchTest(testFun) || testFun;
1762- }
1763- testFun(debug);
1764- var status = numFailures > 0 ? "failure" : "success";
1765- } catch (e) {
1766- var status = "error";
1767- if ($("td.details ol", row).length == 0) {
1768- $("<ol></ol>").appendTo($("td.details", row));
1769- }
1770- $("<li><b>Exception raised:</b> <code class='error'></code></li>")
1771- .find("code").text(JSON.stringify(e)).end()
1772- .appendTo($("td.details ol", row));
1773- if (debug) {
1774- currentRow = null;
1775- throw e;
1776- }
1777- }
1778- if ($("td.details ol", row).length) {
1779- $("<a href='#'>Run with debugger</a>").click(function() {
1780- runTest(this, undefined, true);
1781- }).prependTo($("td.details ol", row));
1782- }
1783- var duration = new Date().getTime() - start;
1784- $("td.status", row).removeClass("running").addClass(status).text(status);
1785- $("td.duration", row).text(duration + "ms");
1786- $("#toolbar li.current").text("Finished: "+row.id);
1787- updateTestsFooter();
1788- currentRow = null;
1789- if (callback) callback();
1790- if (!noSave) saveTestReport();
1791- }
1792- $("td.status", row).addClass("running").text("running…");
1793- setTimeout(run, 100);
1794-}
1795-
1796-function showSource(cell) {
1797- var name = $(cell).text();
1798- var win = window.open("", name, "width=700,height=500,resizable=yes,scrollbars=yes");
1799- win.document.location = "script/test/" + name + ".js";
1800-}
1801-
1802-var readyToRun;
1803-function setupAdminParty(fun) {
1804- if (readyToRun) {
1805- fun();
1806- } else {
1807- function removeAdmins(confs, doneFun) {
1808- // iterate through the config and remove current user last
1809- // current user is at front of list
1810- var remove = confs.pop();
1811- if (remove) {
1812- $.couch.config({
1813- success : function() {
1814- removeAdmins(confs, doneFun);
1815- }
1816- }, "admins", remove[0], null);
1817- } else {
1818- doneFun();
1819- }
1820- };
1821- $.couch.session({
1822- success : function(resp) {
1823- var userCtx = resp.userCtx;
1824- if (userCtx.name && userCtx.roles.indexOf("_admin") != -1) {
1825- // admin but not admin party. dialog offering to make admin party
1826- $.showDialog("dialog/_admin_party.html", {
1827- submit: function(data, callback) {
1828- $.couch.config({
1829- success : function(conf) {
1830- var meAdmin, adminConfs = [];
1831- for (var name in conf) {
1832- if (name == userCtx.name) {
1833- meAdmin = [name, conf[name]];
1834- } else {
1835- adminConfs.push([name, conf[name]]);
1836- }
1837- }
1838- adminConfs.unshift(meAdmin);
1839- removeAdmins(adminConfs, function() {
1840- callback();
1841- $.futon.session.sidebar();
1842- readyToRun = true;
1843- setTimeout(fun, 500);
1844- });
1845- }
1846- }, "admins");
1847- }
1848- });
1849- } else if (userCtx.roles.indexOf("_admin") != -1) {
1850- // admin party!
1851- readyToRun = true;
1852- fun();
1853- } else {
1854- // not an admin
1855- alert("Error: You need to be an admin to run the tests.");
1856- };
1857- }
1858- });
1859- }
1860-};
1861-
1862-function updateTestsListing() {
1863- for (var name in couchTests) {
1864- var testFunction = couchTests[name];
1865- var row = $("<tr><th></th><td></td><td></td><td></td></tr>")
1866- .find("th").text(name).attr("title", "Show source").click(function() {
1867- showSource(this);
1868- }).end()
1869- .find("td:nth(0)").addClass("status").text("not run").end()
1870- .find("td:nth(1)").addClass("duration").end()
1871- .find("td:nth(2)").addClass("details").end();
1872- $("<button type='button' class='run' title='Run test'></button>").click(function() {
1873- this.blur();
1874- var self = this;
1875- // check for admin party
1876- setupAdminParty(function() {
1877- runTest(self);
1878- });
1879- return false;
1880- }).prependTo(row.find("th"));
1881- row.attr("id", name).appendTo("#tests tbody.content");
1882- }
1883- $("#tests tr").removeClass("odd").filter(":odd").addClass("odd");
1884- updateTestsFooter();
1885-}
1886-
1887-function updateTestsFooter() {
1888- var tests = $("#tests tbody.content tr td.status");
1889- var testsRun = tests.filter(".success, .error, .failure");
1890- var testsFailed = testsRun.not(".success");
1891- var totalDuration = 0;
1892- $("#tests tbody.content tr td.duration:contains('ms')").each(function() {
1893- var text = $(this).text();
1894- totalDuration += parseInt(text.substr(0, text.length - 2), 10);
1895- });
1896- $("#tests tbody.footer td").html("<span>"+testsRun.length + " of " + tests.length +
1897- " test(s) run, " + testsFailed.length + " failures (" +
1898- totalDuration + " ms)</span> ");
1899-}
1900-
1901-// make report and save to local db
1902-// display how many reports need replicating to the mothership
1903-// have button to replicate them
1904-
1905-function saveTestReport(report) {
1906- var report = makeTestReport();
1907- if (report) {
1908- var db = $.couch.db("test_suite_reports");
1909- var saveReport = function(db_info) {
1910- report.db = db_info;
1911- $.couch.info({success : function(node_info) {
1912- report.node = node_info;
1913- db.saveDoc(report);
1914- }});
1915- };
1916- var createDb = function() {
1917- db.create({success: function() {
1918- db.info({success:saveReport});
1919- }});
1920- };
1921- db.info({error: createDb, success:saveReport});
1922- }
1923-};
1924-
1925-function makeTestReport() {
1926- var report = {};
1927- report.summary = $("#tests tbody.footer td").text();
1928- report.platform = testPlatform();
1929- var date = new Date();
1930- report.timestamp = date.getTime();
1931- report.timezone = date.getTimezoneOffset();
1932- report.tests = [];
1933- $("#tests tbody.content tr").each(function() {
1934- var status = $("td.status", this).text();
1935- if (status != "not run") {
1936- var test = {};
1937- test.name = this.id;
1938- test.status = status;
1939- test.duration = parseInt($("td.duration", this).text());
1940- test.details = [];
1941- $("td.details li", this).each(function() {
1942- test.details.push($(this).text());
1943- });
1944- if (test.details.length == 0) {
1945- delete test.details;
1946- }
1947- report.tests.push(test);
1948- }
1949- });
1950- if (report.tests.length > 0) return report;
1951-};
1952-
1953-function testPlatform() {
1954- var b = $.browser;
1955- var bs = ["mozilla", "msie", "opera", "safari"];
1956- for (var i=0; i < bs.length; i++) {
1957- if (b[bs[i]]) {
1958- return {"browser" : bs[i], "version" : b.version};
1959- }
1960- };
1961- return {"browser" : "undetected"};
1962-}
1963-
1964-
1965-function reportTests() {
1966- // replicate the database to couchdb.couchdb.org
1967-}
1968-
1969-// Use T to perform a test that returns false on failure and if the test fails,
1970-// display the line that failed.
1971-// Example:
1972-// T(MyValue==1);
1973-function T(arg1, arg2, testName) {
1974- if (!arg1) {
1975- if (currentRow) {
1976- if ($("td.details ol", currentRow).length == 0) {
1977- $("<ol></ol>").appendTo($("td.details", currentRow));
1978- }
1979- var message = (arg2 != null ? arg2 : arg1).toString();
1980- $("<li><b>Assertion " + (testName ? "'" + testName + "'" : "") + " failed:</b> <code class='failure'></code></li>")
1981- .find("code").text(message).end()
1982- .appendTo($("td.details ol", currentRow));
1983- }
1984- numFailures += 1;
1985- }
1986-}
1987-
1988-function TIsnull(actual, testName) {
1989- T(actual === null, "expected 'null', got '"
1990- + repr(actual) + "'", testName);
1991-}
1992-
1993-function TEquals(expected, actual, testName) {
1994- T(equals(expected, actual), "expected '" + repr(expected) +
1995- "', got '" + repr(actual) + "'", testName);
1996-}
1997-
1998-function TEqualsIgnoreCase(expected, actual, testName) {
1999- T(equals(expected.toUpperCase(), actual.toUpperCase()), "expected '" + repr(expected) +
2000- "', got '" + repr(actual) + "'", testName);
2001-}
2002-
2003-function equals(a,b) {
2004- if (a === b) return true;
2005- try {
2006- return repr(a) === repr(b);
2007- } catch (e) {
2008- return false;
2009- }
2010-}
2011-
2012-function repr(val) {
2013- if (val === undefined) {
2014- return null;
2015- } else if (val === null) {
2016- return "null";
2017- } else {
2018- return JSON.stringify(val);
2019- }
2020-}
2021-
2022-function makeDocs(start, end, templateDoc) {
2023- var templateDocSrc = templateDoc ? JSON.stringify(templateDoc) : "{}";
2024- if (end === undefined) {
2025- end = start;
2026- start = 0;
2027- }
2028- var docs = [];
2029- for (var i = start; i < end; i++) {
2030- var newDoc = eval("(" + templateDocSrc + ")");
2031- newDoc._id = (i).toString();
2032- newDoc.integer = i;
2033- newDoc.string = (i).toString();
2034- docs.push(newDoc);
2035- }
2036- return docs;
2037-}
2038-
2039-function run_on_modified_server(settings, fun) {
2040- try {
2041- // set the settings
2042- for(var i=0; i < settings.length; i++) {
2043- var s = settings[i];
2044- var xhr = CouchDB.request("PUT", "/_config/" + s.section + "/" + s.key, {
2045- body: JSON.stringify(s.value),
2046- headers: {"X-Couch-Persist": "false"}
2047- });
2048- CouchDB.maybeThrowError(xhr);
2049- s.oldValue = xhr.responseText;
2050- }
2051- // run the thing
2052- fun();
2053- } finally {
2054- // unset the settings
2055- for(var j=0; j < i; j++) {
2056- var s = settings[j];
2057- if(s.oldValue == "\"\"\n") { // unset value
2058- CouchDB.request("DELETE", "/_config/" + s.section + "/" + s.key, {
2059- headers: {"X-Couch-Persist": "false"}
2060- });
2061- } else {
2062- CouchDB.request("PUT", "/_config/" + s.section + "/" + s.key, {
2063- body: s.oldValue,
2064- headers: {"X-Couch-Persist": "false"}
2065- });
2066- }
2067- }
2068- }
2069-}
2070-
2071-function stringFun(fun) {
2072- var string = fun.toSource ? fun.toSource() : "(" + fun.toString() + ")";
2073- return string;
2074-}
2075-
2076-function waitForSuccess(fun, tag) {
2077- var start = new Date();
2078- while(true) {
2079- if (new Date() - start > 5000) {
2080- throw("timeout: "+tag);
2081- } else {
2082- try {
2083- fun();
2084- break;
2085- } catch (e) {}
2086- // sync http req allow async req to happen
2087- CouchDB.request("GET", "/test_suite_db/?tag="+encodeURIComponent(tag));
2088- }
2089- }
2090-}
2091-
2092-function waitForRestart() {
2093- var waiting = true;
2094- // Wait for the server to go down but don't
2095- // wait too long because we might miss the
2096- // the unavailable period.
2097- var count = 25;
2098- while (waiting && count > 0) {
2099- count--;
2100- try {
2101- CouchDB.request("GET", "/");
2102- } catch(e) {
2103- waiting = false;
2104- }
2105- }
2106- // Wait for it to come back up
2107- waiting = true;
2108- while (waiting) {
2109- try {
2110- CouchDB.request("GET", "/");
2111- waiting = false;
2112- } catch(e) {
2113- // the request will fail until restart completes
2114- }
2115- }
2116-};
2117-
2118-function restartServer() {
2119- var xhr;
2120- try {
2121- CouchDB.request("POST", "/_restart");
2122- } catch(e) {
2123- // this request may sometimes fail
2124- }
2125- waitForRestart();
2126-}
2127-
2128-// legacy functions for CouchDB < 1.2.0
2129-// we keep them to make sure we keep BC
2130-CouchDB.user_prefix = "org.couchdb.user:";
2131-
2132-CouchDB.prepareUserDoc = function(user_doc, new_password) {
2133- user_doc._id = user_doc._id || CouchDB.user_prefix + user_doc.name;
2134- if (new_password) {
2135- // handle the password crypto
2136- user_doc.salt = CouchDB.newUuids(1)[0];
2137- user_doc.password_sha = hex_sha1(new_password + user_doc.salt);
2138- }
2139- user_doc.type = "user";
2140- if (!user_doc.roles) {
2141- user_doc.roles = [];
2142- }
2143- return user_doc;
2144-};
2145
2146=== removed directory '.pc/include_a_comment_before_jsonp_output.patch'
2147=== removed directory '.pc/include_a_comment_before_jsonp_output.patch/src'
2148=== removed directory '.pc/include_a_comment_before_jsonp_output.patch/src/couchdb'
2149=== removed file '.pc/include_a_comment_before_jsonp_output.patch/src/couchdb/couch_httpd.erl'
2150--- .pc/include_a_comment_before_jsonp_output.patch/src/couchdb/couch_httpd.erl 2013-01-18 22:04:32 +0000
2151+++ .pc/include_a_comment_before_jsonp_output.patch/src/couchdb/couch_httpd.erl 1970-01-01 00:00:00 +0000
2152@@ -1,1081 +0,0 @@
2153-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
2154-% use this file except in compliance with the License. You may obtain a copy of
2155-% the License at
2156-%
2157-% http://www.apache.org/licenses/LICENSE-2.0
2158-%
2159-% Unless required by applicable law or agreed to in writing, software
2160-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
2161-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
2162-% License for the specific language governing permissions and limitations under
2163-% the License.
2164-
2165--module(couch_httpd).
2166--include("couch_db.hrl").
2167-
2168--export([start_link/0, start_link/1, stop/0, config_change/2,
2169- handle_request/5]).
2170-
2171--export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,qs_json_value/3]).
2172--export([path/1,absolute_uri/2,body_length/1]).
2173--export([verify_is_server_admin/1,unquote/1,quote/1,recv/2,recv_chunked/4,error_info/1]).
2174--export([make_fun_spec_strs/1]).
2175--export([make_arity_1_fun/1, make_arity_2_fun/1, make_arity_3_fun/1]).
2176--export([parse_form/1,json_body/1,json_body_obj/1,body/1,doc_etag/1, make_etag/1, etag_respond/3]).
2177--export([primary_header_value/2,partition/1,serve_file/3,serve_file/4, server_header/0]).
2178--export([start_chunked_response/3,send_chunk/2,log_request/2]).
2179--export([start_response_length/4, start_response/3, send/2]).
2180--export([start_json_response/2, start_json_response/3, end_json_response/1]).
2181--export([send_response/4,send_method_not_allowed/2,send_error/4, send_redirect/2,send_chunked_error/2]).
2182--export([send_json/2,send_json/3,send_json/4,last_chunk/1,parse_multipart_request/3]).
2183--export([accepted_encodings/1,handle_request_int/5,validate_referer/1,validate_ctype/2]).
2184-
2185-start_link() ->
2186- start_link(http).
2187-start_link(http) ->
2188- Port = couch_config:get("httpd", "port", "5984"),
2189- start_link(?MODULE, [{port, Port}]);
2190-start_link(https) ->
2191- Port = couch_config:get("ssl", "port", "6984"),
2192- CertFile = couch_config:get("ssl", "cert_file", nil),
2193- KeyFile = couch_config:get("ssl", "key_file", nil),
2194- Options = case CertFile /= nil andalso KeyFile /= nil of
2195- true ->
2196- SslOpts = [{certfile, CertFile}, {keyfile, KeyFile}],
2197-
2198- %% set password if one is needed for the cert
2199- SslOpts1 = case couch_config:get("ssl", "password", nil) of
2200- nil -> SslOpts;
2201- Password ->
2202- SslOpts ++ [{password, Password}]
2203- end,
2204- % do we verify certificates ?
2205- FinalSslOpts = case couch_config:get("ssl",
2206- "verify_ssl_certificates", "false") of
2207- "false" -> SslOpts1;
2208- "true" ->
2209- case couch_config:get("ssl",
2210- "cacert_file", nil) of
2211- nil ->
2212- io:format("Verify SSL certificate "
2213- ++"enabled but file containing "
2214- ++"PEM encoded CA certificates is "
2215- ++"missing", []),
2216- throw({error, missing_cacerts});
2217- CaCertFile ->
2218- Depth = list_to_integer(couch_config:get("ssl",
2219- "ssl_certificate_max_depth",
2220- "1")),
2221- FinalOpts = [
2222- {cacertfile, CaCertFile},
2223- {depth, Depth},
2224- {verify, verify_peer}],
2225- % allows custom verify fun.
2226- case couch_config:get("ssl",
2227- "verify_fun", nil) of
2228- nil -> FinalOpts;
2229- SpecStr ->
2230- FinalOpts
2231- ++ [{verify_fun, make_arity_3_fun(SpecStr)}]
2232- end
2233- end
2234- end,
2235-
2236- [{port, Port},
2237- {ssl, true},
2238- {ssl_opts, FinalSslOpts}];
2239- false ->
2240- io:format("SSL enabled but PEM certificates are missing.", []),
2241- throw({error, missing_certs})
2242- end,
2243- start_link(https, Options).
2244-start_link(Name, Options) ->
2245- % read config and register for configuration changes
2246-
2247- % just stop if one of the config settings change. couch_server_sup
2248- % will restart us and then we will pick up the new settings.
2249-
2250- BindAddress = couch_config:get("httpd", "bind_address", any),
2251- DefaultSpec = "{couch_httpd_db, handle_request}",
2252- DefaultFun = make_arity_1_fun(
2253- couch_config:get("httpd", "default_handler", DefaultSpec)
2254- ),
2255-
2256- UrlHandlersList = lists:map(
2257- fun({UrlKey, SpecStr}) ->
2258- {?l2b(UrlKey), make_arity_1_fun(SpecStr)}
2259- end, couch_config:get("httpd_global_handlers")),
2260-
2261- DbUrlHandlersList = lists:map(
2262- fun({UrlKey, SpecStr}) ->
2263- {?l2b(UrlKey), make_arity_2_fun(SpecStr)}
2264- end, couch_config:get("httpd_db_handlers")),
2265-
2266- DesignUrlHandlersList = lists:map(
2267- fun({UrlKey, SpecStr}) ->
2268- {?l2b(UrlKey), make_arity_3_fun(SpecStr)}
2269- end, couch_config:get("httpd_design_handlers")),
2270-
2271- UrlHandlers = dict:from_list(UrlHandlersList),
2272- DbUrlHandlers = dict:from_list(DbUrlHandlersList),
2273- DesignUrlHandlers = dict:from_list(DesignUrlHandlersList),
2274- {ok, ServerOptions} = couch_util:parse_term(
2275- couch_config:get("httpd", "server_options", "[]")),
2276- {ok, SocketOptions} = couch_util:parse_term(
2277- couch_config:get("httpd", "socket_options", "[]")),
2278-
2279- set_auth_handlers(),
2280-
2281- Loop = fun(Req)->
2282- case SocketOptions of
2283- [] ->
2284- ok;
2285- _ ->
2286- ok = mochiweb_socket:setopts(Req:get(socket), SocketOptions)
2287- end,
2288- apply(?MODULE, handle_request, [
2289- Req, DefaultFun, UrlHandlers, DbUrlHandlers, DesignUrlHandlers
2290- ])
2291- end,
2292-
2293- % set mochiweb options
2294- FinalOptions = lists:append([Options, ServerOptions, [
2295- {loop, Loop},
2296- {name, Name},
2297- {ip, BindAddress}]]),
2298-
2299- % launch mochiweb
2300- {ok, Pid} = case mochiweb_http:start(FinalOptions) of
2301- {ok, MochiPid} ->
2302- {ok, MochiPid};
2303- {error, Reason} ->
2304- io:format("Failure to start Mochiweb: ~s~n",[Reason]),
2305- throw({error, Reason})
2306- end,
2307-
2308- ok = couch_config:register(fun ?MODULE:config_change/2, Pid),
2309- {ok, Pid}.
2310-
2311-
2312-stop() ->
2313- mochiweb_http:stop(couch_httpd),
2314- mochiweb_http:stop(https).
2315-
2316-config_change("httpd", "bind_address") ->
2317- ?MODULE:stop();
2318-config_change("httpd", "port") ->
2319- ?MODULE:stop();
2320-config_change("httpd", "default_handler") ->
2321- ?MODULE:stop();
2322-config_change("httpd", "server_options") ->
2323- ?MODULE:stop();
2324-config_change("httpd", "socket_options") ->
2325- ?MODULE:stop();
2326-config_change("httpd", "authentication_handlers") ->
2327- set_auth_handlers();
2328-config_change("httpd_global_handlers", _) ->
2329- ?MODULE:stop();
2330-config_change("httpd_db_handlers", _) ->
2331- ?MODULE:stop();
2332-config_change("ssl", _) ->
2333- ?MODULE:stop().
2334-
2335-set_auth_handlers() ->
2336- AuthenticationSrcs = make_fun_spec_strs(
2337- couch_config:get("httpd", "authentication_handlers", "")),
2338- AuthHandlers = lists:map(
2339- fun(A) -> {make_arity_1_fun(A), ?l2b(A)} end, AuthenticationSrcs),
2340- ok = application:set_env(couch, auth_handlers, AuthHandlers).
2341-
2342-% SpecStr is a string like "{my_module, my_fun}"
2343-% or "{my_module, my_fun, <<"my_arg">>}"
2344-make_arity_1_fun(SpecStr) ->
2345- case couch_util:parse_term(SpecStr) of
2346- {ok, {Mod, Fun, SpecArg}} ->
2347- fun(Arg) -> Mod:Fun(Arg, SpecArg) end;
2348- {ok, {Mod, Fun}} ->
2349- fun(Arg) -> Mod:Fun(Arg) end
2350- end.
2351-
2352-make_arity_2_fun(SpecStr) ->
2353- case couch_util:parse_term(SpecStr) of
2354- {ok, {Mod, Fun, SpecArg}} ->
2355- fun(Arg1, Arg2) -> Mod:Fun(Arg1, Arg2, SpecArg) end;
2356- {ok, {Mod, Fun}} ->
2357- fun(Arg1, Arg2) -> Mod:Fun(Arg1, Arg2) end
2358- end.
2359-
2360-make_arity_3_fun(SpecStr) ->
2361- case couch_util:parse_term(SpecStr) of
2362- {ok, {Mod, Fun, SpecArg}} ->
2363- fun(Arg1, Arg2, Arg3) -> Mod:Fun(Arg1, Arg2, Arg3, SpecArg) end;
2364- {ok, {Mod, Fun}} ->
2365- fun(Arg1, Arg2, Arg3) -> Mod:Fun(Arg1, Arg2, Arg3) end
2366- end.
2367-
2368-% SpecStr is "{my_module, my_fun}, {my_module2, my_fun2}"
2369-make_fun_spec_strs(SpecStr) ->
2370- re:split(SpecStr, "(?<=})\\s*,\\s*(?={)", [{return, list}]).
2371-
2372-handle_request(MochiReq, DefaultFun, UrlHandlers, DbUrlHandlers,
2373- DesignUrlHandlers) ->
2374-
2375- MochiReq1 = couch_httpd_vhost:dispatch_host(MochiReq),
2376-
2377- handle_request_int(MochiReq1, DefaultFun,
2378- UrlHandlers, DbUrlHandlers, DesignUrlHandlers).
2379-
2380-handle_request_int(MochiReq, DefaultFun,
2381- UrlHandlers, DbUrlHandlers, DesignUrlHandlers) ->
2382- Begin = now(),
2383- % for the path, use the raw path with the query string and fragment
2384- % removed, but URL quoting left intact
2385- RawUri = MochiReq:get(raw_path),
2386- {"/" ++ Path, _, _} = mochiweb_util:urlsplit_path(RawUri),
2387-
2388- Headers = MochiReq:get(headers),
2389-
2390- % get requested path
2391- RequestedPath = case MochiReq:get_header_value("x-couchdb-vhost-path") of
2392- undefined ->
2393- case MochiReq:get_header_value("x-couchdb-requested-path") of
2394- undefined -> RawUri;
2395- R -> R
2396- end;
2397- P -> P
2398- end,
2399-
2400- HandlerKey =
2401- case mochiweb_util:partition(Path, "/") of
2402- {"", "", ""} ->
2403- <<"/">>; % Special case the root url handler
2404- {FirstPart, _, _} ->
2405- list_to_binary(FirstPart)
2406- end,
2407- ?LOG_DEBUG("~p ~s ~p from ~p~nHeaders: ~p", [
2408- MochiReq:get(method),
2409- RawUri,
2410- MochiReq:get(version),
2411- MochiReq:get(peer),
2412- mochiweb_headers:to_list(MochiReq:get(headers))
2413- ]),
2414-
2415- Method1 =
2416- case MochiReq:get(method) of
2417- % already an atom
2418- Meth when is_atom(Meth) -> Meth;
2419-
2420- % Non standard HTTP verbs aren't atoms (COPY, MOVE etc) so convert when
2421- % possible (if any module references the atom, then it's existing).
2422- Meth -> couch_util:to_existing_atom(Meth)
2423- end,
2424- increment_method_stats(Method1),
2425-
2426- % allow broken HTTP clients to fake a full method vocabulary with an X-HTTP-METHOD-OVERRIDE header
2427- MethodOverride = MochiReq:get_primary_header_value("X-HTTP-Method-Override"),
2428- Method2 = case lists:member(MethodOverride, ["GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT", "COPY"]) of
2429- true ->
2430- ?LOG_INFO("MethodOverride: ~s (real method was ~s)", [MethodOverride, Method1]),
2431- case Method1 of
2432- 'POST' -> couch_util:to_existing_atom(MethodOverride);
2433- _ ->
2434- % Ignore X-HTTP-Method-Override when the original verb isn't POST.
2435- % I'd like to send a 406 error to the client, but that'd require a nasty refactor.
2436- % throw({not_acceptable, <<"X-HTTP-Method-Override may only be used with POST requests.">>})
2437- Method1
2438- end;
2439- _ -> Method1
2440- end,
2441-
2442- % alias HEAD to GET as mochiweb takes care of stripping the body
2443- Method = case Method2 of
2444- 'HEAD' -> 'GET';
2445- Other -> Other
2446- end,
2447-
2448- HttpReq = #httpd{
2449- mochi_req = MochiReq,
2450- peer = MochiReq:get(peer),
2451- method = Method,
2452- requested_path_parts =
2453- [?l2b(unquote(Part)) || Part <- string:tokens(RequestedPath, "/")],
2454- path_parts = [?l2b(unquote(Part)) || Part <- string:tokens(Path, "/")],
2455- db_url_handlers = DbUrlHandlers,
2456- design_url_handlers = DesignUrlHandlers,
2457- default_fun = DefaultFun,
2458- url_handlers = UrlHandlers,
2459- user_ctx = erlang:erase(pre_rewrite_user_ctx)
2460- },
2461-
2462- HandlerFun = couch_util:dict_find(HandlerKey, UrlHandlers, DefaultFun),
2463- {ok, AuthHandlers} = application:get_env(couch, auth_handlers),
2464-
2465- {ok, Resp} =
2466- try
2467- case authenticate_request(HttpReq, AuthHandlers) of
2468- #httpd{} = Req ->
2469- HandlerFun(Req);
2470- Response ->
2471- Response
2472- end
2473- catch
2474- throw:{http_head_abort, Resp0} ->
2475- {ok, Resp0};
2476- throw:{invalid_json, S} ->
2477- ?LOG_ERROR("attempted upload of invalid JSON (set log_level to debug to log it)", []),
2478- ?LOG_DEBUG("Invalid JSON: ~p",[S]),
2479- send_error(HttpReq, {bad_request, invalid_json});
2480- throw:unacceptable_encoding ->
2481- ?LOG_ERROR("unsupported encoding method for the response", []),
2482- send_error(HttpReq, {not_acceptable, "unsupported encoding"});
2483- throw:bad_accept_encoding_value ->
2484- ?LOG_ERROR("received invalid Accept-Encoding header", []),
2485- send_error(HttpReq, bad_request);
2486- exit:normal ->
2487- exit(normal);
2488- exit:snappy_nif_not_loaded ->
2489- ErrorReason = "To access the database or view index, Apache CouchDB"
2490- " must be built with Erlang OTP R13B04 or higher.",
2491- ?LOG_ERROR("~s", [ErrorReason]),
2492- send_error(HttpReq, {bad_otp_release, ErrorReason});
2493- throw:Error ->
2494- Stack = erlang:get_stacktrace(),
2495- ?LOG_DEBUG("Minor error in HTTP request: ~p",[Error]),
2496- ?LOG_DEBUG("Stacktrace: ~p",[Stack]),
2497- send_error(HttpReq, Error);
2498- error:badarg ->
2499- Stack = erlang:get_stacktrace(),
2500- ?LOG_ERROR("Badarg error in HTTP request",[]),
2501- ?LOG_INFO("Stacktrace: ~p",[Stack]),
2502- send_error(HttpReq, badarg);
2503- error:function_clause ->
2504- Stack = erlang:get_stacktrace(),
2505- ?LOG_ERROR("function_clause error in HTTP request",[]),
2506- ?LOG_INFO("Stacktrace: ~p",[Stack]),
2507- send_error(HttpReq, function_clause);
2508- Tag:Error ->
2509- Stack = erlang:get_stacktrace(),
2510- ?LOG_ERROR("Uncaught error in HTTP request: ~p",[{Tag, Error}]),
2511- ?LOG_INFO("Stacktrace: ~p",[Stack]),
2512- send_error(HttpReq, Error)
2513- end,
2514- RequestTime = round(timer:now_diff(now(), Begin)/1000),
2515- couch_stats_collector:record({couchdb, request_time}, RequestTime),
2516- couch_stats_collector:increment({httpd, requests}),
2517- {ok, Resp}.
2518-
2519-% Try authentication handlers in order until one sets a user_ctx
2520-% the auth funs also have the option of returning a response
2521-% move this to couch_httpd_auth?
2522-authenticate_request(#httpd{user_ctx=#user_ctx{}} = Req, _AuthHandlers) ->
2523- Req;
2524-authenticate_request(#httpd{} = Req, []) ->
2525- case couch_config:get("couch_httpd_auth", "require_valid_user", "false") of
2526- "true" ->
2527- throw({unauthorized, <<"Authentication required.">>});
2528- "false" ->
2529- Req#httpd{user_ctx=#user_ctx{}}
2530- end;
2531-authenticate_request(#httpd{} = Req, [{AuthFun, AuthSrc} | RestAuthHandlers]) ->
2532- R = case AuthFun(Req) of
2533- #httpd{user_ctx=#user_ctx{}=UserCtx}=Req2 ->
2534- Req2#httpd{user_ctx=UserCtx#user_ctx{handler=AuthSrc}};
2535- Else -> Else
2536- end,
2537- authenticate_request(R, RestAuthHandlers);
2538-authenticate_request(Response, _AuthSrcs) ->
2539- Response.
2540-
2541-increment_method_stats(Method) ->
2542- couch_stats_collector:increment({httpd_request_methods, Method}).
2543-
2544-validate_referer(Req) ->
2545- Host = host_for_request(Req),
2546- Referer = header_value(Req, "Referer", fail),
2547- case Referer of
2548- fail ->
2549- throw({bad_request, <<"Referer header required.">>});
2550- Referer ->
2551- {_,RefererHost,_,_,_} = mochiweb_util:urlsplit(Referer),
2552- if
2553- RefererHost =:= Host -> ok;
2554- true -> throw({bad_request, <<"Referer header must match host.">>})
2555- end
2556- end.
2557-
2558-validate_ctype(Req, Ctype) ->
2559- case header_value(Req, "Content-Type") of
2560- undefined ->
2561- throw({bad_ctype, "Content-Type must be "++Ctype});
2562- ReqCtype ->
2563- case string:tokens(ReqCtype, ";") of
2564- [Ctype] -> ok;
2565- [Ctype, _Rest] -> ok;
2566- _Else ->
2567- throw({bad_ctype, "Content-Type must be "++Ctype})
2568- end
2569- end.
2570-
2571-% Utilities
2572-
2573-partition(Path) ->
2574- mochiweb_util:partition(Path, "/").
2575-
2576-header_value(#httpd{mochi_req=MochiReq}, Key) ->
2577- MochiReq:get_header_value(Key).
2578-
2579-header_value(#httpd{mochi_req=MochiReq}, Key, Default) ->
2580- case MochiReq:get_header_value(Key) of
2581- undefined -> Default;
2582- Value -> Value
2583- end.
2584-
2585-primary_header_value(#httpd{mochi_req=MochiReq}, Key) ->
2586- MochiReq:get_primary_header_value(Key).
2587-
2588-accepted_encodings(#httpd{mochi_req=MochiReq}) ->
2589- case MochiReq:accepted_encodings(["gzip", "identity"]) of
2590- bad_accept_encoding_value ->
2591- throw(bad_accept_encoding_value);
2592- [] ->
2593- throw(unacceptable_encoding);
2594- EncList ->
2595- EncList
2596- end.
2597-
2598-serve_file(Req, RelativePath, DocumentRoot) ->
2599- serve_file(Req, RelativePath, DocumentRoot, []).
2600-
2601-serve_file(#httpd{mochi_req=MochiReq}=Req, RelativePath, DocumentRoot, ExtraHeaders) ->
2602- log_request(Req, 200),
2603- {ok, MochiReq:serve_file(RelativePath, DocumentRoot,
2604- server_header() ++ couch_httpd_auth:cookie_auth_header(Req, []) ++ ExtraHeaders)}.
2605-
2606-qs_value(Req, Key) ->
2607- qs_value(Req, Key, undefined).
2608-
2609-qs_value(Req, Key, Default) ->
2610- couch_util:get_value(Key, qs(Req), Default).
2611-
2612-qs_json_value(Req, Key, Default) ->
2613- case qs_value(Req, Key, Default) of
2614- Default ->
2615- Default;
2616- Result ->
2617- ?JSON_DECODE(Result)
2618- end.
2619-
2620-qs(#httpd{mochi_req=MochiReq}) ->
2621- MochiReq:parse_qs().
2622-
2623-path(#httpd{mochi_req=MochiReq}) ->
2624- MochiReq:get(path).
2625-
2626-host_for_request(#httpd{mochi_req=MochiReq}) ->
2627- XHost = couch_config:get("httpd", "x_forwarded_host", "X-Forwarded-Host"),
2628- case MochiReq:get_header_value(XHost) of
2629- undefined ->
2630- case MochiReq:get_header_value("Host") of
2631- undefined ->
2632- {ok, {Address, Port}} = inet:sockname(MochiReq:get(socket)),
2633- inet_parse:ntoa(Address) ++ ":" ++ integer_to_list(Port);
2634- Value1 ->
2635- Value1
2636- end;
2637- Value -> Value
2638- end.
2639-
2640-absolute_uri(#httpd{mochi_req=MochiReq}=Req, Path) ->
2641- Host = host_for_request(Req),
2642- XSsl = couch_config:get("httpd", "x_forwarded_ssl", "X-Forwarded-Ssl"),
2643- Scheme = case MochiReq:get_header_value(XSsl) of
2644- "on" -> "https";
2645- _ ->
2646- XProto = couch_config:get("httpd", "x_forwarded_proto", "X-Forwarded-Proto"),
2647- case MochiReq:get_header_value(XProto) of
2648- %% Restrict to "https" and "http" schemes only
2649- "https" -> "https";
2650- _ -> case MochiReq:get(scheme) of
2651- https -> "https";
2652- http -> "http"
2653- end
2654- end
2655- end,
2656- Scheme ++ "://" ++ Host ++ Path.
2657-
2658-unquote(UrlEncodedString) ->
2659- mochiweb_util:unquote(UrlEncodedString).
2660-
2661-quote(UrlDecodedString) ->
2662- mochiweb_util:quote_plus(UrlDecodedString).
2663-
2664-parse_form(#httpd{mochi_req=MochiReq}) ->
2665- mochiweb_multipart:parse_form(MochiReq).
2666-
2667-recv(#httpd{mochi_req=MochiReq}, Len) ->
2668- MochiReq:recv(Len).
2669-
2670-recv_chunked(#httpd{mochi_req=MochiReq}, MaxChunkSize, ChunkFun, InitState) ->
2671- % Fun is called once with each chunk
2672- % Fun({Length, Binary}, State)
2673- % called with Length == 0 on the last time.
2674- MochiReq:stream_body(MaxChunkSize, ChunkFun, InitState).
2675-
2676-body_length(Req) ->
2677- case header_value(Req, "Transfer-Encoding") of
2678- undefined ->
2679- case header_value(Req, "Content-Length") of
2680- undefined -> undefined;
2681- Length -> list_to_integer(Length)
2682- end;
2683- "chunked" -> chunked;
2684- Unknown -> {unknown_transfer_encoding, Unknown}
2685- end.
2686-
2687-body(#httpd{mochi_req=MochiReq, req_body=undefined} = Req) ->
2688- case body_length(Req) of
2689- undefined ->
2690- MaxSize = list_to_integer(
2691- couch_config:get("couchdb", "max_document_size", "4294967296")),
2692- MochiReq:recv_body(MaxSize);
2693- chunked ->
2694- ChunkFun = fun({0, _Footers}, Acc) ->
2695- lists:reverse(Acc);
2696- ({_Len, Chunk}, Acc) ->
2697- [Chunk | Acc]
2698- end,
2699- recv_chunked(Req, 8192, ChunkFun, []);
2700- Len ->
2701- MochiReq:recv_body(Len)
2702- end;
2703-body(#httpd{req_body=ReqBody}) ->
2704- ReqBody.
2705-
2706-json_body(Httpd) ->
2707- ?JSON_DECODE(body(Httpd)).
2708-
2709-json_body_obj(Httpd) ->
2710- case json_body(Httpd) of
2711- {Props} -> {Props};
2712- _Else ->
2713- throw({bad_request, "Request body must be a JSON object"})
2714- end.
2715-
2716-
2717-
2718-doc_etag(#doc{revs={Start, [DiskRev|_]}}) ->
2719- "\"" ++ ?b2l(couch_doc:rev_to_str({Start, DiskRev})) ++ "\"".
2720-
2721-make_etag(Term) ->
2722- <<SigInt:128/integer>> = couch_util:md5(term_to_binary(Term)),
2723- iolist_to_binary([$", io_lib:format("~.36B", [SigInt]), $"]).
2724-
2725-etag_match(Req, CurrentEtag) when is_binary(CurrentEtag) ->
2726- etag_match(Req, binary_to_list(CurrentEtag));
2727-
2728-etag_match(Req, CurrentEtag) ->
2729- EtagsToMatch = string:tokens(
2730- header_value(Req, "If-None-Match", ""), ", "),
2731- lists:member(CurrentEtag, EtagsToMatch).
2732-
2733-etag_respond(Req, CurrentEtag, RespFun) ->
2734- case etag_match(Req, CurrentEtag) of
2735- true ->
2736- % the client has this in their cache.
2737- send_response(Req, 304, [{"ETag", CurrentEtag}], <<>>);
2738- false ->
2739- % Run the function.
2740- RespFun()
2741- end.
2742-
2743-verify_is_server_admin(#httpd{user_ctx=UserCtx}) ->
2744- verify_is_server_admin(UserCtx);
2745-verify_is_server_admin(#user_ctx{roles=Roles}) ->
2746- case lists:member(<<"_admin">>, Roles) of
2747- true -> ok;
2748- false -> throw({unauthorized, <<"You are not a server admin.">>})
2749- end.
2750-
2751-log_request(#httpd{mochi_req=MochiReq,peer=Peer}, Code) ->
2752- ?LOG_INFO("~s - - ~s ~s ~B", [
2753- Peer,
2754- MochiReq:get(method),
2755- MochiReq:get(raw_path),
2756- Code
2757- ]).
2758-
2759-
2760-start_response_length(#httpd{mochi_req=MochiReq}=Req, Code, Headers, Length) ->
2761- log_request(Req, Code),
2762- couch_stats_collector:increment({httpd_status_codes, Code}),
2763- Resp = MochiReq:start_response_length({Code, Headers ++ server_header() ++ couch_httpd_auth:cookie_auth_header(Req, Headers), Length}),
2764- case MochiReq:get(method) of
2765- 'HEAD' -> throw({http_head_abort, Resp});
2766- _ -> ok
2767- end,
2768- {ok, Resp}.
2769-
2770-start_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers) ->
2771- log_request(Req, Code),
2772- couch_stats_collector:increment({httpd_status_cdes, Code}),
2773- CookieHeader = couch_httpd_auth:cookie_auth_header(Req, Headers),
2774- Headers2 = Headers ++ server_header() ++ CookieHeader,
2775- Resp = MochiReq:start_response({Code, Headers2}),
2776- case MochiReq:get(method) of
2777- 'HEAD' -> throw({http_head_abort, Resp});
2778- _ -> ok
2779- end,
2780- {ok, Resp}.
2781-
2782-send(Resp, Data) ->
2783- Resp:send(Data),
2784- {ok, Resp}.
2785-
2786-no_resp_conn_header([]) ->
2787- true;
2788-no_resp_conn_header([{Hdr, _}|Rest]) ->
2789- case string:to_lower(Hdr) of
2790- "connection" -> false;
2791- _ -> no_resp_conn_header(Rest)
2792- end.
2793-
2794-http_1_0_keep_alive(Req, Headers) ->
2795- KeepOpen = Req:should_close() == false,
2796- IsHttp10 = Req:get(version) == {1, 0},
2797- NoRespHeader = no_resp_conn_header(Headers),
2798- case KeepOpen andalso IsHttp10 andalso NoRespHeader of
2799- true -> [{"Connection", "Keep-Alive"} | Headers];
2800- false -> Headers
2801- end.
2802-
2803-start_chunked_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers) ->
2804- log_request(Req, Code),
2805- couch_stats_collector:increment({httpd_status_codes, Code}),
2806- Headers2 = http_1_0_keep_alive(MochiReq, Headers),
2807- Resp = MochiReq:respond({Code, Headers2 ++ server_header() ++ couch_httpd_auth:cookie_auth_header(Req, Headers2), chunked}),
2808- case MochiReq:get(method) of
2809- 'HEAD' -> throw({http_head_abort, Resp});
2810- _ -> ok
2811- end,
2812- {ok, Resp}.
2813-
2814-send_chunk(Resp, Data) ->
2815- case iolist_size(Data) of
2816- 0 -> ok; % do nothing
2817- _ -> Resp:write_chunk(Data)
2818- end,
2819- {ok, Resp}.
2820-
2821-last_chunk(Resp) ->
2822- Resp:write_chunk([]),
2823- {ok, Resp}.
2824-
2825-send_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers, Body) ->
2826- log_request(Req, Code),
2827- couch_stats_collector:increment({httpd_status_codes, Code}),
2828- Headers2 = http_1_0_keep_alive(MochiReq, Headers),
2829- if Code >= 400 ->
2830- ?LOG_DEBUG("httpd ~p error response:~n ~s", [Code, Body]);
2831- true -> ok
2832- end,
2833- {ok, MochiReq:respond({Code, Headers2 ++ server_header() ++ couch_httpd_auth:cookie_auth_header(Req, Headers2), Body})}.
2834-
2835-send_method_not_allowed(Req, Methods) ->
2836- send_error(Req, 405, [{"Allow", Methods}], <<"method_not_allowed">>, ?l2b("Only " ++ Methods ++ " allowed")).
2837-
2838-send_json(Req, Value) ->
2839- send_json(Req, 200, Value).
2840-
2841-send_json(Req, Code, Value) ->
2842- send_json(Req, Code, [], Value).
2843-
2844-send_json(Req, Code, Headers, Value) ->
2845- initialize_jsonp(Req),
2846- DefaultHeaders = [
2847- {"Content-Type", negotiate_content_type(Req)},
2848- {"Cache-Control", "must-revalidate"}
2849- ],
2850- Body = [start_jsonp(), ?JSON_ENCODE(Value), end_jsonp(), $\n],
2851- send_response(Req, Code, DefaultHeaders ++ Headers, Body).
2852-
2853-start_json_response(Req, Code) ->
2854- start_json_response(Req, Code, []).
2855-
2856-start_json_response(Req, Code, Headers) ->
2857- initialize_jsonp(Req),
2858- DefaultHeaders = [
2859- {"Content-Type", negotiate_content_type(Req)},
2860- {"Cache-Control", "must-revalidate"}
2861- ],
2862- {ok, Resp} = start_chunked_response(Req, Code, DefaultHeaders ++ Headers),
2863- case start_jsonp() of
2864- [] -> ok;
2865- Start -> send_chunk(Resp, Start)
2866- end,
2867- {ok, Resp}.
2868-
2869-end_json_response(Resp) ->
2870- send_chunk(Resp, end_jsonp() ++ [$\n]),
2871- last_chunk(Resp).
2872-
2873-initialize_jsonp(Req) ->
2874- case get(jsonp) of
2875- undefined -> put(jsonp, qs_value(Req, "callback", no_jsonp));
2876- _ -> ok
2877- end,
2878- case get(jsonp) of
2879- no_jsonp -> [];
2880- [] -> [];
2881- CallBack ->
2882- try
2883- % make sure jsonp is configured on (default off)
2884- case couch_config:get("httpd", "allow_jsonp", "false") of
2885- "true" ->
2886- validate_callback(CallBack);
2887- _Else ->
2888- put(jsonp, no_jsonp)
2889- end
2890- catch
2891- Error ->
2892- put(jsonp, no_jsonp),
2893- throw(Error)
2894- end
2895- end.
2896-
2897-start_jsonp() ->
2898- case get(jsonp) of
2899- no_jsonp -> [];
2900- [] -> [];
2901- CallBack -> CallBack ++ "("
2902- end.
2903-
2904-end_jsonp() ->
2905- case erlang:erase(jsonp) of
2906- no_jsonp -> [];
2907- [] -> [];
2908- _ -> ");"
2909- end.
2910-
2911-validate_callback(CallBack) when is_binary(CallBack) ->
2912- validate_callback(binary_to_list(CallBack));
2913-validate_callback([]) ->
2914- ok;
2915-validate_callback([Char | Rest]) ->
2916- case Char of
2917- _ when Char >= $a andalso Char =< $z -> ok;
2918- _ when Char >= $A andalso Char =< $Z -> ok;
2919- _ when Char >= $0 andalso Char =< $9 -> ok;
2920- _ when Char == $. -> ok;
2921- _ when Char == $_ -> ok;
2922- _ when Char == $[ -> ok;
2923- _ when Char == $] -> ok;
2924- _ ->
2925- throw({bad_request, invalid_callback})
2926- end,
2927- validate_callback(Rest).
2928-
2929-
2930-error_info({Error, Reason}) when is_list(Reason) ->
2931- error_info({Error, ?l2b(Reason)});
2932-error_info(bad_request) ->
2933- {400, <<"bad_request">>, <<>>};
2934-error_info({bad_request, Reason}) ->
2935- {400, <<"bad_request">>, Reason};
2936-error_info({query_parse_error, Reason}) ->
2937- {400, <<"query_parse_error">>, Reason};
2938-% Prior art for md5 mismatch resulting in a 400 is from AWS S3
2939-error_info(md5_mismatch) ->
2940- {400, <<"content_md5_mismatch">>, <<"Possible message corruption.">>};
2941-error_info(not_found) ->
2942- {404, <<"not_found">>, <<"missing">>};
2943-error_info({not_found, Reason}) ->
2944- {404, <<"not_found">>, Reason};
2945-error_info({not_acceptable, Reason}) ->
2946- {406, <<"not_acceptable">>, Reason};
2947-error_info(conflict) ->
2948- {409, <<"conflict">>, <<"Document update conflict.">>};
2949-error_info({forbidden, Msg}) ->
2950- {403, <<"forbidden">>, Msg};
2951-error_info({unauthorized, Msg}) ->
2952- {401, <<"unauthorized">>, Msg};
2953-error_info(file_exists) ->
2954- {412, <<"file_exists">>, <<"The database could not be "
2955- "created, the file already exists.">>};
2956-error_info({bad_ctype, Reason}) ->
2957- {415, <<"bad_content_type">>, Reason};
2958-error_info(requested_range_not_satisfiable) ->
2959- {416, <<"requested_range_not_satisfiable">>, <<"Requested range not satisfiable">>};
2960-error_info({error, illegal_database_name}) ->
2961- {400, <<"illegal_database_name">>, <<"Only lowercase characters (a-z), "
2962- "digits (0-9), and any of the characters _, $, (, ), +, -, and / "
2963- "are allowed. Must begin with a letter.">>};
2964-error_info({missing_stub, Reason}) ->
2965- {412, <<"missing_stub">>, Reason};
2966-error_info({Error, Reason}) ->
2967- ?LOG_ERROR("Uncaught server error: ~p", [{Error, Reason}]),
2968- {500, couch_util:to_binary(Error), couch_util:to_binary(Reason)};
2969-error_info(Error) ->
2970- ?LOG_ERROR("Uncaught server error: ~p", [Error]),
2971- {500, <<"unknown_error">>, couch_util:to_binary(Error)}.
2972-
2973-error_headers(#httpd{mochi_req=MochiReq}=Req, Code, ErrorStr, ReasonStr) ->
2974- if Code == 401 ->
2975- % this is where the basic auth popup is triggered
2976- case MochiReq:get_header_value("X-CouchDB-WWW-Authenticate") of
2977- undefined ->
2978- case couch_config:get("httpd", "WWW-Authenticate", nil) of
2979- nil ->
2980- % If the client is a browser and the basic auth popup isn't turned on
2981- % redirect to the session page.
2982- case ErrorStr of
2983- <<"unauthorized">> ->
2984- case couch_config:get("couch_httpd_auth", "authentication_redirect", nil) of
2985- nil -> {Code, []};
2986- AuthRedirect ->
2987- case couch_config:get("couch_httpd_auth", "require_valid_user", "false") of
2988- "true" ->
2989- % send the browser popup header no matter what if we are require_valid_user
2990- {Code, [{"WWW-Authenticate", "Basic realm=\"server\""}]};
2991- _False ->
2992- case MochiReq:accepts_content_type("application/json") of
2993- true ->
2994- {Code, []};
2995- false ->
2996- case MochiReq:accepts_content_type("text/html") of
2997- true ->
2998- % Redirect to the path the user requested, not
2999- % the one that is used internally.
3000- UrlReturnRaw = case MochiReq:get_header_value("x-couchdb-vhost-path") of
3001- undefined ->
3002- MochiReq:get(path);
3003- VHostPath ->
3004- VHostPath
3005- end,
3006- RedirectLocation = lists:flatten([
3007- AuthRedirect,
3008- "?return=", couch_util:url_encode(UrlReturnRaw),
3009- "&reason=", couch_util:url_encode(ReasonStr)
3010- ]),
3011- {302, [{"Location", absolute_uri(Req, RedirectLocation)}]};
3012- false ->
3013- {Code, []}
3014- end
3015- end
3016- end
3017- end;
3018- _Else ->
3019- {Code, []}
3020- end;
3021- Type ->
3022- {Code, [{"WWW-Authenticate", Type}]}
3023- end;
3024- Type ->
3025- {Code, [{"WWW-Authenticate", Type}]}
3026- end;
3027- true ->
3028- {Code, []}
3029- end.
3030-
3031-send_error(_Req, {already_sent, Resp, _Error}) ->
3032- {ok, Resp};
3033-
3034-send_error(Req, Error) ->
3035- {Code, ErrorStr, ReasonStr} = error_info(Error),
3036- {Code1, Headers} = error_headers(Req, Code, ErrorStr, ReasonStr),
3037- send_error(Req, Code1, Headers, ErrorStr, ReasonStr).
3038-
3039-send_error(Req, Code, ErrorStr, ReasonStr) ->
3040- send_error(Req, Code, [], ErrorStr, ReasonStr).
3041-
3042-send_error(Req, Code, Headers, ErrorStr, ReasonStr) ->
3043- send_json(Req, Code, Headers,
3044- {[{<<"error">>, ErrorStr},
3045- {<<"reason">>, ReasonStr}]}).
3046-
3047-% give the option for list functions to output html or other raw errors
3048-send_chunked_error(Resp, {_Error, {[{<<"body">>, Reason}]}}) ->
3049- send_chunk(Resp, Reason),
3050- last_chunk(Resp);
3051-
3052-send_chunked_error(Resp, Error) ->
3053- {Code, ErrorStr, ReasonStr} = error_info(Error),
3054- JsonError = {[{<<"code">>, Code},
3055- {<<"error">>, ErrorStr},
3056- {<<"reason">>, ReasonStr}]},
3057- send_chunk(Resp, ?l2b([$\n,?JSON_ENCODE(JsonError),$\n])),
3058- last_chunk(Resp).
3059-
3060-send_redirect(Req, Path) ->
3061- send_response(Req, 301, [{"Location", absolute_uri(Req, Path)}], <<>>).
3062-
3063-negotiate_content_type(Req) ->
3064- case get(jsonp) of
3065- no_jsonp -> negotiate_content_type1(Req);
3066- [] -> negotiate_content_type1(Req);
3067- _Callback -> "text/javascript"
3068- end.
3069-
3070-negotiate_content_type1(#httpd{mochi_req=MochiReq}) ->
3071- %% Determine the appropriate Content-Type header for a JSON response
3072- %% depending on the Accept header in the request. A request that explicitly
3073- %% lists the correct JSON MIME type will get that type, otherwise the
3074- %% response will have the generic MIME type "text/plain"
3075- AcceptedTypes = case MochiReq:get_header_value("Accept") of
3076- undefined -> [];
3077- AcceptHeader -> string:tokens(AcceptHeader, ", ")
3078- end,
3079- case lists:member("application/json", AcceptedTypes) of
3080- true -> "application/json";
3081- false -> "text/plain; charset=utf-8"
3082- end.
3083-
3084-server_header() ->
3085- [{"Server", "CouchDB/" ++ couch_server:get_version() ++
3086- " (Erlang OTP/" ++ erlang:system_info(otp_release) ++ ")"}].
3087-
3088-
3089--record(mp, {boundary, buffer, data_fun, callback}).
3090-
3091-
3092-parse_multipart_request(ContentType, DataFun, Callback) ->
3093- Boundary0 = iolist_to_binary(get_boundary(ContentType)),
3094- Boundary = <<"\r\n--", Boundary0/binary>>,
3095- Mp = #mp{boundary= Boundary,
3096- buffer= <<>>,
3097- data_fun=DataFun,
3098- callback=Callback},
3099- {Mp2, _NilCallback} = read_until(Mp, <<"--", Boundary0/binary>>,
3100- fun nil_callback/1),
3101- #mp{buffer=Buffer, data_fun=DataFun2, callback=Callback2} =
3102- parse_part_header(Mp2),
3103- {Buffer, DataFun2, Callback2}.
3104-
3105-nil_callback(_Data)->
3106- fun nil_callback/1.
3107-
3108-get_boundary({"multipart/" ++ _, Opts}) ->
3109- case couch_util:get_value("boundary", Opts) of
3110- S when is_list(S) ->
3111- S
3112- end;
3113-get_boundary(ContentType) ->
3114- {"multipart/" ++ _ , Opts} = mochiweb_util:parse_header(ContentType),
3115- get_boundary({"multipart/", Opts}).
3116-
3117-
3118-
3119-split_header(<<>>) ->
3120- [];
3121-split_header(Line) ->
3122- {Name, [$: | Value]} = lists:splitwith(fun (C) -> C =/= $: end,
3123- binary_to_list(Line)),
3124- [{string:to_lower(string:strip(Name)),
3125- mochiweb_util:parse_header(Value)}].
3126-
3127-read_until(#mp{data_fun=DataFun, buffer=Buffer}=Mp, Pattern, Callback) ->
3128- case find_in_binary(Pattern, Buffer) of
3129- not_found ->
3130- Callback2 = Callback(Buffer),
3131- {Buffer2, DataFun2} = DataFun(),
3132- Buffer3 = iolist_to_binary(Buffer2),
3133- read_until(Mp#mp{data_fun=DataFun2,buffer=Buffer3}, Pattern, Callback2);
3134- {partial, 0} ->
3135- {NewData, DataFun2} = DataFun(),
3136- read_until(Mp#mp{data_fun=DataFun2,
3137- buffer= iolist_to_binary([Buffer,NewData])},
3138- Pattern, Callback);
3139- {partial, Skip} ->
3140- <<DataChunk:Skip/binary, Rest/binary>> = Buffer,
3141- Callback2 = Callback(DataChunk),
3142- {NewData, DataFun2} = DataFun(),
3143- read_until(Mp#mp{data_fun=DataFun2,
3144- buffer= iolist_to_binary([Rest | NewData])},
3145- Pattern, Callback2);
3146- {exact, 0} ->
3147- PatternLen = size(Pattern),
3148- <<_:PatternLen/binary, Rest/binary>> = Buffer,
3149- {Mp#mp{buffer= Rest}, Callback};
3150- {exact, Skip} ->
3151- PatternLen = size(Pattern),
3152- <<DataChunk:Skip/binary, _:PatternLen/binary, Rest/binary>> = Buffer,
3153- Callback2 = Callback(DataChunk),
3154- {Mp#mp{buffer= Rest}, Callback2}
3155- end.
3156-
3157-
3158-parse_part_header(#mp{callback=UserCallBack}=Mp) ->
3159- {Mp2, AccCallback} = read_until(Mp, <<"\r\n\r\n">>,
3160- fun(Next) -> acc_callback(Next, []) end),
3161- HeaderData = AccCallback(get_data),
3162-
3163- Headers =
3164- lists:foldl(fun(Line, Acc) ->
3165- split_header(Line) ++ Acc
3166- end, [], re:split(HeaderData,<<"\r\n">>, [])),
3167- NextCallback = UserCallBack({headers, Headers}),
3168- parse_part_body(Mp2#mp{callback=NextCallback}).
3169-
3170-parse_part_body(#mp{boundary=Prefix, callback=Callback}=Mp) ->
3171- {Mp2, WrappedCallback} = read_until(Mp, Prefix,
3172- fun(Data) -> body_callback_wrapper(Data, Callback) end),
3173- Callback2 = WrappedCallback(get_callback),
3174- Callback3 = Callback2(body_end),
3175- case check_for_last(Mp2#mp{callback=Callback3}) of
3176- {last, #mp{callback=Callback3}=Mp3} ->
3177- Mp3#mp{callback=Callback3(eof)};
3178- {more, Mp3} ->
3179- parse_part_header(Mp3)
3180- end.
3181-
3182-acc_callback(get_data, Acc)->
3183- iolist_to_binary(lists:reverse(Acc));
3184-acc_callback(Data, Acc)->
3185- fun(Next) -> acc_callback(Next, [Data | Acc]) end.
3186-
3187-body_callback_wrapper(get_callback, Callback) ->
3188- Callback;
3189-body_callback_wrapper(Data, Callback) ->
3190- Callback2 = Callback({body, Data}),
3191- fun(Next) -> body_callback_wrapper(Next, Callback2) end.
3192-
3193-
3194-check_for_last(#mp{buffer=Buffer, data_fun=DataFun}=Mp) ->
3195- case Buffer of
3196- <<"--",_/binary>> -> {last, Mp};
3197- <<_, _, _/binary>> -> {more, Mp};
3198- _ -> % not long enough
3199- {Data, DataFun2} = DataFun(),
3200- check_for_last(Mp#mp{buffer= <<Buffer/binary, Data/binary>>,
3201- data_fun = DataFun2})
3202- end.
3203-
3204-find_in_binary(B, Data) when size(B) > 0 ->
3205- case size(Data) - size(B) of
3206- Last when Last < 0 ->
3207- partial_find(B, Data, 0, size(Data));
3208- Last ->
3209- find_in_binary(B, size(B), Data, 0, Last)
3210- end.
3211-
3212-find_in_binary(B, BS, D, N, Last) when N =< Last->
3213- case D of
3214- <<_:N/binary, B:BS/binary, _/binary>> ->
3215- {exact, N};
3216- _ ->
3217- find_in_binary(B, BS, D, 1 + N, Last)
3218- end;
3219-find_in_binary(B, BS, D, N, Last) when N =:= 1 + Last ->
3220- partial_find(B, D, N, BS - 1).
3221-
3222-partial_find(_B, _D, _N, 0) ->
3223- not_found;
3224-partial_find(B, D, N, K) ->
3225- <<B1:K/binary, _/binary>> = B,
3226- case D of
3227- <<_Skip:N/binary, B1/binary>> ->
3228- {partial, N};
3229- _ ->
3230- partial_find(B, D, 1 + N, K - 1)
3231- end.
3232-
3233-
3234
3235=== removed directory '.pc/logrotate_as_couchdb.patch'
3236=== removed directory '.pc/logrotate_as_couchdb.patch/etc'
3237=== removed directory '.pc/logrotate_as_couchdb.patch/etc/logrotate.d'
3238=== removed file '.pc/logrotate_as_couchdb.patch/etc/logrotate.d/couchdb.tpl.in'
3239--- .pc/logrotate_as_couchdb.patch/etc/logrotate.d/couchdb.tpl.in 2012-11-18 12:24:24 +0000
3240+++ .pc/logrotate_as_couchdb.patch/etc/logrotate.d/couchdb.tpl.in 1970-01-01 00:00:00 +0000
3241@@ -1,9 +0,0 @@
3242-%localstatelogdir%/*.log {
3243- weekly
3244- rotate 10
3245- copytruncate
3246- delaycompress
3247- compress
3248- notifempty
3249- missingok
3250-}
3251
3252=== removed directory '.pc/wait_for_couchdb_stop.patch'
3253=== removed directory '.pc/wait_for_couchdb_stop.patch/etc'
3254=== removed directory '.pc/wait_for_couchdb_stop.patch/etc/init'
3255=== removed file '.pc/wait_for_couchdb_stop.patch/etc/init/couchdb.tpl.in'
3256--- .pc/wait_for_couchdb_stop.patch/etc/init/couchdb.tpl.in 2012-11-18 12:24:24 +0000
3257+++ .pc/wait_for_couchdb_stop.patch/etc/init/couchdb.tpl.in 1970-01-01 00:00:00 +0000
3258@@ -1,157 +0,0 @@
3259-#!/bin/sh -e
3260-
3261-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
3262-# use this file except in compliance with the License. You may obtain a copy of
3263-# the License at
3264-#
3265-# http://www.apache.org/licenses/LICENSE-2.0
3266-#
3267-# Unless required by applicable law or agreed to in writing, software
3268-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
3269-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
3270-# License for the specific language governing permissions and limitations under
3271-# the License.
3272-
3273-### BEGIN INIT INFO
3274-# Provides: couchdb
3275-# Required-Start: $local_fs $remote_fs
3276-# Required-Stop: $local_fs $remote_fs
3277-# Default-Start: 2 3 4 5
3278-# Default-Stop: 0 1 6
3279-# Short-Description: Apache CouchDB init script
3280-# Description: Apache CouchDB init script for the database server.
3281-### END INIT INFO
3282-
3283-SCRIPT_OK=0
3284-SCRIPT_ERROR=1
3285-
3286-DESCRIPTION="database server"
3287-NAME=couchdb
3288-SCRIPT_NAME=`basename $0`
3289-COUCHDB=%bindir%/%couchdb_command_name%
3290-CONFIGURATION_FILE=%sysconfdir%/default/couchdb
3291-RUN_DIR=%localstaterundir%
3292-LSB_LIBRARY=/lib/lsb/init-functions
3293-
3294-if test ! -x $COUCHDB; then
3295- exit $SCRIPT_ERROR
3296-fi
3297-
3298-if test -r $CONFIGURATION_FILE; then
3299- . $CONFIGURATION_FILE
3300-fi
3301-
3302-log_daemon_msg () {
3303- # Dummy function to be replaced by LSB library.
3304-
3305- echo $@
3306-}
3307-
3308-log_end_msg () {
3309- # Dummy function to be replaced by LSB library.
3310-
3311- if test "$1" != "0"; then
3312- echo "Error with $DESCRIPTION: $NAME"
3313- fi
3314- return $1
3315-}
3316-
3317-if test -r $LSB_LIBRARY; then
3318- . $LSB_LIBRARY
3319-fi
3320-
3321-run_command () {
3322- command="$1"
3323- if test -n "$COUCHDB_OPTIONS"; then
3324- command="$command $COUCHDB_OPTIONS"
3325- fi
3326- if test -n "$COUCHDB_USER"; then
3327- if su $COUCHDB_USER -c "$command"; then
3328- return $SCRIPT_OK
3329- else
3330- return $SCRIPT_ERROR
3331- fi
3332- else
3333- if $command; then
3334- return $SCRIPT_OK
3335- else
3336- return $SCRIPT_ERROR
3337- fi
3338- fi
3339-}
3340-
3341-start_couchdb () {
3342- # Start Apache CouchDB as a background process.
3343-
3344- test -e "$RUN_DIR" || \
3345- install -m 755 -o "$COUCHDB_USER" -g "$COUCHDB_USER" -d "$RUN_DIR"
3346- command="$COUCHDB -b"
3347- if test -n "$COUCHDB_STDOUT_FILE"; then
3348- command="$command -o $COUCHDB_STDOUT_FILE"
3349- fi
3350- if test -n "$COUCHDB_STDERR_FILE"; then
3351- command="$command -e $COUCHDB_STDERR_FILE"
3352- fi
3353- if test -n "$COUCHDB_RESPAWN_TIMEOUT"; then
3354- command="$command -r $COUCHDB_RESPAWN_TIMEOUT"
3355- fi
3356- run_command "$command" > /dev/null
3357-}
3358-
3359-stop_couchdb () {
3360- # Stop the running Apache CouchDB process.
3361-
3362- run_command "$COUCHDB -d" > /dev/null
3363-}
3364-
3365-display_status () {
3366- # Display the status of the running Apache CouchDB process.
3367-
3368- run_command "$COUCHDB -s"
3369-}
3370-
3371-parse_script_option_list () {
3372- # Parse arguments passed to the script and take appropriate action.
3373-
3374- case "$1" in
3375- start)
3376- log_daemon_msg "Starting $DESCRIPTION" $NAME
3377- if start_couchdb; then
3378- log_end_msg $SCRIPT_OK
3379- else
3380- log_end_msg $SCRIPT_ERROR
3381- fi
3382- ;;
3383- stop)
3384- log_daemon_msg "Stopping $DESCRIPTION" $NAME
3385- if stop_couchdb; then
3386- log_end_msg $SCRIPT_OK
3387- else
3388- log_end_msg $SCRIPT_ERROR
3389- fi
3390- ;;
3391- restart|force-reload)
3392- log_daemon_msg "Restarting $DESCRIPTION" $NAME
3393- if stop_couchdb; then
3394- if start_couchdb; then
3395- log_end_msg $SCRIPT_OK
3396- else
3397- log_end_msg $SCRIPT_ERROR
3398- fi
3399- else
3400- log_end_msg $SCRIPT_ERROR
3401- fi
3402- ;;
3403- status)
3404- display_status
3405- ;;
3406- *)
3407- cat << EOF >&2
3408-Usage: $SCRIPT_NAME {start|stop|restart|force-reload|status}
3409-EOF
3410- exit $SCRIPT_ERROR
3411- ;;
3412- esac
3413-}
3414-
3415-parse_script_option_list $@
3416
3417=== modified file 'AUTHORS'
3418--- AUTHORS 2012-07-30 22:49:59 +0000
3419+++ AUTHORS 2013-08-30 22:06:57 +0000
3420@@ -20,5 +20,11 @@
3421 * Bob Dionne <bitdiddle@apache.org>
3422 * Dave Cottlehuber <dch@apache.org>
3423 * Jason Smith <jhs@apache.org>
3424+ * Joan Touzet <joant@ieee.org>
3425+ * Dale Harvey <dale@apache.org>
3426+ * Dirkjan Ochtman <djc@apache.org>
3427+ * Alexander Shorin <kxepal@apache.org>
3428+ * Garren Smith <garren@apache.org>
3429+ * Sue Lockwood <deathbear@apache.org>
3430
3431 For a list of other credits see the `THANKS` file.
3432
3433=== modified file 'BUGS'
3434--- BUGS 2009-04-14 16:32:45 +0000
3435+++ BUGS 2013-08-30 22:06:57 +0000
3436@@ -1,6 +1,8 @@
3437 Apache CouchDB BUGS
3438 ===================
3439
3440-Please see the [documentation][1] on how to report bugs with Apache CouchDB.
3441-
3442-[1] http://couchdb.apache.org/community/issues.html
3443+Visit our issue tracker:
3444+
3445+ https://issues.apache.org/jira/browse/CouchDB
3446+
3447+You can use this to report bugs, request features, or suggest enhancements.
3448
3449=== removed file 'CHANGES'
3450--- CHANGES 2012-07-30 22:49:59 +0000
3451+++ CHANGES 1970-01-01 00:00:00 +0000
3452@@ -1,874 +0,0 @@
3453-Apache CouchDB CHANGES
3454-======================
3455-
3456-Version 1.2.0
3457--------------
3458-
3459-Authentication:
3460-
3461- * Fix use of OAuth with VHosts and URL rewriting.
3462- * OAuth secrets can now be stored in the users system database
3463- as an alternative to key value pairs in the .ini configuration.
3464- By default this is disabled (secrets are stored in the .ini)
3465- but can be enabled via the .ini configuration key `use_users_db`
3466- in the `couch_httpd_oauth` section.
3467- * Documents in the _users database are no longer publicly
3468- readable.
3469- * Confidential information in the _replication database is no
3470- longer publicly readable.
3471- * Password hashes are now calculated by CouchDB. Clients are no
3472- longer required to do this manually.
3473- * Cookies used for authentication can be made persistent by enabling
3474- the .ini configuration key `allow_persistent_cookies' in the
3475- `couch_httpd_auth` section.
3476-
3477-Build System:
3478-
3479- * cURL is no longer required to build CouchDB as it is only
3480- used by the command line JS test runner. If cURL is available
3481- when building CouchJS you can enable the HTTP bindings by
3482- passing -H on the command line.
3483- * Temporarily made `make check` pass with R15B. A more thorough
3484- fix is in the works (COUCHDB-1424).
3485- * Fixed --with-js-include and --with-js-lib options.
3486- * Added --with-js-lib-name option.
3487-
3488-HTTP Interface:
3489-
3490- * Added a native JSON parser.
3491- * The _active_tasks API now offers more granular fields. Each
3492- task type is now able to expose different properties.
3493- * Added built-in changes feed filter `_view`.
3494- * Fixes to the `_changes` feed heartbeat option which caused
3495- heartbeats to be missed when used with a filter. This caused
3496- timeouts of continuous pull replications with a filter.
3497- * Properly restart the SSL socket on configuration changes.
3498-
3499-Replicator:
3500-
3501- * A new replicator implementation. It offers more performance and
3502- configuration options.
3503- * Passing non-string values to query_params is now a 400 bad
3504- request. This is to reduce the surprise that all parameters
3505- are converted to strings internally.
3506- * Added optional field `since_seq` to replication objects/documents.
3507- It allows to bootstrap a replication from a specific source sequence
3508- number.
3509- * Simpler replication cancellation. In addition to the current method,
3510- replications can now be canceled by specifying the replication ID
3511- instead of the original replication object/document.
3512-
3513-Storage System:
3514-
3515- * Added optional database and view index file compression (using Google's
3516- snappy or zlib's deflate). This feature is enabled by default, but it
3517- can be disabled by adapting local.ini accordingly. The on-disk format
3518- is upgraded on compaction and new DB/view creation to support this.
3519- * Several performance improvements, most notably regarding database writes
3520- and view indexing.
3521- * Computation of the size of the latest MVCC snapshot data and all its
3522- supporting metadata, both for database and view index files. This
3523- information is exposed as the `data_size` attribute in the database and
3524- view group information URIs.
3525- * The size of the buffers used for database and view compaction is now
3526- configurable.
3527- * Added support for automatic database and view compaction. This feature
3528- is disabled by default, but it can be enabled via the .ini configuration.
3529- * Performance improvements for the built-in changes feed filters `_doc_ids`
3530- and `_design'.
3531-
3532-View Server:
3533-
3534- * Add CoffeeScript (http://coffeescript.org/) as a first class view server
3535- language.
3536- * Fixed old index file descriptor leaks after a view cleanup.
3537- * The requested_path property keeps the pre-rewrite path even when no VHost
3538- configuration is matched.
3539- * Fixed incorrect reduce query results when using pagination parameters.
3540- * Made icu_driver work with Erlang R15B and later.
3541- * Avoid invalidating view indexes when running out of file descriptors.
3542-
3543-OAuth:
3544-
3545- * Updated bundled erlang_oauth library to the latest version.
3546-
3547-Futon:
3548-
3549- * The `Status` screen (active tasks) now displays two new task status
3550- fields: `Started on` and `Updated on`.
3551- * Futon remembers view code every time it is saved, allowing to save an
3552- edit that amounts to a revert.
3553-
3554-Log System:
3555-
3556- * Log correct stacktrace in all cases.
3557- * Improvements to log messages for file-related errors.
3558-
3559-Version 1.1.1
3560--------------
3561-
3562-* Support SpiderMonkey 1.8.5
3563-* Add configurable maximum to the number of bytes returned by _log.
3564-* Allow CommonJS modules to be an empty string.
3565-* Bump minimum Erlang version to R13B02.
3566-* Do not run deleted validate_doc_update functions.
3567-* ETags for views include current sequence if include_docs=true.
3568-* Fix bug where duplicates can appear in _changes feed.
3569-* Fix bug where update handlers break after conflict resolution.
3570-* Fix bug with _replicator where include "filter" could crash couch.
3571-* Fix crashes when compacting large views.
3572-* Fix file descriptor leak in _log
3573-* Fix missing revisions in _changes?style=all_docs.
3574-* Improve handling of compaction at max_dbs_open limit.
3575-* JSONP responses now send "text/javascript" for Content-Type.
3576-* Link to ICU 4.2 on Windows.
3577-* Permit forward slashes in path to update functions.
3578-* Reap couchjs processes that hit reduce_overflow error.
3579-* Status code can be specified in update handlers.
3580-* Support provides() in show functions.
3581-* _view_cleanup when ddoc has no views now removes all index files.
3582-* max_replication_retry_count now supports "infinity".
3583-* Fix replication crash when source database has a document with empty ID.
3584-* Fix deadlock when assigning couchjs processes to serve requests.
3585-* Fixes to the document multipart PUT API.
3586-* Fixes regarding file descriptor leaks for databases with views.
3587-
3588-Version 1.1.0
3589--------------
3590-
3591-All CHANGES for 1.0.2 and 1.0.3 also apply to 1.1.0.
3592-
3593-HTTP Interface:
3594-
3595- * Native SSL support.
3596- * Added support for HTTP range requests for attachments.
3597- * Added built-in filters for `_changes`: `_doc_ids` and `_design`.
3598- * Added configuration option for TCP_NODELAY aka "Nagle".
3599- * Allow POSTing arguments to `_changes`.
3600- * Allow `keys` parameter for GET requests to views.
3601- * Allow wildcards in vhosts definitions.
3602- * More granular ETag support for views.
3603- * More flexible URL rewriter.
3604- * Added support for recognizing "Q values" and media parameters in
3605- HTTP Accept headers.
3606- * Validate doc ids that come from a PUT to a URL.
3607-
3608-Externals:
3609-
3610- * Added OS Process module to manage daemons outside of CouchDB.
3611- * Added HTTP Proxy handler for more scalable externals.
3612-
3613-Replicator:
3614-
3615- * Added `_replicator` database to manage replications.
3616- * Fixed issues when an endpoint is a remote database accessible via SSL.
3617- * Added support for continuous by-doc-IDs replication.
3618- * Fix issue where revision info was omitted when replicating attachments.
3619- * Integrity of attachment replication is now verified by MD5.
3620-
3621-Storage System:
3622-
3623- * Multiple micro-optimizations when reading data.
3624-
3625-View Server:
3626-
3627- * Added CommonJS support to map functions.
3628- * Added `stale=update_after` query option that triggers a view update after
3629- returning a `stale=ok` response.
3630- * Warn about empty result caused by `startkey` and `endkey` limiting.
3631- * Built-in reduce function `_sum` now accepts lists of integers as input.
3632- * Added view query aliases start_key, end_key, start_key_doc_id and
3633- end_key_doc_id.
3634-
3635-Futon:
3636-
3637- * Added a "change password"-feature to Futon.
3638-
3639-URL Rewriter & Vhosts:
3640-
3641- * Fix for variable substituion
3642-
3643-Version 1.0.3
3644--------------
3645-
3646-General:
3647-
3648- * Fixed compatibility issues with Erlang R14B02.
3649-
3650-HTTP Interface:
3651-
3652- * Fix bug that allows invalid UTF-8 after valid escapes.
3653- * The query parameter `include_docs` now honors the parameter `conflicts`.
3654- This applies to queries against map views, _all_docs and _changes.
3655- * Added support for inclusive_end with reduce views.
3656-
3657-Storage System:
3658-
3659- * More performant queries against _changes and _all_docs when using the
3660- `include_docs` parameter.
3661-
3662-Replicator:
3663-
3664- * Enabled replication over IPv6.
3665- * Fixed for crashes in continuous and filtered changes feeds.
3666- * Fixed error when restarting replications in OTP R14B02.
3667- * Upgrade ibrowse to version 2.2.0.
3668- * Fixed bug when using a filter and a limit of 1.
3669-
3670-Security:
3671-
3672- * Fixed OAuth signature computation in OTP R14B02.
3673- * Handle passwords with : in them.
3674-
3675-Futon:
3676-
3677- * Made compatible with jQuery 1.5.x.
3678-
3679-Etap Test Suite:
3680-
3681- * Etap tests no longer require use of port 5984. They now use a randomly
3682- selected port so they won't clash with a running CouchDB.
3683-
3684-Windows:
3685-
3686- * Windows builds now require ICU >= 4.4.0 and Erlang >= R14B03. See
3687- COUCHDB-1152, and COUCHDB-963 + OTP-9139 for more information.
3688-
3689-Version 1.0.2
3690--------------
3691-
3692-Futon:
3693-
3694- * Make test suite work with Safari and Chrome.
3695- * Fixed animated progress spinner.
3696- * Fix raw view document link due to overzealous URI encoding.
3697- * Spell javascript correctly in loadScript(uri).
3698-
3699-Storage System:
3700-
3701- * Fix leaking file handles after compacting databases and views.
3702- * Fix databases forgetting their validation function after compaction.
3703- * Fix occasional timeout errors after successfully compacting large databases.
3704- * Fix ocassional error when writing to a database that has just been compacted.
3705- * Fix occasional timeout errors on systems with slow or heavily loaded IO.
3706- * Fix for OOME when compactions include documents with many conflicts.
3707- * Fix for missing attachment compression when MIME types included parameters.
3708- * Preserve purge metadata during compaction to avoid spurious view rebuilds.
3709- * Fix spurious conflicts introduced when uploading an attachment after
3710- a doc has been in a conflict. See COUCHDB-902 for details.
3711- * Fix for frequently edited documents in multi-master deployments being
3712- duplicated in _changes and _all_docs. See COUCHDDB-968 for details on how
3713- to repair.
3714- * Significantly higher read and write throughput against database and
3715- view index files.
3716-
3717-Log System:
3718-
3719- * Reduce lengthy stack traces.
3720- * Allow logging of native <xml> types.
3721-
3722-HTTP Interface:
3723-
3724- * Allow reduce=false parameter in map-only views.
3725- * Fix parsing of Accept headers.
3726- * Fix for multipart GET APIs when an attachment was created during a
3727- local-local replication. See COUCHDB-1022 for details.
3728-
3729-Replicator:
3730-
3731- * Updated ibrowse library to 2.1.2 fixing numerous replication issues.
3732- * Make sure that the replicator respects HTTP settings defined in the config.
3733- * Fix error when the ibrowse connection closes unexpectedly.
3734- * Fix authenticated replication (with HTTP basic auth) of design documents
3735- with attachments.
3736- * Various fixes to make replication more resilient for edge-cases.
3737-
3738-View Server:
3739-
3740- * Don't trigger view updates when requesting `_design/doc/_info`.
3741- * Fix for circular references in CommonJS requires.
3742- * Made isArray() function available to functions executed in the query server.
3743- * Documents are now sealed before being passed to map functions.
3744- * Force view compaction failure when duplicated document data exists. When
3745- this error is seen in the logs users should rebuild their views from
3746- scratch to fix the issue. See COUCHDB-999 for details.
3747-
3748-Version 1.0.1
3749--------------
3750-
3751-Storage System:
3752-
3753- * Fix data corruption bug COUCHDB-844. Please see
3754- http://couchdb.apache.org/notice/1.0.1.html for details.
3755-
3756-Replicator:
3757-
3758- * Added support for replication via an HTTP/HTTPS proxy.
3759- * Fix pull replication of attachments from 0.11 to 1.0.x.
3760- * Make the _changes feed work with non-integer seqnums.
3761-
3762-HTTP Interface:
3763-
3764- * Expose `committed_update_seq` for monitoring purposes.
3765- * Show fields saved along with _deleted=true. Allows for auditing of deletes.
3766- * More robust Accept-header detection.
3767-
3768-Authentication:
3769-
3770- * Enable basic-auth popup when required to access the server, to prevent
3771- people from getting locked out.
3772-
3773-Futon:
3774-
3775- * User interface element for querying stale (cached) views.
3776-
3777-Build and System Integration:
3778-
3779- * Included additional source files for distribution.
3780-
3781-Version 1.0.0
3782--------------
3783-
3784-Security:
3785-
3786- * Added authentication caching, to avoid repeated opening and closing of the
3787- users database for each request requiring authentication.
3788-
3789-Storage System:
3790-
3791- * Small optimization for reordering result lists.
3792- * More efficient header commits.
3793- * Use O_APPEND to save lseeks.
3794- * Faster implementation of pread_iolist(). Further improves performance on
3795- concurrent reads.
3796-
3797-View Server:
3798-
3799- * Faster default view collation.
3800- * Added option to include update_seq in view responses.
3801-
3802-Version 0.11.2
3803---------------
3804-
3805-Replicator:
3806-
3807- * Fix bug when pushing design docs by non-admins, which was hanging the
3808- replicator for no good reason.
3809- * Fix bug when pulling design documents from a source that requires
3810- basic-auth.
3811-
3812-HTTP Interface:
3813-
3814- * Better error messages on invalid URL requests.
3815-
3816-Authentication:
3817-
3818- * User documents can now be deleted by admins or the user.
3819-
3820-Security:
3821-
3822- * Avoid potential DOS attack by guarding all creation of atoms.
3823-
3824-Futon:
3825-
3826- * Add some Futon files that were missing from the Makefile.
3827-
3828-Version 0.11.1
3829---------------
3830-
3831-HTTP Interface:
3832-
3833- * Mask passwords in active tasks and logging.
3834- * Update mochijson2 to allow output of BigNums not in float form.
3835- * Added support for X-HTTP-METHOD-OVERRIDE.
3836- * Better error message for database names.
3837- * Disable jsonp by default.
3838- * Accept gzip encoded standalone attachments.
3839- * Made max_concurrent_connections configurable.
3840- * Made changes API more robust.
3841- * Send newly generated document rev to callers of an update function.
3842-
3843-Futon:
3844-
3845- * Use "expando links" for over-long document values in Futon.
3846- * Added continuous replication option.
3847- * Added option to replicating test results anonymously to a community
3848- CouchDB instance.
3849- * Allow creation and deletion of config entries.
3850- * Fixed display issues with doc ids that have escaped characters.
3851- * Fixed various UI issues.
3852-
3853-Build and System Integration:
3854-
3855- * Output of `couchdb --help` has been improved.
3856- * Fixed compatibility with the Erlang R14 series.
3857- * Fixed warnings on Linux builds.
3858- * Fixed build error when aclocal needs to be called during the build.
3859- * Require ICU 4.3.1.
3860- * Fixed compatibility with Solaris.
3861-
3862-Security:
3863-
3864- * Added authentication redirect URL to log in clients.
3865- * Fixed query parameter encoding issue in oauth.js.
3866- * Made authentication timeout configurable.
3867- * Temporary views are now admin-only resources.
3868-
3869-Storage System:
3870-
3871- * Don't require a revpos for attachment stubs.
3872- * Added checking to ensure when a revpos is sent with an attachment stub,
3873- it's correct.
3874- * Make file deletions async to avoid pauses during compaction and db
3875- deletion.
3876- * Fixed for wrong offset when writing headers and converting them to blocks,
3877- only triggered when header is larger than 4k.
3878- * Preserve _revs_limit and instance_start_time after compaction.
3879-
3880-Configuration System:
3881-
3882- * Fixed timeout with large .ini files.
3883-
3884-JavaScript Clients:
3885-
3886- * Added tests for couch.js and jquery.couch.js
3887- * Added changes handler to jquery.couch.js.
3888- * Added cache busting to jquery.couch.js if the user agent is msie.
3889- * Added support for multi-document-fetch (via _all_docs) to jquery.couch.js.
3890- * Added attachment versioning to jquery.couch.js.
3891- * Added option to control ensure_full_commit to jquery.couch.js.
3892- * Added list functionality to jquery.couch.js.
3893- * Fixed issues where bulkSave() wasn't sending a POST body.
3894-
3895-View Server:
3896-
3897- * Provide a UUID to update functions (and all other functions) that they can
3898- use to create new docs.
3899- * Upgrade CommonJS modules support to 1.1.1.
3900- * Fixed erlang filter funs and normalize filter fun API.
3901- * Fixed hang in view shutdown.
3902-
3903-Log System:
3904-
3905- * Log HEAD requests as HEAD, not GET.
3906- * Keep massive JSON blobs out of the error log.
3907- * Fixed a timeout issue.
3908-
3909-Replication System:
3910-
3911- * Refactored various internal APIs related to attachment streaming.
3912- * Fixed hanging replication.
3913- * Fixed keepalive issue.
3914-
3915-URL Rewriter & Vhosts:
3916-
3917- * Allow more complex keys in rewriter.
3918- * Allow global rewrites so system defaults are available in vhosts.
3919- * Allow isolation of databases with vhosts.
3920- * Fix issue with passing variables to query parameters.
3921-
3922-Test Suite:
3923-
3924- * Made the test suite overall more reliable.
3925-
3926-Version 0.11.0
3927---------------
3928-
3929-Security:
3930-
3931- * Fixed CVE-2010-0009: Apache CouchDB Timing Attack Vulnerability.
3932- * Added default cookie-authentication and users database.
3933- * Added Futon user interface for user signup and login.
3934- * Added per-database reader access control lists.
3935- * Added per-database security object for configuration data in validation
3936- functions.
3937- * Added proxy authentication handler
3938-
3939-HTTP Interface:
3940-
3941- * Provide Content-MD5 header support for attachments.
3942- * Added URL Rewriter handler.
3943- * Added virtual host handling.
3944-
3945-View Server:
3946-
3947- * Added optional 'raw' binary collation for faster view builds where Unicode
3948- collation is not important.
3949- * Improved view index build time by reducing ICU collation callouts.
3950- * Improved view information objects.
3951- * Bug fix for partial updates during view builds.
3952- * Move query server to a design-doc based protocol.
3953- * Use json2.js for JSON serialization for compatiblity with native JSON.
3954- * Major refactoring of couchjs to lay the groundwork for disabling cURL
3955- support. The new HTTP interaction acts like a synchronous XHR. Example usage
3956- of the new system is in the JavaScript CLI test runner.
3957-
3958-Replication:
3959-
3960- * Added option to implicitly create replication target databases.
3961- * Avoid leaking file descriptors on automatic replication restarts.
3962- * Added option to replicate a list of documents by id.
3963- * Allow continuous replication to be cancelled.
3964-
3965-Storage System:
3966-
3967- * Adds batching of multiple updating requests, to improve throughput with many
3968- writers. Removed the now redundant couch_batch_save module.
3969- * Adds configurable compression of attachments.
3970-
3971-Runtime Statistics:
3972-
3973- * Statistics are now calculated for a moving window instead of non-overlapping
3974- timeframes.
3975- * Fixed a problem with statistics timers and system sleep.
3976- * Moved statistic names to a term file in the priv directory.
3977-
3978-Futon:
3979-
3980- * Added a button for view compaction.
3981- * JSON strings are now displayed as-is in the document view, without the escaping of
3982- new-lines and quotes. That dramatically improves readability of multi-line
3983- strings.
3984- * Same goes for editing of JSON string values. When a change to a field value is
3985- submitted, and the value is not valid JSON it is assumed to be a string. This
3986- improves editing of multi-line strings a lot.
3987- * Hitting tab in textareas no longer moves focus to the next form field, but simply
3988- inserts a tab character at the current caret position.
3989- * Fixed some font declarations.
3990-
3991-Build and System Integration:
3992-
3993- * Updated and improved source documentation.
3994- * Fixed distribution preparation for building on Mac OS X.
3995- * Added support for building a Windows installer as part of 'make dist'.
3996- * Bug fix for building couch.app's module list.
3997- * ETap tests are now run during make distcheck. This included a number of
3998- updates to the build system to properly support VPATH builds.
3999- * Gavin McDonald setup a build-bot instance. More info can be found at
4000- http://ci.apache.org/buildbot.html
4001-
4002-Version 0.10.1
4003---------------
4004-
4005-Replicator:
4006-
4007- * Stability enhancements regarding redirects, timeouts, OAuth.
4008-
4009-Query Server:
4010-
4011- * Avoid process leaks
4012- * Allow list and view to span languages
4013-
4014-Stats:
4015-
4016- * Eliminate new process flood on system wake
4017-
4018-Build and System Integration:
4019-
4020- * Test suite now works with the distcheck target.
4021-
4022-Version 0.10.0
4023---------------
4024-
4025-Storage Format:
4026-
4027- * Add move headers with checksums to the end of database files for extra robust
4028- storage and faster storage.
4029-
4030-View Server:
4031-
4032- * Added native Erlang views for high-performance applications.
4033-
4034-HTTP Interface:
4035-
4036- * Added optional cookie-based authentication handler.
4037- * Added optional two-legged OAuth authentication handler.
4038-
4039-Build and System Integration:
4040-
4041- * Changed `couchdb` script configuration options.
4042- * Added default.d and local.d configuration directories to load sequence.
4043-
4044-
4045-Version 0.9.2
4046--------------
4047-
4048-Replication:
4049-
4050- * Fix replication with 0.10 servers initiated by an 0.9 server (COUCHDB-559).
4051-
4052-Build and System Integration:
4053-
4054- * Remove branch callbacks to allow building couchjs against newer versions of
4055- Spidermonkey.
4056-
4057-Version 0.9.1
4058--------------
4059-
4060-Build and System Integration:
4061-
4062- * PID file directory is now created by the SysV/BSD daemon scripts.
4063- * Fixed the environment variables shown by the configure script.
4064- * Fixed the build instructions shown by the configure script.
4065- * Updated ownership and permission advice in `README` for better security.
4066-
4067-Configuration and stats system:
4068-
4069- * Corrected missing configuration file error message.
4070- * Fixed incorrect recording of request time.
4071-
4072-Database Core:
4073-
4074- * Document validation for underscore prefixed variables.
4075- * Made attachment storage less sparse.
4076- * Fixed problems when a database with delayed commits pending is considered
4077- idle, and subject to losing changes when shutdown. (COUCHDB-334)
4078-
4079-External Handlers:
4080-
4081- * Fix POST requests.
4082-
4083-Futon:
4084-
4085- * Redirect when loading a deleted view URI from the cookie.
4086-
4087-HTTP Interface:
4088-
4089- * Attachment requests respect the "rev" query-string parameter.
4090-
4091-JavaScript View Server:
4092-
4093- * Useful JavaScript Error messages.
4094-
4095-Replication:
4096-
4097- * Added support for Unicode characters transmitted as UTF-16 surrogate pairs.
4098- * URL-encode attachment names when necessary.
4099- * Pull specific revisions of an attachment, instead of just the latest one.
4100- * Work around a rare chunk-merging problem in ibrowse.
4101- * Work with documents containing Unicode characters outside the Basic
4102- Multilingual Plane.
4103-
4104-Version 0.9.0
4105--------------
4106-
4107-Futon Utility Client:
4108-
4109- * Added pagination to the database listing page.
4110- * Implemented attachment uploading from the document page.
4111- * Added page that shows the current configuration, and allows modification of
4112- option values.
4113- * Added a JSON "source view" for document display.
4114- * JSON data in view rows is now syntax highlighted.
4115- * Removed the use of an iframe for better integration with browser history and
4116- bookmarking.
4117- * Full database listing in the sidebar has been replaced by a short list of
4118- recent databases.
4119- * The view editor now allows selection of the view language if there is more
4120- than one configured.
4121- * Added links to go to the raw view or document URI.
4122- * Added status page to display currently running tasks in CouchDB.
4123- * JavaScript test suite split into multiple files.
4124- * Pagination for reduce views.
4125-
4126-Design Document Resource Paths:
4127-
4128- * Added httpd_design_handlers config section.
4129- * Moved _view to httpd_design_handlers.
4130- * Added ability to render documents as non-JSON content-types with _show and
4131- _list functions, which are also httpd_design_handlers.
4132-
4133-HTTP Interface:
4134-
4135- * Added client side UUIDs for idempotent document creation
4136- * HTTP COPY for documents
4137- * Streaming of chunked attachment PUTs to disk
4138- * Remove negative count feature
4139- * Add include_docs option for view queries
4140- * Add multi-key view post for views
4141- * Query parameter validation
4142- * Use stale=ok to request potentially cached view index
4143- * External query handler module for full-text or other indexers.
4144- * Etags for attachments, views, shows and lists
4145- * Show and list functions for rendering documents and views as developer
4146- controlled content-types.
4147- * Attachment names may use slashes to allow uploading of nested directories
4148- (useful for static web hosting).
4149- * Option for a view to run over design documents.
4150- * Added newline to JSON responses. Closes bike-shed.
4151-
4152-Replication:
4153-
4154- * Using ibrowse.
4155- * Checkpoint replications so failures are less expensive.
4156- * Automatically retry of failed replications.
4157- * Stream attachments in pull-replication.
4158-
4159-Database Core:
4160-
4161- * Faster B-tree implementation.
4162- * Changed internal JSON term format.
4163- * Improvements to Erlang VM interactions under heavy load.
4164- * User context and administrator role.
4165- * Update validations with design document validation functions.
4166- * Document purge functionality.
4167- * Ref-counting for database file handles.
4168-
4169-Build and System Integration:
4170-
4171- * The `couchdb` script now supports system chainable configuration files.
4172- * The Mac OS X daemon script now redirects STDOUT and STDERR like SysV/BSD.
4173- * The build and system integration have been improved for portability.
4174- * Added COUCHDB_OPTIONS to etc/default/couchdb file.
4175- * Remove COUCHDB_INI_FILE and COUCHDB_PID_FILE from etc/default/couchdb file.
4176- * Updated `configure.ac` to manually link `libm` for portability.
4177- * Updated `configure.ac` to extended default library paths.
4178- * Removed inets configuration files.
4179- * Added command line test runner.
4180- * Created dev target for make.
4181-
4182-Configuration and stats system:
4183-
4184- * Separate default and local configuration files.
4185- * HTTP interface for configuration changes.
4186- * Statistics framework with HTTP query API.
4187-
4188-Version 0.8.1-incubating
4189-------------------------
4190-
4191-Database Core:
4192-
4193- * Fix for replication problems where the write queues can get backed up if the
4194- writes aren't happening fast enough to keep up with the reads. For a large
4195- replication, this can exhaust memory and crash, or slow down the machine
4196- dramatically. The fix keeps only one document in the write queue at a time.
4197- * Fix for databases sometimes incorrectly reporting that they contain 0
4198- documents after compaction.
4199- * CouchDB now uses ibrowse instead of inets for its internal HTTP client
4200- implementation. This means better replication stability.
4201-
4202-HTTP Interface:
4203-
4204- * Fix for chunked responses where chunks were always being split into multiple
4205- TCP packets, which caused problems with the test suite under Safari, and in
4206- some other cases.
4207- * Fix for an invalid JSON response body being returned for some kinds of
4208- views. (COUCHDB-84)
4209- * Fix for connections not getting closed after rejecting a chunked request.
4210- (COUCHDB-55)
4211- * CouchDB can now be bound to IPv6 addresses.
4212- * The HTTP `Server` header now contains the versions of CouchDB and Erlang.
4213-
4214-JavaScript View Server:
4215-
4216- * Sealing of documents has been disabled due to an incompatibility with
4217- SpiderMonkey 1.9.
4218- * Improve error handling for undefined values emitted by map functions.
4219- (COUCHDB-83)
4220-
4221-Build and System Integration:
4222-
4223- * The `couchdb` script no longer uses `awk` for configuration checks as this
4224- was causing portability problems.
4225- * Updated `sudo` example in `README` to use the `-i` option, this fixes
4226- problems when invoking from a directory the `couchdb` user cannot access.
4227-
4228-Futon:
4229-
4230- * The view selector dropdown should now work in Opera and Internet Explorer
4231- even when it includes optgroups for design documents. (COUCHDB-81)
4232-
4233-Version 0.8.0-incubating
4234-------------------------
4235-
4236-Database Core:
4237-
4238- * The view engine has been completely decoupled from the storage engine. Index
4239- data is now stored in separate files, and the format of the main database
4240- file has changed.
4241- * Databases can now be compacted to reclaim space used for deleted documents
4242- and old document revisions.
4243- * Support for incremental map/reduce views has been added.
4244- * To support map/reduce, the structure of design documents has changed. View
4245- values are now JSON objects containing at least a `map` member, and
4246- optionally a `reduce` member.
4247- * View servers are now identified by name (for example `javascript`) instead of
4248- by media type.
4249- * Automatically generated document IDs are now based on proper UUID generation
4250- using the crypto module.
4251- * The field `content-type` in the JSON representation of attachments has been
4252- renamed to `content_type` (underscore).
4253-
4254-HTTP Interface:
4255-
4256- * CouchDB now uses MochiWeb instead of inets for the HTTP server
4257- implementation. Among other things, this means that the extra configuration
4258- files needed for inets (such as `couch_httpd.conf`) are no longer used.
4259- * The HTTP interface now completely supports the `HEAD` method. (COUCHDB-3)
4260- * Improved compliance of `Etag` handling with the HTTP specification.
4261- (COUCHDB-13)
4262- * Etags are no longer included in responses to document `GET` requests that
4263- include query string parameters causing the JSON response to change without
4264- the revision or the URI having changed.
4265- * The bulk document update API has changed slightly on both the request and the
4266- response side. In addition, bulk updates are now atomic.
4267- * CouchDB now uses `TCP_NODELAY` to fix performance problems with persistent
4268- connections on some platforms due to nagling.
4269- * Including a `?descending=false` query string parameter in requests to views
4270- no longer raises an error.
4271- * Requests to unknown top-level reserved URLs (anything with a leading
4272- underscore) now return a `unknown_private_path` error instead of the
4273- confusing `illegal_database_name`.
4274- * The Temporary view handling now expects a JSON request body, where the JSON
4275- is an object with at least a `map` member, and optional `reduce` and
4276- `language` members.
4277- * Temporary views no longer determine the view server based on the Content-Type
4278- header of the `POST` request, but rather by looking for a `language` member
4279- in the JSON body of the request.
4280- * The status code of responses to `DELETE` requests is now 200 to reflect that
4281- that the deletion is performed synchronously.
4282-
4283-JavaScript View Server:
4284-
4285- * SpiderMonkey is no longer included with CouchDB, but rather treated as a
4286- normal external dependency. A simple C program (`_couchjs`) is provided that
4287- links against an existing SpiderMonkey installation and uses the interpreter
4288- embedding API.
4289- * View functions using the default JavaScript view server can now do logging
4290- using the global `log(message)` function. Log messages are directed into the
4291- CouchDB log at `INFO` level. (COUCHDB-59)
4292- * The global `map(key, value)` function made available to view code has been
4293- renamed to `emit(key, value)`.
4294- * Fixed handling of exceptions raised by view functions.
4295-
4296-Build and System Integration:
4297-
4298- * CouchDB can automatically respawn following a server crash.
4299- * Database server no longer refuses to start with a stale PID file.
4300- * System logrotate configuration provided.
4301- * Improved handling of ICU shared libraries.
4302- * The `couchdb` script now automatically enables SMP support in Erlang.
4303- * The `couchdb` and `couchjs` scripts have been improved for portability.
4304- * The build and system integration have been improved for portability.
4305-
4306-Futon:
4307-
4308- * When adding a field to a document, Futon now just adds a field with an
4309- autogenerated name instead of prompting for the name with a dialog. The name
4310- is automatically put into edit mode so that it can be changed immediately.
4311- * Fields are now sorted alphabetically by name when a document is displayed.
4312- * Futon can be used to create and update permanent views.
4313- * The maximum number of rows to display per page on the database page can now
4314- be adjusted.
4315- * Futon now uses the XMLHTTPRequest API asynchronously to communicate with the
4316- CouchDB HTTP server, so that most operations no longer block the browser.
4317- * View results sorting can now be switched between ascending and descending by
4318- clicking on the `Key` column header.
4319- * Fixed a bug where documents that contained a `@` character could not be
4320- viewed. (COUCHDB-12)
4321- * The database page now provides a `Compact` button to trigger database
4322- compaction. (COUCHDB-38)
4323- * Fixed portential double encoding of document IDs and other URI segments in
4324- many instances. (COUCHDB-39)
4325- * Improved display of attachments.
4326- * The JavaScript Shell has been removed due to unresolved licensing issues.
4327
4328=== modified file 'DEVELOPERS'
4329--- DEVELOPERS 2010-07-26 10:24:11 +0000
4330+++ DEVELOPERS 2013-08-30 22:06:57 +0000
4331@@ -1,6 +1,10 @@
4332 Apache CouchDB DEVELOPERS
4333 =========================
4334
4335+Before you start here, read `INSTALL.Unix` (or `INSTALL.Windows`) and
4336+follow the setup instructions including the installation of all the
4337+listed dependencies for your system.
4338+
4339 Only follow these instructions if you are building from a source checkout.
4340
4341 If you're unsure what this means, ignore this document.
4342@@ -10,30 +14,109 @@
4343
4344 You will need the following installed:
4345
4346+ * GNU Libtool (http://www.gnu.org/software/libtool/)
4347 * GNU Automake (>=1.6.3) (http://www.gnu.org/software/automake/)
4348- * GNU Autoconf (>=2.59) (http://www.gnu.org/software/autoconf/)
4349- * GNU Libtool (http://www.gnu.org/software/libtool/)
4350+ * GNU Autoconf (>=2.63) (http://www.gnu.org/software/autoconf/)
4351+ * GNU Autoconf Archive (http://www.gnu.org/software/autoconf-archive/)
4352+ * pkg-config (http://www.freedesktop.org/wiki/Software/pkg-config)
4353+
4354+You may also need:
4355+
4356+ * Sphinx (http://sphinx.pocoo.org/)
4357+ * LaTex (http://www.latex-project.org/)
4358+ * GNU Texinfo (http://www.gnu.org/software/texinfo/)
4359 * GNU help2man (http://www.gnu.org/software/help2man/)
4360-
4361-The `help2man` tool is optional, but will generate `man` pages for you.
4362+ * GnuPG (http://www.gnupg.org/)
4363+ * md5sum (http://www.microbrew.org/tools/md5sha1sum/)
4364+ * sha1sum (http://www.microbrew.org/tools/md5sha1sum/)
4365+
4366+The first of these optional dependencies are required for building the
4367+documentation. The last three are needed to build releases.
4368+
4369+You will need these optional dependencies installed if:
4370+
4371+ * You are working on the documentation, or
4372+ * You are preparing a distribution archive
4373+
4374+However, you do not need them if:
4375+
4376+ * You are building from a distribution archive, or
4377+ * You don't care about building the documentation
4378+
4379+
4380+Here is a list of *optional* dependencies for various operating systems.
4381+Installation will be easiest, when you install them all.
4382
4383 Debian-based (inc. Ubuntu) Systems
4384 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4385
4386-You can install the dependencies by running:
4387-
4388- apt-get install automake autoconf libtool help2man
4389-
4390-Be sure to update the version numbers to match your system's available packages.
4391+ sudo apt-get install help2man
4392+ sudo apt-get install python-sphinx
4393+ sudo apt-get install texlive-latex-base
4394+ sudo apt-get install texlive-latex-recommended
4395+ sudo apt-get install texlive-latex-extra
4396+ sudo apt-get install texlive-fonts-recommended
4397+ sudo apt-get install texinfo
4398+ sudo apt-get install gnupg
4399+
4400+Gentoo-based Systems
4401+~~~~~~~~~~~~~~~~~~~~
4402+
4403+ sudo emerge texinfo
4404+ sudo emerge gnupg
4405+ sudo emerge coreutils
4406+ sudo emerge pkgconfig
4407+ sudo emerge help2man
4408+ sudo USE=latex emerge sphinx
4409+
4410+RedHat-based (Fedora, Centos, RHEL) Systems
4411+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4412+
4413+ sudo yum install help2man
4414+ sudo yum install python-sphinx
4415+ sudo yum install python-docutils
4416+ sudo yum install python-pygments
4417+ sudo yum install texlive-latex
4418+ sudo yum install texlive-latex-fonts
4419+ sudo yum install texinfo
4420+ sudo yum install gnupg
4421
4422 Mac OS X
4423 ~~~~~~~~
4424
4425-You can install the dependencies by running:
4426-
4427- port install automake autoconf libtool help2man
4428-
4429-You will need MacPorts installed to use the `port` command.
4430+Install Homebrew, if you do not have it already:
4431+
4432+ https://github.com/mxcl/homebrew
4433+
4434+Unless you want to install the optional dependencies, skip to the next section.
4435+
4436+Install what else we can with Homebrew:
4437+
4438+ brew install help2man
4439+ brew install gnupg
4440+ brew install md5sha1sum
4441+
4442+If you don't already have pip installed, install it:
4443+
4444+ sudo easy_install pip
4445+
4446+Now, install the required Python packages:
4447+
4448+ sudo pip install sphinx
4449+ sudo pip install docutils
4450+ sudo pip install pygments
4451+
4452+Download MaxTeX from here:
4453+
4454+ http://www.tug.org/mactex/
4455+
4456+Follow the instructions to get a working LaTeX install on your system.
4457+
4458+Windows
4459+~~~~~~~
4460+
4461+Follow the instructions in INSTALL.Windows and build all components from
4462+source, using the same Visual C++ compiler and runtime.
4463
4464 Bootstrapping
4465 -------------
4466@@ -44,6 +127,33 @@
4467
4468 You must repeat this step every time you update your source checkout.
4469
4470+Configuring
4471+-----------
4472+
4473+Configure the source by running:
4474+
4475+ ./configure
4476+
4477+Note that this will not fail when the optional dependencies are missing.
4478+
4479+To ensure the optional dependencies are installed, run:
4480+
4481+ ./configure --enable-strictness
4482+
4483+If you don't care about docs and want to skip the whole thing, run:
4484+
4485+ ./configure --disable-docs
4486+
4487+If you're working on the build system itself, you can run:
4488+
4489+ ./configure --disable-tests
4490+
4491+This skips the tests allowing quicker `make' cycles.
4492+
4493+If you want to build it into different destination than `/usr/local`.
4494+
4495+ ./configure --prefix=/<your directory path>
4496+
4497 Testing
4498 -------
4499
4500@@ -60,13 +170,13 @@
4501 Releasing
4502 ---------
4503
4504+The release procedure is documented here:
4505+
4506+ https://wiki.apache.org/couchdb/Release_Procedure
4507+
4508 Unix-like Systems
4509 ~~~~~~~~~~~~~~~~~
4510
4511-Configure the source by running:
4512-
4513- ./configure
4514-
4515 Prepare the release artefacts by running:
4516
4517 make distcheck
4518@@ -80,10 +190,6 @@
4519 Microsoft Windows
4520 ~~~~~~~~~~~~~~~~~
4521
4522-Configure the source by running:
4523-
4524- ./configure
4525-
4526 Prepare the release artefacts by running:
4527
4528 make dist
4529
4530=== modified file 'INSTALL'
4531--- INSTALL 2012-07-30 22:49:54 +0000
4532+++ INSTALL 2013-08-30 22:06:57 +0000
4533@@ -1,19 +1,25 @@
4534 Installation Instructions
4535 *************************
4536
4537-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
4538-2006 Free Software Foundation, Inc.
4539+Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
4540+Inc.
4541
4542-This file is free documentation; the Free Software Foundation gives
4543-unlimited permission to copy, distribute and modify it.
4544+ Copying and distribution of this file, with or without modification,
4545+are permitted in any medium without royalty provided the copyright
4546+notice and this notice are preserved. This file is offered as-is,
4547+without warranty of any kind.
4548
4549 Basic Installation
4550 ==================
4551
4552-Briefly, the shell commands `./configure; make; make install' should
4553+ Briefly, the shell commands `./configure; make; make install' should
4554 configure, build, and install this package. The following
4555 more-detailed instructions are generic; see the `README' file for
4556-instructions specific to this package.
4557+instructions specific to this package. Some packages provide this
4558+`INSTALL' file but do not implement all of the features documented
4559+below. The lack of an optional feature in a given package is not
4560+necessarily a bug. More recommendations for GNU packages can be found
4561+in *note Makefile Conventions: (standards)Makefile Conventions.
4562
4563 The `configure' shell script attempts to guess correct values for
4564 various system-dependent variables used during compilation. It uses
4565@@ -42,7 +48,7 @@
4566 you want to change it or regenerate `configure' using a newer version
4567 of `autoconf'.
4568
4569-The simplest way to compile this package is:
4570+ The simplest way to compile this package is:
4571
4572 1. `cd' to the directory containing the package's source code and type
4573 `./configure' to configure the package for your system.
4574@@ -53,12 +59,22 @@
4575 2. Type `make' to compile the package.
4576
4577 3. Optionally, type `make check' to run any self-tests that come with
4578- the package.
4579+ the package, generally using the just-built uninstalled binaries.
4580
4581 4. Type `make install' to install the programs and any data files and
4582- documentation.
4583-
4584- 5. You can remove the program binaries and object files from the
4585+ documentation. When installing into a prefix owned by root, it is
4586+ recommended that the package be configured and built as a regular
4587+ user, and only the `make install' phase executed with root
4588+ privileges.
4589+
4590+ 5. Optionally, type `make installcheck' to repeat any self-tests, but
4591+ this time using the binaries in their final installed location.
4592+ This target does not install anything. Running this target as a
4593+ regular user, particularly if the prior `make install' required
4594+ root privileges, verifies that the installation completed
4595+ correctly.
4596+
4597+ 6. You can remove the program binaries and object files from the
4598 source code directory by typing `make clean'. To also remove the
4599 files that `configure' created (so you can compile the package for
4600 a different kind of computer), type `make distclean'. There is
4601@@ -67,12 +83,22 @@
4602 all sorts of other programs in order to regenerate files that came
4603 with the distribution.
4604
4605+ 7. Often, you can also type `make uninstall' to remove the installed
4606+ files again. In practice, not all packages have tested that
4607+ uninstallation works correctly, even though it is required by the
4608+ GNU Coding Standards.
4609+
4610+ 8. Some packages, particularly those that use Automake, provide `make
4611+ distcheck', which can by used by developers to test that all other
4612+ targets like `make install' and `make uninstall' work correctly.
4613+ This target is generally not run by end users.
4614+
4615 Compilers and Options
4616 =====================
4617
4618-Some systems require unusual options for compilation or linking that the
4619-`configure' script does not know about. Run `./configure --help' for
4620-details on some of the pertinent environment variables.
4621+ Some systems require unusual options for compilation or linking that
4622+the `configure' script does not know about. Run `./configure --help'
4623+for details on some of the pertinent environment variables.
4624
4625 You can give `configure' initial values for configuration parameters
4626 by setting variables in the command line or in the environment. Here
4627@@ -85,25 +111,41 @@
4628 Compiling For Multiple Architectures
4629 ====================================
4630
4631-You can compile the package for more than one kind of computer at the
4632+ You can compile the package for more than one kind of computer at the
4633 same time, by placing the object files for each architecture in their
4634 own directory. To do this, you can use GNU `make'. `cd' to the
4635 directory where you want the object files and executables to go and run
4636 the `configure' script. `configure' automatically checks for the
4637-source code in the directory that `configure' is in and in `..'.
4638+source code in the directory that `configure' is in and in `..'. This
4639+is known as a "VPATH" build.
4640
4641 With a non-GNU `make', it is safer to compile the package for one
4642 architecture at a time in the source code directory. After you have
4643 installed the package for one architecture, use `make distclean' before
4644 reconfiguring for another architecture.
4645
4646+ On MacOS X 10.5 and later systems, you can create libraries and
4647+executables that work on multiple system types--known as "fat" or
4648+"universal" binaries--by specifying multiple `-arch' options to the
4649+compiler but only a single `-arch' option to the preprocessor. Like
4650+this:
4651+
4652+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
4653+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
4654+ CPP="gcc -E" CXXCPP="g++ -E"
4655+
4656+ This is not guaranteed to produce working output in all cases, you
4657+may have to build one architecture at a time and combine the results
4658+using the `lipo' tool if you have problems.
4659+
4660 Installation Names
4661 ==================
4662
4663-By default, `make install' installs the package's commands under
4664+ By default, `make install' installs the package's commands under
4665 `/usr/local/bin', include files under `/usr/local/include', etc. You
4666 can specify an installation prefix other than `/usr/local' by giving
4667-`configure' the option `--prefix=PREFIX'.
4668+`configure' the option `--prefix=PREFIX', where PREFIX must be an
4669+absolute file name.
4670
4671 You can specify separate installation prefixes for
4672 architecture-specific files and architecture-independent files. If you
4673@@ -114,16 +156,47 @@
4674 In addition, if you use an unusual directory layout you can give
4675 options like `--bindir=DIR' to specify different values for particular
4676 kinds of files. Run `configure --help' for a list of the directories
4677-you can set and what kinds of files go in them.
4678+you can set and what kinds of files go in them. In general, the
4679+default for these options is expressed in terms of `${prefix}', so that
4680+specifying just `--prefix' will affect all of the other directory
4681+specifications that were not explicitly provided.
4682+
4683+ The most portable way to affect installation locations is to pass the
4684+correct locations to `configure'; however, many packages provide one or
4685+both of the following shortcuts of passing variable assignments to the
4686+`make install' command line to change installation locations without
4687+having to reconfigure or recompile.
4688+
4689+ The first method involves providing an override variable for each
4690+affected directory. For example, `make install
4691+prefix=/alternate/directory' will choose an alternate location for all
4692+directory configuration variables that were expressed in terms of
4693+`${prefix}'. Any directories that were specified during `configure',
4694+but not in terms of `${prefix}', must each be overridden at install
4695+time for the entire installation to be relocated. The approach of
4696+makefile variable overrides for each directory variable is required by
4697+the GNU Coding Standards, and ideally causes no recompilation.
4698+However, some platforms have known limitations with the semantics of
4699+shared libraries that end up requiring recompilation when using this
4700+method, particularly noticeable in packages that use GNU Libtool.
4701+
4702+ The second method involves providing the `DESTDIR' variable. For
4703+example, `make install DESTDIR=/alternate/directory' will prepend
4704+`/alternate/directory' before all installation names. The approach of
4705+`DESTDIR' overrides is not required by the GNU Coding Standards, and
4706+does not work on platforms that have drive letters. On the other hand,
4707+it does better at avoiding recompilation issues, and works well even
4708+when some directory options were not specified in terms of `${prefix}'
4709+at `configure' time.
4710+
4711+Optional Features
4712+=================
4713
4714 If the package supports it, you can cause programs to be installed
4715 with an extra prefix or suffix on their names by giving `configure' the
4716 option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
4717
4718-Optional Features
4719-=================
4720-
4721-Some packages pay attention to `--enable-FEATURE' options to
4722+ Some packages pay attention to `--enable-FEATURE' options to
4723 `configure', where FEATURE indicates an optional part of the package.
4724 They may also pay attention to `--with-PACKAGE' options, where PACKAGE
4725 is something like `gnu-as' or `x' (for the X Window System). The
4726@@ -135,14 +208,58 @@
4727 you can use the `configure' options `--x-includes=DIR' and
4728 `--x-libraries=DIR' to specify their locations.
4729
4730+ Some packages offer the ability to configure how verbose the
4731+execution of `make' will be. For these packages, running `./configure
4732+--enable-silent-rules' sets the default to minimal output, which can be
4733+overridden with `make V=1'; while running `./configure
4734+--disable-silent-rules' sets the default to verbose, which can be
4735+overridden with `make V=0'.
4736+
4737+Particular systems
4738+==================
4739+
4740+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
4741+CC is not installed, it is recommended to use the following options in
4742+order to use an ANSI C compiler:
4743+
4744+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
4745+
4746+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
4747+
4748+ HP-UX `make' updates targets which have the same time stamps as
4749+their prerequisites, which makes it generally unusable when shipped
4750+generated files such as `configure' are involved. Use GNU `make'
4751+instead.
4752+
4753+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
4754+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
4755+a workaround. If GNU CC is not installed, it is therefore recommended
4756+to try
4757+
4758+ ./configure CC="cc"
4759+
4760+and if that doesn't work, try
4761+
4762+ ./configure CC="cc -nodtk"
4763+
4764+ On Solaris, don't put `/usr/ucb' early in your `PATH'. This
4765+directory contains several dysfunctional programs; working variants of
4766+these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
4767+in your `PATH', put it _after_ `/usr/bin'.
4768+
4769+ On Haiku, software installed for all users goes in `/boot/common',
4770+not `/usr/local'. It is recommended to use the following options:
4771+
4772+ ./configure --prefix=/boot/common
4773+
4774 Specifying the System Type
4775 ==========================
4776
4777-There may be some features `configure' cannot figure out automatically,
4778-but needs to determine by the type of machine the package will run on.
4779-Usually, assuming the package is built to be run on the _same_
4780-architectures, `configure' can figure that out, but if it prints a
4781-message saying it cannot guess the machine type, give it the
4782+ There may be some features `configure' cannot figure out
4783+automatically, but needs to determine by the type of machine the package
4784+will run on. Usually, assuming the package is built to be run on the
4785+_same_ architectures, `configure' can figure that out, but if it prints
4786+a message saying it cannot guess the machine type, give it the
4787 `--build=TYPE' option. TYPE can either be a short name for the system
4788 type, such as `sun4', or a canonical name which has the form:
4789
4790@@ -150,7 +267,8 @@
4791
4792 where SYSTEM can have one of these forms:
4793
4794- OS KERNEL-OS
4795+ OS
4796+ KERNEL-OS
4797
4798 See the file `config.sub' for the possible values of each field. If
4799 `config.sub' isn't included in this package, then this package doesn't
4800@@ -168,9 +286,9 @@
4801 Sharing Defaults
4802 ================
4803
4804-If you want to set default values for `configure' scripts to share, you
4805-can create a site shell script called `config.site' that gives default
4806-values for variables like `CC', `cache_file', and `prefix'.
4807+ If you want to set default values for `configure' scripts to share,
4808+you can create a site shell script called `config.site' that gives
4809+default values for variables like `CC', `cache_file', and `prefix'.
4810 `configure' looks for `PREFIX/share/config.site' if it exists, then
4811 `PREFIX/etc/config.site' if it exists. Or, you can set the
4812 `CONFIG_SITE' environment variable to the location of the site script.
4813@@ -179,7 +297,7 @@
4814 Defining Variables
4815 ==================
4816
4817-Variables not defined in a site shell script can be set in the
4818+ Variables not defined in a site shell script can be set in the
4819 environment passed to `configure'. However, some packages may run
4820 configure again during the build, and the customized values of these
4821 variables may be lost. In order to avoid this problem, you should set
4822@@ -198,11 +316,19 @@
4823 `configure' Invocation
4824 ======================
4825
4826-`configure' recognizes the following options to control how it operates.
4827+ `configure' recognizes the following options to control how it
4828+operates.
4829
4830 `--help'
4831 `-h'
4832- Print a summary of the options to `configure', and exit.
4833+ Print a summary of all of the options to `configure', and exit.
4834+
4835+`--help=short'
4836+`--help=recursive'
4837+ Print a summary of the options unique to this package's
4838+ `configure', and exit. The `short' variant lists options used
4839+ only in the top level, while the `recursive' variant lists options
4840+ also present in any nested packages.
4841
4842 `--version'
4843 `-V'
4844@@ -229,6 +355,16 @@
4845 Look for the package's source code in directory DIR. Usually
4846 `configure' can determine that directory automatically.
4847
4848+`--prefix=DIR'
4849+ Use DIR as the installation prefix. *note Installation Names::
4850+ for more details, including other options available for fine-tuning
4851+ the installation locations.
4852+
4853+`--no-create'
4854+`-n'
4855+ Run the configure checks, but stop before creating any output
4856+ files.
4857+
4858 `configure' also accepts some other, not widely useful, options. Run
4859 `configure --help' for more details.
4860
4861
4862=== modified file 'INSTALL.Unix'
4863--- INSTALL.Unix 2012-07-30 22:49:59 +0000
4864+++ INSTALL.Unix 2013-08-30 22:06:57 +0000
4865@@ -3,6 +3,16 @@
4866
4867 A high-level guide to Unix-like systems, inc. Mac OS X and Ubuntu.
4868
4869+Community installation guides are available on the wiki:
4870+
4871+ http://wiki.apache.org/couchdb/Installation
4872+
4873+This document is the canonical source of installation information. However, many
4874+systems have gotchas that you need to be aware of. In addition, dependencies
4875+frequently change as distributions update their archives. If you're running into
4876+trouble, be sure to check out the wiki. If you have any tips to share, please
4877+also update the wiki so that others can benefit from your experience.
4878+
4879 Troubleshooting
4880 ---------------
4881
4882@@ -25,69 +35,91 @@
4883
4884 You should have the following installed:
4885
4886- * Erlang OTP (>=R12B5) (http://erlang.org/)
4887- * ICU (http://icu.sourceforge.net/)
4888- * OpenSSL (http://www.openssl.org/)
4889- * Mozilla SpiderMonkey (1.7) (http://www.mozilla.org/js/spidermonkey/)
4890- * GNU Make (http://www.gnu.org/software/make/)
4891- * GNU Compiler Collection (http://gcc.gnu.org/)
4892- * libcurl (http://curl.haxx.se/libcurl/)
4893- * help2man (http://www.gnu.org/s/help2man/)
4894+ * Erlang OTP (>=R13B04, <R17) (http://erlang.org/)
4895+ * ICU (http://icu-project.org/)
4896+ * OpenSSL (http://www.openssl.org/)
4897+ * Mozilla SpiderMonkey (1.7) (http://www.mozilla.org/js/spidermonkey/)
4898+ * GNU Make (http://www.gnu.org/software/make/)
4899+ * GNU Compiler Collection (http://gcc.gnu.org/)
4900+ * libcurl (http://curl.haxx.se/libcurl/)
4901+ * help2man (http://www.gnu.org/s/help2man/)
4902+ * Python (>=2.7) for docs (http://python.org/)
4903+ * Python Sphinx (>=1.1.3) (http://pypi.python.org/pypi/Sphinx)
4904
4905-It is recommended that you install Erlang OTP R12B-5 or above where possible.
4906+It is recommended that you install Erlang OTP R13B-4 or above where possible.
4907 You will only need libcurl if you plan to run the JavaScript test suite. And
4908 help2man is only need if you plan on installing the CouchDB man pages.
4909-
4910-Ubuntu
4911-~~~~~~
4912-
4913-For up to date instructions, please see:
4914-
4915- http://wiki.apache.org/couchdb/Installing_on_Ubuntu
4916-
4917-Unfortunately, it seems that installing dependancies on Ubuntu is troublesome.
4918+Python and Sphinx are only required for building the online documentation.
4919
4920 Debian-based Systems
4921 ~~~~~~~~~~~~~~~~~~~~
4922
4923-You can install the build tools by running:
4924+You can install the dependencies by running:
4925
4926 sudo apt-get install build-essential
4927-
4928-You can install the other dependencies by running:
4929-
4930- sudo apt-get install erlang libicu-dev libmozjs-dev libcurl4-openssl-dev
4931+ sudo apt-get install erlang-base-hipe
4932+ sudo apt-get install erlang-dev
4933+ sudo apt-get install erlang-manpages
4934+ sudo apt-get install erlang-eunit
4935+ sudo apt-get install erlang-nox
4936+ sudo apt-get install libicu-dev
4937+ sudo apt-get install libmozjs-dev
4938+ sudo apt-get install libcurl4-openssl-dev
4939+ sudo apt-get install pkg-config
4940+
4941+There are lots of Erlang packages. If there is a problem with your install, try
4942+a different mix. There is more information on the wiki. Additionally, you might
4943+want to install some of the optional Erlang tools which may also be useful.
4944
4945 Be sure to update the version numbers to match your system's available packages.
4946
4947+For up to date instructions, please see:
4948+
4949+ http://wiki.apache.org/couchdb/Installing_on_Debian
4950+
4951+ http://wiki.apache.org/couchdb/Installing_on_Ubuntu
4952+
4953+Unfortunately, it seems that installing dependencies on Ubuntu is troublesome.
4954+
4955+RedHat-based (Fedora, Centos, RHEL) Systems
4956+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4957+
4958+You can install the dependencies by running:
4959+
4960+ sudo yum groupinstall "Development Tools"
4961+ sudo yum install autoconf
4962+ sudo yum install autoconf-archive
4963+ sudo yum install automake
4964+ sudo yum install libtool
4965+ sudo yum install perl-Test-Harness
4966+ sudo yum install erlang-etap
4967+ sudo yum install erlang-erts
4968+ sudo yum install erlang-os_mon
4969+ sudo yum install erlang-eunit
4970+ sudo yum install libicu-devel
4971+ sudo yum install js-devel
4972+ sudo yum install curl-devel
4973+ sudo yum install pkg-config
4974+
4975+While CouchDB builds against the default js-devel-1.7.0 included in some
4976+distributions, it's recommended to use a more recent js-devel-1.8.5.
4977+
4978 Mac OS X
4979 ~~~~~~~~
4980
4981-You can install the build tools by running:
4982-
4983- open /Applications/Installers/Xcode\ Tools/XcodeTools.mpkg
4984+To build CouchDB from source on Mac OS X, you will need to install Xcode.
4985
4986 You can install the other dependencies by running:
4987
4988- brew install erlang icu4c spidermonkey curl
4989-
4990-You may want to link ICU so that CouchDB can find the header files automatically:
4991-
4992- brew link icu4c
4993-
4994-The same is true for recent versions of Erlang:
4995-
4996- brew link erlang
4997-
4998-If you are upgrading your version of CouchDB and have an older nspr and
4999-Spidermonkey installed you may encounter an error during the ./configure step
5000-below. This is generally due to nspr being installed without its pkg-config
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches