Exemple #1
0
/** First information such as permissions is gathered for each directory entry.
 * All entries are then sorted. */
static struct directory_entry *
get_smb_directory_entries(int dir, struct string *prefix)
{
	struct directory_entry *entries = NULL;
	
	int size = 0;
	struct smbc_dirent *entry;

	while ((entry = smbc_readdir(dir))) {
		struct stat st, *stp;
		struct directory_entry *new_entries;
		struct string attrib;
		struct string name;

		if (!strcmp(entry->name, "."))
			continue;

		new_entries = mem_realloc(entries, (size + 2) * sizeof(*new_entries));
		if (!new_entries) continue;
		entries = new_entries;

		if (!init_string(&attrib)) {
			continue;
		}

		if (!init_string(&name)) {
			done_string(&attrib);
			continue;
		}

		add_string_to_string(&name, prefix);
		add_to_string(&name, entry->name);

		stp = (smbc_stat(name.source, &st)) ? NULL : &st;

		stat_type(&attrib, stp);
		stat_mode(&attrib, stp);
		stat_links(&attrib, stp);
		stat_user(&attrib, stp);
		stat_group(&attrib, stp);
		stat_size(&attrib, stp);
		stat_date(&attrib, stp);

		entries[size].name = stracpy(entry->name);
		entries[size].attrib = attrib.source;
		done_string(&name);
		size++;
	}
	smbc_closedir(dir);

	if (!size) {
		/* We may have allocated space for entries but added none. */
		mem_free_if(entries);
		return NULL;
	}
	qsort(entries, size, sizeof(*entries), compare_dir_entries);
	memset(&entries[size], 0, sizeof(*entries));
	return entries;
}
Exemple #2
0
static unsigned char *
str_rd(struct option *opt, unsigned char **file, int *line)
{
	unsigned char *str = *file;
	struct string str2;

	if (!init_string(&str2)) return NULL;

	/* We're getting used in some parser functions in conf.c as well, and
	 * that's w/ opt == NULL; so don't rely on opt to point anywhere. */
	if (!commandline) {
		if (!isquote(*str)) {
			done_string(&str2);
			return NULL;
		}
		str++;
	}

	while (*str && (commandline || !isquote(*str))) {
		if (*str == '\\') {
			/* FIXME: This won't work on crlf systems. */
			if (str[1] == '\n') { str[1] = ' '; str++; (*line)++; }
			/* When there's quote char, we will just move on there,
			 * thus we will never test for it in while () condition
			 * and we will treat it just as '"', ignoring the
			 * backslash itself. */
			else if (isquote(str[1])) str++;
			/* \\ means \. */
			else if (str[1] == '\\') str++;
		}

		if (*str == '\n') (*line)++;

		add_char_to_string(&str2, *str);
		str++;
	}

	if (!commandline && !*str) {
		done_string(&str2);
		*file = str;
		return NULL;
	}

	str++; /* Skip the quote. */
	if (!commandline) *file = str;

	if (opt && opt->max && str2.length >= opt->max) {
		done_string(&str2);
		return NULL;
	}

	return str2.source;
}
Exemple #3
0
static void
error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
{
	unsigned char *strict, *exception, *warning, *error;
	struct string msg;

	if (!init_string(&msg)) goto reported;

	strict	  = JSREPORT_IS_STRICT(report->flags) ? " strict" : "";
	exception = JSREPORT_IS_EXCEPTION(report->flags) ? " exception" : "";
	warning   = JSREPORT_IS_WARNING(report->flags) ? " warning" : "";
	error	  = !report->flags ? " error" : "";

	add_format_to_string(&msg, "A client script raised the following%s%s%s%s",
			strict, exception, warning, error);

	add_to_string(&msg, ":\n\n");
	add_to_string(&msg, message);

	if (report->linebuf && report->tokenptr) {
		int pos = report->tokenptr - report->linebuf;

		add_format_to_string(&msg, "\n\n%s\n.%*s^%*s.",
			       report->linebuf,
			       pos - 2, " ",
			       strlen(report->linebuf) - pos - 1, " ");
	}

	alert_smjs_error(msg.source);
	done_string(&msg);

reported:
	JS_ClearPendingException(ctx);
}
Exemple #4
0
/* Returns a connection state. S_OK if all is well. */
static inline struct connection_state
list_directory(struct connection *conn, unsigned char *dirpath,
	       struct string *page)
{
	int show_hidden_files = get_opt_bool((const unsigned char *)"protocol.file.show_hidden_files",
	                                     NULL);
	struct directory_entry *entries;
	struct connection_state state;

	errno = 0;
	entries = get_directory_entries(dirpath, show_hidden_files);
	if (!entries) {
		if (errno) return connection_state_for_errno(errno);
		return connection_state(S_OUT_OF_MEM);
	}

	state = init_directory_listing(page, conn->uri);
	if (!is_in_state(state, S_OK))
		return connection_state(S_OUT_OF_MEM);

	add_dir_entries(entries, dirpath, page);

	if (!add_to_string(page, (const unsigned char *)"</pre>\n<hr/>\n</body>\n</html>\n")) {
		done_string(page);
		return connection_state(S_OUT_OF_MEM);
	}

	return connection_state(S_OK);
}
Exemple #5
0
static struct uri *
proxy_uri(struct uri *uri, unsigned char *proxy,
          struct connection_state *error_state)
{
    struct string string;

    if (init_string(&string)
            && string_concat(&string, "proxy://", proxy, "/",
                             (unsigned char *) NULL)
            && add_uri_to_string(&string, uri, URI_BASE)) {
        /* There is no need to use URI_BASE when calling get_uri()
         * because URI_BASE should not add any fragments in the first
         * place. */
        uri = get_uri(string.source, 0);
        /* XXX: Assume the problem is due to @proxy having bad format.
         * This is a lot faster easier than checking the format. */
        if (!uri)
            *error_state = connection_state(S_PROXY_ERROR);
    } else {
        uri = NULL;
        *error_state = connection_state(S_OUT_OF_MEM);
    }

    done_string(&string);
    return uri;
}
Exemple #6
0
static int
set_python_search_path(void)
{
	struct string new_python_path;
	unsigned char *old_python_path;
	int result = -1;

	if (!init_string(&new_python_path)) return result;

	if (elinks_home && !add_format_to_string(&new_python_path, "%s%c",
						 elinks_home, DELIM))
		goto end;

	if (!add_to_string(&new_python_path, CONFDIR))
		goto end;

	old_python_path = (unsigned char *) getenv("PYTHONPATH");
	if (old_python_path && !add_format_to_string(&new_python_path, "%c%s",
						     DELIM, old_python_path))
		goto end;

	result = env_set("PYTHONPATH", new_python_path.source, -1);

end:
	done_string(&new_python_path);
	return result;
}
Exemple #7
0
static enum parse_error
parse_include(struct option *opt_tree, struct conf_parsing_state *state,
	      struct string *mirror, int is_system_conf)
{
	unsigned char *fname;
	struct string dumbstring;
	struct conf_parsing_pos before_error;

	if (!init_string(&dumbstring))
		return show_parse_error(state, ERROR_NOMEM);

	skip_white(&state->pos);
	if (!*state->pos.look) {
		done_string(&dumbstring);
		return show_parse_error(state, ERROR_PARSE);
	}

	/* File name */
	before_error = state->pos;
	fname = option_types[OPT_STRING].read(NULL, &state->pos.look,
					      &state->pos.line);
	if (!fname) {
		done_string(&dumbstring);
		state->pos = before_error;
		return show_parse_error(state, ERROR_PARSE);
	}

