Esempio n. 1
0
/**
 * This is the same as urn_get_sha1(), only the leading "urn:" part
 * is missing (typically a URN embedded in a GGEP "u").
 *
 * `buf' MUST start with "sha1:" or "bitprint:" indications.  Since the
 * leading "urn:" part is missing, we cannot be lenient.
 *
 * Extract the SHA1 out of it, placing it in the supplied `digest' buffer.
 *
 * @return whether we successfully extracted the SHA1.
 */
bool
urn_get_sha1_no_prefix(const char *buf, struct sha1 *sha1)
{
	const char *p;
	size_t len;

	/*
	 * We handle both "sha1:" and "bitprint:".  In the latter case,
	 * the first 32 bytes of the bitprint is the SHA1.
	 */

	if (
		NULL == (p = is_strcaseprefix(buf, "sha1:")) &&
		NULL == (p = is_strcaseprefix(buf, "bitprint:"))
	)
		return FALSE;

	len = clamp_strlen(p, SHA1_BASE32_SIZE);
	if (parse_base32_sha1(p, len, sha1))
		return TRUE;

	/*
	 * Maybe it was generated by clueless people who use an hexadecimal
	 * representation?
	 */

	len = clamp_strlen(p, SHA1_BASE16_SIZE);
	return parse_base16_sha1(p, len, sha1);
}
Esempio n. 2
0
/**
 * Is the X-Alt header really holding a collection of IP:port (with possible
 * push alt-locs containing a prefixing GUID) or is it mistakenly called
 * X-Alt but is really an old X-Gnutella-Alternate-Location containing a
 * list of HTTP URLs.
 */
static bool
huge_is_pure_xalt(const char *value, size_t len)
{
	host_addr_t addr;

	/*
	 * This is pure heuristics, knowing that if we return TRUE, we'll parse
	 * the X-Alt header in the format that is emitted by the majority of
	 * vendors.
	 *
	 * We try to avoid the more costly pattern_qsearch() call if we can,
	 * and our heuristic should catch 99% of the cases.  And pattern_qsearch()
	 * should quickly return true if the X-Alt is not a collection of IP:port.
	 */

	if (is_strcaseprefix(value, "tls="))
		return TRUE;

	if (string_to_host_addr(value, NULL, &addr))
		return TRUE;

	if (pattern_qsearch(has_http_urls, value, len, 0, qs_any))
		return FALSE;

	return TRUE;
}
Esempio n. 3
0
/**
 * Extract the TTH out of a "urn:tree:tiger" URN.
 * Note that the TTH is expected to be solely base32-encoded here.
 *
 * @return whether TTH was successfully extracted.
 */
bool
urn_get_tth(const char *buf, size_t size, struct tth *tth)
{
	static const char prefix[] = "urn:tree:tiger";
	size_t len;
	const char *p;

	g_assert(0 == size || NULL != buf);
	g_assert(tth);

	if (size < CONST_STRLEN(prefix) + 1 /* ":" */ + TTH_BASE32_SIZE) {
		return FALSE;
	}
	p = is_strcaseprefix(buf, prefix);
	if (NULL == p) {
		return FALSE;
	}
	if ('/' == *p) {
		/* RAZA puts a slash after "tiger" */
		if (size < CONST_STRLEN(prefix) + 2 /* "/:" */ + TTH_BASE32_SIZE){
			return FALSE;
		}
		p++;
	}
	if (':' != *p++) {
		return FALSE;
	}
	len = base32_decode(tth->data, TTH_RAW_SIZE, p, TTH_BASE32_SIZE);
	if (len != TTH_RAW_SIZE) {
		return FALSE;
	}
	return TRUE;
}
Esempio n. 4
0
struct magnet_source *
magnet_parse_exact_source(const char *uri, const char **error_str)
{
	clear_error_str(&error_str);
	g_return_val_if_fail(uri, NULL);

	/* TODO: This should be handled elsewhere e.g., downloads.c in
	 *		a generic way. */

	if (is_strcaseprefix(uri, "http://")) {
		return magnet_parse_http_source(uri, error_str);
	} else if (is_strcaseprefix(uri, "push://")) {
		return magnet_parse_push_source(uri, error_str);
	} else {
		*error_str =
			_("MAGNET URI contained source URL for an unsupported protocol");
		/* Skip this parameter */
		return NULL;
	}
}
Esempio n. 5
0
static struct magnet_source *
magnet_parse_http_source(const char *uri, const char **error_str)
{
	const char *p;

	clear_error_str(&error_str);
	g_return_val_if_fail(uri, NULL);

	p = is_strcaseprefix(uri, "http://");
	g_return_val_if_fail(p, NULL);

	return magnet_parse_location(p, error_str);
}
Esempio n. 6
0
/**
 * Locate the start of "urn:bitprint:" indications and extract
 * the SHA1 and TTH out of it, placing them in the supplied buffers.
 *
 * @return whether we successfully extracted the bitprint, i.e. the two
 * hashes.
 */
