Merge "Increase default value of receive.timeout"
diff --git a/.buckconfig b/.buckconfig
index 7b75225..51318f3 100644
--- a/.buckconfig
+++ b/.buckconfig
@@ -1,5 +1,4 @@
 [alias]
-  all = //:all
   api = //:api
   api_deploy = //tools/maven:api_deploy
   api_install = //tools/maven:api_install
diff --git a/.buckversion b/.buckversion
index ab18d5d..9daac2c 100644
--- a/.buckversion
+++ b/.buckversion
@@ -1 +1 @@
-7e153d4a69044d059288d353fc1a442e07cbea58
+1b03b4313b91b634bd604fc3487a05f877e59dee
diff --git a/BUCK b/BUCK
index 82f1d72..c986874 100644
--- a/BUCK
+++ b/BUCK
@@ -23,19 +23,7 @@
   '//gerrit-plugin-gwtui:gwtui-api-javadoc',
 ]
 
-genrule(
+zip_file(
   name = 'api',
-  cmd = 'echo done >$OUT',
-  deps = API_DEPS,
-  out = '__fake.api__',
-)
-
-genrule(
-  name = 'all',
-  cmd = 'echo done >$OUT',
-  deps = [
-    ':api',
-    ':release',
-  ],
-  out = '__fake.all__',
+  srcs = API_DEPS,
 )
diff --git a/Documentation/BUCK b/Documentation/BUCK
index dfac617..126bf1f 100644
--- a/Documentation/BUCK
+++ b/Documentation/BUCK
@@ -3,8 +3,8 @@
 include_defs('//tools/git.defs')
 
 DOC_DIR = 'Documentation'
-JSUI = ['//gerrit-gwtui:ui_module']
-MAIN = ['//gerrit-pgm:pgm'] + JSUI
+JSUI = '//gerrit-gwtui:ui_module'
+MAIN = '//gerrit-pgm:pgm'
 SRCS = glob(['*.txt'], excludes = ['licenses.txt'])
 
 genasciidoc(
@@ -30,16 +30,19 @@
 
 genrule(
   name = 'licenses.txt',
-  cmd = '$(exe :gen_licenses) --asciidoc ' + ' '.join(MAIN) + ' >$OUT',
-  deps = MAIN,
+  cmd = '$(exe :gen_licenses) --asciidoc '
+    + '--classpath $(classpath %s) ' % MAIN
+    + '--classpath $(classpath %s) ' % JSUI
+    + MAIN + ' ' + JSUI + ' >$OUT',
   out = 'licenses.txt',
 )
 
 # Required by Google for gerrit-review.
 genrule(
   name = 'js_licenses.txt',
-  cmd = '$(exe :gen_licenses) --partial ' + ' '.join(JSUI) + ' >$OUT',
-  deps = JSUI,
+  cmd = '$(exe :gen_licenses) --partial '
+    + '--classpath $(classpath %s) ' % JSUI
+    + JSUI + ' >$OUT',
   out = 'js_licenses.txt',
 )
 
diff --git a/Documentation/config-reverseproxy.txt b/Documentation/config-reverseproxy.txt
index c3dd12e..eff777b 100644
--- a/Documentation/config-reverseproxy.txt
+++ b/Documentation/config-reverseproxy.txt
@@ -99,7 +99,7 @@
 	  listen 80;
 	  server_name review.example.com;
 
-	  location /r/ {
+	  location ^~ /r/ {
 	    proxy_pass        http://127.0.0.1:8081;
 	    proxy_set_header  X-Forwarded-For $remote_addr;
 	    proxy_set_header  Host $host;
diff --git a/Documentation/dev-buck.txt b/Documentation/dev-buck.txt
index 7d30a91..10f3319 100644
--- a/Documentation/dev-buck.txt
+++ b/Documentation/dev-buck.txt
@@ -275,15 +275,6 @@
   buck-out/gen/release/release.war
 ----
 
-[[all]]
-=== Combined build target
-
-To build release and api targets, a combined build target is provided:
-
-----
-  buck build all
-----
-
 [[tests]]
 == Running Unit Tests
 
diff --git a/Documentation/gen_licenses.py b/Documentation/gen_licenses.py
index 8b2d096..db3480b 100755
--- a/Documentation/gen_licenses.py
+++ b/Documentation/gen_licenses.py
@@ -28,6 +28,7 @@
 parser = argparse.ArgumentParser()
 parser.add_argument('--asciidoc', action='store_true')
 parser.add_argument('--partial', action='store_true')
+parser.add_argument('--classpath', action='append')
 parser.add_argument('targets', nargs='+')
 args = parser.parse_args()
 
@@ -41,6 +42,7 @@
   graph = defaultdict(list)
   while not path.isfile('.buckconfig'):
     chdir('..')
+  # TODO(davido): use passed in classpath from Buck instead
   p = Popen(
     ['buck', 'audit', 'classpath', '--dot'] + args.targets,
     stdout = PIPE)
diff --git a/README.md b/README.md
index 573042d..f5b929d 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,7 @@
 Install [Buck](http://facebook.github.io/buck/setup/install.html) and run the following:
 
         git clone --recursive https://gerrit.googlesource.com/gerrit
-        cd gerrit && buck build all
+        cd gerrit && buck build release
 
 ## Install binary packages (Deb/Rpm)
 
diff --git a/contrib/convertkey/pom.xml b/contrib/convertkey/pom.xml
new file mode 100644
index 0000000..bc71b9e
--- /dev/null
+++ b/contrib/convertkey/pom.xml
@@ -0,0 +1,89 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>com.googlesource.gerrit</groupId>
+  <artifactId>convertkey</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>convertkey</name>
+  <url>http://maven.apache.org</url>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>2.8</version>
+        <executions>
+          <execution>
+            <id>copy-dependencies</id>
+            <phase>prepare-package</phase>
+            <goals>
+              <goal>copy-dependencies</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${project.build.directory}/lib</outputDirectory>
+              <overWriteReleases>false</overWriteReleases>
+              <overWriteSnapshots>false</overWriteSnapshots>
+              <overWriteIfNewer>true</overWriteIfNewer>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <archive>
+            <manifest>
+              <addClasspath>true</addClasspath>
+              <classpathPrefix>lib/</classpathPrefix>
+              <mainClass>com.googlesource.gerrit.convertkey.ConvertKey</mainClass>
+            </manifest>
+          </archive>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sshd</groupId>
+      <artifactId>sshd-core</artifactId>
+      <version>0.14.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcprov-jdk15on</artifactId>
+      <version>1.52</version>
+    </dependency>
+    <dependency>
+      <groupId>org.bouncycastle</groupId>
+      <artifactId>bcpkix-jdk15on</artifactId>
+      <version>1.52</version>
+    </dependency>
+    <dependency>
+      <groupId>com.jcraft</groupId>
+      <artifactId>jsch</artifactId>
+      <version>0.1.53</version>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-nop</artifactId>
+      <version>1.7.12</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/contrib/convertkey/src/main/java/com/googlesource/gerrit/convertkey/ConvertKey.java b/contrib/convertkey/src/main/java/com/googlesource/gerrit/convertkey/ConvertKey.java
new file mode 100644
index 0000000..5c6ef58
--- /dev/null
+++ b/contrib/convertkey/src/main/java/com/googlesource/gerrit/convertkey/ConvertKey.java
@@ -0,0 +1,73 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.convertkey;
+
+import com.jcraft.jsch.HostKey;
+import com.jcraft.jsch.JSchException;
+
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+
+import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.security.KeyPair;
+import java.security.GeneralSecurityException;
+
+public class ConvertKey {
+  public static void main(String[] args)
+      throws GeneralSecurityException, JSchException, IOException {
+    SimpleGeneratorHostKeyProvider p;
+
+    if (args.length != 1) {
+      System.err.println("Error: requires path to the SSH host key");
+      return;
+    } else {
+      File file = new File(args[0]);
+      if (!file.exists() || !file.isFile() || !file.canRead()) {
+        System.err.println("Error: ssh key should exist and be readable");
+        return;
+      }
+    }
+
+    p = new SimpleGeneratorHostKeyProvider();
+    // Gerrit's SSH "simple" keys are always RSA.
+    p.setPath(args[0]);
+    p.setAlgorithm("RSA");
+    Iterable<KeyPair> keys = p.loadKeys(); // forces the key to generate.
+    for (KeyPair k : keys) {
+      System.out.println("Public Key (" + k.getPublic().getAlgorithm() + "):");
+      // From Gerrit's SshDaemon class; use JSch to get the public
+      // key/type
+      final Buffer buf = new Buffer();
+      buf.putRawPublicKey(k.getPublic());
+      final byte[] keyBin = buf.getCompactData();
+      HostKey pub = new HostKey("localhost", keyBin);
+      System.out.println(pub.getType() + " " + pub.getKey());
+      System.out.println("Private Key:");
+      // Use Bouncy Castle to write the private key back in PEM format
+      // (PKCS#1)
+      // http://stackoverflow.com/questions/25129822/export-rsa-public-key-to-pem-string-using-java
+      StringWriter privout = new StringWriter();
+      JcaPEMWriter privWriter = new JcaPEMWriter(privout);
+      privWriter.writeObject(k.getPrivate());
+      privWriter.close();
+      System.out.println(privout);
+    }
+  }
+
+}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
index 2e991d9..16e7e61 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
@@ -21,9 +21,20 @@
 
 /** Data sent as part of the host page, to bootstrap the UI. */
 public class HostPageData {
+  /**
+   * Name of the cookie in which the XSRF token is sent from the server to the
+   * client during host page bootstrapping.
+   */
+  public static final String XSRF_COOKIE_NAME = "XSRF_TOKEN";
+
+  /**
+   * Name of the HTTP header in which the client must send the XSRF token to the
+   * server on each request.
+   */
+  public static final String XSRF_HEADER_NAME = "X-Gerrit-Auth";
+
   public String version;
   public DiffPreferencesInfo accountDiffPref;
-  public String xGerritAuth;
   public Theme theme;
   public List<String> plugins;
   public List<Message> messages;
diff --git a/gerrit-gwtui-common/BUCK b/gerrit-gwtui-common/BUCK
index ef4de82..436714a 100644
--- a/gerrit-gwtui-common/BUCK
+++ b/gerrit-gwtui-common/BUCK
@@ -49,7 +49,6 @@
 genrule(
   name = 'diffy_image_files_ln',
   cmd = 'ln -s $(location :diffy_image_files) $OUT',
-  deps = [':diffy_image_files'],
   out = 'diffy_images.jar',
 )
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index ee67116..30e85ae 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -17,6 +17,7 @@
 import static com.google.gerrit.common.data.GlobalCapability.CREATE_GROUP;
 import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT;
 import static com.google.gerrit.common.data.GlobalCapability.VIEW_PLUGINS;
+import static com.google.gerrit.common.data.HostPageData.XSRF_COOKIE_NAME;
 
 import com.google.gerrit.client.account.AccountApi;
 import com.google.gerrit.client.account.AccountCapabilities;
@@ -477,8 +478,7 @@
         if (result.accountDiffPref != null) {
           myAccountDiffPref = result.accountDiffPref;
         }
-        if (result.xGerritAuth != null) {
-          xGerritAuth = result.xGerritAuth;
+        if (result.accountDiffPref != null) {
           // TODO: Support options on the GetDetail REST endpoint so that it can
           // also return the preferences. Then we can fetch everything with a
           // single request and we don't need the callback group anymore.
@@ -513,6 +513,8 @@
           editPrefs = null;
           onModuleLoad2(result);
         }
+        xGerritAuth = Cookies.getCookie(XSRF_COOKIE_NAME);
+        Cookies.removeCookie(XSRF_COOKIE_NAME);
       }
     }));
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java
index 771423e..a0e25ad 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java
@@ -21,6 +21,7 @@
 
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.RpcStatus;
+import com.google.gerrit.common.data.HostPageData;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.core.client.Scheduler;
@@ -449,7 +450,7 @@
     }
     req.setHeader("Accept", JSON_TYPE);
     if (Gerrit.getXGerritAuth() != null) {
-      req.setHeader("X-Gerrit-Auth", Gerrit.getXGerritAuth());
+      req.setHeader(HostPageData.XSRF_HEADER_NAME, Gerrit.getXGerritAuth());
     }
     return req;
   }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/CacheBasedWebSession.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/CacheBasedWebSession.java
index a6e4b44..a1cfec7 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/CacheBasedWebSession.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/CacheBasedWebSession.java
@@ -16,6 +16,7 @@
 
 import static java.util.concurrent.TimeUnit.HOURS;
 
+import com.google.gerrit.common.data.HostPageData;
 import com.google.gerrit.httpd.WebSessionManager.Key;
 import com.google.gerrit.httpd.WebSessionManager.Val;
 import com.google.gerrit.reviewdb.client.Account;
@@ -80,7 +81,7 @@
           val = manager.createVal(key, val);
         }
 