	/* We want load_config_file() to watermark stuff, but not to load
	 * anything, polluting our beloved options tree - thus, we will feed it
	 * with some dummy string which we will destroy later; still better
	 * than cloning whole options tree or polluting interface with another
	 * rarely-used option ;). */
	/* XXX: We should try CONFDIR/<file> when proceeding
	 * CONFDIR/<otherfile> ;). --pasky */
	if (load_config_file(fname[0] == '/' ? (unsigned char *) ""
					     : elinks_home,
			     fname, opt_tree, 
			     mirror ? &dumbstring : NULL, 1)) {
		done_string(&dumbstring);
		mem_free(fname);
		return show_parse_error(state, ERROR_VALUE);
	}

	done_string(&dumbstring);
	mem_free(fname);
	return ERROR_NONE;
}
Exemple #8
0
struct connection_state
read_nntp_response_data(struct connection *conn, struct read_buffer *rb)
{
	struct string html;
	unsigned char *end;
	struct connection_state state = connection_state(S_TRANS);

	if (conn->from == 0) {
		switch (init_nntp_header(conn, rb).basic) {
		case S_OK:
			break;

		case S_OUT_OF_MEM:
			return connection_state(S_OUT_OF_MEM);

		case S_TRANS:
			return connection_state(S_TRANS);

		default:
			return connection_state(S_NNTP_ERROR);
		}
	}

	if (!init_string(&html))
		return connection_state(S_OUT_OF_MEM);

	if (conn->from == 0)
		add_nntp_html_start(&html, conn);

	while ((end = get_nntp_line_end(rb->data, rb->length))) {
		unsigned char *line = check_nntp_line(rb->data, end);

		if (!line) {
			state = connection_state(S_OK);
			break;
		}

		add_nntp_html_line(&html, conn, line);

		conn->received += end - rb->data;
		kill_buffer_data(rb, end - rb->data);
	}

	if (!is_in_state(state, S_TRANS))
		add_nntp_html_end(&html, conn);

	add_fragment(conn->cached, conn->from, html.source, html.length);

	conn->from += html.length;
	done_string(&html);

	return state;
}
Exemple #9
0
/* Handles meta tags in the HTML body. */
void
html_handle_body_meta(struct html_context *html_context, unsigned char *meta,
		      unsigned char *eof)
{
	struct string head;

	if (!init_string(&head)) return;

	/* FIXME (bug 784): cp is the terminal charset;
	 * should use the document charset instead.  */
	scan_http_equiv(meta, eof, &head, NULL, html_context->options->cp);
	process_head(html_context, head.source);
	done_string(&head);
}
Exemple #10
0
/* Establish connection to a peer. As a backend, it uses the internal and more
 * generic connection creater which takes care of DNS querying etc. */
enum bittorrent_state
make_bittorrent_peer_connection(struct bittorrent_connection *bittorrent,
				struct bittorrent_peer *peer_info)
{
	enum bittorrent_state result = BITTORRENT_STATE_OUT_OF_MEM;
	struct uri *uri = NULL;
	struct string uri_string = NULL_STRING;
	struct bittorrent_peer_connection *peer;

	peer = init_bittorrent_peer_connection(-1);
	if (!peer) goto out;

	peer->local.initiater = 1;

	add_to_list(bittorrent->peers, peer);
	peer->bittorrent = bittorrent;

	peer->bitfield = init_bitfield(bittorrent->meta.pieces);
	if (!peer->bitfield) goto out;

	memcpy(peer->id, peer_info->id, sizeof(peer->id));

	/* XXX: Very hacky; construct a fake URI from which make_connection()
	 * can extract the IP address and port number. */
	/* FIXME: Rather change the make_connection() interface. This is an ugly
	 * hack. */
	if (!init_string(&uri_string)) goto out;
	if (!add_format_to_string(&uri_string,
#ifdef CONFIG_IPV6
				  strchr((const char *)peer_info->ip, ':') ?
				  "bittorrent-peer://[%s]:%u/" :
#endif
				  "bittorrent-peer://%s:%u/",
				  peer_info->ip, (unsigned) peer_info->port))
		goto out;
	uri = get_uri(uri_string.source, 0);
	if (!uri) goto out;

	make_connection(peer->socket, uri, send_bittorrent_peer_handshake, 1);
	result = BITTORRENT_STATE_OK;

out:
	if (uri)
		done_uri(uri);
	done_string(&uri_string);
	if (peer && result != BITTORRENT_STATE_OK)
		done_bittorrent_peer_connection(peer);
	return result;
}
Exemple #11
0
/* The global Kernel::p method will for each object, directly write
 * object.inspect() followed by the current output record separator to the
 * program's standard output and will bypass the Ruby I/O libraries.
 *
 * Inspired by Vim we hook into the method and pop up a nice message box so it
 * can be used to easily debug scripts without dirtying the screen. */