bool
urn_get_bitprint(const char *buf, size_t size,
	struct sha1 *sha1, struct tth *tth)
{
	static const char prefix[] = "urn:bitprint:";
	size_t len;
	const char *p;
	bool base16_tth = FALSE;

	g_assert(0 == size || NULL != buf);
	g_assert(sha1);
	g_assert(tth);

	/*
	 * Because some clueless sites list magnets with hexadecimal-encoded
	 * values, we attempt to parse both base32 and base16 encoded hashes.
	 *
	 * Note that we expect both hashes to be similarily encoded.
	 */

	if (size < CONST_STRLEN(prefix) + BITPRINT_BASE32_SIZE)
		return FALSE;
	p = is_strcaseprefix(buf, prefix);
	if (NULL == p)
		return FALSE;
	if (!parse_base32_sha1(p, SHA1_BASE32_SIZE, sha1)) {
		if (
			size >= CONST_STRLEN(prefix) + BITPRINT_BASE16_SIZE &&
			parse_base16_sha1(p, SHA1_BASE16_SIZE, sha1)
		) {
			p += SHA1_BASE16_SIZE;
			base16_tth = TRUE;		/* SHA1 was hexa, expects TTH as hexa */
		} else {
			return FALSE;
		}
	} else {
		p += SHA1_BASE32_SIZE;
	}
	if ('.' != *p++) {
		return FALSE;
	}
	if (base16_tth) {
		len = base16_decode(tth, sizeof *tth, p, TTH_BASE16_SIZE);
	} else {
		len = base32_decode(tth, sizeof *tth, p, TTH_BASE32_SIZE);
	}
	if (len != TTH_RAW_SIZE) {
		return FALSE;
	}
	return TRUE;
}
Esempio n. 7
0
static enum shell_reply
shell_exec_download_add(struct gnutella_shell *sh,
	int argc, const char *argv[])
{
	const char *url;
	gboolean success;

	shell_check(sh);
	g_assert(argv);
	g_assert(argc > 0);

	if (argc < 3) {
		shell_set_msg(sh, _("URL missing"));
		goto error;
	}
	url = argv[2];

	if (is_strcaseprefix(url, "http://")) {
		success = download_handle_http(url);
	} else if (is_strcaseprefix(url, "magnet:?")) {
		unsigned n_downloads, n_searches;

		n_downloads = download_handle_magnet(url);
		n_searches = search_handle_magnet(url);
		success = n_downloads > 0 || n_searches > 0;
	} else {
		success = FALSE;
	}
	if (!success) {
		shell_set_msg(sh, _("The download could not be created"));
		goto error;
	}
	shell_set_msg(sh, _("Download added"));
	return REPLY_READY;

error:
	return REPLY_ERROR;
}
Esempio n. 8
0
static bool
filename_is_reserved(const char *filename)
{
	const char *endptr;

	if ('\0' == filename[0])
		return TRUE;

	/**
	 * FIXME: Doesn't this apply to CYGWIN, too?
	 */
	if (!is_running_on_mingw())
		return FALSE;

	/**
	 * The following may be a superset because PRN1 is (probably) not reserved.
	 */

	if (!(
	 	(endptr = is_strcaseprefix(filename, "aux")) ||
		(endptr = is_strcaseprefix(filename, "com")) ||
		(endptr = is_strcaseprefix(filename, "con")) ||
		(endptr = is_strcaseprefix(filename, "lpt")) ||
		(endptr = is_strcaseprefix(filename, "nul")) ||
		(endptr = is_strcaseprefix(filename, "prn"))
	))
		return FALSE;

	switch (*endptr) {
	case '\0':
		return TRUE;
	case '.':
		/* con.txt is reserved con.blah.txt isn't */
		return NULL == strchr(&endptr[1], '.');
	case '1': case '2': case '3': case '4': case '5': case '6': case '7':
	case '8': case '9':
		/* lpt0, com0 are not reserved */
		endptr++;
		switch (*endptr) {
		case '\0':
			return TRUE;
		case '.':
			/* com1.txt is reserved com1.blah.txt isn't */
			return NULL == strchr(&endptr[1], '.');
		}
		break;
	}

	/* com1blah.txt is not reserved */
	return FALSE;
}
Esempio n. 9
0
/**
 * Try to connect to the list of nodes given by in following form:
 *
 * list = <node> | <node>, 1*<node>
 * port = 1..65535
 * hostname = 1*[a-zA-Z0-9.-]
 * node = hostname [":" <port>]
 *       | <IPv4 address>[":" <port>]
 *		 | <IPv6 address>
 *		 | "[" <IPv6 address> "]:" <port>
 * peer = ["tls:"]["g2:"]<node>
 *
 * If the port is omitted, the default port (GTA_PORT: 6346) is used.
 * The case-insensitive prefix "tls:" requests a TLS (encrypted) connection.
 */
