You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ClientVersionUtil.java 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (C) 2012, Google Inc. and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.http.server;
  11. import javax.servlet.http.HttpServletRequest;
  12. /**
  13. * Parses Git client User-Agent strings.
  14. */
  15. public class ClientVersionUtil {
  16. /**
  17. * An invalid version of Git
  18. *
  19. * @return maximum version array, indicating an invalid version of Git.
  20. */
  21. public static int[] invalidVersion() {
  22. return new int[] { Integer.MAX_VALUE };
  23. }
  24. /**
  25. * Parse a Git client User-Agent header value.
  26. *
  27. * @param version
  28. * git client version string, of the form "git/1.7.9".
  29. * @return components of the version string. {@link #invalidVersion()} if
  30. * the version string cannot be parsed.
  31. */
  32. public static int[] parseVersion(String version) {
  33. if (version != null && version.startsWith("git/"))
  34. return splitVersion(version.substring("git/".length()));
  35. return invalidVersion();
  36. }
  37. private static int[] splitVersion(String versionString) {
  38. char[] str = versionString.toCharArray();
  39. int[] ver = new int[4];
  40. int end = 0;
  41. int acc = 0;
  42. for (int i = 0; i < str.length; i++) {
  43. char c = str[i];
  44. if ('0' <= c && c <= '9') {
  45. acc *= 10;
  46. acc += c - '0';
  47. } else if (c == '.') {
  48. if (end == ver.length)
  49. ver = grow(ver);
  50. ver[end++] = acc;
  51. acc = 0;
  52. } else if (c == 'g' && 0 < i && str[i - 1] == '.' && 0 < end) {
  53. // Non-tagged builds may contain a mangled git describe output.
  54. // "1.7.6.1.45.gbe0cc". The 45 isn't a valid component. Drop it.
  55. ver[end - 1] = 0;
  56. acc = 0;
  57. break;
  58. } else if (c == '-' && (i + 2) < str.length
  59. && str[i + 1] == 'r' && str[i + 2] == 'c') {
  60. // Release candidates aren't the same as a final release.
  61. if (acc > 0)
  62. acc--;
  63. break;
  64. } else
  65. break;
  66. }
  67. if (acc != 0) {
  68. if (end == ver.length)
  69. ver = grow(ver);
  70. ver[end++] = acc;
  71. } else {
  72. while (0 < end && ver[end - 1] == 0)
  73. end--;
  74. }
  75. if (end < ver.length) {
  76. int[] n = new int[end];
  77. System.arraycopy(ver, 0, n, 0, end);
  78. ver = n;
  79. }
  80. return ver;
  81. }
  82. private static int[] grow(int[] tmp) {
  83. int[] n = new int[tmp.length + 1];
  84. System.arraycopy(tmp, 0, n, 0, tmp.length);
  85. return n;
  86. }
  87. /**
  88. * Compare two version strings for natural ordering.
  89. *
  90. * @param a
  91. * first parsed version string.
  92. * @param b
  93. * second parsed version string.
  94. * @return &lt; 0 if a is before b; 0 if a equals b; &gt;0 if a is after b.
  95. */
  96. public static int compare(int[] a, int[] b) {
  97. for (int i = 0; i < a.length && i < b.length; i++) {
  98. int cmp = a[i] - b[i];
  99. if (cmp != 0)
  100. return cmp;
  101. }
  102. return a.length - b.length;
  103. }
  104. /**
  105. * Convert a parsed version back to a string.
  106. *
  107. * @param ver
  108. * the parsed version array.
  109. * @return a string, e.g. "1.6.6.0".
  110. */
  111. public static String toString(int[] ver) {
  112. StringBuilder b = new StringBuilder();
  113. for (int v : ver) {
  114. if (b.length() > 0)
  115. b.append('.');
  116. b.append(v);
  117. }
  118. return b.toString();
  119. }
  120. /**
  121. * Check if a Git client has the known push status bug.
  122. * <p>
  123. * These buggy clients do not display the status report from a failed push
  124. * over HTTP.
  125. *
  126. * @param version
  127. * parsed version of the Git client software.
  128. * @return true if the bug is present.
  129. * @deprecated no widely used Git versions need this any more
  130. */
  131. @Deprecated
  132. public static boolean hasPushStatusBug(int[] version) {
  133. return false;
  134. }
  135. /**
  136. * Check if a Git client has the known chunked request body encoding bug.
  137. * <p>
  138. * Git 1.7.5 contains a unique bug where chunked requests are malformed.
  139. * This applies to both fetch and push.
  140. *
  141. * @param version
  142. * parsed version of the Git client software.
  143. * @param request
  144. * incoming HTTP request.
  145. * @return true if the client has the chunked encoding bug.
  146. * @deprecated no widely used Git versions need this any more
  147. */
  148. @Deprecated
  149. public static boolean hasChunkedEncodingRequestBug(
  150. int[] version, HttpServletRequest request) {
  151. return false;
  152. }
  153. private ClientVersionUtil() {
  154. }
  155. }