aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/NetRCTest.java191
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java319
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRCCredentialsProvider.java116
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java3
4 files changed, 629 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/NetRCTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/NetRCTest.java
new file mode 100644
index 0000000000..ba449508fd
--- /dev/null
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/NetRCTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2014, Alexey Kuznetsov <axet@me.com>
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * 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 the Eclipse Foundation, 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.
+ */
+
+package org.eclipse.jgit.transport;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import org.eclipse.jgit.junit.RepositoryTestCase;
+import org.eclipse.jgit.util.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class NetRCTest extends RepositoryTestCase {
+ private File home;
+
+ private NetRC netrc;
+
+ private File configFile;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ home = new File(trash, "home");
+ FileUtils.mkdir(home);
+
+ configFile = new File(home, ".netrc");
+ }
+
+ private void config(final String data) throws IOException {
+ final OutputStreamWriter fw = new OutputStreamWriter(
+ new FileOutputStream(configFile), "UTF-8");
+ fw.write(data);
+ fw.close();
+ }
+
+ @Test
+ public void testNetRCFile() throws Exception {
+ config("machine my.host login test password 2222"
+ + "\n"
+
+ + "#machine ignore.host.example login ignoreuser password 5555"
+ + "\n"
+
+ + "machine twolinehost.example #login kuznetsov.alexey password 5555"
+ + "\n"
+
+ + "login twologin password 6666"
+ + "\n"
+
+ + "machine afterlinehost.example login test1 password 8888"
+ + "\n"
+
+ + "machine macdef.example login test7 password 7777 macdef mac1"
+ + "\n"
+
+ + "init +apc 1" + "\n"
+
+ + "init2 +apc 2" + "\n");
+
+ netrc = new NetRC(configFile);
+
+ assertNull(netrc.getEntry("ignore.host.example"));
+
+ assertNull(netrc.getEntry("cignore.host.example"));
+
+ assertEquals("twologin", netrc.getEntry("twolinehost.example").login);
+ assertEquals("6666", new String(
+ netrc.getEntry("twolinehost.example").password));
+
+ assertEquals("test1", netrc.getEntry("afterlinehost.example").login);
+ assertEquals("8888", new String(
+ netrc.getEntry("afterlinehost.example").password));
+
+ // macdef test
+ assertEquals("test7", netrc.getEntry("macdef.example").login);
+ assertEquals("7777", new String(
+ netrc.getEntry("macdef.example").password));
+ assertEquals("init +apc 1" + "\n" + "init2 +apc 2" + "\n",
+ netrc.getEntry("macdef.example").macbody);
+ }
+
+ @Test
+ public void testNetRCDefault() throws Exception {
+ config("machine my.host login test password 2222"
+ + "\n"
+
+ + "#machine ignore.host.example login ignoreuser password 5555"
+ + "\n"
+
+ + "machine twolinehost.example #login kuznetsov.alexey password 5555"
+ + "\n"
+
+ + "login twologin password 6666"
+ + "\n"
+
+ + "machine afterlinehost.example login test1 password 8888"
+ + "\n"
+
+ + "machine macdef.example login test7 password 7777 macdef mac1"
+ + "\n"
+
+ + "init +apc 1" + "\n"
+
+ + "init2 +apc 2" + "\n"
+
+ + "\n"
+
+ + "default login test5 password 3333" + "\n"
+
+ );
+
+ netrc = new NetRC(configFile);
+
+ // default test
+ assertEquals("test5", netrc.getEntry("ignore.host.example").login);
+ assertEquals("3333", new String(
+ netrc.getEntry("ignore.host.example").password));
+
+ // default test
+ assertEquals("test5", new String(
+ netrc.getEntry("ignore.host.example").login));
+ assertEquals("3333", new String(
+ netrc.getEntry("ignore.host.example").password));
+
+ // default test
+ assertEquals("test5", netrc.getEntry("cignore.host.example").login);
+ assertEquals("3333", new String(
+ netrc.getEntry("cignore.host.example").password));
+
+ assertEquals("twologin", netrc.getEntry("twolinehost.example").login);
+ assertEquals("6666", new String(
+ netrc.getEntry("twolinehost.example").password));
+
+ assertEquals("test1", netrc.getEntry("afterlinehost.example").login);
+ assertEquals("8888", new String(
+ netrc.getEntry("afterlinehost.example").password));
+
+ // macdef test
+ assertEquals("test7", netrc.getEntry("macdef.example").login);
+ assertEquals("7777", new String(
+ netrc.getEntry("macdef.example").password));
+ assertEquals("init +apc 1" + "\n" + "init2 +apc 2" + "\n",
+ netrc.getEntry("macdef.example").macbody);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java
new file mode 100644
index 0000000000..bacab7e21e
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRC.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2014, Alexey Kuznetsov <axet@me.com>
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * 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 the Eclipse Foundation, 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.
+ */
+
+package org.eclipse.jgit.transport;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jgit.util.FS;
+
+/**
+ * NetRC file parser.
+ *
+ * @since 3.5
+ */
+public class NetRC {
+ static final Pattern NETRC = Pattern.compile("(\\S+)"); //$NON-NLS-1$
+
+ /**
+ * 'default' netrc entry. This is the same as machine name except that
+ * default matches any name. There can be only one default token, and it
+ * must be after all machine tokens.
+ */
+ static final String DEFAULT_ENTRY = "default"; //$NON-NLS-1$
+
+ /**
+ * .netrc file entry
+ */
+ public static class NetRCEntry {
+ /**
+ * login netrc entry
+ */
+ public String login;
+
+ /**
+ * password netrc entry
+ */
+ public char[] password;
+
+ /**
+ * machine netrc entry
+ */
+ public String machine;
+
+ /**
+ * account netrc entry
+ */
+ public String account;
+
+ /**
+ * macdef netrc entry. Defines a macro. This token functions like the
+ * ftp macdef command functions. A macro is defined with the specified
+ * name; its contents begins with the next .netrc line and continues
+ * until a null line (consecutive new-line characters) is encountered.
+ * If a macro named init is defined, it is automatically executed as the
+ * last step in the auto-login process.
+ */
+ public String macdef;
+
+ /**
+ * macro script body of macdef entry.
+ */
+ public String macbody;
+
+ /**
+ * Default constructor
+ */
+ public NetRCEntry() {
+ }
+
+ boolean complete() {
+ return login != null && password != null && machine != null;
+ }
+ }
+
+ private File netrc;
+
+ private long lastModified;
+
+ private Map<String, NetRCEntry> hosts = new HashMap<String, NetRCEntry>();
+
+ private static final TreeMap<String, State> STATE = new TreeMap<String, NetRC.State>() {
+ private static final long serialVersionUID = -4285910831814853334L;
+ {
+ put("machine", State.MACHINE); //$NON-NLS-1$
+ put("login", State.LOGIN); //$NON-NLS-1$
+ put("password", State.PASSWORD); //$NON-NLS-1$
+ put(DEFAULT_ENTRY, State.DEFAULT);
+ put("account", State.ACCOUNT); //$NON-NLS-1$
+ put("macdef", State.MACDEF); //$NON-NLS-1$
+ }
+ };
+
+ enum State {
+ COMMAND, MACHINE, LOGIN, PASSWORD, DEFAULT, ACCOUNT, MACDEF
+ }
+
+ /** */
+ public NetRC() {
+ netrc = getDefaultFile();
+ if (netrc != null)
+ parse();
+ }
+
+ /**
+ * @param netrc
+ * the .netrc file
+ */
+ public NetRC(File netrc) {
+ this.netrc = netrc;
+ parse();
+ }
+
+ private static File getDefaultFile() {
+ File home = FS.DETECTED.userHome();
+ File netrc = new File(home, ".netrc"); //$NON-NLS-1$
+ if (netrc.exists())
+ return netrc;
+
+ netrc = new File(home, "_netrc"); //$NON-NLS-1$
+ if (netrc.exists())
+ return netrc;
+
+ return null;
+ }
+
+ /**
+ * Get entry by host name
+ *
+ * @param host
+ * @return entry associated with host name or null
+ */
+ public NetRCEntry getEntry(String host) {
+ if (netrc == null)
+ return null;
+
+ if (this.lastModified != this.netrc.lastModified())
+ parse();
+
+ NetRCEntry entry = this.hosts.get(host);
+
+ if (entry == null)
+ entry = this.hosts.get(DEFAULT_ENTRY);
+
+ return entry;
+ }
+
+ /**
+ * @return all entries collected from .netrc file
+ */
+ public Collection<NetRCEntry> getEntries() {
+ return hosts.values();
+ }
+
+ private void parse() {
+ this.hosts.clear();
+ this.lastModified = this.netrc.lastModified();
+
+ BufferedReader r = null;
+ try {
+ r = new BufferedReader(new FileReader(netrc));
+ String line = null;
+
+ NetRCEntry entry = new NetRCEntry();
+
+ State state = State.COMMAND;
+
+ String macbody = ""; //$NON-NLS-1$
+
+ Matcher matcher = NETRC.matcher(""); //$NON-NLS-1$
+ while ((line = r.readLine()) != null) {
+
+ // reading macbody
+ if (entry.macdef != null && entry.macbody == null) {
+ if (line.length() == 0) {
+ entry.macbody = macbody;
+ macbody = ""; //$NON-NLS-1$
+ continue;
+ }
+ macbody += line + "\n"; //$NON-NLS-1$;
+ continue;
+ }
+
+ matcher.reset(line);
+ while (matcher.find()) {
+ String command = matcher.group().toLowerCase();
+ if (command.startsWith("#")) { //$NON-NLS-1$
+ matcher.reset(""); //$NON-NLS-1$
+ continue;
+ }
+ state = STATE.get(command);
+ if (state == null)
+ state = State.COMMAND;
+
+ switch (state) {
+ case COMMAND:
+ break;
+ case ACCOUNT:
+ if (entry.account != null && entry.complete()) {
+ hosts.put(entry.machine, entry);
+ entry = new NetRCEntry();
+ }
+ if (matcher.find())
+ entry.account = matcher.group();
+ state = State.COMMAND;
+ break;
+ case LOGIN:
+ if (entry.login != null && entry.complete()) {
+ hosts.put(entry.machine, entry);
+ entry = new NetRCEntry();
+ }
+ if (matcher.find())
+ entry.login = matcher.group();
+ state = State.COMMAND;
+ break;
+ case PASSWORD:
+ if (entry.password != null && entry.complete()) {
+ hosts.put(entry.machine, entry);
+ entry = new NetRCEntry();
+ }
+ if (matcher.find())
+ entry.password = matcher.group().toCharArray();
+ state = State.COMMAND;
+ break;
+ case DEFAULT:
+ if (entry.machine != null && entry.complete()) {
+ hosts.put(entry.machine, entry);
+ entry = new NetRCEntry();
+ }
+ entry.machine = DEFAULT_ENTRY;
+ state = State.COMMAND;
+ break;
+ case MACDEF:
+ if (entry.macdef != null && entry.complete()) {
+ hosts.put(entry.machine, entry);
+ entry = new NetRCEntry();
+ }
+ if (matcher.find())
+ entry.macdef = matcher.group();
+ state = State.COMMAND;
+ break;
+ case MACHINE:
+ if (entry.machine != null && entry.complete()) {
+ hosts.put(entry.machine, entry);
+ entry = new NetRCEntry();
+ }
+ if (matcher.find())
+ entry.machine = matcher.group();
+ state = State.COMMAND;
+ break;
+ }
+ }
+ }
+
+ // reading macbody on EOF
+ if (entry.macdef != null && entry.macbody == null)
+ entry.macbody = macbody;
+
+ if (entry.complete())
+ hosts.put(entry.machine, entry);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ if (r != null)
+ r.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRCCredentialsProvider.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRCCredentialsProvider.java
new file mode 100644
index 0000000000..74909998ce
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/NetRCCredentialsProvider.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2014, Alexey Kuznetsov <axet@me.com>
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * 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 the Eclipse Foundation, 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.
+ */
+package org.eclipse.jgit.transport;
+
+import org.eclipse.jgit.errors.UnsupportedCredentialItem;
+import org.eclipse.jgit.transport.NetRC.NetRCEntry;
+
+/**
+ * Simple .netrc credentials provider. It can lookup the first machine entry
+ * from your .netrc file.
+ *
+ * @since 3.5
+ */
+public class NetRCCredentialsProvider extends CredentialsProvider {
+
+ NetRC netrc = new NetRC();
+
+ /** */
+ public NetRCCredentialsProvider() {
+ }
+
+ /**
+ * Install default provider for the .netrc parser.
+ */
+ public static void install() {
+ CredentialsProvider.setDefault(new NetRCCredentialsProvider());
+ }
+
+ @Override
+ public boolean supports(CredentialItem... items) {
+ for (CredentialItem i : items) {
+ if (i instanceof CredentialItem.Username)
+ continue;
+ else if (i instanceof CredentialItem.Password)
+ continue;
+ else
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean get(URIish uri, CredentialItem... items)
+ throws UnsupportedCredentialItem {
+ NetRCEntry cc = netrc.getEntry(uri.getHost());
+
+ if (cc == null)
+ return false;
+
+ for (CredentialItem i : items) {
+ if (i instanceof CredentialItem.Username) {
+ ((CredentialItem.Username) i).setValue(cc.login);
+ continue;
+ }
+ if (i instanceof CredentialItem.Password) {
+ ((CredentialItem.Password) i).setValue(cc.password);
+ continue;
+ }
+ if (i instanceof CredentialItem.StringType) {
+ if (i.getPromptText().equals("Password: ")) { //$NON-NLS-1$
+ ((CredentialItem.StringType) i).setValue(new String(
+ cc.password));
+ continue;
+ }
+ }
+ throw new UnsupportedCredentialItem(uri, i.getClass().getName()
+ + ":" + i.getPromptText()); //$NON-NLS-1$
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isInteractive() {
+ return false;
+ }
+
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
index e13bfd3005..c4a6bd966e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -264,6 +264,9 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
}
http = local.getConfig().get(HTTP_KEY);
proxySelector = ProxySelector.getDefault();
+
+ if (getCredentialsProvider() == null)
+ setCredentialsProvider(new NetRCCredentialsProvider());
}
/**