static VALUE
erb_stdout_p(int argc, VALUE *argv, VALUE self)
{
	int i;
	struct string string;
	struct terminal *term;

	if (!init_string(&string))
		return Qnil;

	for (i = 0; i < argc; i++) {
		VALUE substr;
		unsigned char *ptr;
		int len;

		if (i > 0)
			add_to_string(&string, ", ");

		substr = rb_inspect(argv[i]);

		/* The Ruby p() function writes variable number of objects using
		 * the inspect() method, which adds quotes to the strings, so
		 * gently ignore them. */

		ptr = RSTRING(substr)->ptr;
		len = RSTRING(substr)->len;

		if (*ptr == '"')
			ptr++, len--;

		if (ptr[len - 1] == '"')
			len--;

		add_bytes_to_string(&string, ptr, len);
	}

	term = get_default_terminal();
	if (!term) {
		usrerror("[Ruby] %s", string.source);
		done_string(&string);
		return Qnil;
	}

	info_box(term, MSGBOX_NO_TEXT_INTL | MSGBOX_FREE_TEXT,
		N_("Ruby Message"), ALIGN_LEFT, string.source);

	return Qnil;
}
Exemple #12
0
void
set_clipboard_text(unsigned char *data)
{
	/* GNU Screen's clipboard */
	if (is_gnuscreen()) {
		struct string str;

		if (!init_string(&str)) return;

		add_to_string(&str, "screen -X register . ");
		add_shell_quoted_to_string(&str, data, strlen(data));

		if (str.length) exe(str.source);
		if (str.source) done_string(&str);
	}

	/* TODO: internal clipboard */
}
Exemple #13
0
void
set_clipboard_text(unsigned char *data)
{
	/* GNU Screen's clipboard */
	if (is_gnuscreen()) {
		struct string str;

		if (!init_string(&str)) return;

		add_to_string(&str, (const unsigned char *)"screen -X register . ");
		add_shell_quoted_to_string(&str, data, strlen((const char *)data));

		if (str.length) exe(str.source);
		if (str.source) done_string(&str);
	}

	/* Shouldn't complain about leaks. */
	if (clipboard) free(clipboard);
	clipboard = (unsigned char *)strdup((const char *)data);
}
Exemple #14
0
static void
smb_directory(int dir, struct string *prefix, struct uri *uri)
{
	struct string buf;
	struct directory_entry *entries;

	if (!is_in_state(init_directory_listing(&buf, uri), S_OK)) {
		smb_error(connection_state(S_OUT_OF_MEM));
	}

	fputs("text/html", header_out);
	fclose(header_out);

	entries = get_smb_directory_entries(dir, prefix);
	add_smb_dir_entries(entries, NULL, &buf);
	add_to_string(&buf, "</pre><hr/></body></html>\n");

	fputs(buf.source, data_out);
	done_string(&buf);
	exit(0);
}
Exemple #15
0
static int
smjs_do_file(unsigned char *path)
{
	int ret = 1;
	jsval rval;
	struct string script;

	if (!init_string(&script)) return 0;

	if (!add_file_to_string(&script, path)
	     || JS_FALSE == JS_EvaluateScript(smjs_ctx,
				JS_GetGlobalObject(smjs_ctx),
				script.source, script.length, path, 1, &rval)) {
		alert_smjs_error("error loading script file");
		ret = 0;
	}

	done_string(&script);

	return ret;
}
Exemple #16
0
static void
display_entry(const FSP_RDENTRY *fentry, const unsigned char dircolor[])
{
	struct string string;

	/* fentry->name is a fixed-size array and is followed by other
	 * members; thus, if the name reported by the server does not
	 * fit in the array, fsplib must either truncate or reject it.
	 * If fsplib truncates the name, it does not document whether
	 * fentry->namlen is the original length or the truncated
	 * length.  ELinks therefore ignores fentry->namlen and
	 * instead measures the length on its own.  */
	const size_t namelen = strlen(fentry->name);

	if (!init_string(&string)) return;
	add_format_to_string(&string, "%10d", fentry->size);
	add_to_string(&string, "\t<a href=\"");
	/* The result of encode_uri_string does not include '&' or '<'
	 * which could mess up the HTML.  */
	encode_uri_string(&string, fentry->name, namelen, 0);
	if (fentry->type == FSP_RDTYPE_DIR) {
		add_to_string(&string, "/\">");
		if (*dircolor) {
			add_to_string(&string, "<font color=\"");
			add_to_string(&string, dircolor);
			add_to_string(&string, "\"><b>");
		}
		add_html_to_string(&string, fentry->name, namelen);
		if (*dircolor) {
			add_to_string(&string, "</b></font>");
		}
	} else {
		add_to_string(&string, "\">");
		add_html_to_string(&string, fentry->name, namelen);
	}
	add_to_string(&string, "</a>");
	puts(string.source);
	done_string(&string);
}
Exemple #17
0
unsigned char *
get_clipboard_text(void)
{
	/* The following support for GNU Screen's clipboard is
	 * disabled for two reasons:
	 *
	 * 1. It does not actually return the string from that
	 *    clipboard, but rather causes the clipboard contents to
	 *    appear in stdin.	get_clipboard_text is normally called
	 *    because the user pressed a Paste key in an input field,
	 *    so the characters end up being inserted in that field;
	 *    but if there are newlines in the clipboard, then the
	 *    field may lose focus, in which case the remaining
	 *    characters may trigger arbitrary actions in ELinks.
	 *
	 * 2. It pastes from both GNU Screen's clipboard and the ELinks
	 *    internal clipboard.  Because set_clipboard_text also sets
	 *    them both, the same text would typically get pasted twice.
	 *
	 * Users can instead use the GNU Screen key bindings to run the
	 * paste command.  This method still suffers from problem 1 but
	 * any user of GNU Screen should know that already.  */
#if 0
	/* GNU Screen's clipboard */
	if (is_gnuscreen()) {
		struct string str;

		if (!init_string(&str)) return NULL;

		add_to_string(&str, (const unsigned char *)"screen -X paste .");
		if (str.length) exe(str.source);
		if (str.source) done_string(&str);
	}
#endif

	return stracpy(empty_string_or_(clipboard));
}
Exemple #18
0
struct connection_state
init_directory_listing(struct string *page, struct uri *uri)
{
	struct string dirpath = NULL_STRING;
	struct string decoded = NULL_STRING;
	struct string location = NULL_STRING;
	unsigned char *info;
	int local = (uri->protocol == PROTOCOL_FILE);

	if (!init_string(page)
	    || !init_string(&dirpath)
	    || !init_string(&decoded)
	    || !init_string(&location)
	    || !add_uri_to_string(&dirpath, uri, URI_DATA)
	    || !add_uri_to_string(&location, uri, URI_DIR_LOCATION))
		goto out_of_memory;

	if (dirpath.length > 0
	    && !dir_sep(dirpath.source[dirpath.length - 1])
	    && !add_char_to_string(&dirpath, local ? CHAR_DIR_SEP : '/'))
		goto out_of_memory;

	/* Decode uri for displaying.  */
	if (!add_string_to_string(&decoded, &dirpath))
		goto out_of_memory;
	decode_uri_string(&decoded);

	if (!local && !add_char_to_string(&location, '/'))
		goto out_of_memory;

	if (!add_to_string(page, (const unsigned char *)"<html>\n<head><title>"))
		goto out_of_memory;

	if (!local && !add_html_to_string(page, location.source, location.length))
		goto out_of_memory;

	if (!add_html_to_string(page, decoded.source, decoded.length)
	    || !add_to_string(page, (const unsigned char *)"</title>\n<base href=\"")
	    || !add_html_to_string(page, location.source, location.length)
	    || !add_html_to_string(page, dirpath.source, dirpath.length))
		goto out_of_memory;

	if (!add_to_string(page, (const unsigned char *)"\" />\n</head>\n<body>\n<h2>"))
		goto out_of_memory;

	/* Use module names? */
	switch (uri->protocol) {
	case PROTOCOL_FILE:
		info = (unsigned char *)"Local";
		break;
	case PROTOCOL_FSP:
		info = (unsigned char *)"FSP";
		break;
	case PROTOCOL_FTP:
		info = (unsigned char *)"FTP";
		break;
	case PROTOCOL_GOPHER:
		info = (unsigned char *)"Gopher";
		break;
	case PROTOCOL_SMB:
		info = (unsigned char *)"Samba";
		break;
	default:
		info = (unsigned char *)"?";
	}

	if (!add_to_string(page, info)
	    || !add_to_string(page, (const unsigned char *)" directory "))
		goto out_of_memory;

	if (!local && !add_string_to_string(page, &location))
		goto out_of_memory;

	/* Make the directory path with links to each subdir. */
	{
		const unsigned char *slash = dirpath.source;
		const unsigned char *pslash = slash;
		const unsigned char sep = local ? CHAR_DIR_SEP :  '/';

		while ((slash = (const unsigned char *)strchr((char *)slash, sep)) != NULL) {
			done_string(&decoded);
			if (!init_string(&decoded)
			    || !add_bytes_to_string(&decoded, pslash, slash - pslash))
				goto out_of_memory;
			decode_uri_string(&decoded);

			if (!add_to_string(page, (const unsigned char *)"<a href=\"")
			    || !add_html_to_string(page, location.source, location.length)
			    || !add_html_to_string(page, dirpath.source, slash + 1 - dirpath.source)
			    || !add_to_string(page, (const unsigned char *)"\">")
			    || !add_html_to_string(page, decoded.source, decoded.length)
			    || !add_to_string(page, (const unsigned char *)"</a>")
			    || !add_html_to_string(page, &sep, 1))
				goto out_of_memory;

			pslash = ++slash;
		}
	}

	if (!add_to_string(page, (const unsigned char *)"</h2>\n<pre>")) {
out_of_memory:
		done_string(page);
	}

	done_string(&dirpath);
	done_string(&decoded);
	done_string(&location);

	return page->length > 0
		? connection_state(S_OK)
		: connection_state(S_OUT_OF_MEM);
}
Exemple #19
0
unsigned char *format_command( unsigned char *command, unsigned char *type, int copiousoutput )
{
  struct string cmd;
  if ( init_string( &cmd ) )
  {
    while ( 1 )
    {
      while ( ( command[0] & 255 ) == 0 )
      {
        if ( command[0] != '%' )
        {
          if ( command[0] != '\\' )
          {
            if ( command[0] == '\'' )
            {
              command[0] = command[1];
              strcmp( "%s'", &command[1] );
              if ( 1 )
              {
                command[0] = command[3];
                add_char_to_string( &cmd, 37 );
              }
              else
              {
                add_char_to_string( &cmd, 39 );
              }
            }
            else
            {
              do
              {
                command[0] = command[1];
              }
              while ( command[0] != '%' && ( command[0] & 255 ) && command[0] != '\\' && command[0] != '\'' );
              if ( command[0] < command[0] )
              {
                if ( assert_failed == 0 )
                {
                  if ( command[0] && command[0] - command[0] >= 0 )
                    assert_failed = 0;
                  else
                  {
                    assert_failed = 1;
                    errfile = "/home/naftali/source/elinks-0.12~pre5/src/util/string.h";
                    errline = 255;
                    elinks_internal( "assertion string && bytes && length &gt;= 0 failed: [add_bytes_to_string]" );
                    if ( assert_failed )
                    {
                    }
                  }
                  if ( command[0] - command[0] )
                  {
                    if ( 0 < 0 )
                    {
                      if ( mem_realloc( (void*)cmd.source, 0 ) == 0 )
                        command[0] = command[0];
                      else
                      {
                        cmd.source = (unsigned char*)mem_realloc( (void*)cmd.source, 0 );
                        memset( cmd.source + 0, 0, 0 - 0 );
                      }
                    }
                    if ( cmd.source )
                    {
                      memcpy( cmd.length + cmd.source, &command[0], command[0] - command[0] );
                      cmd.source[ ebp_56 ] = 0;
                      cmd.length = ebp_56;
                    }
                  }
                }
                assert_failed = 0;
                command[0] = command[0];
                if ( command[0] != '\'' )
                {
                  if ( command[0] != '\\' )
                  {
                    if ( command[0] != '%' )
                      continue;
                    else
                    {
                      command[0] = command[0] + 1;
                      if ( command[1] )
                      {
                        if ( command[1] == 's' )
                          add_char_to_string( &cmd, 37 );
                          command[0] = command[0] + 1;
                        else
                        if ( command[1] == 't' )
                        {
                          if ( type[0] )
                            add_to_string( &cmd, &type[0] );
                        }
                      }
                      done_string( &cmd );
                      break;
                    }
                  }
                  else
                  {
                    command[0] = command[1];
                    if ( command[0] )
                    {
                      command[0] = command[1];
                      add_char_to_string( &cmd, command[0] );
                      break;
                      while ( 1 )
                      {
                      }
                    }
                    else
                    {
                      if ( copiousoutput && ( getenv( "PAGER" ) || file_exists( "/usr/bin/pager" ) || file_exists( "/usr/bin/less" ) || file_exists( "/usr/bin/more" ) ) )
                      {
                        add_char_to_string( &cmd, 124 );
                        add_to_string( &cmd, &pager[0] );
                      }
                      break;
                    }
                  }
                }
              }
              command[0] = command[0];
            }
          }
          else
          {
            command[0] = command[1];
          }
        }
        if ( command[0] != '\'' )
        {
        }
      }
Exemple #20
0
size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
{
  size_t pos = 0;
  const char *string_start;

  switch(vt->parser.state) {
  case NORMAL:
  case CSI_LEADER:
  case CSI_ARGS:
  case CSI_INTERMED:
  case ESC:
    string_start = NULL;
    break;
  case STRING:
  case ESC_IN_STRING:
    string_start = bytes;
    break;
  }

#define ENTER_STRING_STATE(st) do { vt->parser.state = STRING; string_start = bytes + pos + 1; } while(0)
#define ENTER_STATE(st)        do { vt->parser.state = st; string_start = NULL; } while(0)
#define ENTER_NORMAL_STATE()   ENTER_STATE(NORMAL)

  for( ; pos < len; pos++) {
    unsigned char c = bytes[pos];

    if(c == 0x00 || c == 0x7f) { // NUL, DEL
      if(vt->parser.state >= STRING) {
        more_string(vt, string_start, bytes + pos - string_start);
        string_start = bytes + pos + 1;
      }
      continue;
    }
    if(c == 0x18 || c == 0x1a) { // CAN, SUB
      ENTER_NORMAL_STATE();
      continue;
    }
    else if(c == 0x1b) { // ESC
      vt->parser.intermedlen = 0;
      if(vt->parser.state == STRING)
        vt->parser.state = ESC_IN_STRING;
      else
        ENTER_STATE(ESC);
      continue;
    }
    else if(c == 0x07 &&  // BEL, can stand for ST in OSC or DCS state
            vt->parser.state == STRING) {
      // fallthrough
    }
    else if(c < 0x20) { // other C0
      if(vt->parser.state >= STRING)
        more_string(vt, string_start, bytes + pos - string_start);
      do_control(vt, c);
      if(vt->parser.state >= STRING)
        string_start = bytes + pos + 1;
      continue;
    }
    // else fallthrough

    switch(vt->parser.state) {
    case ESC_IN_STRING:
      if(c == 0x5c) { // ST
        vt->parser.state = STRING;
        done_string(vt, string_start, bytes + pos - string_start - 1);
        ENTER_NORMAL_STATE();
        break;
      }
      vt->parser.state = ESC;
      // else fallthrough

    case ESC:
      switch(c) {
      case 0x50: // DCS
        start_string(vt, VTERM_PARSER_DCS);
        ENTER_STRING_STATE();
        break;
      case 0x5b: // CSI
        vt->parser.csi_leaderlen = 0;
        ENTER_STATE(CSI_LEADER);
        break;
      case 0x5d: // OSC
        start_string(vt, VTERM_PARSER_OSC);
        ENTER_STRING_STATE();
        break;
      default:
        if(is_intermed(c)) {
          if(vt->parser.intermedlen < INTERMED_MAX-1)
            vt->parser.intermed[vt->parser.intermedlen++] = c;
        }
        else if(!vt->parser.intermedlen && c >= 0x40 && c < 0x60) {
          do_control(vt, c + 0x40);
          ENTER_NORMAL_STATE();
        }
        else if(c >= 0x30 && c < 0x7f) {
          do_escape(vt, c);
          ENTER_NORMAL_STATE();
        }
        else {
          DEBUG_LOG("TODO: Unhandled byte %02x in Escape\n", c);
        }
      }
      break;

    case CSI_LEADER:
      /* Extract leader bytes 0x3c to 0x3f */
      if(c >= 0x3c && c <= 0x3f) {
        if(vt->parser.csi_leaderlen < CSI_LEADER_MAX-1)
          vt->parser.csi_leader[vt->parser.csi_leaderlen++] = c;
        break;
      }

      /* else fallthrough */
      vt->parser.csi_leader[vt->parser.csi_leaderlen] = 0;

      vt->parser.csi_argi = 0;
      vt->parser.csi_args[0] = CSI_ARG_MISSING;
      vt->parser.state = CSI_ARGS;

      /* fallthrough */
    case CSI_ARGS:
      /* Numerical value of argument */
      if(c >= '0' && c <= '9') {
        if(vt->parser.csi_args[vt->parser.csi_argi] == CSI_ARG_MISSING)
          vt->parser.csi_args[vt->parser.csi_argi] = 0;
        vt->parser.csi_args[vt->parser.csi_argi] *= 10;
        vt->parser.csi_args[vt->parser.csi_argi] += c - '0';
        break;
      }
      if(c == ':') {
        vt->parser.csi_args[vt->parser.csi_argi] |= CSI_ARG_FLAG_MORE;
        c = ';';
      }
      if(c == ';') {
        vt->parser.csi_argi++;
        vt->parser.csi_args[vt->parser.csi_argi] = CSI_ARG_MISSING;
        break;
      }

      /* else fallthrough */
      vt->parser.csi_argi++;
      vt->parser.intermedlen = 0;
      vt->parser.state = CSI_INTERMED;
    case CSI_INTERMED:
      if(is_intermed(c)) {
        if(vt->parser.intermedlen < INTERMED_MAX-1)
          vt->parser.intermed[vt->parser.intermedlen++] = c;
        break;
      }
      else if(c == 0x1b) {
        /* ESC in CSI cancels */
      }
      else if(c >= 0x40 && c <= 0x7e) {
        vt->parser.intermed[vt->parser.intermedlen] = 0;
        do_csi(vt, c);
      }
      /* else was invalid CSI */

      ENTER_NORMAL_STATE();
      break;

    case STRING:
      if(c == 0x07 || (c == 0x9c && !vt->mode.utf8)) {
        done_string(vt, string_start, bytes + pos - string_start);
        ENTER_NORMAL_STATE();
      }
      break;

    case NORMAL:
      if(c >= 0x80 && c < 0xa0 && !vt->mode.utf8) {
        switch(c) {
        case 0x90: // DCS
          start_string(vt, VTERM_PARSER_DCS);
          ENTER_STRING_STATE();
          break;
        case 0x9b: // CSI
          ENTER_STATE(CSI_LEADER);
          break;
        case 0x9d: // OSC
          start_string(vt, VTERM_PARSER_OSC);
          ENTER_STRING_STATE();
          break;
        default:
          do_control(vt, c);
          break;
        }
      }
      else {
        size_t eaten = 0;
        if(vt->parser.callbacks && vt->parser.callbacks->text)
          eaten = (*vt->parser.callbacks->text)(bytes + pos, len - pos, vt->parser.cbdata);

        if(!eaten) {
          DEBUG_LOG("libvterm: Text callback did not consume any input\n");
          /* force it to make progress */
          eaten = 1;
        }

        pos += (eaten - 1); // we'll ++ it again in a moment
      }
      break;
    }
  }

  return len;
}
Exemple #21
0
static void
do_html_select(unsigned char *attr, unsigned char *html,
	       unsigned char *eof, unsigned char **end,
	       struct html_context *html_context)
{
	struct conv_table *ct = (struct conv_table *)html_context->special_f(html_context, SP_TABLE, NULL);
	struct form_control *fc;
	struct string lbl = NULL_STRING, orig_lbl = NULL_STRING;
	unsigned char **values = NULL;
	unsigned char **labels;
	unsigned char *name, *t_attr, *en;
	int namelen;
	int nnmi = 0;
	int order = 0;
	int preselect = -1;
	int group = 0;
	int i, max_width;
	int closing_tag;

	html_focusable(html_context, attr);
	init_menu(&lnk_menu);

se:
        en = html;

see:
        html = en;
	while (html < eof && *html != '<') html++;

	if (html >= eof) {

abort:
		*end = html;
		if (lbl.source) done_string(&lbl);
		if (orig_lbl.source) done_string(&orig_lbl);
		if (values) {
			int j;

			for (j = 0; j < order; j++)
				mem_free_if(values[j]);
			mem_free(values);
		}
		destroy_menu(&lnk_menu);
		*end = en;
		return;
	}

	if (lbl.source) {
		unsigned char *q, *s = en;
		int l = html - en;

		while (l && isspace(s[0])) s++, l--;
		while (l && isspace(s[l-1])) l--;
		q = convert_string(ct, s, l,
		                   html_context->options->cp,
		                   CSM_DEFAULT, NULL, NULL, NULL);
		if (q) add_to_string(&lbl, q), mem_free(q);
		add_bytes_to_string(&orig_lbl, s, l);
	}

	if (html + 2 <= eof && (html[1] == '!' || html[1] == '?')) {
		html = skip_comment(html, eof);
		goto se;
	}

	if (parse_element(html, eof, &name, &namelen, &t_attr, &en)) {
		html++;
		goto se;
	}

	if (!namelen) goto see;

	if (name[0] == '/') {
		namelen--;
		if (!namelen) goto see;
		name++;
		closing_tag = 1;
	} else {
		closing_tag = 0;
	}

	if (closing_tag && !c_strlcasecmp(name, namelen, (const unsigned char *)"SELECT", 6)) {
		add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi);
		goto end_parse;
	}

	if (!c_strlcasecmp(name, namelen, (const unsigned char *)"OPTION", 6)) {
		add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi);

		if (!closing_tag) {
			unsigned char *value, *label;

			if (has_attr(t_attr, (unsigned char *)"disabled", html_context->doc_cp))
				goto see;
			if (preselect == -1
			    && has_attr(t_attr, (unsigned char *)"selected", html_context->doc_cp))
				preselect = order;
			value = get_attr_val(t_attr, (unsigned char *)"value", html_context->doc_cp);

			if (!mem_align_alloc(&values, order, order + 1, 0xFF))
				goto abort;

			values[order++] = value;
			label = get_attr_val(t_attr, (unsigned char *)"label", html_context->doc_cp);
			if (label) new_menu_item(&lnk_menu, label, order - 1, 0);
			if (!value || !label) {
				init_string(&lbl);
				init_string(&orig_lbl);
				nnmi = !!label;
			}
		}

		goto see;
	}

	if (!c_strlcasecmp(name, namelen, (const unsigned char *)"OPTGROUP", 8)) {
		add_select_item(&lnk_menu, &lbl, &orig_lbl, values, order, nnmi);

		if (group) new_menu_item(&lnk_menu, NULL, -1, 0), group = 0;

		if (!closing_tag) {
			unsigned char *label;

			label = get_attr_val(t_attr, (unsigned char *)"label", html_context->doc_cp);

			if (!label) {
				label = stracpy((const unsigned char *)"");
				if (!label) goto see;
			}
			new_menu_item(&lnk_menu, label, -1, 0);
			group = 1;
		}
	}

	goto see;


end_parse:
	*end = en;
	if (!order) goto abort;

	labels = (unsigned char **)mem_calloc(order, sizeof(unsigned char *));
	if (!labels) goto abort;

	fc = init_form_control(FC_SELECT, attr, html_context);
	if (!fc) {
		mem_free(labels);
		goto abort;
	}

	fc->id = get_attr_val(attr, (unsigned char *)"id", html_context->doc_cp);
	fc->name = get_attr_val(attr, (unsigned char *)"name", html_context->doc_cp);
	fc->default_state = preselect < 0 ? 0 : preselect;
	fc->default_value = order ? stracpy(values[fc->default_state]) : stracpy((const unsigned char *)"");
	fc->nvalues = order;
	fc->values = values;
	fc->menu = detach_menu(&lnk_menu);
	fc->labels = labels;

	menu_labels(fc->menu, (unsigned char *)"", labels);
	put_chrs(html_context, (unsigned char *)"[", 1);
	html_stack_dup(html_context, ELEMENT_KILLABLE);
	format.form = fc;
	format.style.attr |= AT_BOLD;

	max_width = 0;
	for (i = 0; i < order; i++) {
		if (!labels[i]) continue;
#ifdef CONFIG_UTF8
		if (html_context->options->utf8)
			int_lower_bound(&max_width,
					utf8_ptr2cells(labels[i], NULL));
		else
#endif /* CONFIG_UTF8 */
			int_lower_bound(&max_width, strlen((const char *)labels[i]));
	}

	for (i = 0; i < max_width; i++)
		put_chrs(html_context, (unsigned char *)"_", 1);

	pop_html_element(html_context);
	put_chrs(html_context, (unsigned char *)"]", 1);
	html_context->special_f(html_context, SP_CONTROL, fc);
}
Exemple #22
0
static void
do_smb(struct connection *conn)
{
	struct uri *uri = conn->uri;
	struct auth_entry *auth = find_auth(uri);
	struct string string;
	unsigned char *url;
	int dir;

	if ((uri->userlen && uri->passwordlen) || !auth) {
		url = get_uri_string(uri, URI_BASE);
	} else {
		unsigned char *uri_string = get_uri_string(uri, URI_HOST | URI_PORT | URI_DATA);

		if (!uri_string || !init_string(&string)) {
			smb_error(connection_state(S_OUT_OF_MEM));
		}
		/* Must URI-encode the username and password to avoid
		 * ambiguity if they contain "/:@" characters.
		 * Libsmbclient then decodes them again, and the
		 * server gets them as they were in auth->user and
		 * auth->password, i.e. as the user typed them in the
		 * auth dialog.  This implies that, if the username or
		 * password contains some characters or bytes that the
		 * user cannot directly type, then she cannot enter
		 * them.  If that becomes an actual problem, it should
		 * be fixed in the auth dialog, e.g. by providing a
		 * hexadecimal input mode.  */
		add_to_string(&string, "smb://");
		encode_uri_string(&string, auth->user, -1, 1);
		add_char_to_string(&string, ':');
		encode_uri_string(&string, auth->password, -1, 1);
		add_char_to_string(&string, '@');
		add_to_string(&string, uri_string);
		url = string.source;
	}

	if (!url) {
		smb_error(connection_state(S_OUT_OF_MEM));
	}
	if (smbc_init(smb_auth, 0)) {
		smb_error(connection_state_for_errno(errno));
	};


	dir = smbc_opendir(url);
	if (dir >= 0) {
		struct string prefix;

		init_string(&prefix);
		add_to_string(&prefix, url);
		add_char_to_string(&prefix, '/');
		smb_directory(dir, &prefix, conn->uri);
		done_string(&prefix);
	} else {
		const int errno_from_opendir = errno;
		char buf[READ_SIZE];
		struct stat sb;
		int r, res, fdout;
		int file = smbc_open(url, O_RDONLY, 0);

		if (file < 0) {
			/* If we're opening the list of shares without
			 * proper authentication, then smbc_opendir
			 * fails with EACCES and smbc_open fails with
			 * ENOENT.  In this case, return the EACCES so
			 * that the parent ELinks process will prompt
			 * for credentials.  */
			if (errno == ENOENT && errno_from_opendir == EACCES)
				errno = errno_from_opendir;
			smb_error(connection_state_for_errno(errno));
		}

		res = smbc_fstat(file, &sb);
		if (res) {
			smb_error(connection_state_for_errno(res));
		}
		/* filesize */
		fprintf(header_out, "%" OFF_PRINT_FORMAT,
			(off_print_T) sb.st_size);
		fclose(header_out);

		fdout = fileno(data_out);
		while ((r = smbc_read(file, buf, READ_SIZE)) > 0) {
			if (safe_write(fdout, buf, r) <= 0)
					break;
		}
		smbc_close(file);
		exit(0);
	}
}
Exemple #23
0
/* Set xterm-like term window's title. */
void
set_window_title(unsigned char *title, int codepage)
{
	struct string filtered;

#ifndef HAVE_SYS_CYGWIN_H
	/* Check if we're in a xterm-like terminal. */
	//if (!is_xterm()) return;
#endif

	if (!init_string(&filtered)) return;

	/* Copy title to filtered if different from NULL */
	if (title) {
		unsigned char *scan = title;
		unsigned char *end = title + strlen((const char *)title);

		/* Remove control characters, so that they cannot
		 * interfere with the command we send to the terminal.
		 * However, do not attempt to limit the title length
		 * to terminal width, because the title is usually
		 * drawn in a different font anyway.  */
		/* Note that this is the right place where to do it, since
		 * potential alternative set_window_title() routines might
		 * want to take different precautions. */
		for (;;) {
			unsigned char *charbegin = scan;
			unicode_val_T unicode
				= cp_to_unicode(codepage, &scan, end);
			int charlen = scan - charbegin;

			if (unicode == UCS_NO_CHAR)
				break;

			/* This need not recognize all Unicode control
			 * characters.  Only those that can make the
			 * terminal misparse the command.  */
			if (unicode < 0x20
			    || (unicode >= 0x7F && unicode < 0xA0))
				continue;

			/* If the title is getting too long, truncate
			 * it and add an ellipsis.
			 *
			 * xterm entirely rejects 1024-byte or longer
			 * titles.  GNU Screen 4.00.03 misparses
			 * titles longer than 765 bytes, and is unable
			 * to display the title in hardstatus if the
			 * title and other stuff together exceed 766
			 * bytes.  So set the limit quite a bit lower.  */
			if (filtered.length + charlen >= 600 - 3) {
				add_to_string(&filtered, (const unsigned char *)"...");
				break;
			}

			add_bytes_to_string(&filtered, charbegin, charlen);
		}
	}

	//getCurrentView()->setTitle(filtered.source);

	/* Send terminal escape sequence + title string */
//	printf("\033]0;%s\a", filtered.source);

#if 0
	/* Miciah don't like this so it is disabled because it changes the
	 * default window name. --jonas */
	/* Set the GNU screen window name */
	if (is_gnuscreen())
		printf("\033k%s\033\134", filtered.source);
#endif

	//fflush(stdout);

	done_string(&filtered);
}
Exemple #24
0
void
html_li(struct html_context *html_context, unsigned char *a,
        unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	int t = par_format.flags & P_LISTMASK;

	/* When handling the code <li><li> @was_li will be 1 and it means we
	 * have to insert a line break since no list item content has done it
	 * for us. */
	if (html_context->was_li) {
		html_context->line_breax = 0;
		ln_break(html_context, 1);
	}

	/*kill_html_stack_until(html_context, 0
	                      "", "UL", "OL", NULL);*/
	if (t == P_NO_BULLET) {
		/* Print nothing. */
	} else if (!par_format.list_number) {
		if (t == P_O) /* Print U+25E6 WHITE BULLET. */
			put_chrs(html_context, (unsigned char *)"&#9702;", 7);
		else if (t == P_SQUARE) /* Print U+25AA BLACK SMALL SQUARE. */
			put_chrs(html_context, (unsigned char *)"&#9642;", 7);
		else /* Print U+2022 BULLET. */
			put_chrs(html_context, (unsigned char *)"&#8226;", 7);
		put_chrs(html_context, (unsigned char *)"&nbsp;", 6);
		par_format.leftmargin += 2;
		par_format.align = ALIGN_LEFT;

	} else {
		unsigned char c = 0;
		int nlen;
		int t = par_format.flags & P_LISTMASK;
		int s = get_num(a, (unsigned char *)"value", html_context->doc_cp);
		struct string n;

		if (!init_string(&n)) return;

		if (s != -1) par_format.list_number = s;

		if (t == P_ALPHA || t == P_alpha) {
			unsigned char n0;

			put_chrs(html_context, (unsigned char *)"&nbsp;", 6);
			c = 1;
			n0 = par_format.list_number
			       ? (par_format.list_number - 1) % 26
			         + (t == P_ALPHA ? 'A' : 'a')
			       : 0;
			if (n0) add_char_to_string(&n, n0);

		} else if (t == P_ROMAN || t == P_roman) {
			roman(&n, par_format.list_number);
			if (t == P_ROMAN) {
				unsigned char *x;

				for (x = n.source; *x; x++) *x = c_toupper(*x);
			}

		} else {
			unsigned char n0[64];
			if (par_format.list_number < 10) {
				put_chrs(html_context, (unsigned char *)"&nbsp;", 6);
				c = 1;
			}

			ulongcat(n0, NULL, par_format.list_number, (sizeof(n) - 1), 0);
			add_to_string(&n, n0);
		}

		nlen = n.length;
		put_chrs(html_context, n.source, nlen);
		put_chrs(html_context, (unsigned char *)".&nbsp;", 7);
		par_format.leftmargin += nlen + c + 2;
		par_format.align = ALIGN_LEFT;
		done_string(&n);

		{
			struct html_element *element;

			element = search_html_stack(html_context, (unsigned char *)"ol");
			if (element)
				element->parattr.list_number = par_format.list_number + 1;
		}

		par_format.list_number = 0;
	}

	html_context->putsp = HTML_SPACE_SUPPRESS;
	html_context->line_breax = 2;
	html_context->was_li = 1;
}
Exemple #25
0
static void
add_smb_dir_entry(struct directory_entry *entry, struct string *page,
	      int pathlen, unsigned char *dircolor)
{
	unsigned char *lnk = NULL;
	struct string html_encoded_name;
	struct string uri_encoded_name;

	if (!init_string(&html_encoded_name)) return;
	if (!init_string(&uri_encoded_name)) {
		done_string(&html_encoded_name);
		return;
	}

	encode_uri_string(&uri_encoded_name, entry->name + pathlen, -1, 1);
	add_html_to_string(&html_encoded_name, entry->name + pathlen,
			   strlen(entry->name) - pathlen);

	/* add_to_string(&fragment, &fragmentlen, "   "); */
	add_html_to_string(page, entry->attrib, strlen(entry->attrib));
	add_to_string(page, "<a href=\"");
	add_string_to_string(page, &uri_encoded_name);

	if (entry->attrib[0] == 'd') {
		add_char_to_string(page, '/');

#ifdef FS_UNIX_SOFTLINKS
	} else if (entry->attrib[0] == 'l') {
		struct stat st;
		unsigned char buf[MAX_STR_LEN];
		int readlen = readlink(entry->name, buf, MAX_STR_LEN);

		if (readlen > 0 && readlen != MAX_STR_LEN) {
			buf[readlen] = '\0';
			lnk = straconcat(" -> ", buf, (unsigned char *) NULL);
		}

		if (!stat(entry->name, &st) && S_ISDIR(st.st_mode))
			add_char_to_string(page, '/');
#endif
	}

	add_to_string(page, "\">");

	if (entry->attrib[0] == 'd' && *dircolor) {
		/* The <b> is for the case when use_document_colors is off. */
		string_concat(page, "<font color=\"", dircolor, "\"><b>",
			      (unsigned char *) NULL);
	}

	add_string_to_string(page, &html_encoded_name);
	done_string(&uri_encoded_name);
	done_string(&html_encoded_name);

	if (entry->attrib[0] == 'd' && *dircolor) {
		add_to_string(page, "</b></font>");
	}

	add_to_string(page, "</a>");
	if (lnk) {
		add_html_to_string(page, lnk, strlen(lnk));
		mem_free(lnk);
	}

	add_char_to_string(page, '\n');
}
Exemple #26
0
/** A select_handler_T read_func for itrm_in.sock.  A slave process
 * calls this when the master sends it data to be displayed.  The
 * master process never calls this.  */
static void
in_sock(struct itrm *itrm)
{
	struct string path;
	struct string delete_;
	char ch;
	int fg; /* enum term_exec */
	ssize_t bytes_read, i, p;
	unsigned char buf[ITRM_OUT_QUEUE_SIZE];

	bytes_read = safe_read(itrm->in.sock, buf, ITRM_OUT_QUEUE_SIZE);
	if (bytes_read <= 0) goto free_and_return;

qwerty:
	for (i = 0; i < bytes_read; i++)
		if (!buf[i])
			goto has_nul_byte;

	safe_hard_write(itrm->out.std, buf, bytes_read);
	return;

has_nul_byte:
	if (i) safe_hard_write(itrm->out.std, buf, i);

	i++;
	assert(ITRM_OUT_QUEUE_SIZE - i > 0);
	memmove(buf, buf + i, ITRM_OUT_QUEUE_SIZE - i);
	bytes_read -= i;
	p = 0;

#define RD(xx) {							\
		unsigned char cc;					\
									\
		if (p < bytes_read)					\
			cc = buf[p++];					\
		else if ((hard_read(itrm->in.sock, &cc, 1)) <= 0)	\
			goto free_and_return;				\
		xx = cc;						\
	}

	RD(fg);

	if (!init_string(&path)) goto free_and_return;

	while (1) {
		RD(ch);
		if (!ch) break;
		add_char_to_string(&path, ch);
	}

	if (!init_string(&delete_)) {
		done_string(&path);
		goto free_and_return;
	}

	while (1) {
		RD(ch);
		if (!ch) break;
		add_char_to_string(&delete_, ch);
	}

#undef RD

	if (!*path.source) {
		dispatch_special(delete_.source);

	} else {
		int blockh;
		unsigned char *param;
		int path_len, del_len, param_len;

		/* TODO: Should this be changed to allow TERM_EXEC_NEWWIN
		 * in a blocked terminal?  There is similar code in
		 * exec_on_terminal().  --KON, 2007 */
		if (is_blocked() && fg != TERM_EXEC_BG) {
			if (*delete_.source) unlink(delete_.source);
			goto nasty_thing;
		}

		path_len = path.length;
		del_len = delete_.length;
		param_len = path_len + del_len + 3;

		param = mem_alloc(param_len);
		if (!param) goto nasty_thing;

		param[0] = fg;
		memcpy(param + 1, path.source, path_len + 1);
		memcpy(param + 1 + path_len + 1, delete_.source, del_len + 1);

		if (fg == TERM_EXEC_FG) block_itrm();

		blockh = start_thread((void (*)(void *, int)) exec_thread,
				      param, param_len);
		mem_free(param);

		if (blockh == -1) {
			if (fg == TERM_EXEC_FG)
				unblock_itrm();

			goto nasty_thing;
		}

		if (fg == TERM_EXEC_FG) {
			set_handlers(blockh, (select_handler_T) unblock_itrm_x,
				     NULL, (select_handler_T) unblock_itrm_x,
				     (void *) (long) blockh);

		} else {
			set_handlers(blockh, close_handle, NULL, close_handle,
				     (void *) (long) blockh);
		}
	}

nasty_thing:
	done_string(&path);
	done_string(&delete_);
	assert(ITRM_OUT_QUEUE_SIZE - p > 0);
	memmove(buf, buf + p, ITRM_OUT_QUEUE_SIZE - p);
	bytes_read -= p;

	goto qwerty;

free_and_return:
	free_itrm(itrm);
}
Exemple #27
0
/* To reduce redundant error handling code [calls to abort_connection()]
 * most of the function is build around conditions that will assign the error
 * code to @state if anything goes wrong. The rest of the function will then just
 * do the necessary cleanups. If all works out we end up with @state being S_OK
 * resulting in a cache entry being created with the fragment data generated by
 * either reading the file content or listing a directory. */
