Exemple #1
0
/**
 * Compute character mask "hash", using one bit per letter of the alphabet,
 * plus one for any digit.
 */
static guint32
mask_hash(const char *s) {
	guchar c;
	guint32 mask = 0;

	while ((c = (guchar) *s++)) {
		if (is_ascii_space(c))
			continue;
		else if (is_ascii_digit(c))
			mask |= MASK_DIGIT;
		else {
			int idx = ascii_tolower(c) - 97;
			if (idx >= 0 && idx < 26)
				mask |= MASK_LETTER(idx);
		}
	}

	return mask;
}
Exemple #2
0
/**
 * Parse gtk-gnutella's version number in User-Agent/Server string `str'
 * and extract relevant information into `ver'.
 *
 * @param str	the version string to be parsed
 * @param ver	the structure filled with parsed information
 * @param end	filled with a pointer to the first unparsed character
 *
 * @returns TRUE if we parsed a gtk-gnutella version correctly, FALSE if we
 * were not facing a gtk-gnutella version, or if we did not recognize it.
 */
static bool
version_parse(const char *str, version_t *ver, const char **end)
{
	const char *v;
	int error;

	/*
	 * Modern version numbers are formatted like this:
	 *
	 *    gtk-gnutella/0.85 (04/04/2002; X11; FreeBSD 4.6-STABLE i386)
	 *    gtk-gnutella/0.90u (24/06/2002; X11; Linux 2.4.18-pre7 i686)
	 *    gtk-gnutella/0.90b (24/06/2002; X11; Linux 2.4.18-2emi i686)
	 *    gtk-gnutella/0.90b2 (24/06/2002; X11; Linux 2.4.18-2emi i686)
	 *
	 * The letter after the version number is either 'u' for unstable, 'a'
	 * for alpha, 'b' for beta, or nothing for a stable release.  It can be
	 * followed by digits when present.
	 *
	 * In prevision for future possible extensions, we also parse
	 *
	 *    gtk-gnutella/0.90.1b2 (24/06/2002; X11; Linux 2.4.18-2emi i686)
	 *
	 * where the third number is the "patchlevel".
	 *
	 * Starting 2006-08-26, the user-agent string includes the SVN revision
	 * at the time of the build.  To be compatible with the servents out
	 * there, the version is included as an optional tag following the date.
	 *
	 *    gtk-gnutella/0.85 (04/04/2002; r3404; X11; FreeBSD 4.6-STABLE i386)
	 *
	 * However, we also start parsing the new format that we shall use when
	 * all current GTKG out there have expired:
	 *
	 *    gtk-gnutella/0.85-3404 (04/04/2002; X11; FreeBSD 4.6-STABLE i386)
	 *    gtk-gnutella/0.90b2-3404 (04/04/2002; X11; FreeBSD 4.6-STABLE i386)
	 *
	 * where the '-3404' introduces the build number.
	 *
	 * Since switching to git (2011-09-11), the SVN build is no longer present
	 * but rather the output of "git describe" is used to show any difference
	 * with the latest release tag.
	 *
	 * A release would be described as:
	 *
	 *    gtk-gnutella/0.97.1 (2011-09-11; GTK1; Linux i686)
	 *
	 * but any change on top of that would be seen as:
	 *
	 *    gtk-gnutella/0.97.1-24-g844b7 (2011-09-11; GTK1; Linux i686)
	 *
	 * to indicate that 24 commits were made after the release, and the commit
	 * ID is 844b7... (only enough hexadecimal digits are output to make the
	 * string unique at the time it was generated.
	 *
	 * If furthermore a build is done from a dirty git repository, the string
	 * "-dirty" is appended after the commit ID:
	 *
	 *    gtk-gnutella/0.97.1-24-g844b7-dirty (2011-09-11; GTK1; Linux i686)
	 */

	if (NULL == (v = is_strprefix(str, GTA_PRODUCT_NAME "/")))
		return FALSE;

	/*
	 * Parse "major.minor", followed by optional ".patchlevel".
	 */

	ver->major = parse_uint32(v, &v, 10, &error);
	if (error)
		return FALSE;

	if (*v++ != '.')
		return FALSE;

	ver->minor = parse_uint32(v, &v, 10, &error);
	if (error)
		return FALSE;

	if ('.' == *v) {
		v++;
		ver->patchlevel = parse_uint32(v, &v, 10, &error);
		if (error)
			return FALSE;
	} else
		ver->patchlevel = 0;

	/*
	 * Parse optional tag letter "x" followed by optional "taglevel".
	 */

	if (is_ascii_alpha(*v)) {
		ver->tag = *v++;
		if (is_ascii_digit(*v)) {
			ver->taglevel = parse_uint32(v, &v, 10, &error);
			if (error)
				return FALSE;
		} else
			ver->taglevel = 0;
	} else {
		ver->tag = '\0';
		ver->taglevel = 0;
	}

	/*
	 * Parse optional "-build" (legacy SVN) or "-change-bxxxxxxxx" (git
	 * version scheme) to be able to sort identical versions with distinct
	 * changes applied to them.
	 */

	if ('-' == *v) {
		v++;
		if (!is_strprefix(v, "dirty")) {
			ver->build = parse_uint32(v, &v, 10, &error);
			if (error)
				return FALSE;
		}
	} else
		ver->build = 0;

	if (end != NULL)
		*end = v;

	if (GNET_PROPERTY(version_debug) > 1)
		version_dump(str, ver, "#");

	return TRUE;
}