mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-07-04 11:49:53 +02:00
Implement mercurial cgi protocol as extension (#1458)
* Handle mercurial cgi protocol with an hg extension * Refactor CGI executor to allow command arguments * Unify python scripts and hg extensions * Implement new auto configuration * Use HKEY_LOCAL_MACHINE instead of HKEY_CURRENT_USER registry keys to find mercurial installations on windows
This commit is contained in:
committed by
René Pfeuffer
parent
99d389b2af
commit
b61d817c9c
@@ -21,12 +21,13 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.web.cgi;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
@@ -48,7 +49,9 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
@@ -110,18 +113,8 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param cmd
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void execute(String cmd) throws IOException
|
||||
public void execute(String cmd)
|
||||
{
|
||||
File command = new File(cmd);
|
||||
EnvList env = new EnvList(environment);
|
||||
@@ -150,21 +143,16 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
|
||||
env.set(ENV_PATH_TRANSLATED, pathTranslated);
|
||||
|
||||
String execCmd = path;
|
||||
|
||||
if ((execCmd.charAt(0) != '"') && (execCmd.indexOf(' ') >= 0))
|
||||
{
|
||||
execCmd = "\"".concat(execCmd).concat("\"");
|
||||
}
|
||||
|
||||
if (interpreter != null)
|
||||
{
|
||||
execCmd = interpreter.concat(" ").concat(execCmd);
|
||||
List<String> execCmd = new ArrayList<>();
|
||||
if (interpreter != null) {
|
||||
execCmd.add(interpreter);
|
||||
}
|
||||
execCmd.add(command.getAbsolutePath());
|
||||
execCmd.addAll(getArgs());
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("execute cgi: {}", execCmd);
|
||||
logger.debug("execute cgi: {}", Joiner.on(' ').join(execCmd));
|
||||
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
@@ -173,10 +161,11 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
}
|
||||
|
||||
Process p = null;
|
||||
|
||||
try
|
||||
{
|
||||
p = Runtime.getRuntime().exec(execCmd, env.getEnvArray(), workDirectory);
|
||||
try {
|
||||
ProcessBuilder builder = new ProcessBuilder(execCmd);
|
||||
builder.directory(workDirectory);
|
||||
builder.environment().putAll(env.asMap());
|
||||
p = builder.start();
|
||||
execute(p);
|
||||
}
|
||||
catch (IOException ex)
|
||||
@@ -329,15 +318,14 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
env.set(ENV_SERVER_SOFTWARE,
|
||||
SERVER_SOFTWARE_PREFIX.concat(SCMContext.getContext().getVersion()));
|
||||
|
||||
Enumeration enm = request.getHeaderNames();
|
||||
Enumeration<String> enm = request.getHeaderNames();
|
||||
|
||||
while (enm.hasMoreElements())
|
||||
{
|
||||
String name = (String) enm.nextElement();
|
||||
String name = enm.nextElement();
|
||||
String value = request.getHeader(name);
|
||||
|
||||
env.set(ENV_HTTP_HEADER_PREFIX + name.toUpperCase().replace('-', '_'),
|
||||
value);
|
||||
env.set(ENV_HTTP_HEADER_PREFIX + name.toUpperCase().replace('-', '_'), value);
|
||||
}
|
||||
|
||||
// these extra ones were from printenv on www.dev.nomura.co.uk
|
||||
@@ -394,6 +382,7 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
private void execute(Process process) throws IOException
|
||||
{
|
||||
InputStream processIS = null;
|
||||
@@ -418,61 +407,26 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param is
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void parseHeaders(InputStream is) throws IOException
|
||||
{
|
||||
private void parseHeaders(InputStream is) throws IOException {
|
||||
String line = null;
|
||||
|
||||
while ((line = getTextLineFromStream(is)).length() > 0)
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
while ((line = getTextLineFromStream(is)).length() > 0) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(" ".concat(line));
|
||||
}
|
||||
|
||||
if (!line.startsWith(RESPONSE_HEADER_HTTP_PREFIX))
|
||||
{
|
||||
if (!line.startsWith(RESPONSE_HEADER_HTTP_PREFIX)) {
|
||||
int k = line.indexOf(':');
|
||||
|
||||
if (k > 0)
|
||||
{
|
||||
if (k > 0) {
|
||||
String key = line.substring(0, k).trim();
|
||||
String value = line.substring(k + 1).trim();
|
||||
|
||||
if (RESPONSE_HEADER_LOCATION.equalsIgnoreCase(key))
|
||||
{
|
||||
if (RESPONSE_HEADER_LOCATION.equalsIgnoreCase(key)) {
|
||||
response.sendRedirect(response.encodeRedirectURL(value));
|
||||
}
|
||||
else if (RESPONSE_HEADER_STATUS.equalsIgnoreCase(key))
|
||||
{
|
||||
String[] token = value.split(" ");
|
||||
int status = Integer.parseInt(token[0]);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("CGI returned with status {}", status);
|
||||
}
|
||||
|
||||
if (status < 304)
|
||||
{
|
||||
response.setStatus(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
response.sendError(status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
} else if (RESPONSE_HEADER_STATUS.equalsIgnoreCase(key)) {
|
||||
handleStatus(value);
|
||||
} else {
|
||||
// add remaining header items to our response header
|
||||
response.addHeader(key, value);
|
||||
}
|
||||
@@ -481,6 +435,19 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStatus(String value) throws IOException {
|
||||
String[] token = value.split(" ");
|
||||
int status = Integer.parseInt(token[0]);
|
||||
|
||||
logger.debug("CGI returned with status {}", status);
|
||||
|
||||
if (status < 304) {
|
||||
response.setStatus(status);
|
||||
} else {
|
||||
response.sendError(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -513,26 +480,21 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
*/
|
||||
private void processErrorStreamAsync(final Process process)
|
||||
{
|
||||
executor.execute(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
InputStream errorStream = null;
|
||||
executor.execute(() -> {
|
||||
InputStream errorStream = null;
|
||||
|
||||
try
|
||||
{
|
||||
errorStream = process.getErrorStream();
|
||||
processErrorStream(errorStream);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not read errorstream", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(errorStream);
|
||||
}
|
||||
try
|
||||
{
|
||||
errorStream = process.getErrorStream();
|
||||
processErrorStream(errorStream);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.error("could not read errorstream", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtil.close(errorStream);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -615,6 +577,7 @@ public class DefaultCGIExecutor extends AbstractCGIExecutor
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
getExceptionHandler().handleException(request, response, ex);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user