Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/certbot/certbot.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Warren <bmw@eff.org>2016-04-14 03:42:19 +0300
committerBrad Warren <bmw@eff.org>2016-04-14 03:42:19 +0300
commit214343ed6aa9db12524a45df34f5a26b73abed67 (patch)
tree8f3948fc4396ba9a95bdd78c5f119706bc54b17f /letshelp-certbot
parent0ce45a77f940013b1fc3f4e83b0e29102a98e69f (diff)
rename letshelp-letsencrypt
Diffstat (limited to 'letshelp-certbot')
-rw-r--r--letshelp-certbot/LICENSE.txt190
-rw-r--r--letshelp-certbot/MANIFEST.in4
-rw-r--r--letshelp-certbot/README.rst1
-rw-r--r--letshelp-certbot/docs/.gitignore1
-rw-r--r--letshelp-certbot/docs/Makefile192
-rw-r--r--letshelp-certbot/docs/_static/.gitignore0
-rw-r--r--letshelp-certbot/docs/_templates/.gitignore0
-rw-r--r--letshelp-certbot/docs/api.rst8
-rw-r--r--letshelp-certbot/docs/api/index.rst11
-rw-r--r--letshelp-certbot/docs/conf.py311
-rw-r--r--letshelp-certbot/docs/index.rst27
-rw-r--r--letshelp-certbot/docs/make.bat263
-rw-r--r--letshelp-certbot/letshelp_certbot/__init__.py1
-rwxr-xr-xletshelp-certbot/letshelp_certbot/apache.py307
-rw-r--r--letshelp-certbot/letshelp_certbot/apache_test.py234
-rw-r--r--letshelp-certbot/letshelp_certbot/testdata/mods-available/ssl.load2
l---------letshelp-certbot/letshelp_certbot/testdata/mods-enabled/ssl.load1
-rw-r--r--letshelp-certbot/letshelp_certbot/testdata/super_secret_file.txt1
-rw-r--r--letshelp-certbot/letshelp_certbot/testdata/uncommonly_named_k3y6
-rw-r--r--letshelp-certbot/letshelp_certbot/testdata/uncommonly_named_p4sswd1
-rw-r--r--letshelp-certbot/readthedocs.org.requirements.txt10
-rw-r--r--letshelp-certbot/setup.py59
22 files changed, 1630 insertions, 0 deletions
diff --git a/letshelp-certbot/LICENSE.txt b/letshelp-certbot/LICENSE.txt
new file mode 100644
index 000000000..981c46c9f
--- /dev/null
+++ b/letshelp-certbot/LICENSE.txt
@@ -0,0 +1,190 @@
+ Copyright 2015 Electronic Frontier Foundation and others
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
diff --git a/letshelp-certbot/MANIFEST.in b/letshelp-certbot/MANIFEST.in
new file mode 100644
index 000000000..623392f28
--- /dev/null
+++ b/letshelp-certbot/MANIFEST.in
@@ -0,0 +1,4 @@
+include LICENSE.txt
+include README.rst
+recursive-include docs *
+recursive-include letshelp_certbot/testdata *
diff --git a/letshelp-certbot/README.rst b/letshelp-certbot/README.rst
new file mode 100644
index 000000000..bbe2f2570
--- /dev/null
+++ b/letshelp-certbot/README.rst
@@ -0,0 +1 @@
+Let's help Certbot client
diff --git a/letshelp-certbot/docs/.gitignore b/letshelp-certbot/docs/.gitignore
new file mode 100644
index 000000000..ba65b13af
--- /dev/null
+++ b/letshelp-certbot/docs/.gitignore
@@ -0,0 +1 @@
+/_build/
diff --git a/letshelp-certbot/docs/Makefile b/letshelp-certbot/docs/Makefile
new file mode 100644
index 000000000..4b392ab8d
--- /dev/null
+++ b/letshelp-certbot/docs/Makefile
@@ -0,0 +1,192 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " applehelp to make an Apple Help Book"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+ @echo " coverage to run coverage check of the documentation (if enabled)"
+
+clean:
+ rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/letshelp-certbot.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/letshelp-certbot.qhc"
+
+applehelp:
+ $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
+ @echo
+ @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
+ @echo "N.B. You won't be able to view it unless you put it in" \
+ "~/Library/Documentation/Help or install it in your application" \
+ "bundle."
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/letshelp-certbot"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/letshelp-certbot"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+coverage:
+ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+ @echo "Testing of coverage in the sources finished, look at the " \
+ "results in $(BUILDDIR)/coverage/python.txt."
+
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/letshelp-certbot/docs/_static/.gitignore b/letshelp-certbot/docs/_static/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/letshelp-certbot/docs/_static/.gitignore
diff --git a/letshelp-certbot/docs/_templates/.gitignore b/letshelp-certbot/docs/_templates/.gitignore
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/letshelp-certbot/docs/_templates/.gitignore
diff --git a/letshelp-certbot/docs/api.rst b/letshelp-certbot/docs/api.rst
new file mode 100644
index 000000000..8668ec5d8
--- /dev/null
+++ b/letshelp-certbot/docs/api.rst
@@ -0,0 +1,8 @@
+=================
+API Documentation
+=================
+
+.. toctree::
+ :glob:
+
+ api/**
diff --git a/letshelp-certbot/docs/api/index.rst b/letshelp-certbot/docs/api/index.rst
new file mode 100644
index 000000000..5ced5f501
--- /dev/null
+++ b/letshelp-certbot/docs/api/index.rst
@@ -0,0 +1,11 @@
+:mod:`letshelp_certbot`
+---------------------------
+
+.. automodule:: letshelp_certbot
+ :members:
+
+:mod:`letshelp_certbot.apache`
+==================================
+
+.. automodule:: letshelp_certbot.apache
+ :members:
diff --git a/letshelp-certbot/docs/conf.py b/letshelp-certbot/docs/conf.py
new file mode 100644
index 000000000..ba669113a
--- /dev/null
+++ b/letshelp-certbot/docs/conf.py
@@ -0,0 +1,311 @@
+# -*- coding: utf-8 -*-
+#
+# letshelp-certbot documentation build configuration file, created by
+# sphinx-quickstart on Sun Oct 18 13:40:19 2015.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+import shlex
+
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath(os.path.join(here, '..')))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.intersphinx',
+ 'sphinx.ext.todo',
+ 'sphinx.ext.coverage',
+ 'sphinx.ext.viewcode',
+]
+
+autodoc_member_order = 'bysource'
+autodoc_default_flags = ['show-inheritance', 'private-members']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'letshelp-certbot'
+copyright = u'2014-2015, Let\'s Encrypt Project'
+author = u'Let\'s Encrypt Project'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0'
+# The full version, including alpha/beta/rc tags.
+release = '0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = 'en'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+default_role = 'py:obj'
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = True
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+
+# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs
+# on_rtd is whether we are on readthedocs.org
+on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
+if not on_rtd: # only import and set the theme if we're building docs locally
+ import sphinx_rtd_theme
+ html_theme = 'sphinx_rtd_theme'
+ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
+# otherwise, readthedocs.org uses their theme by default, so no need to specify it
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
+# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
+#html_search_language = 'en'
+
+# A dictionary with options for the search language support, empty by default.
+# Now only 'ja' uses this config value
+#html_search_options = {'type': 'default'}
+
+# The name of a javascript file (relative to the configuration directory) that
+# implements a search results scorer. If empty, the default will be used.
+#html_search_scorer = 'scorer.js'
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'letshelp-certbotdoc'
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+ # The paper size ('letterpaper' or 'a4paper').
+ #'papersize': 'letterpaper',
+
+ # The font size ('10pt', '11pt' or '12pt').
+ #'pointsize': '10pt',
+
+ # Additional stuff for the LaTeX preamble.
+ #'preamble': '',
+
+ # Latex figure (float) alignment
+ #'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (master_doc, 'letshelp-certbot.tex', u'letshelp-certbot Documentation',
+ u'Let\'s Encrypt Project', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'letshelp-certbot', u'letshelp-certbot Documentation',
+ [author], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'letshelp-certbot', u'letshelp-certbot Documentation',
+ author, 'letshelp-certbot', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+
+intersphinx_mapping = {
+ 'python': ('https://docs.python.org/', None),
+ 'acme': ('https://acme-python.readthedocs.org/en/latest/', None),
+ 'certbot': ('https://letsencrypt.readthedocs.org/en/latest/', None),
+}
diff --git a/letshelp-certbot/docs/index.rst b/letshelp-certbot/docs/index.rst
new file mode 100644
index 000000000..678d9be2e
--- /dev/null
+++ b/letshelp-certbot/docs/index.rst
@@ -0,0 +1,27 @@
+.. letshelp-certbot documentation master file, created by
+ sphinx-quickstart on Sun Oct 18 13:40:19 2015.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to letshelp-certbot's documentation!
+================================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+
+.. toctree::
+ :maxdepth: 1
+
+ api
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/letshelp-certbot/docs/make.bat b/letshelp-certbot/docs/make.bat
new file mode 100644
index 000000000..0229b4f69
--- /dev/null
+++ b/letshelp-certbot/docs/make.bat
@@ -0,0 +1,263 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ echo. coverage to run coverage check of the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+REM Check if sphinx-build is available and fallback to Python version if any
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 goto sphinx_python
+goto sphinx_ok
+
+:sphinx_python
+
+set SPHINXBUILD=python -m sphinx.__init__
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+:sphinx_ok
+
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\letshelp-certbot.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\letshelp-certbot.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %~dp0
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "coverage" (
+ %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of coverage in the sources finished, look at the ^
+results in %BUILDDIR%/coverage/python.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+:end
diff --git a/letshelp-certbot/letshelp_certbot/__init__.py b/letshelp-certbot/letshelp_certbot/__init__.py
new file mode 100644
index 000000000..6882a19d4
--- /dev/null
+++ b/letshelp-certbot/letshelp_certbot/__init__.py
@@ -0,0 +1 @@
+"""Tools for submitting server configurations"""
diff --git a/letshelp-certbot/letshelp_certbot/apache.py b/letshelp-certbot/letshelp_certbot/apache.py
new file mode 100755
index 000000000..5752bdab0
--- /dev/null
+++ b/letshelp-certbot/letshelp_certbot/apache.py
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+"""Certbot Apache configuration submission script"""
+
+from __future__ import print_function
+
+import argparse
+import atexit
+import contextlib
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tarfile
+import tempfile
+import textwrap
+
+
+_DESCRIPTION = """
+Let's Help is a simple script you can run to help out the Certbot
+project. Since Certbot will support automatically configuring HTTPS on
+many servers, we want to test this functionality on as many configurations as
+possible. This script will create a sanitized copy of your Apache
+configuration, notifying you of the files that have been selected. If (and only
+if) you approve this selection, these files will be sent to the Certbot
+developers.
+
+"""
+
+
+_NO_APACHECTL = """
+Unable to find `apachectl` which is required for this script to work. If it is
+installed, please run this script again with the --apache-ctl command line
+argument and the path to the binary.
+
+"""
+
+
+# Keywords likely to be found in filenames of sensitive files
+_SENSITIVE_FILENAME_REGEX = re.compile(r"^(?!.*proxy_fdpass).*pass.*$|private|"
+ r"secret|^(?!.*certbot).*cert.*$|crt|"
+ r"key|rsa|dsa|pw|\.pem|\.der|\.p12|"
+ r"\.pfx|\.p7b")
+
+
+def make_and_verify_selection(server_root, temp_dir):
+ """Copies server_root to temp_dir and verifies selection with the user
+
+ :param str server_root: Path to the Apache server root
+ :param str temp_dir: Path to the temporary directory to copy files to
+
+ """
+ copied_files, copied_dirs = copy_config(server_root, temp_dir)
+
+ print(textwrap.fill("A secure copy of the files that have been selected "
+ "for submission has been created under {0}. All "
+ "comments have been removed and the files are only "
+ "accessible by the current user. A list of the files "
+ "that have been included is shown below. Please make "
+ "sure that this selection does not contain private "
+ "keys, passwords, or any other sensitive "
+ "information.".format(temp_dir)))
+ print("\nFiles:")
+ for copied_file in copied_files:
+ print(copied_file)
+ print("Directories (including all contained files):")
+ for copied_dir in copied_dirs:
+ print(copied_dir)
+
+ sys.stdout.write("\nIs it safe to submit these files? ")
+ while True:
+ ans = raw_input("(Y)es/(N)o: ").lower()
+ if ans.startswith("y"):
+ return
+ elif ans.startswith("n"):
+ sys.exit("Your files were not submitted")
+
+
+def copy_config(server_root, temp_dir):
+ """Safely copies server_root to temp_dir and returns copied files
+
+ :param str server_root: Absolute path to the Apache server root
+ :param str temp_dir: Path to the temporary directory to copy files to
+
+ :returns: List of copied files and a list of leaf directories where
+ all contained files were copied
+ :rtype: `tuple` of `list` of `str`
+
+ """
+ copied_files, copied_dirs = [], []
+ dir_len = len(os.path.dirname(server_root))
+
+ for config_path, config_dirs, config_files in os.walk(server_root):
+ temp_path = os.path.join(temp_dir, config_path[dir_len + 1:])
+ os.mkdir(temp_path)
+
+ copied_all = True
+ copied_files_in_current_dir = []
+ for config_file in config_files:
+ config_file_path = os.path.join(config_path, config_file)
+ temp_file_path = os.path.join(temp_path, config_file)
+ if os.path.islink(config_file_path):
+ os.symlink(os.readlink(config_file_path), temp_file_path)
+ elif safe_config_file(config_file_path):
+ copy_file_without_comments(config_file_path, temp_file_path)
+ copied_files_in_current_dir.append(config_file_path)
+ else:
+ copied_all = False
+
+ # If copied all files in leaf directory
+ if copied_all and not config_dirs:
+ copied_dirs.append(config_path)
+ else:
+ copied_files += copied_files_in_current_dir
+
+ return copied_files, copied_dirs
+
+
+def copy_file_without_comments(source, destination):
+ """Copies source to destination, removing comments
+
+ :param str source: Path to the file to be copied
+ :param str destination: Path where source should be copied to
+
+ """
+ with open(source, "r") as infile:
+ with open(destination, "w") as outfile:
+ for line in infile:
+ if not (line.isspace() or line.lstrip().startswith("#")):
+ outfile.write(line)
+
+
+def safe_config_file(config_file):
+ """Returns True if config_file can be safely copied
+
+ :param str config_file: Path to an Apache configuration file
+
+ :returns: True if config_file can be safely copied
+ :rtype: bool
+
+ """
+ config_file_lower = config_file.lower()
+ if _SENSITIVE_FILENAME_REGEX.search(config_file_lower):
+ return False
+
+ proc = subprocess.Popen(["file", config_file],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ file_output, _ = proc.communicate()
+
+ if "ASCII" in file_output:
+ possible_password_file = empty_or_all_comments = True
+ with open(config_file) as config_fd:
+ for line in config_fd:
+ if not (line.isspace() or line.lstrip().startswith("#")):
+ empty_or_all_comments = False
+ if line.startswith("-----BEGIN"):
+ return False
+ elif ":" not in line:
+ possible_password_file = False
+ # If file isn't empty or commented out and could be a password file,
+ # don't include it in selection. It is safe to include the file if
+ # it consists solely of comments because comments are removed before
+ # submission.
+ return empty_or_all_comments or not possible_password_file
+
+ return False
+
+
+def setup_tempdir(args):
+ """Creates a temporary directory and necessary files for config
+
+ :param argparse.Namespace args: Parsed command line arguments
+
+ :returns: Path to temporary directory
+ :rtype: str
+
+ """
+ tempdir = tempfile.mkdtemp()
+
+ with open(os.path.join(tempdir, "config_file"), "w") as config_fd:
+ config_fd.write(args.config_file + "\n")
+
+ proc = subprocess.Popen([args.apache_ctl, "-v"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ with open(os.path.join(tempdir, "version"), "w") as version_fd:
+ version_fd.write(proc.communicate()[0])
+
+ proc = subprocess.Popen([args.apache_ctl, "-d", args.server_root, "-f",
+ args.config_file, "-M"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ with open(os.path.join(tempdir, "modules"), "w") as modules_fd:
+ modules_fd.write(proc.communicate()[0])
+
+ proc = subprocess.Popen([args.apache_ctl, "-d", args.server_root, "-f",
+ args.config_file, "-t", "-D", "DUMP_VHOSTS"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ with open(os.path.join(tempdir, "vhosts"), "w") as vhosts_fd:
+ vhosts_fd.write(proc.communicate()[0])
+
+ return tempdir
+
+
+def verify_config(args):
+ """Verifies server_root and config_file specify a valid config
+
+ :param argparse.Namespace args: Parsed command line arguments
+
+ """
+ with open(os.devnull, "w") as devnull:
+ try:
+ subprocess.check_call([args.apache_ctl, "-d", args.server_root,
+ "-f", args.config_file, "-t"],
+ stdout=devnull, stderr=subprocess.STDOUT)
+ except OSError:
+ sys.exit(_NO_APACHECTL)
+ except subprocess.CalledProcessError:
+ sys.exit("Syntax check from apachectl failed")
+
+
+def locate_config(apache_ctl):
+ """Uses the apachectl binary to find configuration files
+
+ :param str apache_ctl: Path to `apachectl` binary
+
+
+ :returns: Path to Apache server root and main configuration file
+ :rtype: `tuple` of `str`
+
+ """
+ try:
+ proc = subprocess.Popen([apache_ctl, "-V"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ output, _ = proc.communicate()
+ except OSError:
+ sys.exit(_NO_APACHECTL)
+
+ server_root = config_file = ""
+ for line in output.splitlines():
+ # Relevant output lines are of the form: -D DIRECTIVE="VALUE"
+ if "HTTPD_ROOT" in line:
+ server_root = line[line.find('"') + 1:-1]
+ elif "SERVER_CONFIG_FILE" in line:
+ config_file = line[line.find('"') + 1:-1]
+
+ if not (server_root and config_file):
+ sys.exit("Unable to locate Apache configuration. Please run this "
+ "script again and specify --server-root and --config-file")
+
+ return server_root, config_file
+
+
+def get_args():
+ """Parses command line arguments
+
+ :returns: Parsed command line options
+ :rtype: argparse.Namespace
+
+ """
+ parser = argparse.ArgumentParser(description=_DESCRIPTION)
+ parser.add_argument("-c", "--apache-ctl", default="apachectl",
+ help="path to the `apachectl` binary")
+ parser.add_argument("-d", "--server-root",
+ help=("location of the root directory of your Apache "
+ "configuration"))
+ parser.add_argument("-f", "--config-file",
+ help=("location of your main Apache configuration "
+ "file relative to the server root"))
+ args = parser.parse_args()
+
+ # args.server_root XOR args.config_file
+ if bool(args.server_root) != bool(args.config_file):
+ sys.exit("If either --server-root and --config-file are specified, "
+ "they both must be included")
+ elif args.server_root and args.config_file:
+ args.server_root = os.path.abspath(args.server_root)
+ args.config_file = os.path.abspath(args.config_file)
+
+ if args.config_file.startswith(args.server_root):
+ args.config_file = args.config_file[len(args.server_root) + 1:]
+ else:
+ sys.exit("This script expects the Apache configuration file to be "
+ "inside the server root")
+
+ return args
+
+
+def main():
+ """Main script execution"""
+ args = get_args()
+ if args.server_root is None:
+ args.server_root, args.config_file = locate_config(args.apache_ctl)
+
+ verify_config(args)
+ tempdir = setup_tempdir(args)
+ atexit.register(lambda: shutil.rmtree(tempdir))
+ make_and_verify_selection(args.server_root, tempdir)
+
+ tarpath = os.path.join(tempdir, "config.tar.gz")
+ # contextlib.closing used for py26 support
+ with contextlib.closing(tarfile.open(tarpath, mode="w:gz")) as tar:
+ tar.add(tempdir, arcname=".")
+
+ # TODO: Submit tarpath
+
+
+if __name__ == "__main__":
+ main() # pragma: no cover
diff --git a/letshelp-certbot/letshelp_certbot/apache_test.py b/letshelp-certbot/letshelp_certbot/apache_test.py
new file mode 100644
index 000000000..0c1b5f2f6
--- /dev/null
+++ b/letshelp-certbot/letshelp_certbot/apache_test.py
@@ -0,0 +1,234 @@
+"""Tests for letshelp.letshelp_certbot_apache.py"""
+import argparse
+import functools
+import os
+import pkg_resources
+import subprocess
+import tarfile
+import tempfile
+import unittest
+
+import mock
+
+import letshelp_certbot.apache as letshelp_le_apache
+
+
+_PARTIAL_CONF_PATH = os.path.join("mods-available", "ssl.load")
+_PARTIAL_LINK_PATH = os.path.join("mods-enabled", "ssl.load")
+_CONFIG_FILE = pkg_resources.resource_filename(
+ __name__, os.path.join("testdata", _PARTIAL_CONF_PATH))
+_PASSWD_FILE = pkg_resources.resource_filename(
+ __name__, os.path.join("testdata", "uncommonly_named_p4sswd"))
+_KEY_FILE = pkg_resources.resource_filename(
+ __name__, os.path.join("testdata", "uncommonly_named_k3y"))
+_SECRET_FILE = pkg_resources.resource_filename(
+ __name__, os.path.join("testdata", "super_secret_file.txt"))
+
+
+_MODULE_NAME = "letshelp_certbot.apache"
+
+
+_COMPILE_SETTINGS = """Server version: Apache/2.4.10 (Debian)
+Server built: Mar 15 2015 09:51:43
+Server's Module Magic Number: 20120211:37
+Server loaded: APR 1.5.1, APR-UTIL 1.5.4
+Compiled using: APR 1.5.1, APR-UTIL 1.5.4
+Architecture: 64-bit
+Server MPM: event
+ threaded: yes (fixed thread count)
+ forked: yes (variable process count)
+Server compiled with....
+ -D APR_HAS_SENDFILE
+ -D APR_HAS_MMAP
+ -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
+ -D APR_USE_SYSVSEM_SERIALIZE
+ -D APR_USE_PTHREAD_SERIALIZE
+ -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
+ -D APR_HAS_OTHER_CHILD
+ -D AP_HAVE_RELIABLE_PIPED_LOGS
+ -D DYNAMIC_MODULE_LIMIT=256
+ -D HTTPD_ROOT="/etc/apache2"
+ -D SUEXEC_BIN="/usr/lib/apache2/suexec"
+ -D DEFAULT_PIDLOG="/var/run/apache2.pid"
+ -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
+ -D DEFAULT_ERRORLOG="logs/error_log"
+ -D AP_TYPES_CONFIG_FILE="mime.types"
+ -D SERVER_CONFIG_FILE="apache2.conf"
+
+"""
+
+
+class LetsHelpApacheTest(unittest.TestCase):
+ @mock.patch(_MODULE_NAME + ".copy_config")
+ def test_make_and_verify_selection(self, mock_copy_config):
+ mock_copy_config.return_value = (["apache2.conf"], ["apache2"])
+
+ with mock.patch("__builtin__.raw_input") as mock_input:
+ with mock.patch(_MODULE_NAME + ".sys.stdout"):
+ mock_input.side_effect = ["Yes", "No"]
+ letshelp_le_apache.make_and_verify_selection("root", "temp")
+ self.assertRaises(
+ SystemExit, letshelp_le_apache.make_and_verify_selection,
+ "server_root", "temp_dir")
+
+ def test_copy_config(self):
+ tempdir = tempfile.mkdtemp()
+ server_root = pkg_resources.resource_filename(__name__, "testdata")
+ letshelp_le_apache.copy_config(server_root, tempdir)
+
+ temp_testdata = os.path.join(tempdir, "testdata")
+ self.assertFalse(os.path.exists(os.path.join(
+ temp_testdata, os.path.basename(_PASSWD_FILE))))
+ self.assertFalse(os.path.exists(os.path.join(
+ temp_testdata, os.path.basename(_KEY_FILE))))
+ self.assertFalse(os.path.exists(os.path.join(
+ temp_testdata, os.path.basename(_SECRET_FILE))))
+ self.assertTrue(os.path.exists(os.path.join(
+ temp_testdata, _PARTIAL_CONF_PATH)))
+ self.assertTrue(os.path.exists(os.path.join(
+ temp_testdata, _PARTIAL_LINK_PATH)))
+
+ def test_copy_file_without_comments(self):
+ dest = tempfile.mkstemp()[1]
+ letshelp_le_apache.copy_file_without_comments(_PASSWD_FILE, dest)
+
+ with open(_PASSWD_FILE) as original:
+ with open(dest) as copy:
+ for original_line, copied_line in zip(original, copy):
+ self.assertEqual(original_line, copied_line)
+
+ @mock.patch(_MODULE_NAME + ".subprocess.Popen")
+ def test_safe_config_file(self, mock_popen):
+ mock_popen().communicate.return_value = ("PEM RSA private key", None)
+ self.assertFalse(letshelp_le_apache.safe_config_file("filename"))
+
+ mock_popen().communicate.return_value = ("ASCII text", None)
+ self.assertFalse(letshelp_le_apache.safe_config_file(_PASSWD_FILE))
+ self.assertFalse(letshelp_le_apache.safe_config_file(_KEY_FILE))
+ self.assertFalse(letshelp_le_apache.safe_config_file(_SECRET_FILE))
+ self.assertTrue(letshelp_le_apache.safe_config_file(_CONFIG_FILE))
+
+ @mock.patch(_MODULE_NAME + ".subprocess.Popen")
+ def test_tempdir(self, mock_popen):
+ mock_popen().communicate.side_effect = [
+ ("version", None), ("modules", None), ("vhosts", None)]
+ args = _get_args()
+
+ tempdir = letshelp_le_apache.setup_tempdir(args)
+
+ with open(os.path.join(tempdir, "config_file")) as config_fd:
+ self.assertEqual(config_fd.read(), args.config_file + "\n")
+
+ with open(os.path.join(tempdir, "version")) as version_fd:
+ self.assertEqual(version_fd.read(), "version")
+
+ with open(os.path.join(tempdir, "modules")) as modules_fd:
+ self.assertEqual(modules_fd.read(), "modules")
+
+ with open(os.path.join(tempdir, "vhosts")) as vhosts_fd:
+ self.assertEqual(vhosts_fd.read(), "vhosts")
+
+ @mock.patch(_MODULE_NAME + ".subprocess.check_call")
+ def test_verify_config(self, mock_check_call):
+ args = _get_args()
+ mock_check_call.side_effect = [
+ None, OSError, subprocess.CalledProcessError(1, "apachectl")]
+
+ letshelp_le_apache.verify_config(args)
+ self.assertRaises(SystemExit, letshelp_le_apache.verify_config, args)
+ self.assertRaises(SystemExit, letshelp_le_apache.verify_config, args)
+
+ @mock.patch(_MODULE_NAME + ".subprocess.Popen")
+ def test_locate_config(self, mock_popen):
+ mock_popen().communicate.side_effect = [
+ OSError, ("bad_output", None), (_COMPILE_SETTINGS, None)]
+
+ self.assertRaises(
+ SystemExit, letshelp_le_apache.locate_config, "ctl")
+ self.assertRaises(
+ SystemExit, letshelp_le_apache.locate_config, "ctl")
+ server_root, config_file = letshelp_le_apache.locate_config("ctl")
+ self.assertEqual(server_root, "/etc/apache2")
+ self.assertEqual(config_file, "apache2.conf")
+
+ @mock.patch(_MODULE_NAME + ".argparse")
+ def test_get_args(self, mock_argparse):
+ argv = ["-d", "/etc/apache2"]
+ mock_argparse.ArgumentParser.return_value = _create_mock_parser(argv)
+ self.assertRaises(SystemExit, letshelp_le_apache.get_args)
+
+ server_root = "/etc/apache2"
+ config_file = server_root + "/apache2.conf"
+ argv = ["-d", server_root, "-f", config_file]
+ mock_argparse.ArgumentParser.return_value = _create_mock_parser(argv)
+ args = letshelp_le_apache.get_args()
+ self.assertEqual(args.apache_ctl, "apachectl")
+ self.assertEqual(args.server_root, server_root)
+ self.assertEqual(args.config_file, os.path.basename(config_file))
+
+ server_root = "/etc/apache2"
+ config_file = "/etc/httpd/httpd.conf"
+ argv = ["-d", server_root, "-f", config_file]
+ mock_argparse.ArgumentParser.return_value = _create_mock_parser(argv)
+ self.assertRaises(SystemExit, letshelp_le_apache.get_args)
+
+ def test_main_with_args(self):
+ with mock.patch(_MODULE_NAME + ".get_args"):
+ self._test_main_common()
+
+ def test_main_without_args(self):
+ with mock.patch(_MODULE_NAME + ".get_args") as get_args:
+ args = _get_args()
+ server_root, config_file = args.server_root, args.config_file
+ args.server_root = args.config_file = None
+ get_args.return_value = args
+ with mock.patch(_MODULE_NAME + ".locate_config") as locate:
+ locate.return_value = (server_root, config_file)
+ self._test_main_common()
+
+ def _test_main_common(self):
+ with mock.patch(_MODULE_NAME + ".verify_config"):
+ with mock.patch(_MODULE_NAME + ".setup_tempdir") as mock_setup:
+ tempdir_path = tempfile.mkdtemp()
+ mock_setup.return_value = tempdir_path
+ with mock.patch(_MODULE_NAME + ".make_and_verify_selection"):
+ testdir_basename = "test"
+ os.mkdir(os.path.join(tempdir_path, testdir_basename))
+
+ letshelp_le_apache.main()
+
+ tar = tarfile.open(os.path.join(
+ tempdir_path, "config.tar.gz"))
+
+ tempdir = tar.next()
+ self.assertTrue(tempdir.isdir())
+ self.assertEqual(tempdir.name, ".")
+
+ testdir = tar.next()
+ self.assertTrue(testdir.isdir())
+ self.assertEqual(os.path.basename(testdir.name),
+ testdir_basename)
+
+ self.assertEqual(tar.next(), None)
+
+
+def _create_mock_parser(argv):
+ parser = argparse.ArgumentParser()
+ mock_parser = mock.MagicMock()
+ mock_parser.add_argument = parser.add_argument
+ mock_parser.parse_args = functools.partial(parser.parse_args, argv)
+
+ return mock_parser
+
+
+def _get_args():
+ args = argparse.Namespace()
+ args.apache_ctl = "apache_ctl"
+ args.config_file = "config_file"
+ args.server_root = "server_root"
+
+ return args
+
+
+if __name__ == "__main__":
+ unittest.main() # pragma: no cover
diff --git a/letshelp-certbot/letshelp_certbot/testdata/mods-available/ssl.load b/letshelp-certbot/letshelp_certbot/testdata/mods-available/ssl.load
new file mode 100644
index 000000000..3d2336ae0
--- /dev/null
+++ b/letshelp-certbot/letshelp_certbot/testdata/mods-available/ssl.load
@@ -0,0 +1,2 @@
+# Depends: setenvif mime socache_shmcb
+LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
diff --git a/letshelp-certbot/letshelp_certbot/testdata/mods-enabled/ssl.load b/letshelp-certbot/letshelp_certbot/testdata/mods-enabled/ssl.load
new file mode 120000
index 000000000..9d7972384
--- /dev/null
+++ b/letshelp-certbot/letshelp_certbot/testdata/mods-enabled/ssl.load
@@ -0,0 +1 @@
+../mods-available/ssl.load \ No newline at end of file
diff --git a/letshelp-certbot/letshelp_certbot/testdata/super_secret_file.txt b/letshelp-certbot/letshelp_certbot/testdata/super_secret_file.txt
new file mode 100644
index 000000000..9f592eb7d
--- /dev/null
+++ b/letshelp-certbot/letshelp_certbot/testdata/super_secret_file.txt
@@ -0,0 +1 @@
+hunter2
diff --git a/letshelp-certbot/letshelp_certbot/testdata/uncommonly_named_k3y b/letshelp-certbot/letshelp_certbot/testdata/uncommonly_named_k3y
new file mode 100644
index 000000000..659274d1d
--- /dev/null
+++ b/letshelp-certbot/letshelp_certbot/testdata/uncommonly_named_k3y
@@ -0,0 +1,6 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIGrAgEAAiEAm2Fylv+Uz7trgTW8EBHP3FQSMeZs2GNQ6VRo1sIVJEkCAwEAAQIh
+AJT0BA/xD01dFCAXzSNyj9nfSZa3NpqzJZZn/eOm7vghAhEAzUVNZn4lLLBD1R6N
+E8TKNQIRAMHHyn3O5JeY36lwKwkUlEUCEAliRauN0L0+QZuYjfJ9aJECEGx4dru3
+rTPCyighdqWNlHUCEQCiLjlwSRtWgmMBudCkVjzt
+-----END RSA PRIVATE KEY-----
diff --git a/letshelp-certbot/letshelp_certbot/testdata/uncommonly_named_p4sswd b/letshelp-certbot/letshelp_certbot/testdata/uncommonly_named_p4sswd
new file mode 100644
index 000000000..3559c1d1f
--- /dev/null
+++ b/letshelp-certbot/letshelp_certbot/testdata/uncommonly_named_p4sswd
@@ -0,0 +1 @@
+johntheripper:$apr1$fIGE9.JL$jTCwNWZy9Ak/yvOLuOyzQ1
diff --git a/letshelp-certbot/readthedocs.org.requirements.txt b/letshelp-certbot/readthedocs.org.requirements.txt
new file mode 100644
index 000000000..7858b312f
--- /dev/null
+++ b/letshelp-certbot/readthedocs.org.requirements.txt
@@ -0,0 +1,10 @@
+# readthedocs.org gives no way to change the install command to "pip
+# install -e .[docs]" (that would in turn install documentation
+# dependencies), but it allows to specify a requirements.txt file at
+# https://readthedocs.org/dashboard/letsencrypt/advanced/ (c.f. #259)
+
+# Although ReadTheDocs certainly doesn't need to install the project
+# in --editable mode (-e), just "pip install .[docs]" does not work as
+# expected and "pip install -e .[docs]" must be used instead
+
+-e letshelp-certbot[docs]
diff --git a/letshelp-certbot/setup.py b/letshelp-certbot/setup.py
new file mode 100644
index 000000000..e625b288c
--- /dev/null
+++ b/letshelp-certbot/setup.py
@@ -0,0 +1,59 @@
+import sys
+
+from setuptools import setup
+from setuptools import find_packages
+
+
+version = '0.6.0.dev0'
+
+install_requires = [
+ 'setuptools', # pkg_resources
+]
+if sys.version_info < (2, 7):
+ install_requires.append('mock<1.1.0')
+else:
+ install_requires.append('mock')
+
+docs_extras = [
+ 'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags
+ 'sphinx_rtd_theme',
+]
+
+setup(
+ name='letshelp-certbot',
+ version=version,
+ description="Let's help Certbot client",
+ url='https://github.com/letsencrypt/letsencrypt',
+ author="Electronic Frontier Foundation",
+ author_email='client-dev@letsencrypt.org',
+ license='Apache License 2.0',
+ classifiers=[
+ 'Development Status :: 3 - Alpha',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: Apache Software License',
+ 'Operating System :: POSIX :: Linux',
+ 'Programming Language :: Python',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.6',
+ 'Programming Language :: Python :: 2.7',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Topic :: Security',
+ 'Topic :: System :: Installation/Setup',
+ 'Topic :: System :: Networking',
+ 'Topic :: System :: Systems Administration',
+ 'Topic :: Utilities',
+ ],
+
+ packages=find_packages(),
+ include_package_data=True,
+ install_requires=install_requires,
+ extras_require={
+ 'docs': docs_extras,
+ },
+ entry_points={
+ 'console_scripts': [
+ 'letshelp-certbot-apache = letshelp_certbot.apache:main',
+ ],
+ },
+ test_suite='letshelp_certbot',
+)