Example #1
0
static enum evhook_status
script_hook_goto_url(va_list ap, void *data)
{
	unsigned char **url = va_arg(ap, unsigned char **);
	struct session *ses = va_arg(ap, struct session *);
	int error;
	VALUE args[2];
	VALUE result;

	if (*url == NULL)
		return EVENT_HOOK_STATUS_NEXT;

	args[0] = rb_str_new(*url, strlen((const char *)*url));

	if (!ses || !have_location(ses)) {
		args[1] = Qnil;
	} else {
		args[1] = rb_str_new(struri(cur_loc(ses)->vs.uri), strlen((const char *)struri(cur_loc(ses)->vs.uri)));
	}

	result = erb_protected_method_call("goto_url_hook", 2, args, &error);
	if (error) {
		erb_report_error(ses, error);
		return EVENT_HOOK_STATUS_NEXT;
	}

	switch (rb_type(result)) {
	case T_STRING:
	{
		unsigned char *new_url;

		new_url = memacpy(RSTRING(result)->ptr, RSTRING(result)->len);
		if (new_url) {
			mem_free_set(url, new_url);
		}
		break;
	}
	case T_NIL:
		break;

	default:
		alert_ruby_error(ses, "goto_url_hook must return a string or nil");
	}

	return EVENT_HOOK_STATUS_NEXT;
}
Example #2
0
static enum listbox_match
match_cache_entry(struct listbox_item *item, struct terminal *term,
		  unsigned char *text)
{
	struct cache_entry *cached = item->udata;

	if (c_strcasestr(struri(cached->uri), text)
	    || (cached->head && c_strcasestr(cached->head, text)))
		return LISTBOX_MATCH_OK;

	return LISTBOX_MATCH_NO;
}
Example #3
0
static void
add_nntp_html_line(struct string *html, struct connection *conn,
		   unsigned char *line)
{
	struct nntp_connection_info *nntp = conn->info;

	switch (nntp->target) {
	case NNTP_TARGET_ARTICLE_NUMBER:
	case NNTP_TARGET_MESSAGE_ID:
	case NNTP_TARGET_GROUP_MESSAGE_ID:
		add_html_to_string(html, line, strlen(line));
		break;

	case NNTP_TARGET_ARTICLE_RANGE:
	case NNTP_TARGET_GROUP:
	case NNTP_TARGET_GROUPS:
	{
		unsigned char *field = line;

		line = strchr((const char *)line, '\t');
		if (!line)
			field = "";
		else
			*line++ = 0;
		add_format_to_string(html, "<li value=\"%s\"><a href=\"%s/%s\">",
				     field, struri(conn->uri), field);

		field = line;
		line = strchr((const char *)line, '\t');
		if (line)
			*line++ = 0;

		add_header_to_string(html, field);
		add_to_string(html, "</a> ");

		if (line) {
			field = line;
			line = strchr((const char *)line, '\t');
			if (line)
				*line++ = 0;

			add_header_to_string(html, field);
		}
		add_to_string(html, "</li>");
		break;
	}
	case NNTP_TARGET_QUIT:
		break;
	}

	add_char_to_string(html, '\n');
}
Example #4
0
static enum evhook_status
script_hook_pre_format_html(va_list ap, void *data)
{
	struct session *ses = va_arg(ap, struct session *);
	struct cache_entry *cached = va_arg(ap, struct cache_entry *);
	struct fragment *fragment = get_cache_fragment(cached);
	unsigned char *url = struri(cached->uri);

	if (my_perl && ses && url && cached->length && *fragment->data)
		do_script_hook_pre_format_html(url, cached, fragment);

	return EVENT_HOOK_STATUS_NEXT;
}
Example #5
0
static enum evhook_status
script_hook_pre_format_html(va_list ap, void *data)
{
	struct session *ses = va_arg(ap, struct session *);
	struct cache_entry *cached = va_arg(ap, struct cache_entry *);
	struct fragment *fragment = get_cache_fragment(cached);
	unsigned char *url = struri(cached->uri);
	int error;
	VALUE args[2];
	VALUE result;

	evhook_use_params(ses && cached);

	if (!cached->length || !*fragment->data)
		return EVENT_HOOK_STATUS_NEXT;

	args[0] = rb_str_new2(url);
	args[1] = rb_str_new(fragment->data, fragment->length);

	result = erb_protected_method_call("pre_format_html_hook", 2, args, &error);
	if (error) {
		erb_report_error(ses, error);
		return EVENT_HOOK_STATUS_NEXT;
	}

	switch (rb_type(result)) {
	case T_STRING:
	{
		int len = RSTRING(result)->len;

		add_fragment(cached, 0, RSTRING(result)->ptr, len);
		normalize_cache_entry(cached, len);

		break;
	}
	case T_NIL:
		break;

	default:
		alert_ruby_error(ses, "pre_format_html_hook must return a string or nil");
	}

	return EVENT_HOOK_STATUS_NEXT;
}
Example #6
0
static inline void
do_script_hook_goto_url(struct session *ses, unsigned char **url)
{
	int count;
	dSP;	/* Keep in variables declaration block. */

	ENTER;
	SAVETMPS;

	PUSHMARK(SP);
	my_XPUSHs(*url, strlen((const char *)*url));
	if (!ses || !have_location(ses)) {
		XPUSHs(sv_2mortal(newSV(0)));
	} else {
		unsigned char *uri = struri(cur_loc(ses)->vs.uri);

		my_XPUSHs(uri, strlen((const char *)uri));
	}
	PUTBACK;

	count = call_pv("goto_url_hook", G_EVAL | G_SCALAR);
	if (SvTRUE(ERRSV)) count = 0;	/* FIXME: error message ? */
	SPAGAIN;
	if (count == 1) {
#ifndef CONFIG_PERL_POPPX_WITHOUT_N_A
		STRLEN n_a;	/* Used by POPpx macro. */
#endif
		unsigned char *new_url = POPpx;

		if (new_url) {
			unsigned char *n = stracpy(new_url);

			if (n) {
				mem_free_set(url, n);
			}
		}
	}

	PUTBACK;
	FREETMPS;
	LEAVE;
}
Example #7
0
struct uri *
get_proxy_uri(struct uri *uri, struct connection_state *error_state)
{
    if (uri->protocol == PROTOCOL_PROXY) {
        return get_composed_uri(uri, URI_BASE);
    } else {
#ifdef CONFIG_SCRIPTING
        unsigned char *tmp = NULL;
        static int get_proxy_event_id = EVENT_NONE;

        set_event_id(get_proxy_event_id, "get-proxy");
        trigger_event(get_proxy_event_id, &tmp, struri(uri));

        uri = get_proxy_worker(uri, tmp, error_state);
        mem_free_if(tmp);
        return uri;
#else
        return get_proxy_worker(uri, NULL, error_state);
#endif
    }
}
Example #8
0
File: uri.c Project: Efreak/elinks
enum uri_errno
parse_uri(struct uri *uri, unsigned char *uristring)
{
	unsigned char *prefix_end, *host_end;
#ifdef CONFIG_IPV6
	unsigned char *lbracket, *rbracket;
#endif

	assertm(uristring != NULL, "No uri to parse.");
	memset(uri, 0, sizeof(*uri));

	/* Nothing to do for an empty url. */
	if_assert_failed return 0;
	if (!*uristring) return URI_ERRNO_EMPTY;

	uri->string = uristring;
	uri->protocollen = get_protocol_length(uristring);

	/* Invalid */
	if (!uri->protocollen) return URI_ERRNO_INVALID_PROTOCOL;

	/* Figure out whether the protocol is known */
	uri->protocol = get_protocol(struri(uri), uri->protocollen);

	prefix_end = uristring + uri->protocollen; /* ':' */

	/* Check if there's a digit after the protocol name. */
	if (isdigit(*prefix_end)) {
		uri->ip_family = uristring[uri->protocollen] - '0';
		prefix_end++;
	}
	if (*prefix_end != ':')
		return URI_ERRNO_INVALID_PROTOCOL;
	prefix_end++;

	/* Skip slashes */

	if (prefix_end[0] == '/' && prefix_end[1] == '/') {
		if (prefix_end[2] == '/'
		    && get_protocol_need_slash_after_host(uri->protocol))
			return URI_ERRNO_TOO_MANY_SLASHES;

		prefix_end += 2;

	} else if (get_protocol_need_slashes(uri->protocol)) {
		return URI_ERRNO_NO_SLASHES;
	}

	if (get_protocol_free_syntax(uri->protocol)) {
		uri->data = prefix_end;
		uri->datalen = strlen(prefix_end);
		return URI_ERRNO_OK;

	} else if (uri->protocol == PROTOCOL_FILE) {
		int datalen = strcspn(prefix_end, "#" POST_CHAR_S);
		unsigned char *frag_or_post = prefix_end + datalen;

		/* Extract the fragment part. */
		if (datalen >= 0) {
			if (*frag_or_post == '#') {
				uri->fragment = frag_or_post + 1;
				uri->fragmentlen = strcspn(uri->fragment, POST_CHAR_S);
				frag_or_post = uri->fragment + uri->fragmentlen;
			}
			if (*frag_or_post == POST_CHAR) {
				uri->post = frag_or_post + 1;
			}
		} else {
			datalen = strlen(prefix_end);
		}

		/* A bit of a special case, but using the "normal" host
		 * parsing seems a bit scary at this point. (see bug 107). */
		if (datalen > 9 && !c_strncasecmp(prefix_end, "localhost/", 10)) {
			prefix_end += 9;
			datalen -= 9;
		}

		uri->data = prefix_end;
		uri->datalen = datalen;

		return URI_ERRNO_OK;
	}

	/* Isolate host */

#ifdef CONFIG_IPV6
	/* Get brackets enclosing IPv6 address */
	lbracket = strchr((const char *)prefix_end, '[');
	if (lbracket) {
		rbracket = strchr((const char *)lbracket, ']');
		/* [address] is handled only inside of hostname part (surprisingly). */
		if (rbracket && rbracket < prefix_end + strcspn(prefix_end, "/"))
			uri->ipv6 = 1;
		else
			lbracket = rbracket = NULL;
	} else {
		rbracket = NULL;
	}
#endif

	/* Possibly skip auth part */
	host_end = prefix_end + strcspn(prefix_end, "@");

	if (prefix_end + strcspn(prefix_end, "/") > host_end
	    && *host_end) { /* we have auth info here */
		unsigned char *user_end;

		/* Allow '@' in the password component */
		while (strcspn(host_end + 1, "@") < strcspn(host_end + 1, "/?"))
			host_end = host_end + 1 + strcspn(host_end + 1, "@");

		user_end = strchr((const char *)prefix_end, ':');

		if (!user_end || user_end > host_end) {
			uri->user = prefix_end;
			uri->userlen = host_end - prefix_end;
		} else {
			uri->user = prefix_end;
			uri->userlen = user_end - prefix_end;
			uri->password = user_end + 1;
			uri->passwordlen = host_end - user_end - 1;
		}
		prefix_end = host_end + 1;
	}

#ifdef CONFIG_IPV6
	if (uri->ipv6)
		host_end = rbracket + strcspn(rbracket, ":/?");
	else
#endif
		host_end = prefix_end + strcspn(prefix_end, ":/?");

#ifdef CONFIG_IPV6
	if (uri->ipv6) {
		int addrlen = rbracket - lbracket - 1;

		/* Check for valid length.
		 * addrlen >= sizeof(hostbuf) is theorically impossible
		 * but i keep the test in case of... Safer, imho --Zas */
		assertm(addrlen >= 0 && addrlen < NI_MAXHOST,
			"parse_uri(): addrlen value is bad (%d) for URL '%s'. "
			"Problems are likely to be encountered. Please report "
			"this, it is a security bug!", addrlen, uristring);
		if_assert_failed return URI_ERRNO_IPV6_SECURITY;

		uri->host = lbracket + 1;
		uri->hostlen = addrlen;
	} else
Example #9
0
/* @cache_entry_class.getProperty */
static JSBool
cache_entry_get_property(JSContext *ctx, JSObject *obj, jsid id, jsval *vp)
{
	struct cache_entry *cached;
	JSBool ret;

	/* This can be called if @obj if not itself an instance of the
	 * appropriate class but has one in its prototype chain.  Fail
	 * such calls.  */
	if (!JS_InstanceOf(ctx, obj, (JSClass *) &cache_entry_class, NULL))
		return JS_FALSE;

	cached = JS_GetInstancePrivate(ctx, obj,
				       (JSClass *) &cache_entry_class, NULL);
	if (!cached) return JS_FALSE; /* already detached */

	assert(cache_entry_is_valid(cached));
	if_assert_failed return JS_FALSE;

	/* Get a strong reference to the cache entry to prevent it
	 * from being deleted if some function called below decides to
	 * collect garbage.  After this, all code paths must
	 * eventually unlock the object.  */
	object_lock(cached);

	undef_to_jsval(ctx, vp);

	if (!JSID_IS_INT(id))
		ret = JS_FALSE;
	else switch (JSID_TO_INT(id)) {
	case CACHE_ENTRY_CONTENT: {
		struct fragment *fragment = get_cache_fragment(cached);

		if (!fragment) {
			ret = JS_FALSE;
			break;
		}

		*vp = STRING_TO_JSVAL(JS_NewStringCopyN(smjs_ctx,
	                                                fragment->data,
	                                                fragment->length));

		ret = JS_TRUE;
		break;
	}
	case CACHE_ENTRY_TYPE:
		*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
	                                                cached->content_type));

		ret = JS_TRUE;
		break;
	case CACHE_ENTRY_HEAD:
		*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
	                                                cached->head));

		ret = JS_TRUE;
		break;
	case CACHE_ENTRY_LENGTH:
		*vp = INT_TO_JSVAL(cached->length);

		ret = JS_TRUE;
		break;
	case CACHE_ENTRY_URI:
		*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(smjs_ctx,
		                                        struri(cached->uri)));

		ret = JS_TRUE;
		break;
	default:
		/* Unrecognized integer property ID; someone is using
		 * the object as an array.  SMJS builtin classes (e.g.
		 * js_RegExpClass) just return JS_TRUE in this case
		 * and leave *@vp unchanged.  Do the same here.
		 * (Actually not quite the same, as we already used
		 * @undef_to_jsval.)  */
		ret = JS_TRUE;
		break;
	}

	object_unlock(cached);
	return ret;
}