Add tools to the repository.


Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 920c091ac3ee15079194c82ae8a7a18215f3f23c
diff --git a/google/__init__.py b/google/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/google/__init__.py
@@ -0,0 +1 @@
+
diff --git a/google/gethash_timer.py b/google/gethash_timer.py
new file mode 100644
index 0000000..b36a5df
--- /dev/null
+++ b/google/gethash_timer.py
@@ -0,0 +1,168 @@
+#!/usr/bin/python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Issue a series of GetHash requests to the SafeBrowsing servers and measure the
+# response times.
+#
+# Usage:
+#
+#   $ ./gethash_timer.py --period=600 --samples=20 --output=resp.csv
+#
+#   --period (or -p):  The amount of time (in seconds) to wait between GetHash
+#                      requests. Using a value of more than 300 (5 minutes) to
+#                      include the effect of DNS.
+#
+#   --samples (or -s): The number of requests to issue. If this parameter is not
+#                      specified, the test will run indefinitely.
+#
+#   --output (or -o):  The path to a file where the output will be written in
+#                      CSV format: sample_number,response_code,elapsed_time_ms
+
+import getopt
+import httplib
+import sys
+import time
+
+_GETHASH_HOST = 'safebrowsing.clients.google.com'
+_GETHASH_REQUEST = '/safebrowsing/gethash?client=googleclient&appver=1.0&pver=2.1'
+
+# Global logging file handle.
+g_file_handle = None
+
+
+def IssueGetHash(prefix):
+  '''Issue one GetHash request to the safebrowsing servers.
+  Args:
+    prefix: A 4 byte value to look up on the server.
+  Returns:
+    The HTTP response code for the GetHash request.
+  '''
+  body = '4:4\n' + prefix
+  h = httplib.HTTPConnection(_GETHASH_HOST)
+  h.putrequest('POST', _GETHASH_REQUEST)
+  h.putheader('content-length', str(len(body)))
+  h.endheaders()
+  h.send(body)
+  response_code = h.getresponse().status
+  h.close()
+  return response_code
+
+
+def TimedGetHash(prefix):
+  '''Measure the amount of time it takes to receive a GetHash response.
+  Args:
+    prefix: A 4 byte value to look up on the the server.
+  Returns:
+    A tuple of HTTP resonse code and the response time (in milliseconds).
+  '''
+  start = time.time()
+  response_code = IssueGetHash(prefix)
+  return response_code, (time.time() - start) * 1000
+
+
+def RunTimedGetHash(period, samples=None):
+  '''Runs an experiment to measure the amount of time it takes to receive
+  multiple responses from the GetHash servers.
+
+  Args:
+    period:  A floating point value that indicates (in seconds) the delay
+             between requests.
+    samples: An integer value indicating the number of requests to make.
+             If 'None', the test continues indefinitely.
+  Returns:
+    None.
+  '''
+  global g_file_handle
+  prefix = '\x50\x61\x75\x6c'
+  sample_count = 1
+  while True:
+    response_code, elapsed_time = TimedGetHash(prefix)
+    LogResponse(sample_count, response_code, elapsed_time)
+    sample_count += 1
+    if samples is not None and sample_count == samples:
+      break
+    time.sleep(period)
+
+
+def LogResponse(sample_count, response_code, elapsed_time):
+  '''Output the response for one GetHash query.
+  Args:
+    sample_count:  The current sample number.
+    response_code: The HTTP response code for the GetHash request.
+    elapsed_time:  The round-trip time (in milliseconds) for the
+                   GetHash request.
+  Returns:
+    None.
+  '''
+  global g_file_handle
+  output_list = (sample_count, response_code, elapsed_time)
+  print 'Request: %d, status: %d, elapsed time: %f ms' % output_list
+  if g_file_handle is not None:
+    g_file_handle.write(('%d,%d,%f' % output_list) + '\n')
+    g_file_handle.flush()
+
+
+def SetupOutputFile(file_name):
+  '''Open a file for logging results.
+  Args:
+    file_name: A path to a file to store the output.
+  Returns:
+    None.
+  '''
+  global g_file_handle
+  g_file_handle = open(file_name, 'w')
+
+
+if __name__ == '__main__':
+  period = 10
+  samples = None
+
+  options, args = getopt.getopt(sys.argv[1:],
+                                's:p:o:',
+                                ['samples=', 'period=', 'output='])
+  for option, value in options:
+    if option == '-s' or option == '--samples':
+      samples = int(value)
+    elif option == '-p' or option == '--period':
+      period = float(value)
+    elif option == '-o' or option == '--output':
+      file_name = value
+    else:
+      print 'Bad option: %s' % option
+      sys.exit(1)
+  try:
+    print 'Starting Timed GetHash ----------'
+    SetupOutputFile(file_name)
+    RunTimedGetHash(period, samples)
+  except KeyboardInterrupt:
+    pass
+
+  print 'Timed GetHash complete ----------'
+  g_file_handle.close()
diff --git a/google/httpd_config/httpd.conf b/google/httpd_config/httpd.conf
new file mode 100644
index 0000000..fc7a498
--- /dev/null
+++ b/google/httpd_config/httpd.conf
@@ -0,0 +1,734 @@
+##
+## httpd.conf -- Apache HTTP server configuration file
+##
+
+#
+# Based upon the NCSA server configuration files originally by Rob McCool.
+#
+# This is the main Apache server configuration file.  It contains the
+# configuration directives that give the server its instructions.
+# See <URL:http://httpd.apache.org/docs/> for detailed information about
+# the directives.
+#
+# Do NOT simply read the instructions in here without understanding
+# what they do.  They're here only as hints or reminders.  If you are unsure
+# consult the online docs. You have been warned.  
+#
+# After this file is processed, the server will look for and process
+# /private/etc/httpd/srm.conf and then /private/etc/httpd/access.conf
+# unless you have overridden these with ResourceConfig and/or
+# AccessConfig directives here.
+#
+# The configuration directives are grouped into three basic sections:
+#  1. Directives that control the operation of the Apache server process as a
+#     whole (the 'global environment').
+#  2. Directives that define the parameters of the 'main' or 'default' server,
+#     which responds to requests that aren't handled by a virtual host.
+#     These directives also provide default values for the settings
+#     of all virtual hosts.
+#  3. Settings for virtual hosts, which allow Web requests to be sent to
+#     different IP addresses or hostnames and have them handled by the
+#     same Apache server process.
+#
+# Configuration and logfile names: If the filenames you specify for many
+# of the server's control files begin with "/" (or "drive:/" for Win32), the
+# server will use that explicit path.  If the filenames do *not* begin
+# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"
+# with ServerRoot set to "/usr/local/apache" will be interpreted by the
+# server as "/usr/local/apache/logs/foo.log".
+#
+
+### Section 1: Global Environment
+#
+# The directives in this section affect the overall operation of Apache,
+# such as the number of concurrent requests it can handle or where it
+# can find its configuration files.
+#
+
+#
+# ServerType is either inetd, or standalone.  Inetd mode is only supported on
+# Unix platforms.
+#
+ServerType standalone
+
+#
+# ServerRoot: The top of the directory tree under which the server's
+# configuration, error, and log files are kept.
+#
+# NOTE!  If you intend to place this on an NFS (or otherwise network)
+# mounted filesystem then please read the LockFile documentation
+# (available at <URL:http://www.apache.org/docs/mod/core.html#lockfile>);
+# you will save yourself a lot of trouble.
+#
+#ServerRoot "/usr"
+
+#
+# The LockFile directive sets the path to the lockfile used when Apache
+# is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or
+# USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be left at
+# its default value. The main reason for changing it is if the logs
+# directory is NFS mounted, since the lockfile MUST BE STORED ON A LOCAL
+# DISK. The PID of the main server process is automatically appended to
+# the filename. 
+#
+#LockFile "/private/var/run/httpd.lock"
+
+#
+# PidFile: The file in which the server should record its process
+# identification number when it starts.
+#
+PidFile "/tmp/WebKit/httpd.pid"
+
+#
+# ScoreBoardFile: File used to store internal server process information.
+# Not all architectures require this.  But if yours does (you'll know because
+# this file will be  created when you run Apache) then you *must* ensure that
+# no two invocations of Apache share the same scoreboard file.
+#
+ScoreBoardFile "/tmp/WebKit/httpd.scoreboard"
+
+#
+# In the standard configuration, the server will process httpd.conf (this 
+# file, specified by the -f command line option), srm.conf, and access.conf 
+# in that order.  The latter two files are now distributed empty, as it is 
+# recommended that all directives be kept in a single file for simplicity.  
+# The commented-out values below are the built-in defaults.  You can have the 
+# server ignore these files altogether by using "/dev/null" (for Unix) or
+# "nul" (for Win32) for the arguments to the directives.
+#
+ResourceConfig /dev/null
+AccessConfig /dev/null
+
+#
+# Timeout: The number of seconds before receives and sends time out.
+#
+Timeout 300
+
+#
+# KeepAlive: Whether or not to allow persistent connections (more than
+# one request per connection). Set to "Off" to deactivate.
+#
+KeepAlive On
+
+#
+# MaxKeepAliveRequests: The maximum number of requests to allow
+# during a persistent connection. Set to 0 to allow an unlimited amount.
+# We recommend you leave this number high, for maximum performance.
+#
+MaxKeepAliveRequests 100
+
+#
+# KeepAliveTimeout: Number of seconds to wait for the next request from the
+# same client on the same connection.
+#
+KeepAliveTimeout 15
+
+#
+# Server-pool size regulation.  Rather than making you guess how many
+# server processes you need, Apache dynamically adapts to the load it
+# sees --- that is, it tries to maintain enough server processes to
+# handle the current load, plus a few spare servers to handle transient
+# load spikes (e.g., multiple simultaneous requests from a single
+# Netscape browser).
+#
+# It does this by periodically checking how many servers are waiting
+# for a request.  If there are fewer than MinSpareServers, it creates
+# a new spare.  If there are more than MaxSpareServers, some of the
+# spares die off.  The default values are probably OK for most sites.
+#
+MinSpareServers 1
+MaxSpareServers 5
+
+#
+# Number of servers to start initially --- should be a reasonable ballpark
+# figure.
+#
+StartServers 1
+
+#
+# Limit on total number of servers running, i.e., limit on the number
+# of clients who can simultaneously connect --- if this limit is ever
+# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW.
+# It is intended mainly as a brake to keep a runaway server from taking
+# the system with it as it spirals down...
+#
+MaxClients 150
+
+#
+# MaxRequestsPerChild: the number of requests each child process is
+# allowed to process before the child dies.  The child will exit so
+# as to avoid problems after prolonged use when Apache (and maybe the
+# libraries it uses) leak memory or other resources.  On most systems, this
+# isn't really needed, but a few (such as Solaris) do have notable leaks
+# in the libraries. For these platforms, set to something like 10000
+# or so; a setting of 0 means unlimited.
+#
+# NOTE: This value does not include keepalive requests after the initial
+#       request per connection. For example, if a child process handles
+#       an initial request and 10 subsequent "keptalive" requests, it
+#       would only count as 1 request towards this limit.
+#
+MaxRequestsPerChild 100000
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#
+Listen 127.0.0.1:8000
+Listen 127.0.0.1:8080
+Listen 127.0.0.1:8081
+Listen 127.0.0.1:9000
+Listen 127.0.0.1:9080
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Please read the file http://httpd.apache.org/docs/dso.html for more
+# details about the DSO mechanism and run `httpd -l' for the list of already
+# built-in (statically linked and thus always available) modules in your httpd
+# binary.
+#
+# Note: The order in which modules are loaded is important.  Don't change
+# the order below without expert advice.
+#
+# Example:
+# LoadModule foo_module lib/apache/mod_foo.dll
+#LoadModule vhost_alias_module  lib/apache/mod_vhost_alias.dll
+#LoadModule env_module          lib/apache/mod_env.dll
+LoadModule config_log_module    lib/apache/mod_log_config.dll
+#LoadModule mime_magic_module   lib/apache/mod_mime_magic.dll
+LoadModule mime_module          lib/apache/mod_mime.dll
+LoadModule negotiation_module   lib/apache/mod_negotiation.dll
+#LoadModule status_module       lib/apache/mod_status.dll
+#LoadModule info_module         lib/apache/mod_info.dll
+LoadModule includes_module      lib/apache/mod_include.dll
+LoadModule autoindex_module     lib/apache/mod_autoindex.dll
+#LoadModule dir_module          lib/apache/mod_dir.dll
+LoadModule cgi_module           lib/apache/mod_cgi.dll
+LoadModule asis_module          lib/apache/mod_asis.dll
+LoadModule imap_module          lib/apache/mod_imap.dll
+LoadModule action_module        lib/apache/mod_actions.dll
+#LoadModule speling_module      lib/apache/mod_speling.dll
+#LoadModule userdir_module      lib/apache/mod_userdir.dll
+LoadModule alias_module         lib/apache/mod_alias.dll
+LoadModule rewrite_module       lib/apache/mod_rewrite.dll
+LoadModule access_module        lib/apache/mod_access.dll
+LoadModule auth_module          lib/apache/mod_auth.dll
+#LoadModule anon_auth_module    lib/apache/mod_auth_anon.dll
+#LoadModule dbm_auth_module     lib/apache/mod_auth_dbm.dll
+#LoadModule digest_module       lib/apache/mod_digest.dll
+#LoadModule proxy_module        lib/apache/libproxy.dll
+#LoadModule cern_meta_module    lib/apache/mod_cern_meta.dll
+#LoadModule expires_module      lib/apache/mod_expires.dll
+LoadModule headers_module       lib/apache/mod_headers.dll
+#LoadModule usertrack_module    lib/apache/mod_usertrack.dll
+#LoadModule log_forensic_module lib/apache/mod_log_forensic.dll
+#LoadModule unique_id_module    lib/apache/mod_unique_id.dll
+#LoadModule setenvif_module     lib/apache/mod_setenvif.dll
+#LoadModule dav_module          lib/apache/libdav.dll
+#LoadModule ssl_module          lib/apache/libssl.dll
+#LoadModule perl_module         lib/apache/libperl.dll
+LoadModule php4_module          lib/apache/libphp4.dll
+#LoadModule hfs_apple_module    lib/apache/mod_hfs_apple.dll
+#LoadModule bonjour_module      lib/apache/mod_bonjour.dll
+
+#  Reconstruction of the complete module list from all available modules
+#  (static and shared ones) to achieve correct module execution order.
+#  [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO]
+ClearModuleList
+#AddModule mod_vhost_alias.c
+#AddModule mod_env.c
+AddModule mod_log_config.c
+#AddModule mod_mime_magic.c
+AddModule mod_mime.c
+AddModule mod_negotiation.c
+#AddModule mod_status.c
+#AddModule mod_info.c
+AddModule mod_include.c
+AddModule mod_autoindex.c
+#AddModule mod_dir.c
+AddModule mod_cgi.c
+AddModule mod_asis.c
+AddModule mod_imap.c
+AddModule mod_actions.c
+#AddModule mod_speling.c
+#AddModule mod_userdir.c
+AddModule mod_alias.c
+AddModule mod_rewrite.c
+AddModule mod_access.c
+AddModule mod_auth.c
+#AddModule mod_auth_anon.c
+#AddModule mod_auth_dbm.c
+#AddModule mod_digest.c
+#AddModule mod_proxy.c
+#AddModule mod_cern_meta.c
+#AddModule mod_expires.c
+AddModule mod_headers.c
+#AddModule mod_usertrack.c
+#AddModule mod_log_forensic.c
+#AddModule mod_unique_id.c
+AddModule mod_so.c
+#AddModule mod_setenvif.c
+#AddModule mod_dav.c
+#AddModule mod_ssl.c
+#AddModule mod_perl.c
+AddModule mod_php4.c
+#AddModule mod_hfs_apple.c
+#AddModule mod_bonjour.c
+
+### Section 2: 'Main' server configuration
+#
+# The directives in this section set up the values used by the 'main'
+# server, which responds to any requests that aren't handled by a
+# <VirtualHost> definition.  These values also provide defaults for
+# any <VirtualHost> containers you may define later in the file.
+#
+# All of these directives may appear inside <VirtualHost> containers,
+# in which case these default settings will be overridden for the
+# virtual host being defined.
+#
+
+#
+# ServerName allows you to set a host name which is sent back to clients for
+# your server if it's different than the one the program would get (i.e., use
+# "www" instead of the host's real name).
+#
+# Note: You cannot just invent host names and hope they work. The name you 
+# define here must be a valid DNS name for your host. If you don't understand
+# this, ask your network administrator.
+# If your host doesn't have a registered DNS name, enter its IP address here.
+# You will have to access it by its address (e.g., http://123.45.67.89/)
+# anyway, and this will make redirections work in a sensible way.
+#
+# 127.0.0.1 is the TCP/IP local loop-back address, often named localhost. Your 
+# machine always knows itself by this address. If you use Apache strictly for 
+# local testing and development, you may use 127.0.0.1 as the server name.
+#
+ServerName 127.0.0.1
+
+#
+# DocumentRoot: The directory out of which you will serve your
+# documents. By default, all requests are taken from this directory, but
+# symbolic links and aliases may be used to point to other locations.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#DocumentRoot "/Library/WebServer/Documents"
+
+#
+# Each directory to which Apache has access, can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories). 
+#
+<Directory />
+#
+# This may also be "None", "All", or any combination of "Indexes",
+# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews".
+#
+# Note that "MultiViews" must be named *explicitly* --- "Options All"
+# doesn't give it to you.
+#
+    Options Indexes FollowSymLinks MultiViews ExecCGI Includes
+
+#
+# This controls which options the .htaccess files in directories can
+# override. Can also be "All", or any combination of "Options", "FileInfo", 
+# "AuthConfig", and "Limit"
+#
+    AllowOverride All
+
+#
+# Controls who can get stuff from this server.
+#
+    Order allow,deny
+    Allow from all
+</Directory>
+
+#
+# AccessFileName: The name of the file to look for in each directory
+# for access control information.
+#
+AccessFileName .htaccess
+
+#
+# The following lines prevent .htaccess files from being viewed by
+# Web clients.  Since .htaccess files often contain authorization
+# information, access is disallowed for security reasons.  Comment
+# these lines out if you want Web visitors to see the contents of
+# .htaccess files.  If you change the AccessFileName directive above,
+# be sure to make the corresponding changes here.
+#
+# Also, folks tend to use names such as .htpasswd for password
+# files, so this will protect those as well.
+#
+<Files ~ "^\.([Hh][Tt]|[Dd][Ss]_[Ss])">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</Files>
+
+#
+# Apple specific filesystem protection.
+# 
+
+<Files "rsrc">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</Files>
+
+<Directory  ~ ".*\.\.namedfork">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</Directory>
+
+#
+# CacheNegotiatedDocs: By default, Apache sends "Pragma: no-cache" with each
+# document that was negotiated on the basis of content. This asks proxy
+# servers not to cache the document. Uncommenting the following line disables
+# this behavior, and proxies will be allowed to cache the documents.
+#
+#CacheNegotiatedDocs
+
+#
+# UseCanonicalName:  (new for 1.3)  With this setting turned on, whenever
+# Apache needs to construct a self-referencing URL (a URL that refers back
+# to the server the response is coming from) it will use ServerName and
+# Port to form a "canonical" name.  With this setting off, Apache will
+# use the hostname:port that the client supplied, when possible.  This
+# also affects SERVER_NAME and SERVER_PORT in CGI scripts.
+#
+UseCanonicalName On
+
+#
+# TypesConfig describes where the mime.types file (or equivalent) is
+# to be found.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#
+#<IfModule mod_mime.c>
+#    TypesConfig /private/etc/httpd/mime.types
+#</IfModule>
+
+#
+# DefaultType is the default MIME type the server will use for a document
+# if it cannot otherwise determine one, such as from filename extensions.
+# If your server contains mostly text or HTML documents, "text/plain" is
+# a good value.  If most of your content is binary, such as applications
+# or images, you may want to use "application/octet-stream" instead to
+# keep browsers from trying to display binary files as though they are
+# text.
+#
+DefaultType text/plain
+
+#
+# HostnameLookups: Log the names of clients or just their IP addresses
+# e.g., www.apache.org (on) or 204.62.129.132 (off).
+# The default is off because it'd be overall better for the net if people
+# had to knowingly turn this feature on, since enabling it means that
+# each client request will result in AT LEAST one lookup request to the
+# nameserver.
+#
+HostnameLookups Off
+
+#
+# ErrorLog: The location of the error log file.
+# If you do not specify an ErrorLog directive within a <VirtualHost>
+# container, error messages relating to that virtual host will be
+# logged here.  If you *do* define an error logfile for a <VirtualHost>
+# container, that host's errors will be logged there and not here.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#ErrorLog "/tmp/layout-test-results/error_log"
+
+#
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%p %h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+#
+# The location and format of the access logfile (Common Logfile Format).
+# If you do not define any access logfiles within a <VirtualHost>
+# container, they will be logged here.  Contrariwise, if you *do*
+# define per-<VirtualHost> access logfiles, transactions will be
+# logged therein and *not* in this file.
+#
+# Configured from the httpd command line for WebKit layout tests.
+#CustomLog "/tmp/layout-test-results/access_log" common
+
+#
+# If you prefer a single logfile with access, agent, and referer information
+# (Combined Logfile Format) you can use the following directive.
+#
+#CustomLog "/tmp/layout-test-results/access_log" combined
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (error documents, FTP directory listings,
+# mod_status and mod_info output etc., but not CGI generated documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of:  On | Off | EMail
+#
+ServerSignature On
+
+#
+# Aliases: Add here as many aliases as you need (with no limit). The format is 
+# Alias fakename realname
+#
+<IfModule mod_alias.c>
+</IfModule>
+# End of aliases.
+
+#
+# Redirect allows you to tell clients about documents which used to exist in
+# your server's namespace, but do not anymore. This allows you to tell the
+# clients where to look for the relocated document.
+# Format: Redirect old-URI new-URL
+#
+
+#
+# Document types.
+#
+<IfModule mod_mime.c>
+
+    #
+    # AddLanguage allows you to specify the language of a document. You can
+    # then use content negotiation to give a browser a file in a language
+    # it can understand.  
+    #
+    # Note 1: The suffix does not have to be the same as the language 
+    # keyword --- those with documents in Polish (whose net-standard 
+    # language code is pl) may wish to use "AddLanguage pl .po" to 
+    # avoid the ambiguity with the common suffix for perl scripts.
+    #
+    # Note 2: The example entries below illustrate that in quite
+    # some cases the two character 'Language' abbreviation is not
+    # identical to the two character 'Country' code for its country,
+    # E.g. 'Danmark/dk' versus 'Danish/da'.
+    #
+    # Note 3: In the case of 'ltz' we violate the RFC by using a three char 
+    # specifier. But there is 'work in progress' to fix this and get 
+    # the reference data for rfc1766 cleaned up.
+    #
+    # Danish (da) - Dutch (nl) - English (en) - Estonian (ee)
+    # French (fr) - German (de) - Greek-Modern (el)
+    # Italian (it) - Korean (kr) - Norwegian (no) - Norwegian Nynorsk (nn)
+    # Portugese (pt) - Luxembourgeois* (ltz)
+    # Spanish (es) - Swedish (sv) - Catalan (ca) - Czech(cs)
+    # Polish (pl) - Brazilian Portuguese (pt-br) - Japanese (ja)
+    # Russian (ru)
+    #
+    AddLanguage da .dk
+    AddLanguage nl .nl
+    AddLanguage en .en
+    AddLanguage et .ee
+    AddLanguage fr .fr
+    AddLanguage de .de
+    AddLanguage el .el
+    AddLanguage he .he
+    AddCharset ISO-8859-8 .iso8859-8
+    AddLanguage it .it
+    AddLanguage ja .ja
+    AddCharset ISO-2022-JP .jis
+    AddLanguage kr .kr
+    AddCharset ISO-2022-KR .iso-kr
+    AddLanguage nn .nn
+    AddLanguage no .no
+    AddLanguage pl .po
+    AddCharset ISO-8859-2 .iso-pl
+    AddLanguage pt .pt
+    AddLanguage pt-br .pt-br
+    AddLanguage ltz .lu
+    AddLanguage ca .ca
+    AddLanguage es .es
+    AddLanguage sv .sv
+    AddLanguage cs .cz .cs
+    AddLanguage ru .ru
+    AddLanguage zh-TW .zh-tw
+    AddCharset Big5         .Big5    .big5
+    AddCharset WINDOWS-1251 .cp-1251
+    AddCharset CP866        .cp866
+    AddCharset ISO-8859-5   .iso-ru
+    AddCharset KOI8-R       .koi8-r
+    AddCharset UCS-2        .ucs2
+    AddCharset UCS-4        .ucs4
+    AddCharset UTF-8        .utf8
+
+    # LanguagePriority allows you to give precedence to some languages
+    # in case of a tie during content negotiation.
+    #
+    # Just list the languages in decreasing order of preference. We have
+    # more or less alphabetized them here. You probably want to change this.
+    #
+    <IfModule mod_negotiation.c>
+        LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ru ltz ca es sv tw
+    </IfModule>
+
+    #
+    # AddType allows you to tweak mime.types without actually editing it, or to
+    # make certain files to be certain types.
+    #
+    AddType application/x-tar .tgz
+
+    #
+    # AddEncoding allows you to have certain browsers uncompress
+    # information on the fly. Note: Not all browsers support this.
+    # Despite the name similarity, the following Add* directives have nothing
+    # to do with the FancyIndexing customization directives above.
+    #
+    AddEncoding x-compress .Z
+    AddEncoding x-gzip .gz .tgz
+    #
+    # If the AddEncoding directives above are commented-out, then you
+    # probably should define those extensions to indicate media types:
+    #
+    #AddType application/x-compress .Z
+    #AddType application/x-gzip .gz .tgz
+
+    #
+    # AddHandler allows you to map certain file extensions to "handlers",
+    # actions unrelated to filetype. These can be either built into the server
+    # or added with the Action command (see below)
+    #
+    # If you want to use server side includes, or CGI outside
+    # ScriptAliased directories, uncomment the following lines.
+    #
+    # To use CGI scripts:
+    #
+    AddHandler cgi-script .cgi .pl
+
+    #
+    # To use server-parsed HTML files
+    #
+    AddType text/html .shtml
+    AddHandler server-parsed .shtml
+
+    #
+    # Uncomment the following line to enable Apache's send-asis HTTP file
+    # feature
+    #
+    AddHandler send-as-is asis
+
+    #
+    # If you wish to use server-parsed imagemap files, use
+    #
+    #AddHandler imap-file map
+
+    #
+    # To enable type maps, you might want to use
+    #
+    #AddHandler type-map var
+
+</IfModule>
+# End of document types.
+
+#
+# Action lets you define media types that will execute a script whenever
+# a matching file is called. This eliminates the need for repeated URL
+# pathnames for oft-used CGI file processors.
+# Format: Action media/type /cgi-script/location
+# Format: Action handler-name /cgi-script/location
+#
+
+#
+# MetaDir: specifies the name of the directory in which Apache can find
+# meta information files. These files contain additional HTTP headers
+# to include when sending the document
+#
+#MetaDir .web
+
+#
+# MetaSuffix: specifies the file name suffix for the file containing the
+# meta information.
+#
+#MetaSuffix .meta
+
+#
+# Customizable error response (Apache style)
+#  these come in three flavors
+#
+#    1) plain text
+#ErrorDocument 500 "The server made a boo boo.
+#  n.b.  the single leading (") marks it as text, it does not get output
+#
+#    2) local redirects
+#ErrorDocument 404 /missing.html
+#  to redirect to local URL /missing.html
+#ErrorDocument 404 /cgi-bin/missing_handler.pl
+#  N.B.: You can redirect to a script or a document using server-side-includes.
+#
+#    3) external redirects
+#ErrorDocument 402 http://some.other-server.com/subscription_info.html
+#  N.B.: Many of the environment variables associated with the original
+#  request will *not* be available to such a script.
+
+#
+# Proxy Server directives. Uncomment the following lines to
+# enable the proxy server:
+#
+#<IfModule mod_proxy.c>
+#    ProxyRequests On
+
+#    <Directory proxy:*>
+#        Order deny,allow
+#        Deny from all
+#        Allow from .your-domain.com
+#    </Directory>
+
+    #
+    # Enable/disable the handling of HTTP/1.1 "Via:" headers.
+    # ("Full" adds the server version; "Block" removes all outgoing Via: headers)
+    # Set to one of: Off | On | Full | Block
+    #
+#    ProxyVia On
+
+    #
+    # To enable the cache as well, edit and uncomment the following lines:
+    # (no cacheing without CacheRoot)
+    #
+#    CacheRoot "/private/var/run/proxy"
+#    CacheSize 5
+#    CacheGcInterval 4
+#    CacheMaxExpire 24
+#    CacheLastModifiedFactor 0.1
+#    CacheDefaultExpire 1
+#    NoCache a-domain.com another-domain.edu joes.garage-sale.com
+
+#</IfModule>
+# End of proxy directives.
+
+
+<IfModule mod_php4.c>
+    # If php is turned on, we repsect .php and .phps files.
+    AddType application/x-httpd-php .php
+    AddType application/x-httpd-php-source .phps
+
+    # Since most users will want index.php to work we
+    # also automatically enable index.php
+    <IfModule mod_dir.c>
+        DirectoryIndex index.html index.php
+    </IfModule>
+</IfModule>
+
+<IfModule mod_rewrite.c>
+    RewriteEngine On
+    RewriteCond %{REQUEST_METHOD} ^TRACE
+    RewriteRule .* - [F]
+</IfModule>
diff --git a/google/httpd_config/httpd2.conf b/google/httpd_config/httpd2.conf
new file mode 100644
index 0000000..8c96f75
--- /dev/null
+++ b/google/httpd_config/httpd2.conf
@@ -0,0 +1,280 @@
+## httpd2.conf -- Apache 2.x HTTP server configuration file
+
+#
+# Listen: Allows you to bind Apache to specific IP addresses and/or
+# ports, instead of the default. See also the <VirtualHost>
+# directive.
+#
+Listen 127.0.0.1:8000
+Listen 127.0.0.1:8080
+Listen 127.0.0.1:8081
+Listen 127.0.0.1:8443
+Listen 127.0.0.1:9000
+Listen 127.0.0.1:9080
+Listen 127.0.0.1:9443
+
+#
+# Dynamic Shared Object (DSO) Support
+#
+# To be able to use the functionality of a module which was built as a DSO you
+# have to place corresponding `LoadModule' lines at this location so the
+# directives contained in it are actually available _before_ they are used.
+# Please read the file http://httpd.apache.org/docs/dso.html for more
+# details about the DSO mechanism and run `httpd -l' for the list of already
+# built-in (statically linked and thus always available) modules in your httpd
+# binary.
+#
+# Note: The order in which modules are loaded is important.  Don't change
+# the order below without expert advice.
+#
+#LoadModule authn_file_module lib/apache2/mod_authn_file.so
+#LoadModule authn_dbm_module lib/apache2/mod_authn_dbm.so
+#LoadModule authn_anon_module lib/apache2/mod_authn_anon.so
+#LoadModule authn_dbd_module lib/apache2/mod_authn_dbd.so
+#LoadModule authn_default_module lib/apache2/mod_authn_default.so
+LoadModule authz_host_module lib/apache2/mod_authz_host.so
+#LoadModule authz_groupfile_module lib/apache2/mod_authz_groupfile.so
+#LoadModule authz_user_module lib/apache2/mod_authz_user.so
+#LoadModule authz_dbm_module lib/apache2/mod_authz_dbm.so
+#LoadModule authz_owner_module lib/apache2/mod_authz_owner.so
+#LoadModule authz_default_module lib/apache2/mod_authz_default.so
+#LoadModule auth_basic_module lib/apache2/mod_auth_basic.so
+#LoadModule auth_digest_module lib/apache2/mod_auth_digest.so
+#LoadModule dbd_module lib/apache2/mod_dbd.so
+#LoadModule dumpio_module lib/apache2/mod_dumpio.so
+#LoadModule ext_filter_module lib/apache2/mod_ext_filter.so
+LoadModule include_module lib/apache2/mod_include.so
+#LoadModule filter_module lib/apache2/mod_filter.so
+#LoadModule deflate_module lib/apache2/mod_deflate.so
+LoadModule log_config_module lib/apache2/mod_log_config.so
+#LoadModule log_forensic_module lib/apache2/mod_log_forensic.so
+#LoadModule logio_module lib/apache2/mod_logio.so
+#LoadModule env_module lib/apache2/mod_env.so
+#LoadModule mime_magic_module lib/apache2/mod_mime_magic.so
+#LoadModule cern_meta_module lib/apache2/mod_cern_meta.so
+#LoadModule expires_module lib/apache2/mod_expires.so
+LoadModule headers_module lib/apache2/mod_headers.so
+#LoadModule ident_module lib/apache2/mod_ident.so
+#LoadModule usertrack_module lib/apache2/mod_usertrack.so
+#LoadModule unique_id_module lib/apache2/mod_unique_id.so
+#LoadModule setenvif_module lib/apache2/mod_setenvif.so
+#LoadModule version_module lib/apache2/mod_version.so
+#LoadModule proxy_module lib/apache2/mod_proxy.so
+#LoadModule proxy_connect_module lib/apache2/mod_proxy_connect.so
+#LoadModule proxy_ftp_module lib/apache2/mod_proxy_ftp.so
+#LoadModule proxy_http_module lib/apache2/mod_proxy_http.so
+#LoadModule proxy_ajp_module lib/apache2/mod_proxy_ajp.so
+#LoadModule proxy_balancer_module lib/apache2/mod_proxy_balancer.so
+LoadModule ssl_module lib/apache2/mod_ssl.so
+LoadModule mime_module lib/apache2/mod_mime.so
+#LoadModule dav_module lib/apache2/mod_dav.so
+#LoadModule status_module lib/apache2/mod_status.so
+LoadModule autoindex_module lib/apache2/mod_autoindex.so
+LoadModule asis_module lib/apache2/mod_asis.so
+#LoadModule info_module lib/apache2/mod_info.so
+LoadModule cgi_module lib/apache2/mod_cgi.so
+#LoadModule dav_fs_module lib/apache2/mod_dav_fs.so
+#LoadModule vhost_alias_module lib/apache2/mod_vhost_alias.so
+LoadModule negotiation_module lib/apache2/mod_negotiation.so
+#LoadModule dir_module lib/apache2/mod_dir.so
+LoadModule imagemap_module lib/apache2/mod_imagemap.so
+LoadModule actions_module lib/apache2/mod_actions.so
+#LoadModule speling_module lib/apache2/mod_speling.so
+#LoadModule userdir_module lib/apache2/mod_userdir.so
+LoadModule alias_module lib/apache2/mod_alias.so
+LoadModule rewrite_module lib/apache2/mod_rewrite.so
+LoadModule php5_module lib/apache2/cygphp5.so
+
+#LoadModule imap_module          lib/apache/mod_imap.dll
+#LoadModule access_module        lib/apache/mod_access.dll
+#LoadModule auth_module          lib/apache/mod_auth.dll
+
+
+#
+# Each directory to which Apache has access, can be configured with respect
+# to which services and features are allowed and/or disabled in that
+# directory (and its subdirectories). 
+#
+<Directory />
+    Options Indexes FollowSymLinks MultiViews ExecCGI Includes
+    AllowOverride All
+    Order allow,deny
+    Allow from all
+</Directory>
+
+
+#
+# Apple specific filesystem protection.
+# 
+<Files "rsrc">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</Files>
+<Directory  ~ ".*\.\.namedfork">
+    Order allow,deny
+    Deny from all
+    Satisfy All
+</Directory>
+
+
+#
+# UseCanonicalName:  (new for 1.3)  With this setting turned on, whenever
+# Apache needs to construct a self-referencing URL (a URL that refers back
+# to the server the response is coming from) it will use ServerName and
+# Port to form a "canonical" name.  With this setting off, Apache will
+# use the hostname:port that the client supplied, when possible.  This
+# also affects SERVER_NAME and SERVER_PORT in CGI scripts.
+#
+UseCanonicalName On
+
+
+#
+# The following directives define some format nicknames for use with
+# a CustomLog directive (see below).
+#
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+
+#
+# Optionally add a line containing the server version and virtual host
+# name to server-generated pages (error documents, FTP directory listings,
+# mod_status and mod_info output etc., but not CGI generated documents).
+# Set to "EMail" to also include a mailto: link to the ServerAdmin.
+# Set to one of:  On | Off | EMail
+#
+ServerSignature On
+
+
+#
+# Document types.
+#
+<IfModule mime_module>
+
+    #
+    # AddLanguage allows you to specify the language of a document. You can
+    # then use content negotiation to give a browser a file in a language
+    # it can understand.  
+    #
+    # Note 1: The suffix does not have to be the same as the language 
+    # keyword --- those with documents in Polish (whose net-standard 
+    # language code is pl) may wish to use "AddLanguage pl .po" to 
+    # avoid the ambiguity with the common suffix for perl scripts.
+    #
+    # Note 2: The example entries below illustrate that in quite
+    # some cases the two character 'Language' abbreviation is not
+    # identical to the two character 'Country' code for its country,
+    # E.g. 'Danmark/dk' versus 'Danish/da'.
+    #
+    # Note 3: In the case of 'ltz' we violate the RFC by using a three char 
+    # specifier. But there is 'work in progress' to fix this and get 
+    # the reference data for rfc1766 cleaned up.
+    #
+    # Danish (da) - Dutch (nl) - English (en) - Estonian (ee)
+    # French (fr) - German (de) - Greek-Modern (el)
+    # Italian (it) - Korean (kr) - Norwegian (no) - Norwegian Nynorsk (nn)
+    # Portugese (pt) - Luxembourgeois* (ltz)
+    # Spanish (es) - Swedish (sv) - Catalan (ca) - Czech(cs)
+    # Polish (pl) - Brazilian Portuguese (pt-br) - Japanese (ja)
+    # Russian (ru)
+    #
+    AddLanguage da .dk
+    AddLanguage nl .nl
+    AddLanguage en .en
+    AddLanguage et .ee
+    AddLanguage fr .fr
+    AddLanguage de .de
+    AddLanguage el .el
+    AddLanguage he .he
+    AddCharset ISO-8859-8 .iso8859-8
+    AddLanguage it .it
+    AddLanguage ja .ja
+    AddCharset ISO-2022-JP .jis
+    AddLanguage kr .kr
+    AddCharset ISO-2022-KR .iso-kr
+    AddLanguage nn .nn
+    AddLanguage no .no
+    AddLanguage pl .po
+    AddCharset ISO-8859-2 .iso-pl
+    AddLanguage pt .pt
+    AddLanguage pt-br .pt-br
+    AddLanguage ltz .lu
+    AddLanguage ca .ca
+    AddLanguage es .es
+    AddLanguage sv .sv
+    AddLanguage cs .cz .cs
+    AddLanguage ru .ru
+    AddLanguage zh-TW .zh-tw
+    AddCharset Big5         .Big5    .big5
+    AddCharset WINDOWS-1251 .cp-1251
+    AddCharset CP866        .cp866
+    AddCharset ISO-8859-5   .iso-ru
+    AddCharset KOI8-R       .koi8-r
+    AddCharset UCS-2        .ucs2
+    AddCharset UCS-4        .ucs4
+    AddCharset UTF-8        .utf8
+
+    # LanguagePriority allows you to give precedence to some languages
+    # in case of a tie during content negotiation.
+    #
+    # Just list the languages in decreasing order of preference. We have
+    # more or less alphabetized them here. You probably want to change this.
+    #
+    <IfModule negotiation_module>
+        LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ru ltz ca es sv tw
+    </IfModule>
+
+    #
+    # AddType allows you to tweak mime.types without actually editing it, or to
+    # make certain files to be certain types.
+    #
+    AddType application/x-tar .tgz
+
+    #
+    # AddEncoding allows you to have certain browsers uncompress
+    # information on the fly. Note: Not all browsers support this.
+    # Despite the name similarity, the following Add* directives have nothing
+    # to do with the FancyIndexing customization directives above.
+    #
+    AddEncoding x-compress .Z
+    AddEncoding x-gzip .gz .tgz
+
+    #
+    # AddHandler allows you to map certain file extensions to "handlers",
+    # actions unrelated to filetype. These can be either built into the server
+    # or added with the Action command (see below)
+    #
+    # If you want to use server side includes, or CGI outside
+    # ScriptAliased directories, uncomment the following lines.
+    #
+    # To use CGI scripts:
+    #
+    AddHandler cgi-script .cgi .pl
+
+    #
+    # To use server-parsed HTML files
+    #
+    AddType text/html .shtml
+    AddHandler server-parsed .shtml
+
+    #
+    # Uncomment the following line to enable Apache's send-asis HTTP file
+    # feature
+    #
+    AddHandler send-as-is asis
+</IfModule>
+
+
+<IfModule php5_module>
+    AddType application/x-httpd-php .php
+    AddType application/x-httpd-php-source .phps
+</IfModule>
+
+<IfModule rewrite_module>
+    RewriteEngine On
+    RewriteCond %{REQUEST_METHOD} ^TRACE
+    RewriteRule .* - [F]
+</IfModule>
diff --git a/google/httpd_config/httpd2.pem b/google/httpd_config/httpd2.pem
new file mode 100644
index 0000000..1ad5794
--- /dev/null
+++ b/google/httpd_config/httpd2.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----

+MIIDazCCAtSgAwIBAgIBEDANBgkqhkiG9w0BAQUFADByMQswCQYDVQQGEwJVUzET

+MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIG

+A1UEChMLR29vZ2xlIEluYy4xIDAeBgNVBAMTF2F0dGljdXMuY29ycC5nb29nbGUu

+Y29tMB4XDTA2MDEwMTAwMDAwMFoXDTIwMDEwMTAwMDAwMFowTDELMAkGA1UEBhMC

+VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFDASBgNVBAoTC0dvb2dsZSBJbmMuMRIw

+EAYDVQQDEwkxMjcuMC4wLjEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK0I

+45wdTT2/fui9FfNOR17idQF0L/kpn88D1OzF0w0h3TMBN8szpOxAQYT2MTuB17Dt

+ttMiwzLuoByP7KipmeKy63GFlV7dHS2XEirzP23c/RxZ/7W9UQ/VmgSvXjNzIXyu

+t+Ylfeg6VfFANsPQmov3SIO1Zh3NQRS/d+M5ig7lAgMBAAGjggE1MIIBMTAJBgNV

+HRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZp

+Y2F0ZTAdBgNVHQ4EFgQU6n4XBAZRnkrXMlko23vCClLlztEwgY4GA1UdIwSBhjCB

+g6F2pHQwcjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV

+BAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC0dvb2dsZSBJbmMuMSAwHgYDVQQD

+ExdhdHRpY3VzLmNvcnAuZ29vZ2xlLmNvbYIJAKGvvYc2FdhzMEYGA1UdHwQ/MD0w

+O6A5oDeGNWh0dHA6Ly9jaHJvbWV0d3MuY29ycC5nb29nbGUuY29tOjgwODAvY3Js

+L2F0dGljdXMuY3JsMA0GCSqGSIb3DQEBBQUAA4GBAHt8Zxf4D86QBuWkP2STN4Pg

+aLzut1eaY0u5DOxr3fqrwbaDlPJrJJqQJmMPwUItVMjw+zWO/CmoBY7vsJMcX/57

++kIHoQ+XCQJdOnM7qa3Hslt4bLRx+d0zQqt6/+gBNrz5F36njgansvxjnnacbApv

+uNQFNT5wCAqRadGn4d63

+-----END CERTIFICATE-----

+-----BEGIN RSA PRIVATE KEY-----

+MIICXQIBAAKBgQCtCOOcHU09v37ovRXzTkde4nUBdC/5KZ/PA9TsxdMNId0zATfL

+M6TsQEGE9jE7gdew7bbTIsMy7qAcj+yoqZnisutxhZVe3R0tlxIq8z9t3P0cWf+1

+vVEP1ZoEr14zcyF8rrfmJX3oOlXxQDbD0JqL90iDtWYdzUEUv3fjOYoO5QIDAQAB

+AoGALSNMfMUICTuTF5N7zmR1KcNZUm/Es/KvxYjyWnGghKR4131R2Kg4NYjtjonK

+fgN5CKZ6Msm2seqdydWhnr3fbl3KhPF7nTdFUR6OM4eUuUH3nV1DS1w9AW0Z/4nB

+3OipLkxvTtRomfEUoZdE3I4+2T9iBdfPGduZ3CNR1H9EL2ECQQDfyT3dOVg5Zr7Q

+gZ8rQhyxtA+OhWvqU9F5Ahii002fIMj//rMIowvGesW2rfMwYs/oFF36l2vXOhvh

+whL+hmJ/AkEAxfFnlp8hT3WeRqJ74b3QSkyItWz7XbSQRPFWurPEfNI8wz57Svvy

+8tv396X8yImPwxXhihjSn9bwSHoon0WUmwJBAMt2S1HUblsaCEjIYS/SVwZWIILC

+2Z/d/yiW+FEp7nvMMhNVve8PVohpXVM/CkkmvcJSqjNI8ppnUaxLaDuTcP8CQQCn

+40L7K+ky3g3q1zG/nCEog5WIW/Ev31BmSVRIcuT7Ac5rw3kLdnrvpcbCE9U9uf9n

+dg2f9cHftIyEzKfbv0Z1AkAlX4x7De9edylrZ14IA9BbEe0ztsCik3UGXYriYfwY

+Z9h+uyhqNJT+SaWjb1QcBQ8jbYC0d2zxQSMuf8NxYrd2

+-----END RSA PRIVATE KEY-----

diff --git a/google/httpd_config/mime.types b/google/httpd_config/mime.types
new file mode 100644
index 0000000..6735f1b
--- /dev/null
+++ b/google/httpd_config/mime.types
@@ -0,0 +1,599 @@
+# This is a comment. I love comments.
+
+# This file controls what Internet media types are sent to the client for
+# given file extension(s).  Sending the correct media type to the client
+# is important so they know how to handle the content of the file.
+# Extra types can either be added here or by using an AddType directive
+# in your config files. For more information about Internet media types,
+# please read RFC 2045, 2046, 2047, 2048, and 2077.  The Internet media type
+# registry is at <http://www.iana.org/assignments/media-types/>.
+
+# MIME type			Extensions
+application/activemessage
+application/andrew-inset	ez
+application/applefile
+application/atom+xml		atom
+application/atomicmail
+application/batch-smtp
+application/beep+xml
+application/cals-1840
+application/cnrp+xml
+application/commonground
+application/cpl+xml
+application/cybercash
+application/dca-rft
+application/dec-dx
+application/dvcs
+application/edi-consent
+application/edifact
+application/edi-x12
+application/eshop
+application/font-tdpfr
+application/http
+application/hyperstudio
+application/iges
+application/index
+application/index.cmd
+application/index.obj
+application/index.response
+application/index.vnd
+application/iotp
+application/ipp
+application/isup
+application/mac-binhex40	hqx
+application/mac-compactpro	cpt
+application/macwriteii
+application/marc
+application/mathematica
+application/mathml+xml		mathml
+application/msword		doc
+application/news-message-id
+application/news-transmission
+application/ocsp-request
+application/ocsp-response
+application/octet-stream	bin dms lha lzh exe class so dll dmg
+application/oda			oda
+application/ogg			ogg
+application/parityfec
+application/pdf			pdf
+application/pgp-encrypted
+application/pgp-keys
+application/pgp-signature
+application/pkcs10
+application/pkcs7-mime
+application/pkcs7-signature
+application/pkix-cert
+application/pkix-crl
+application/pkixcmp
+application/postscript		ai eps ps
+application/prs.alvestrand.titrax-sheet
+application/prs.cww
+application/prs.nprend
+application/prs.plucker
+application/qsig
+application/rdf+xml		rdf
+application/reginfo+xml
+application/remote-printing
+application/riscos
+application/rtf
+application/sdp
+application/set-payment
+application/set-payment-initiation
+application/set-registration
+application/set-registration-initiation
+application/sgml
+application/sgml-open-catalog
+application/sieve
+application/slate
+application/smil		smi smil
+application/srgs		gram
+application/srgs+xml		grxml
+application/timestamp-query
+application/timestamp-reply
+application/tve-trigger
+application/vemmi
+application/vnd.3gpp.pic-bw-large
+application/vnd.3gpp.pic-bw-small
+application/vnd.3gpp.pic-bw-var
+application/vnd.3gpp.sms
+application/vnd.3m.post-it-notes
+application/vnd.accpac.simply.aso
+application/vnd.accpac.simply.imp
+application/vnd.acucobol
+application/vnd.acucorp
+application/vnd.adobe.xfdf
+application/vnd.aether.imp
+application/vnd.amiga.ami
+application/vnd.anser-web-certificate-issue-initiation
+application/vnd.anser-web-funds-transfer-initiation
+application/vnd.audiograph
+application/vnd.blueice.multipass
+application/vnd.bmi
+application/vnd.businessobjects
+application/vnd.canon-cpdl
+application/vnd.canon-lips
+application/vnd.cinderella
+application/vnd.claymore
+application/vnd.commerce-battelle
+application/vnd.commonspace
+application/vnd.contact.cmsg
+application/vnd.cosmocaller
+application/vnd.criticaltools.wbs+xml
+application/vnd.ctc-posml
+application/vnd.cups-postscript
+application/vnd.cups-raster
+application/vnd.cups-raw
+application/vnd.curl
+application/vnd.cybank
+application/vnd.data-vision.rdz
+application/vnd.dna
+application/vnd.dpgraph
+application/vnd.dreamfactory
+application/vnd.dxr
+application/vnd.ecdis-update
+application/vnd.ecowin.chart
+application/vnd.ecowin.filerequest
+application/vnd.ecowin.fileupdate
+application/vnd.ecowin.series
+application/vnd.ecowin.seriesrequest
+application/vnd.ecowin.seriesupdate
+application/vnd.enliven
+application/vnd.epson.esf
+application/vnd.epson.msf
+application/vnd.epson.quickanime
+application/vnd.epson.salt
+application/vnd.epson.ssf
+application/vnd.ericsson.quickcall
+application/vnd.eudora.data
+application/vnd.fdf
+application/vnd.ffsns
+application/vnd.fints
+application/vnd.flographit
+application/vnd.framemaker
+application/vnd.fsc.weblaunch
+application/vnd.fujitsu.oasys
+application/vnd.fujitsu.oasys2
+application/vnd.fujitsu.oasys3
+application/vnd.fujitsu.oasysgp
+application/vnd.fujitsu.oasysprs
+application/vnd.fujixerox.ddd
+application/vnd.fujixerox.docuworks
+application/vnd.fujixerox.docuworks.binder
+application/vnd.fut-misnet
+application/vnd.grafeq
+application/vnd.groove-account
+application/vnd.groove-help
+application/vnd.groove-identity-message
+application/vnd.groove-injector
+application/vnd.groove-tool-message
+application/vnd.groove-tool-template
+application/vnd.groove-vcard
+application/vnd.hbci
+application/vnd.hhe.lesson-player
+application/vnd.hp-hpgl
+application/vnd.hp-hpid
+application/vnd.hp-hps
+application/vnd.hp-pcl
+application/vnd.hp-pclxl
+application/vnd.httphone
+application/vnd.hzn-3d-crossword
+application/vnd.ibm.afplinedata
+application/vnd.ibm.electronic-media
+application/vnd.ibm.minipay
+application/vnd.ibm.modcap
+application/vnd.ibm.rights-management
+application/vnd.ibm.secure-container
+application/vnd.informix-visionary
+application/vnd.intercon.formnet
+application/vnd.intertrust.digibox
+application/vnd.intertrust.nncp
+application/vnd.intu.qbo
+application/vnd.intu.qfx
+application/vnd.irepository.package+xml
+application/vnd.is-xpr
+application/vnd.japannet-directory-service
+application/vnd.japannet-jpnstore-wakeup
+application/vnd.japannet-payment-wakeup
+application/vnd.japannet-registration
+application/vnd.japannet-registration-wakeup
+application/vnd.japannet-setstore-wakeup
+application/vnd.japannet-verification
+application/vnd.japannet-verification-wakeup
+application/vnd.jisp
+application/vnd.kde.karbon
+application/vnd.kde.kchart
+application/vnd.kde.kformula
+application/vnd.kde.kivio
+application/vnd.kde.kontour
+application/vnd.kde.kpresenter
+application/vnd.kde.kspread
+application/vnd.kde.kword
+application/vnd.kenameaapp
+application/vnd.koan
+application/vnd.liberty-request+xml
+application/vnd.llamagraphics.life-balance.desktop
+application/vnd.llamagraphics.life-balance.exchange+xml
+application/vnd.lotus-1-2-3
+application/vnd.lotus-approach
+application/vnd.lotus-freelance
+application/vnd.lotus-notes
+application/vnd.lotus-organizer
+application/vnd.lotus-screencam
+application/vnd.lotus-wordpro
+application/vnd.mcd
+application/vnd.mediastation.cdkey
+application/vnd.meridian-slingshot
+application/vnd.micrografx.flo
+application/vnd.micrografx.igx
+application/vnd.mif		mif
+application/vnd.minisoft-hp3000-save
+application/vnd.mitsubishi.misty-guard.trustweb
+application/vnd.mobius.daf
+application/vnd.mobius.dis
+application/vnd.mobius.mbk
+application/vnd.mobius.mqy
+application/vnd.mobius.msl
+application/vnd.mobius.plc
+application/vnd.mobius.txf
+application/vnd.mophun.application
+application/vnd.mophun.certificate
+application/vnd.motorola.flexsuite
+application/vnd.motorola.flexsuite.adsi
+application/vnd.motorola.flexsuite.fis
+application/vnd.motorola.flexsuite.gotap
+application/vnd.motorola.flexsuite.kmr
+application/vnd.motorola.flexsuite.ttc
+application/vnd.motorola.flexsuite.wem
+application/vnd.mozilla.xul+xml	xul
+application/vnd.ms-artgalry
+application/vnd.ms-asf
+application/vnd.ms-excel	xls
+application/vnd.ms-lrm
+application/vnd.ms-powerpoint	ppt
+application/vnd.ms-project
+application/vnd.ms-tnef
+application/vnd.ms-works
+application/vnd.ms-wpl
+application/vnd.mseq
+application/vnd.msign
+application/vnd.music-niff
+application/vnd.musician
+application/vnd.netfpx
+application/vnd.noblenet-directory
+application/vnd.noblenet-sealer
+application/vnd.noblenet-web
+application/vnd.novadigm.edm
+application/vnd.novadigm.edx
+application/vnd.novadigm.ext
+application/vnd.obn
+application/vnd.osa.netdeploy
+application/vnd.palm
+application/vnd.pg.format
+application/vnd.pg.osasli
+application/vnd.powerbuilder6
+application/vnd.powerbuilder6-s
+application/vnd.powerbuilder7
+application/vnd.powerbuilder7-s
+application/vnd.powerbuilder75
+application/vnd.powerbuilder75-s
+application/vnd.previewsystems.box
+application/vnd.publishare-delta-tree
+application/vnd.pvi.ptid1
+application/vnd.pwg-multiplexed
+application/vnd.pwg-xhtml-print+xml
+application/vnd.quark.quarkxpress
+application/vnd.rapid
+application/vnd.rn-realmedia	rm
+application/vnd.s3sms
+application/vnd.sealed.net
+application/vnd.seemail
+application/vnd.shana.informed.formdata
+application/vnd.shana.informed.formtemplate
+application/vnd.shana.informed.interchange
+application/vnd.shana.informed.package
+application/vnd.smaf
+application/vnd.sss-cod
+application/vnd.sss-dtf
+application/vnd.sss-ntf
+application/vnd.street-stream
+application/vnd.svd
+application/vnd.swiftview-ics
+application/vnd.triscape.mxs
+application/vnd.trueapp
+application/vnd.truedoc
+application/vnd.ufdl
+application/vnd.uplanet.alert
+application/vnd.uplanet.alert-wbxml
+application/vnd.uplanet.bearer-choice
+application/vnd.uplanet.bearer-choice-wbxml
+application/vnd.uplanet.cacheop
+application/vnd.uplanet.cacheop-wbxml
+application/vnd.uplanet.channel
+application/vnd.uplanet.channel-wbxml
+application/vnd.uplanet.list
+application/vnd.uplanet.list-wbxml
+application/vnd.uplanet.listcmd
+application/vnd.uplanet.listcmd-wbxml
+application/vnd.uplanet.signal
+application/vnd.vcx
+application/vnd.vectorworks
+application/vnd.vidsoft.vidconference
+application/vnd.visio
+application/vnd.visionary
+application/vnd.vividence.scriptfile
+application/vnd.vsf
+application/vnd.wap.sic
+application/vnd.wap.slc
+application/vnd.wap.wbxml	wbxml
+application/vnd.wap.wmlc	wmlc
+application/vnd.wap.wmlscriptc	wmlsc
+application/vnd.webturbo
+application/vnd.wrq-hp3000-labelled
+application/vnd.wt.stf
+application/vnd.wv.csp+wbxml
+application/vnd.xara
+application/vnd.xfdl
+application/vnd.yamaha.hv-dic
+application/vnd.yamaha.hv-script
+application/vnd.yamaha.hv-voice
+application/vnd.yellowriver-custom-menu
+application/voicexml+xml	vxml
+application/watcherinfo+xml
+application/whoispp-query
+application/whoispp-response
+application/wita
+application/wordperfect5.1
+application/x-bcpio		bcpio
+application/x-cdlink		vcd
+application/x-chess-pgn		pgn
+application/x-compress
+application/x-cpio		cpio
+application/x-csh		csh
+application/x-director		dcr dir dxr
+application/x-dvi		dvi
+application/x-futuresplash	spl
+application/x-gtar		gtar
+application/x-gzip
+application/x-hdf		hdf
+application/x-javascript	js
+application/x-java-jnlp-file	jnlp
+application/x-koan		skp skd skt skm
+application/x-latex		latex
+application/x-netcdf		nc cdf
+application/x-sh		sh
+application/x-shar		shar
+application/x-shockwave-flash	swf
+application/x-stuffit		sit
+application/x-sv4cpio		sv4cpio
+application/x-sv4crc		sv4crc
+application/x-tar		tar
+application/x-tcl		tcl
+application/x-tex		tex
+application/x-texinfo		texinfo texi
+application/x-troff		t tr roff
+application/x-troff-man		man
+application/x-troff-me		me
+application/x-troff-ms		ms
+application/x-ustar		ustar
+application/x-wais-source	src
+application/x400-bp
+application/xhtml+xml		xhtml xht
+application/xslt+xml		xslt
+application/xml			xml xsl
+application/xml-dtd		dtd
+application/xml-external-parsed-entity
+application/zip			zip
+audio/32kadpcm
+audio/amr
+audio/amr-wb
+audio/basic			au snd
+audio/cn
+audio/dat12
+audio/dsr-es201108
+audio/dvi4
+audio/evrc
+audio/evrc0
+audio/g722
+audio/g.722.1
+audio/g723
+audio/g726-16
+audio/g726-24
+audio/g726-32
+audio/g726-40
+audio/g728
+audio/g729
+audio/g729D
+audio/g729E
+audio/gsm
+audio/gsm-efr
+audio/l8
+audio/l16
+audio/l20
+audio/l24
+audio/lpc
+audio/midi			mid midi kar
+audio/mpa
+audio/mpa-robust
+audio/mp4a-latm			m4a m4p
+audio/mpeg			mpga mp2 mp3
+audio/parityfec
+audio/pcma
+audio/pcmu
+audio/prs.sid
+audio/qcelp
+audio/red
+audio/smv
+audio/smv0
+audio/telephone-event
+audio/tone
+audio/vdvi
+audio/vnd.3gpp.iufp
+audio/vnd.cisco.nse
+audio/vnd.cns.anp1
+audio/vnd.cns.inf1
+audio/vnd.digital-winds
+audio/vnd.everad.plj
+audio/vnd.lucent.voice
+audio/vnd.nortel.vbk
+audio/vnd.nuera.ecelp4800
+audio/vnd.nuera.ecelp7470
+audio/vnd.nuera.ecelp9600
+audio/vnd.octel.sbc
+audio/vnd.qcelp
+audio/vnd.rhetorex.32kadpcm
+audio/vnd.vmx.cvsd
+audio/x-aiff			aif aiff aifc
+audio/x-alaw-basic
+audio/x-mpegurl			m3u
+audio/x-pn-realaudio		ram ra
+audio/x-pn-realaudio-plugin
+audio/x-wav			wav
+chemical/x-pdb			pdb
+chemical/x-xyz			xyz
+image/bmp			bmp
+image/cgm			cgm
+image/g3fax
+image/gif			gif
+image/ief			ief
+image/jpeg			jpeg jpg jpe
+image/jp2			jp2
+image/naplps
+image/pict			pict pic pct
+image/png			png
+image/prs.btif
+image/prs.pti
+image/svg+xml			svg
+image/t38
+image/tiff			tiff tif
+image/tiff-fx
+image/vnd.cns.inf2
+image/vnd.djvu			djvu djv
+image/vnd.dwg
+image/vnd.dxf
+image/vnd.fastbidsheet
+image/vnd.fpx
+image/vnd.fst
+image/vnd.fujixerox.edmics-mmr
+image/vnd.fujixerox.edmics-rlc
+image/vnd.globalgraphics.pgb
+image/vnd.mix
+image/vnd.ms-modi
+image/vnd.net-fpx
+image/vnd.svf
+image/vnd.wap.wbmp		wbmp
+image/vnd.xiff
+image/x-cmu-raster		ras
+image/x-macpaint		pntg pnt mac
+image/x-icon			ico
+image/x-portable-anymap		pnm
+image/x-portable-bitmap		pbm
+image/x-portable-graymap	pgm
+image/x-portable-pixmap		ppm
+image/x-quicktime		qtif qti
+image/x-rgb			rgb
+image/x-xbitmap			xbm
+image/x-xpixmap			xpm
+image/x-xwindowdump		xwd
+message/delivery-status
+message/disposition-notification
+message/external-body
+message/http
+message/news
+message/partial
+message/rfc822
+message/s-http
+message/sip
+message/sipfrag
+model/iges			igs iges
+model/mesh			msh mesh silo
+model/vnd.dwf
+model/vnd.flatland.3dml
+model/vnd.gdl
+model/vnd.gs-gdl
+model/vnd.gtw
+model/vnd.mts
+model/vnd.parasolid.transmit.binary
+model/vnd.parasolid.transmit.text
+model/vnd.vtu
+model/vrml			wrl vrml
+multipart/alternative
+multipart/appledouble
+multipart/byteranges
+multipart/digest
+multipart/encrypted
+multipart/form-data
+multipart/header-set
+multipart/mixed
+multipart/parallel
+multipart/related
+multipart/report
+multipart/signed
+multipart/voice-message
+text/calendar			ics ifb
+text/css			css
+text/directory
+text/enriched
+text/html			html htm
+text/parityfec
+text/plain			asc txt
+text/prs.lines.tag
+text/rfc822-headers
+text/richtext			rtx
+text/rtf			rtf
+text/sgml			sgml sgm
+text/t140
+text/tab-separated-values	tsv
+text/uri-list
+text/vnd.abc
+text/vnd.curl
+text/vnd.dmclientscript
+text/vnd.fly
+text/vnd.fmi.flexstor
+text/vnd.in3d.3dml
+text/vnd.in3d.spot
+text/vnd.iptc.nitf
+text/vnd.iptc.newsml
+text/vnd.latex-z
+text/vnd.motorola.reflex
+text/vnd.ms-mediapackage
+text/vnd.net2phone.commcenter.command
+text/vnd.sun.j2me.app-descriptor
+text/vnd.wap.si
+text/vnd.wap.sl
+text/vnd.wap.wml		wml
+text/vnd.wap.wmlscript		wmls
+text/x-setext			etx
+text/xml
+text/xml-external-parsed-entity
+video/bmpeg
+video/bt656
+video/celb
+video/dv
+video/h261
+video/h263
+video/h263-1998
+video/h263-2000
+video/jpeg
+video/mp1s
+video/mp2p
+video/mp2t
+video/mp4			mp4
+video/mp4v-es
+video/mpv
+video/mpeg			mpeg mpg mpe
+video/nv
+video/parityfec
+video/pointer
+video/quicktime			qt mov
+video/smpte292m
+video/vnd.fvt
+video/vnd.motorola.video
+video/vnd.motorola.videop
+video/vnd.mpegurl		mxu m4u
+video/vnd.nokia.interleaved-multimedia
+video/vnd.objectvideo
+video/vnd.vivo
+video/x-dv			dv dif
+video/x-msvideo			avi
+video/x-sgi-movie		movie
+x-conference/x-cooltalk		ice
diff --git a/google/httpd_utils.py b/google/httpd_utils.py
new file mode 100644
index 0000000..7f76ca6
--- /dev/null
+++ b/google/httpd_utils.py
@@ -0,0 +1,219 @@
+#!/bin/env python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""A class to help start/stop a local apache http server."""
+
+import logging
+import optparse
+import os
+import subprocess
+import sys
+import time
+import urllib
+
+import google.path_utils
+import google.platform_utils
+
+class HttpdNotStarted(Exception): pass
+
+def ApacheConfigDir(start_dir):
+  """Returns a path to the directory holding the Apache config files."""
+  return google.path_utils.FindUpward(start_dir, 'tools', 'python',
+                                      'google', 'httpd_config')
+
+
+def GetCygserverPath(start_dir, apache2=False):
+  """Returns the path to the directory holding cygserver.exe file."""
+  cygserver_path = None
+  if apache2:
+    cygserver_path = google.path_utils.FindUpward(start_dir, 'third_party',
+                                                  'cygwin', 'usr', 'sbin')
+  return cygserver_path
+
+  
+def StartServer(document_root=None, output_dir=None, apache2=False):
+  """Starts a local server on port 8000 using the basic configuration files.
+
+  Args:
+    document_root: If present, specifies the document root for the server;
+        otherwise, the filesystem's root (e.g., C:/ or /) will be used.
+    output_dir: If present, specifies where to put server logs; otherwise,
+        they'll be placed in the system's temp dir (e.g., $TEMP or /tmp).
+    apache2: boolean if true will cause this function to configure
+             for Apache 2.x as opposed to Apache 1.3.x
+
+  Returns: the ApacheHttpd object that was created
+  """
+  script_dir = google.path_utils.ScriptDir()
+  platform_util = google.platform_utils.PlatformUtility(script_dir)
+  if not output_dir:
+    output_dir = platform_util.GetTempDirectory()
+  if not document_root:
+    document_root = platform_util.GetFilesystemRoot()
+  apache_config_dir = ApacheConfigDir(script_dir)
+  if apache2:
+    httpd_conf_path = os.path.join(apache_config_dir, 'httpd2.conf')
+  else:
+    httpd_conf_path = os.path.join(apache_config_dir, 'httpd.conf')
+  mime_types_path = os.path.join(apache_config_dir, 'mime.types')
+  start_cmd = platform_util.GetStartHttpdCommand(output_dir,
+                                                 httpd_conf_path,
+                                                 mime_types_path,
+                                                 document_root,
+                                                 apache2=apache2)
+  stop_cmd = platform_util.GetStopHttpdCommand()
+  httpd = ApacheHttpd(start_cmd, stop_cmd, [8000],
+                      cygserver_path=GetCygserverPath(script_dir, apache2))
+  httpd.StartServer()
+  return httpd
+
+
+def StopServers(apache2=False):
+  """Calls the platform's stop command on a newly created server, forcing it
+  to stop.
+
+  The details depend on the behavior of the platform stop command. For example,
+  it's often implemented to kill all running httpd processes, as implied by
+  the name of this function.
+
+  Args:
+    apache2: boolean if true will cause this function to configure
+             for Apache 2.x as opposed to Apache 1.3.x
+  """
+  script_dir = google.path_utils.ScriptDir()
+  platform_util = google.platform_utils.PlatformUtility(script_dir)
+  httpd = ApacheHttpd('', platform_util.GetStopHttpdCommand(), [],
+                      cygserver_path=GetCygserverPath(script_dir, apache2))
+  httpd.StopServer(force=True)
+
+
+class ApacheHttpd(object):
+  def __init__(self, start_command, stop_command, port_list,
+               cygserver_path=None):
+    """Args:
+        start_command: command list to call to start the httpd
+        stop_command: command list to call to stop the httpd if one has been
+            started.  May kill all httpd processes running on the machine.
+        port_list: list of ports expected to respond on the local machine when
+            the server has been successfully started.
+        cygserver_path: Path to cygserver.exe. If specified, exe will be started
+            with server as well as stopped when server is stopped.
+    """
+    self._http_server_proc = None
+    self._start_command = start_command
+    self._stop_command = stop_command
+    self._port_list = port_list
+    self._cygserver_path = cygserver_path
+
+  def StartServer(self):
+    if self._http_server_proc:
+      return
+    if self._cygserver_path:
+      cygserver_exe = os.path.join(self._cygserver_path, "cygserver.exe")
+      cygbin = google.path_utils.FindUpward(cygserver_exe, 'third_party',
+                                            'cygwin', 'bin')
+      env = os.environ
+      env['PATH'] += ";" + cygbin
+      subprocess.Popen(cygserver_exe, env=env)
+    logging.info('Starting http server')
+    self._http_server_proc = subprocess.Popen(self._start_command)
+
+    # Ensure that the server is running on all the desired ports.
+    for port in self._port_list:
+      if not self._UrlIsAlive('http://127.0.0.1:%s/' % str(port)):
+        raise HttpdNotStarted('Failed to start httpd on port %s' % str(port))
+
+  def _UrlIsAlive(self, url):
+    """Checks to see if we get an http response from |url|.
+    We poll the url 5 times with a 1 second delay.  If we don't
+    get a reply in that time, we give up and assume the httpd
+    didn't start properly.
+
+    Args:
+      url: The URL to check.
+    Return:
+      True if the url is alive.
+    """
+    wait_time = 5
+    while wait_time > 0:
+      try:
+        response = urllib.urlopen(url)
+        # Server is up and responding.
+        return True
+      except IOError:
+        pass
+      wait_time -= 1
+      # Wait a second and try again.
+      time.sleep(1)
+
+    return False
+
+  def StopServer(self, force=False):
+    """If we started an httpd.exe process, or if force is True, call
+    self._stop_command (passed in on init so it can be platform-dependent).
+    This will presumably kill it, and may also kill any other httpd.exe
+    processes that are running.
+    """
+    if force or self._http_server_proc:
+      logging.info('Stopping http server')
+      kill_proc = subprocess.Popen(self._stop_command,
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE)
+      logging.info('%s\n%s' % (kill_proc.stdout.read(),
+                               kill_proc.stderr.read()))
+      self._http_server_proc = None
+      if self._cygserver_path:
+        subprocess.Popen(["taskkill.exe", "/f", "/im", "cygserver.exe"],
+                         stdout=subprocess.PIPE,
+                         stderr=subprocess.PIPE)
+
+if '__main__' == __name__:
+  # Provide some command line params for starting/stopping the http server
+  # manually.
+  option_parser = optparse.OptionParser()
+  option_parser.add_option('-k', '--server', help='Server action (start|stop)')
+  option_parser.add_option('-r', '--root', help='Document root (optional)')
+  option_parser.add_option('-a', '--apache2', action='store_true',
+      default=False, help='Starts Apache 2 instead of Apache 1.3 (default).')
+  options, args = option_parser.parse_args()
+
+  if not options.server:
+    print ("Usage: %s -k {start|stop} [-r document_root] [--apache2]" %
+           sys.argv[0])
+    sys.exit(0)
+
+  document_root = None
+  if options.root:
+    document_root = options.root
+
+  if 'start' == options.server:
+    StartServer(document_root, apache2=options.apache2)
+  else:
+    StopServers(apache2=options.apache2)
diff --git a/google/logging_utils.py b/google/logging_utils.py
new file mode 100644
index 0000000..cf9f3fa
--- /dev/null
+++ b/google/logging_utils.py
@@ -0,0 +1,110 @@
+#!/bin/env python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# logging_utils.py
+
+''' Utility functions and objects for logging.
+'''
+
+import logging
+import sys
+
+class StdoutStderrHandler(logging.Handler):
+  ''' Subclass of logging.Handler which outputs to either stdout or stderr
+  based on a threshold level.
+  '''
+
+  def __init__(self, threshold=logging.WARNING, err=sys.stderr, out=sys.stdout):
+    ''' Args:
+          threshold: below this logging level messages are sent to stdout,
+            otherwise they are sent to stderr
+          err: a stream object that error messages are sent to, defaults to
+            sys.stderr
+          out: a stream object that non-error messages are sent to, defaults to
+            sys.stdout
+    '''
+    logging.Handler.__init__(self)
+    self._err = logging.StreamHandler(err)    
+    self._out = logging.StreamHandler(out)
+    self._threshold = threshold
+    self._last_was_err = False
+    
+  def setLevel(self, lvl):
+    logging.Handler.setLevel(self, lvl)
+    self._err.setLevel(lvl)
+    self._out.setLevel(lvl)
+
+  def setFormatter(self, formatter):
+    logging.Handler.setFormatter(self, formatter)
+    self._err.setFormatter(formatter)
+    self._out.setFormatter(formatter)
+
+  def emit(self, record):
+    if record.levelno < self._threshold:
+      self._out.emit(record)
+      self._last_was_err = False
+    else:
+      self._err.emit(record)
+      self._last_was_err = False
+
+  def flush(self):
+    # preserve order on the flushing, the stalest stream gets flushed first
+    if self._last_was_err:
+      self._out.flush()
+      self._err.flush()
+    else:
+      self._err.flush()
+      self._out.flush()
+
+
+FORMAT = "%(asctime)s %(filename)s [%(levelname)s] %(message)s"
+DATEFMT = "%H:%M:%S"
+
+def config_root(level=logging.INFO, threshold=logging.WARNING, format=FORMAT, 
+         datefmt=DATEFMT):
+  ''' Configure the root logger to use a StdoutStderrHandler and some default
+  formatting. 
+    Args:
+      level: messages below this level are ignored
+      threshold: below this logging level messages are sent to stdout,
+        otherwise they are sent to stderr
+      format: format for log messages, see logger.Format
+      datefmt: format for date in log messages
+      
+  '''
+  # to set the handler of the root logging object, we need to do setup
+  # manually rather than using basicConfig
+  root = logging.getLogger()
+  root.setLevel(level)
+  formatter = logging.Formatter(format, datefmt)
+  handler = StdoutStderrHandler(threshold=threshold)
+  handler.setLevel(level)
+  handler.setFormatter(formatter)
+  root.addHandler(handler)
diff --git a/google/path_utils.py b/google/path_utils.py
new file mode 100644
index 0000000..0585614
--- /dev/null
+++ b/google/path_utils.py
@@ -0,0 +1,109 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Some utility methods for getting and manipulating paths."""
+
+# TODO(pamg): Have the buildbot use these, too.
+
+
+import errno
+import os
+import sys
+
+class PathNotFound(Exception): pass
+  
+def ScriptDir():
+  """Get the full path to the directory containing the current script."""
+  script_filename = os.path.abspath(sys.argv[0])
+  return os.path.dirname(script_filename)
+
+def FindAncestor(start_dir, ancestor):
+  """Finds an ancestor dir in a path.
+  
+  For example, FindAncestor('c:\foo\bar\baz', 'bar') would return
+  'c:\foo\bar'.  Unlike FindUpward*, this only looks at direct path ancestors.
+  """
+  start_dir = os.path.abspath(start_dir)
+  path = start_dir
+  while True:
+    (parent, tail) = os.path.split(path)
+    if tail == ancestor:
+      return path
+    if not tail:
+      break
+    path = parent
+  raise PathNotFound("Unable to find ancestor %s in %s" % (ancestor, start_dir))
+
+def FindUpwardParent(start_dir, *desired_list):
+  """Finds the desired object's parent, searching upward from the start_dir.
+
+  Searches start_dir and all its parents looking for the desired directory
+  or file, which may be given in one or more path components. Returns the
+  first directory in which the top desired path component was found, or raises
+  PathNotFound if it wasn't.
+  """
+  desired_path = os.path.join(*desired_list)
+  last_dir = ''
+  cur_dir = start_dir
+  found_path = os.path.join(cur_dir, desired_path)
+  while not os.path.exists(found_path):
+    last_dir = cur_dir
+    cur_dir = os.path.dirname(cur_dir)
+    if last_dir == cur_dir:
+      raise PathNotFound('Unable to find %s above %s' %
+                         (desired_path, start_dir))
+    found_path = os.path.join(cur_dir, desired_path)
+  # Strip the entire original desired path from the end of the one found
+  # and remove a trailing path separator, if present.
+  found_path = found_path[:len(found_path) - len(desired_path)]
+  if found_path.endswith(os.sep):
+    found_path = found_path[:len(found_path) - 1]
+  return found_path
+
+
+def FindUpward(start_dir, *desired_list):
+  """Returns a path to the desired directory or file, searching upward.
+
+  Searches start_dir and all its parents looking for the desired directory
+  or file, which may be given in one or more path components. Returns the full
+  path to the desired object, or raises PathNotFound if it wasn't found.
+  """
+  parent = FindUpwardParent(start_dir, *desired_list)
+  return os.path.join(parent, *desired_list)
+
+
+def MaybeMakeDirectory(*path):
+  """Creates an entire path, if it doesn't already exist."""
+  file_path = os.path.join(*path)
+  try:
+    os.makedirs(file_path)
+  except OSError, e:
+    # errno.EEXIST is "File exists".  If we see another error, re-raise.
+    if e.errno != errno.EEXIST:
+      raise
diff --git a/google/platform_utils.py b/google/platform_utils.py
new file mode 100644
index 0000000..1fcb182
--- /dev/null
+++ b/google/platform_utils.py
@@ -0,0 +1,46 @@
+#!/bin/env python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Platform-specific utilities and pseudo-constants
+
+Any functions whose implementations or values differ from one platform to
+another should be defined in their respective platform_utils_<platform>.py
+modules. The appropriate one of those will be imported into this module to
+provide callers with a common, platform-independent interface.
+"""
+
+import sys
+
+# We may not support the version of Python that a user has installed (Cygwin
+# especially has had problems), but we'll allow the platform utils to be
+# included in any case so we don't get an import error.
+if sys.platform in ('cygwin', 'win32'):
+  from platform_utils_win import *
+
diff --git a/google/platform_utils_win.py b/google/platform_utils_win.py
new file mode 100644
index 0000000..df72e3d
--- /dev/null
+++ b/google/platform_utils_win.py
@@ -0,0 +1,219 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Platform-specific utility methods shared by several scripts."""
+
+import os
+import re
+import subprocess
+import sys
+
+import google.path_utils
+
+# Cache a single cygpath process for use throughout, even across instances of
+# the PlatformUtility class.
+_cygpath_proc = None
+
+class PlatformUtility(object):
+  def __init__(self, base_dir):
+    """Args:
+         base_dir: a directory above which third_party/cygwin can be found,
+             used to locate the cygpath executable for path conversions.
+    """
+    self._cygwin_root = None
+    self._base_dir = base_dir
+
+  def _CygwinRoot(self):
+    """Returns the full path to third_party/cygwin/."""
+    if not self._cygwin_root:
+      self._cygwin_root = google.path_utils.FindUpward(self._base_dir,
+                                                       'third_party', 'cygwin')
+    return self._cygwin_root
+
+  def _PathToExecutable(self, executable):
+    """Returns the full path to an executable in Cygwin's bin dir."""
+    return os.path.join(self._CygwinRoot(), 'bin', executable)
+
+  def GetAbsolutePath(self, path, force=False):
+    """Returns an absolute windows path. If platform is cygwin, converts it to
+    windows style using cygpath.
+
+    For performance reasons, we use a single cygpath process, shared among all
+    instances of this class. Otherwise Python can run out of file handles.
+    """
+    if not force and sys.platform != "cygwin":
+      return os.path.abspath(path)
+    global _cygpath_proc
+    if not _cygpath_proc:
+      cygpath_command = [self._PathToExecutable("cygpath.exe"),
+                         "-a", "-m", "-f", "-"]
+      _cygpath_proc = subprocess.Popen(cygpath_command,
+                                       stdin=subprocess.PIPE,
+                                       stdout=subprocess.PIPE)
+    _cygpath_proc.stdin.write(path + "\n")
+    return _cygpath_proc.stdout.readline().rstrip()
+
+  def GetFilesystemRoot(self):
+    """Returns the root directory of the file system."""
+    return os.environ['SYSTEMDRIVE'] + '\\'
+
+  def GetTempDirectory(self):
+    """Returns the file system's base temp directory, or the filesystem root
+    if the standard temp directory can't be determined.
+
+    Note that this does not use a random subdirectory, so it's not
+    intrinsically secure.  If you need a secure subdir, use the tempfile
+    package.
+    """
+    return os.environ.get('TEMP', self.GetFilesystemRoot())
+
+  def FilenameToUri(self, path, use_http=False, use_ssl=False, port=8000):
+    """Convert a Windows style path to a URI.
+
+    Args:
+      path: For an http URI, the path relative to the httpd server's
+          DocumentRoot; for a file URI, the full path to the file.
+      use_http: if True, returns a URI of the form http://127.0.0.1:8000/.
+          If False, returns a file:/// URI.
+      use_ssl: if True, returns HTTPS URL (https://127.0.0.1:8000/).
+          This parameter is ignored if use_http=False.
+      port: The port number to append when returning an HTTP URI
+    """
+    if use_http:
+      protocol = 'http'
+      if use_ssl:
+        protocol = 'https'
+      path = path.replace("\\", "/")
+      return "%s://127.0.0.1:%s/%s" % (protocol, str(port), path)
+    return "file:///" + self.GetAbsolutePath(path)
+
+  def GetStartHttpdCommand(self, output_dir,
+                           httpd_conf_path, mime_types_path,
+                           document_root=None, apache2=False):
+    """Prepares the config file and output directory to start an httpd server.
+    Returns a list of strings containing the server's command line+args.
+
+    Args:
+      output_dir: the path to the server's output directory, for log files.
+          It will be created if necessary.
+      httpd_conf_path: full path to the httpd.conf file to be used.
+      mime_types_path: full path to the mime.types file to be used.
+      document_root: full path to the DocumentRoot.  If None, the DocumentRoot
+          from the httpd.conf file will be used.  Note that the httpd.conf
+          file alongside this script does not specify any DocumentRoot, so if
+          you're using that one, be sure to specify a document_root here.
+      apache2: boolean if true will cause this function to return start
+               command for Apache 2.x as opposed to Apache 1.3.x
+    """
+
+    if document_root:
+      document_root = GetCygwinPath(document_root)
+    exe_name = "httpd"
+    cert_file = ""
+    if apache2:
+      exe_name = "httpd2"
+      cert_file = google.path_utils.FindUpward(self._base_dir, 'tools',
+                                               'python', 'google',
+                                               'httpd_config', 'httpd2.pem')
+    httpd_vars = {
+      "httpd_executable_path": GetCygwinPath(
+          os.path.join(self._CygwinRoot(), "usr", "sbin", exe_name)),
+      "httpd_conf_path": GetCygwinPath(httpd_conf_path),
+      "ssl_certificate_file": GetCygwinPath(cert_file),
+      "document_root" : document_root,
+      "server_root": GetCygwinPath(os.path.join(self._CygwinRoot(), "usr")),
+      "mime_types_path": GetCygwinPath(mime_types_path),
+      "output_dir": GetCygwinPath(output_dir),
+      "bindir": GetCygwinPath(os.path.join(self._CygwinRoot(), "bin")),
+      "user": os.environ.get("USERNAME", os.environ.get("USER", "")),
+    }
+    if not httpd_vars["user"]:
+      # Failed to get the username from the environment; use whoami.exe
+      # instead.
+      proc = subprocess.Popen(self._PathToExecutable("whoami.exe"),
+                              stdout=subprocess.PIPE)
+      httpd_vars["user"] = proc.stdout.read().strip()
+
+    if not httpd_vars["user"]:
+      raise Exception("Failed to get username.")
+
+    google.path_utils.MaybeMakeDirectory(output_dir)
+
+    # We have to wrap the command in bash because the cygwin environment
+    # is required for httpd to run.
+    # -C: process directive before reading config files
+    # -c: process directive after reading config files
+    # Apache wouldn't run CGIs with permissions==700 unless we add
+    # -c User "<username>"
+    bash = self._PathToExecutable("bash.exe")
+    httpd_cmd_string = (
+      ' PATH=%(bindir)s %(httpd_executable_path)s'
+      ' -f %(httpd_conf_path)s'
+      ' -c \'TypesConfig "%(mime_types_path)s"\''
+      ' -c \'CustomLog "%(output_dir)s/access_log.txt" common\''
+      ' -c \'ErrorLog "%(output_dir)s/error_log.txt"\''
+      ' -c \'PidFile "%(output_dir)s/httpd.pid"\''
+      ' -C \'User "%(user)s"\''
+      ' -C \'ServerRoot "%(server_root)s"\''
+    )
+    if apache2:
+      httpd_cmd_string = ('export CYGWIN=server;' + httpd_cmd_string + 
+          ' -c \'SSLCertificateFile "%(ssl_certificate_file)s"\'')
+    if document_root:
+      httpd_cmd_string += ' -C \'DocumentRoot "%(document_root)s"\''
+
+    httpd_cmd = [bash, "-c", httpd_cmd_string % httpd_vars]
+    return httpd_cmd
+
+  def GetStopHttpdCommand(self):
+    """Returns a list of strings that contains the command line+args needed to
+    stop the http server used in the http tests.
+    """
+    # Force kill (/f) *all* httpd processes.  This has the side effect of
+    # killing httpd processes that we didn't start.
+    return ["taskkill.exe", "/f", "/im", "httpd*"]
+
+###########################################################################
+# This method is specific to windows, expected to be used only by *_win.py
+# files.
+
+def GetCygwinPath(path):
+  """Convert a Windows path to a cygwin path.
+
+  The cygpath utility insists on converting paths that it thinks are Cygwin
+  root paths to what it thinks the correct roots are.  So paths such as
+  "C:\b\slave\webkit-release-kjs\build\third_party\cygwin\bin" are converted to
+  plain "/usr/bin".  To avoid this, we do the conversion manually.
+
+  The path is expected to be an absolute path, on any drive.
+  """
+  drive_regexp = re.compile(r'([a-z]):[/\\]', re.IGNORECASE)
+  def LowerDrive(matchobj):
+    return '/cygdrive/%s/' % matchobj.group(1).lower()
+  path = drive_regexp.sub(LowerDrive, path)
+  return path.replace('\\', '/')
diff --git a/google/process_utils.py b/google/process_utils.py
new file mode 100644
index 0000000..966fdf6
--- /dev/null
+++ b/google/process_utils.py
@@ -0,0 +1,156 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#    * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#    * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#    * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Shared process-related utility functions."""
+
+import errno
+import os
+import subprocess
+import sys
+
+class CommandNotFound(Exception): pass
+
+
+TASKKILL = os.path.join(os.environ['WINDIR'], 'system32', 'taskkill.exe')
+TASKKILL_PROCESS_NOT_FOUND_ERR = 128
+# On windows 2000 there is no taskkill.exe, we need to have pskill somewhere
+# in the path.
+PSKILL = 'pskill.exe'
+PSKILL_PROCESS_NOT_FOUND_ERR = -1
+
+def KillAll(executables):
+  """Tries to kill all copies of each process in the processes list.  Returns
+  an error if any running processes couldn't be killed.
+  """
+  result = 0
+  if os.path.exists(TASKKILL):
+    command = [TASKKILL, '/f', '/im']
+    process_not_found_err = TASKKILL_PROCESS_NOT_FOUND_ERR
+  else:
+    command = [PSKILL, '/t']
+    process_not_found_err = PSKILL_PROCESS_NOT_FOUND_ERR
+
+  for name in executables:
+    new_error = RunCommand(command + [name])
+    # Ignore "process not found" error.
+    if new_error != 0 and new_error != process_not_found_err:
+      result = new_error
+  return result
+
+def RunCommandFull(command, verbose=True, collect_output=False,
+                   print_output=True):
+  """Runs the command list.
+
+  Prints the given command (which should be a list of one or more strings).
+  If specified, prints its stderr (and optionally stdout) to stdout,
+  line-buffered, converting line endings to CRLF (see note below).  If
+  specified, collects the output as a list of lines and returns it.  Waits
+  for the command to terminate and returns its status.
+
+  Args:
+    command: the full command to run, as a list of one or more strings
+    verbose: if True, combines all output (stdout and stderr) into stdout.
+             Otherwise, prints only the command's stderr to stdout.
+    collect_output: if True, collects the output of the command as a list of
+                    lines and returns it
+    print_output: if True, prints the output of the command
+
+  Returns:
+    A tuple consisting of the process's exit status and output.  If
+    collect_output is False, the output will be [].
+
+  Raises:
+    CommandNotFound if the command executable could not be found.
+  """
+  print '\n' + subprocess.list2cmdline(command).replace('\\', '/') + '\n', ###
+
+  if verbose:
+    out = subprocess.PIPE
+    err = subprocess.STDOUT
+  else:
+    out = file(os.devnull, 'w')
+    err = subprocess.PIPE
+  try:
+    proc = subprocess.Popen(command, stdout=out, stderr=err, bufsize=1)
+  except OSError, e:
+    if e.errno == errno.ENOENT:
+      raise CommandNotFound('Unable to find "%s"' % command[0])
+    raise
+
+  output = []
+
+  if verbose:
+    read_from = proc.stdout
+  else:
+    read_from = proc.stderr
+  line = read_from.readline()
+  while line:
+    line = line.rstrip()
+
+    if collect_output:
+      output.append(line)
+
+    if print_output:
+      # Windows Python converts \n to \r\n automatically whenever it
+      # encounters it written to a text file (including stdout).  The only
+      # way around it is to write to a binary file, which isn't feasible for
+      # stdout. So we end up with \r\n here even though we explicitly write
+      # \n.  (We could write \r instead, which doesn't get converted to \r\n,
+      # but that's probably more troublesome for people trying to read the
+      # files.)
+      print line + '\n',
+
+      # Python on windows writes the buffer only when it reaches 4k. This is
+      # not fast enough for all purposes.
+      sys.stdout.flush()
+    line = read_from.readline()
+
+  if not verbose:
+    out.close()
+  return (proc.returncode, output)
+
+def RunCommand(command, verbose=True):
+  """Runs the command list, printing its output and returning its exit status.
+
+  Prints the given command (which should be a list of one or more strings),
+  then runs it and prints its stderr (and optionally stdout) to stdout,
+  line-buffered, converting line endings to CRLF.  Waits for the command to
+  terminate and returns its status.
+
+  Args:
+    command: the full command to run, as a list of one or more strings
+    verbose: if True, combines all output (stdout and stderr) into stdout.
+             Otherwise, prints only the command's stderr to stdout.
+
+  Returns:
+    The process's exit status.
+
+  Raises:
+    CommandNotFound if the command executable could not be found.
+  """
+  return RunCommandFull(command, verbose)[0]