void
nodes_gui_common_connect_by_name(const gchar *line)
{
	const gchar *q;

    g_assert(line);

	q = line;
	while ('\0' != *q) {
		const gchar *endptr, *hostname;
		size_t hostname_len;
		host_addr_t addr;
		guint32 flags;
    	guint16 port;
		bool g2;

		q = skip_ascii_spaces(q);
		if (',' == *q) {
			q++;
			continue;
		}

		addr = zero_host_addr;
		port = GTA_PORT;
		flags = SOCK_F_FORCE;
		endptr = NULL;
		hostname = NULL;
		hostname_len = 0;

		endptr = is_strcaseprefix(q, "tls:");
		if (endptr) {
			flags |= SOCK_F_TLS;
			q = endptr;
		}

		endptr = is_strcaseprefix(q, "g2:");
		if (endptr) {
			g2 = TRUE;
			q = endptr;
		} else {
			g2 = FALSE;
		}

		if (!string_to_host_or_addr(q, &endptr, &addr)) {
			g_message("expected hostname or IP address");
			break;
		}

		if (!is_host_addr(addr)) {
			hostname = q;
			hostname_len = endptr - q;
		}

		q = endptr;

		if (':' == *q) {
			gint error;

			port = parse_uint16(&q[1], &endptr, 10, &error);
			if (error || 0 == port) {
				g_message("cannot parse port");
				break;
			}

			q = skip_ascii_spaces(endptr);
		} else {
			q = skip_ascii_spaces(endptr);
			if ('\0' != *q && ',' != *q) {
				g_message("expected \",\" or \":\"");
				break;
			}
		}

		if (!hostname) {
			if (g2) {
				guc_node_g2_add(addr, port, flags);
			} else {
				guc_node_add(addr, port, flags);
			}
		} else {
			struct add_node_context *ctx;
			gchar *p;

			if ('\0' == hostname[hostname_len])	{
				p = NULL;
			} else {
				size_t n = 1 + hostname_len;

				g_assert(n > hostname_len);
				p = halloc(n);
				g_strlcpy(p, hostname, n);
				hostname = p;
			}

			WALLOC(ctx);
			ctx->port = port;
			ctx->flags = flags;
			ctx->g2 = g2;
			guc_adns_resolve(hostname, add_node_helper, ctx);

			HFREE_NULL(p);
		}
	}
}
Esempio n. 10
0
struct magnet_resource * 
magnet_parse(const char *url, const char **error_str)
{
	static const struct magnet_resource zero_resource;
	struct magnet_resource res;
	const char *p, *next;

	res = zero_resource;
	clear_error_str(&error_str);

	p = is_strcaseprefix(url, "magnet:");
	if (!p) {
		*error_str = "Not a MAGNET URI";
		return NULL;
	}

	if ('?' != p[0]) {
		*error_str = "Invalid MAGNET URI";
		return NULL;
	}
	p++;

	for (/* NOTHING */; p && '\0' != p[0]; p = next) {
		enum magnet_key key;
		const char *endptr;
		char name[16]; /* Large enough to hold longest key we know */

		name[0] = '\0';
		endptr = strchr(p, '=');
		if (endptr && p != endptr) {
			size_t name_len;

			name_len = endptr - p;
			g_assert(size_is_positive(name_len));

			if (name_len < sizeof name) {  /* Ignore overlong key */
				strncat(name, p, name_len);
			}
			p = &endptr[1]; /* Point behind the '=' */
		}

		endptr = strchr(p, '&');
		if (!endptr) {
			endptr = strchr(p, '\0');
		}

		key = magnet_key_get(name);
		if (MAGNET_KEY_NONE == key) {
			g_message("skipping unknown key \"%s\" in MAGNET URI", name);
		} else {
			char *value;
			size_t value_len;

			value_len = endptr - p;
			value = h_strndup(p, value_len);

			plus_to_space(value);
			if (url_unescape(value, TRUE)) {
				magnet_handle_key(&res, name, value);
			} else {
				g_message("badly encoded value in MAGNET URI: \"%s\"", value);
			}
			HFREE_NULL(value);
		}

		while ('&' == endptr[0]) {
			endptr++;
		}
		next = endptr;
	}

	res.sources = g_slist_reverse(res.sources);
	res.searches = g_slist_reverse(res.searches);

	return wcopy(&res, sizeof res);
}