-        String token = request.getHeader("X-Gerrit-Auth");
+        String token = request.getHeader(HostPageData.XSRF_HEADER_NAME);
         if (val != null && token != null && token.equals(val.getAuth())) {
           okPaths.add(AccessPath.REST_API);
         }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
index fec17bb..e21f973 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
@@ -68,6 +68,7 @@
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -193,10 +194,7 @@
     StringWriter w = new StringWriter();
     CurrentUser user = currentUser.get();
     if (user.isIdentifiedUser()) {
-      w.write(HPD_ID + ".xGerritAuth=");
-      json(session.get().getXGerritAuth(), w);
-      w.write(";");
-
+      setXGerritAuthCookie(req, rsp, session.get());
       w.write(HPD_ID + ".accountDiffPref=");
       json(getDiffPreferences(user.asIdentifiedUser()), w);
       w.write(";");
@@ -205,6 +203,7 @@
       json(signedInTheme, w);
       w.write(";");
     } else {
+      setXGerritAuthCookie(req, rsp, null);
       w.write(HPD_ID + ".theme=");
       json(signedOutTheme, w);
       w.write(";");
@@ -231,6 +230,23 @@
     }
   }
 
+  private static void setXGerritAuthCookie(HttpServletRequest req,
+      HttpServletResponse rsp, WebSession session) {
+    String v = session != null ? session.getXGerritAuth() : "";
+    Cookie c = new Cookie(HostPageData.XSRF_COOKIE_NAME, v);
+    c.setPath("/");
+    c.setHttpOnly(false);
+    c.setSecure(isSecure(req));
+    c.setMaxAge(session != null
+        ? -1 // Set the cookie for this browser session.
+        : 0); // Remove the cookie (expire immediately).
+    rsp.addCookie(c);
+  }
+
+  private static boolean isSecure(HttpServletRequest req) {
+    return req.isSecure() || "https".equals(req.getScheme());
+  }
+
   private DiffPreferencesInfo getDiffPreferences(IdentifiedUser user) {
     try {
       return getDiff.apply(new AccountResource(user));
diff --git a/gerrit-war/BUCK b/gerrit-war/BUCK
index 27b1f4a..d5c85ad 100644
--- a/gerrit-war/BUCK
+++ b/gerrit-war/BUCK
@@ -38,7 +38,6 @@
   name = 'webapp_assets',
   cmd = 'cd src/main/webapp; zip -qr $OUT .',
   srcs = glob(['src/main/webapp/**/*']),
-  deps = [],
   out = 'webapp_assets.zip',
   visibility = ['//:'],
 )
diff --git a/tools/BUCK b/tools/BUCK
index e311ff8..489dffc 100644
--- a/tools/BUCK
+++ b/tools/BUCK
@@ -45,7 +45,6 @@
   name = 'buck',
   cmd = 'echo buck=`which buck`>$OUT;' +
     ("echo PATH=\''%s'\' >>$OUT;" % shquote(os_path())),
-  deps = [],
   out = 'buck.properties',
   visibility = ['PUBLIC'],
 )