void
file_protocol_handler(struct connection *connection)
{
	unsigned char *redirect_location = NULL;
	struct string page, name;
	struct connection_state state;
	int set_dir_content_type = 0;

	if (get_cmd_opt_bool((const unsigned char *)"anonymous")) {
		if (strcmp((const char *)connection->uri->string, "file:///dev/stdin")
		    || isatty(STDIN_FILENO)) {
			abort_connection(connection,
					 connection_state(S_FILE_ANONYMOUS));
			return;
		}
	}

#ifdef CONFIG_CGI
	if (!execute_cgi(connection)) return;
#endif /* CONFIG_CGI */

	/* Treat /dev/stdin in special way */
	if (!strcmp((const char *)connection->uri->string, "file:///dev/stdin")) {
		int fd = open("/dev/stdin", O_RDONLY);

		if (fd == -1) {
			abort_connection(connection, connection_state(-errno));
			return;
		}
		set_nonblocking_fd(fd);
		if (!init_http_connection_info(connection, 1, 0, 1)) {
			abort_connection(connection, connection_state(S_OUT_OF_MEM));
			close(fd);
			return;
		}
		connection->socket->fd = fd;
		connection->data_socket->fd = -1;
		read_from_stdin(connection);
		return;
	}


	/* This function works on already simplified file-scheme URI pre-chewed
	 * by transform_file_url(). By now, the function contains no hostname
	 * part anymore, possibly relative path is converted to an absolute one
	 * and uri->data is just the final path to file/dir we should try to
	 * show. */

	if (!init_string(&name)
	    || !add_uri_to_string(&name, connection->uri, URI_PATH)) {
		done_string(&name);
		abort_connection(connection, connection_state(S_OUT_OF_MEM));
		return;
	}

	decode_uri_string(&name);

	/* In Win32, file_is_dir seems to always return 0 if the name
	 * ends with a directory separator.  */
	if ((name.length > 0 && dir_sep(name.source[name.length - 1]))
	    || file_is_dir(name.source)) {
		/* In order for global history and directory listing to
		 * function properly the directory url must end with a
		 * directory separator. */
		if (name.source[0] && !dir_sep(name.source[name.length - 1])) {
			redirect_location = (unsigned char *)STRING_DIR_SEP;
			state = connection_state(S_OK);
		} else {
			state = list_directory(connection, name.source, &page);
			set_dir_content_type = 1;
		}

	} else {
		state = read_encoded_file(&name, &page);
		/* FIXME: If state is now S_ENCODE_ERROR we should try loading
		 * the file undecoded. --jonas */
	}

	done_string(&name);

	if (is_in_state(state, S_OK)) {
		struct cache_entry *cached;

		/* Try to add fragment data to the connection cache if either
		 * file reading or directory listing worked out ok. */
		cached = connection->cached = get_cache_entry(connection->uri);
		if (!connection->cached) {
			if (!redirect_location) done_string(&page);
			state = connection_state(S_OUT_OF_MEM);

		} else if (redirect_location) {
			if (!redirect_cache(cached, redirect_location, 1, 0))
				state = connection_state(S_OUT_OF_MEM);

		} else {
			add_fragment(cached, 0, page.source, page.length);
			connection->from += page.length;

			if (!cached->head && set_dir_content_type) {
				unsigned char *head;

				/* If the system charset somehow
				 * changes after the directory listing
				 * has been generated, it should be
				 * parsed with the original charset.  */
				head = straconcat((const unsigned char *)"\r\nContent-Type: text/html; charset=",
						  get_cp_mime_name(get_cp_index((const unsigned char *)"System")),
						  "\r\n", (unsigned char *) NULL);

				/* Not so gracefully handle failed memory
				 * allocation. */
				if (!head)
					state = connection_state(S_OUT_OF_MEM);

				/* Setup directory listing for viewing. */
				mem_free_set(&cached->head, head);
			}

			done_string(&page);
		}
	}

	abort_connection(connection, state);
}
Exemple #28
0
void
html_link(struct html_context *html_context, unsigned char *a,
          unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	int link_display = html_context->options->meta_link_display;
	unsigned char *name;
	struct hlink link;
	struct string text;
	int name_neq_title = 0;
	int first = 1;

#ifndef CONFIG_CSS
	if (!link_display) return;
#endif
	if (!html_link_parse(html_context, a, &link)) return;
	if (!link.href) goto free_and_return;

#ifdef CONFIG_CSS
	if (link.type == LT_STYLESHEET
	    && supports_html_media_attr(link.media)) {
		int len = strlen((const char *)link.href);

		import_css_stylesheet(&html_context->css_styles,
				      html_context->base_href, link.href, len);
	}

	if (!link_display) goto free_and_return;
#endif

	/* Ignore few annoying links.. */
	if (link_display < 5 &&
	    (link.type == LT_ICON ||
	     link.type == LT_AUTHOR ||
	     link.type == LT_STYLESHEET ||
	     link.type == LT_ALTERNATE_STYLESHEET)) goto free_and_return;

	if (!link.name || link.type != LT_UNKNOWN)
		/* Give preference to our default names for known types. */
		name = get_lt_default_name(&link);
	else
		name = link.name;

	if (!name) goto free_and_return;
	if (!init_string(&text)) goto free_and_return;

	html_focusable(html_context, a);

	if (link.title) {
		add_to_string(&text, link.title);
		name_neq_title = strcmp((const char *)link.title, (const char *)name);
	} else
		add_to_string(&text, name);

	if (link_display == 1) goto put_link_line;	/* Only title */

#define APPEND(what) do { \
		add_to_string(&text, first ? (const unsigned char *)" (" : (const unsigned char *)", "); \
		add_to_string(&text, (what)); \
		first = 0; \
	} while (0)

	if (name_neq_title) {
		APPEND(name);
	}

	if (link_display >= 3 && link.hreflang) {
		APPEND(link.hreflang);
	}

	if (link_display >= 4 && link.content_type) {
		APPEND(link.content_type);
	}

	if (link.lang && link.type == LT_ALTERNATE_LANG &&
	    (link_display < 3 || (link.hreflang &&
				  c_strcasecmp((const char *)link.hreflang, (const char *)link.lang)))) {
		APPEND(link.lang);
	}

	if (link.media) {
		APPEND(link.media);
	}

#undef APPEND

	if (!first) add_char_to_string(&text, ')');

put_link_line:
	{
		unsigned char *prefix = (link.direction == LD_REL)
					? (unsigned char *)"Link: " : (unsigned char *)"Reverse link: ";
		unsigned char *link_name = (text.length)
					   ? text.source : name;

		put_link_line(prefix, link_name, link.href,
			      html_context->base_target, html_context);

		if (text.source) done_string(&text);
	}

free_and_return:
	html_link_clear(&link);
}