Ejemplo n.º 1
0
unsigned char *_( unsigned char *msg, struct terminal *term )
{
  if ( msg && msg )
  {
    if ( term[0] && current_charset != get_terminal_codepage( &term[0] ) )
    {
      bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( &term[0] ) ) );
      current_charset = get_terminal_codepage( &term[0] );
    }
  }
  return &ebx;
}
Ejemplo n.º 2
0
void do_auth_dialog( struct session *ses, void *data )
{
  int edx;
  struct dialog *dlg;
  struct dialog_data *dlg_data;
  struct terminal *term = ses->tab->term;
  struct auth_entry *a;
  unsigned char sticker[1024], *text;
  int sticker_len;
  if ( get_invalid_auth_entry(  ) && !( ( *(char*)(get_invalid_auth_entry(  ) + 112) & 1 ) & 255 ) && get_uri_string( &a->uri->user[0], URI_HTTP_AUTH ) )
  {
    dlg = &a->realm[0];
    if ( 0 != 65 )
    {
      if ( term[0] && current_charset != get_terminal_codepage( &term[0] ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( &term[0] ) ) );
        *ebp_1076 = text[0];
        current_charset = get_terminal_codepage( &term[0] );
      }
      gettext( "Authentication required for %s at %s" );
      text[0] = text[0];
    }
    sticker_len = __snprintf_chk( sticker, 1024, 1, 1024, (char*)gettext( "Authentication required for %s at %s" ), dlg, text[0] );
    mem_free( &text[0] );
    if ( sticker_len <= 1024 )
    {
      dlg = (struct dialog*)mem_calloc( 1, sticker_len + 277 );
      if ( dlg )
      {
        a->bits_at_112/*.1_1of4*/ |= 1;
        dlg->layouter = &generic_dialog_layouter;
        dlg[0].title = _( "Authentication required", &term[0] );
        text[0] = dlg[3].abort;
        memcpy( dlg[3].abort, sticker, sticker_len );
        dlg->udata = (void*)ses[0].next;
        dlg->udata2 = (void*)a[0].next;
        add_dlg_text( dlg, (unsigned char*)dlg[3].abort, ALIGN_LEFT, 0 );
        add_dlg_field_do( dlg, WIDGET_FIELD, _( "Login", &term[0] ), 0, 0, 0, 40, &a->user[0], 0, INPFIELD_FLOAT );
        add_dlg_field_do( dlg, WIDGET_FIELD_PASS, _( "Password", &term[0] ), 0, 0, 0, 40, &a->password[0], 0, INPFIELD_FLOAT );
        add_dlg_button_do( dlg, _( "~OK", &term[0] ), 1, &ok_dialog, 0, &auth_ok, (void*)dlg );
        add_dlg_button_do( dlg, _( "~Cancel", &term[0] ), 2, &ok_dialog, 0, &auth_cancel, (void*)a[0].next );
        if ( assert_failed == 0 )
        {
          assert_failed = dlg->number_of_widgets != 5;
          if ( dlg->number_of_widgets != 5 )
          {
            errfile = "/home/naftali/source/elinks-0.12~pre5/src/protocol/auth/dialogs.c";
            errline = 118;
            elinks_internal( "assertion 5 == (dlg)-&gt;number_of_widgets failed!" );
          }
        }
        if ( dlg_data[0] && a->user[0] && a->password[0] == 0 )
          select_widget_by_id( &dlg_data[0], 1 );
      }
    }
  }
  if ( 0 ^ 0 )
  {
    __stack_chk_fail(  );
  }
  return;
}
Ejemplo n.º 3
0
void show_http_error_document( struct session *ses, void *data )
{
  struct terminal *term = ses->tab->term;
  struct cache_entry *cached;
  struct cache_entry *cache = find_in_cache( &((int*)data)[1] );
  unsigned char *str;
  cached = find_in_cache( &((int*)data)[1] );
  if ( cached || get_cache_entry( &((int*)data)[1] ) )
  {
    if ( 0 != 72 )
    {
      if ( term && current_charset != get_terminal_codepage( term ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
        current_charset = get_terminal_codepage( term );
      }
      gettext( "HTTP error %03d" );
    }
    if ( init_string( ebp_32 ) == 0 )
    {
      if ( asprintfa( (char*)gettext( "HTTP error %03d" ) ) )
        mem_free( (void*)asprintfa( (char*)gettext( "HTTP error %03d" ) ) );
    }
    else
    {
      add_format_to_string( (struct string*)asprintfa( (char*)gettext( "HTTP error %03d" ) ), asprintfa( (char*)gettext( "HTTP error %03d" ) ) );
      if ( 0 != 32 )
      {
        if ( term && current_charset != get_terminal_codepage( term ) )
        {
          bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
          current_charset = get_terminal_codepage( term );
        }
        gettext( "  An error occurred on the server while fetching the document you\n  requested. However, the server did not send back any explanation of what\n  happened, so it is unknown what went wrong. Please contact the web\n  server administrator about this, if you believe that this error should\n  not occur since it is not a nice behaviour from the web server at all\n  and indicates that there is some much deeper problem with the web server\n  software.\n" );
      }
      add_format_to_string( ebp_32, gettext( "  An error occurred on the server while fetching the document you\n  requested. However, the server did not send back any explanation of what\n  happened, so it is unknown what went wrong. Please contact the web\n  server administrator about this, if you believe that this error should\n  not occur since it is not a nice behaviour from the web server at all\n  and indicates that there is some much deeper problem with the web server\n  software.\n" ) );
      add_format_to_string( "  &lt;/p&gt;\n  &lt;p&gt;\n  URI: &lt;a href=\"%s\"&gt;%s&lt;/a&gt;\n", *(int*)(((int*)data)[1]) );
      add_format_to_string( ebp_32, " &lt;/p&gt;\n &lt;hr /&gt;\n &lt;/body&gt;\n&lt;/html&gt;\n" );
      if ( asprintfa( (char*)gettext( "HTTP error %03d" ) ) )
        mem_free( (void*)asprintfa( (char*)gettext( "HTTP error %03d" ) ) );
      str[0] = ebp_32;
      if ( ebp_32 )
      {
        int gettext_codepage = get_terminal_codepage( term );
        if ( cached )
          delete_entry_content( &cache[0] );
        if ( cache->content_type )
          mem_free( (void*)cache->content_type );
        cache->content_type = stracpy( "text/html" );
        if ( cache->head )
          mem_free( (void*)cache->head );
        cache->head = straconcat( "\r\nContent-Type: text/html; charset=" );
        add_fragment( &cache[0], (long long)0, &str[0] );
        mem_free( &str[0] );
        draw_formatted( ses, 1 );
      }
    }
  }
  done_uri( &((int*)data)[1] );
  mem_free( &((int*)data)[0] );
  return;
}
Ejemplo n.º 4
0
void http_send_header(struct connection *c)
{
    static unsigned char *accept_charset = NULL;
    struct http_connection_info *info;
    int http10 = http_bugs.http10;
    struct cache_entry *e = NULL;
    unsigned char *hdr;
    unsigned char *h, *u;
    int l = 0;
    int la;
    unsigned char *post;
    unsigned char *host;

    find_in_cache(c->url, &c->cache);

    host = upcase(c->url[0]) != 'P' ? c->url : get_url_data(c->url);
    set_timeout(c);
    info = mem_calloc(sizeof(struct http_connection_info));
    c->info = info;
    if ((h = get_host_name(host))) {
        info->bl_flags = get_blacklist_flags(h);
        mem_free(h);
    }
    if (info->bl_flags & BL_HTTP10) http10 = 1;
    info->http10 = http10;
    post = strchr(host, POST_CHAR);
    if (post) post++;
    hdr = init_str();
    if (!post) add_to_str(&hdr, &l, "GET ");
    else {
        add_to_str(&hdr, &l, "POST ");
        c->unrestartable = 2;
    }
    if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "/");
    if (!(u = get_url_data(c->url))) {
        mem_free(hdr);
        setcstate(c, S_BAD_URL);
        http_end_request(c, 0);
        return;
    }
    if (post && post < u) {
        mem_free(hdr);
        setcstate(c, S_BAD_URL);
        http_end_request(c, 0);
        return;
    }
    add_url_to_str(&hdr, &l, u);
    if (!http10) add_to_str(&hdr, &l, " HTTP/1.1\r\n");
    else add_to_str(&hdr, &l, " HTTP/1.0\r\n");
    if ((h = get_host_name(host))) {
        add_to_str(&hdr, &l, "Host: ");
        add_to_str(&hdr, &l, h);
        mem_free(h);
        if ((h = get_port_str(host))) {
            add_to_str(&hdr, &l, ":");
            add_to_str(&hdr, &l, h);
            mem_free(h);
        }
        add_to_str(&hdr, &l, "\r\n");
    }
    add_to_str(&hdr, &l, "User-Agent: ");
    if (!(*http_bugs.fake_useragent)) {
        add_to_str(&hdr, &l, "Links (" VERSION_STRING "; ");
        add_to_str(&hdr, &l, system_name);
        if (!F && !list_empty(terminals)) {
            struct terminal *t = terminals.prev;
            if (!t->spec->braille) {
                add_to_str(&hdr, &l, "; ");
                add_num_to_str(&hdr, &l, t->x);
                add_to_str(&hdr, &l, "x");
                add_num_to_str(&hdr, &l, t->y);
            } else {
                add_to_str(&hdr, &l, "; braille");
            }
        }
#ifdef G
        if (F && drv) {
            add_to_str(&hdr, &l, "; ");
            add_to_str(&hdr, &l, drv->name);
        }
#endif
        add_to_str(&hdr, &l, ")\r\n");
    }
    else {
        add_to_str(&hdr, &l, http_bugs.fake_useragent);
        add_to_str(&hdr, &l, "\r\n");
    }
    switch (http_bugs.referer)
    {
    case REFERER_FAKE:
        add_to_str(&hdr, &l, "Referer: ");
        add_to_str(&hdr, &l, http_bugs.fake_referer);
        add_to_str(&hdr, &l, "\r\n");
        break;

    case REFERER_SAME_URL:
        add_to_str(&hdr, &l, "Referer: ");
        add_url_to_str(&hdr, &l, host);
        add_to_str(&hdr, &l, "\r\n");
        break;

    case REFERER_REAL_SAME_SERVER:
    {
        unsigned char *h, *j;
        int brk = 1;
        if ((h = get_host_name(host))) {
            if ((j = get_host_name(c->prev_url))) {
                if (!strcasecmp(h, j)) brk = 0;
                mem_free(j);
            }
            mem_free(h);
        }
        if (brk) break;
        /* fall through */
    }
    case REFERER_REAL:
    {
        unsigned char *ref;
        unsigned char *user, *ins;
        int ulen;
        if (!(c->prev_url)) break;   /* no referrer */

        ref = stracpy(c->prev_url);
        if (!parse_url(ref, NULL, &user, &ulen, NULL, NULL, &ins, NULL, NULL, NULL, NULL, NULL, NULL) && ulen && ins) {
            memmove(user, ins, strlen(ins) + 1);
        }
        add_to_str(&hdr, &l, "Referer: ");
        add_url_to_str(&hdr, &l, ref);
        add_to_str(&hdr, &l, "\r\n");
        mem_free(ref);
    }
    break;
    }

    add_to_str(&hdr, &l, "Accept: */*\r\n");
#if defined(HAVE_ZLIB) || defined(HAVE_BZIP2)
    if (!http_bugs.no_compression && !(info->bl_flags & BL_NO_COMPRESSION)) {
        int q = strlen(c->url);
        if (q >= 2 && !strcasecmp(c->url + q - 2, ".Z")) goto skip_compress;
        if (q >= 3 && !strcasecmp(c->url + q - 3, ".gz")) goto skip_compress;
        if (q >= 4 && !strcasecmp(c->url + q - 4, ".bz2")) goto skip_compress;
        add_to_str(&hdr, &l, "Accept-Encoding: ");
#if defined(HAVE_ZLIB)
        add_to_str(&hdr, &l, "gzip, deflate, ");
#endif
#if defined(HAVE_BZIP2)
        add_to_str(&hdr, &l, "bzip2, ");
#endif
        hdr[l-2] = '\r';
        hdr[l-1] = '\n';
skip_compress:
        ;
    }
#endif
    if (!(accept_charset)) {
        int i;
        unsigned char *cs, *ac;
        int aclen = 0;
        ac = init_str();
        for (i = 0; (cs = get_cp_mime_name(i)); i++) {
            if (aclen) add_to_str(&ac, &aclen, ", ");
            else add_to_str(&ac, &aclen, "Accept-Charset: ");
            add_to_str(&ac, &aclen, cs);
        }
        if (aclen) add_to_str(&ac, &aclen, "\r\n");
        if ((accept_charset = malloc(strlen(ac) + 1))) strcpy(accept_charset, ac);
        else accept_charset = "";
        mem_free(ac);
    }
    if (!(info->bl_flags & BL_NO_CHARSET) && !http_bugs.no_accept_charset) add_to_str(&hdr, &l, accept_charset);
    if (!(info->bl_flags & BL_NO_ACCEPT_LANGUAGE)) {
        add_to_str(&hdr, &l, "Accept-Language: ");
        la = l;
        add_to_str(&hdr, &l, _(TEXT(T__ACCEPT_LANGUAGE), NULL));
        add_to_str(&hdr, &l, ", ");
        if (!strstr(hdr + la, "en,") && !strstr(hdr + la, "en;")) add_to_str(&hdr, &l, "en;q=0.2, ");
        add_to_str(&hdr, &l, "*;q=0.1\r\n");
    }
    if (!http10) {
        if (upcase(c->url[0]) != 'P') add_to_str(&hdr, &l, "Connection: ");
        else add_to_str(&hdr, &l, "Proxy-Connection: ");
        if (!post || !http_bugs.bug_post_no_keepalive) add_to_str(&hdr, &l, "Keep-Alive\r\n");
        else add_to_str(&hdr, &l, "close\r\n");
    }
    if ((e = c->cache)) {
        int code, vers;
        if (get_http_code(e->head, &code, &vers) || code >= 400) goto skip_ifmod_and_range;
        if (!e->incomplete && e->head && c->no_cache <= NC_IF_MOD) {
            unsigned char *m;
            if (e->last_modified) m = stracpy(e->last_modified);
            else if ((m = parse_http_header(e->head, "Date", NULL))) ;
            else if ((m = parse_http_header(e->head, "Expires", NULL))) ;
            else goto skip_ifmod;
            add_to_str(&hdr, &l, "If-Modified-Since: ");
            add_to_str(&hdr, &l, m);
            add_to_str(&hdr, &l, "\r\n");
            mem_free(m);
        }
skip_ifmod:
        ;
    }
    if (c->from && (c->est_length == -1 || c->from < c->est_length) && c->no_cache < NC_IF_MOD && !(info->bl_flags & BL_NO_RANGE)) {
        /* If the cached entity is compressed and we turned off compression,
           request the whole file */
        if ((info->bl_flags & BL_NO_COMPRESSION || http_bugs.no_compression) && e) {
            unsigned char *d;
            if ((d = parse_http_header(e->head, "Transfer-Encoding", NULL))) {
                mem_free(d);
                goto skip_range;
            }
        }
        add_to_str(&hdr, &l, "Range: bytes=");
        add_num_to_str(&hdr, &l, c->from);
        add_to_str(&hdr, &l, "-\r\n");
skip_range:
        ;
    }
skip_ifmod_and_range:
    if (c->no_cache >= NC_PR_NO_CACHE) add_to_str(&hdr, &l, "Pragma: no-cache\r\nCache-Control: no-cache\r\n");
    if ((h = get_auth_string(c->url))) {
        add_to_str(&hdr, &l, h);
        mem_free(h);
    }
    if (post) {
        unsigned char *pd = strchr(post, '\n');
        if (pd) {
            add_to_str(&hdr, &l, "Content-Type: ");
            add_bytes_to_str(&hdr, &l, post, pd - post);
            add_to_str(&hdr, &l, "\r\n");
            post = pd + 1;
        }
        add_to_str(&hdr, &l, "Content-Length: ");
        add_num_to_str(&hdr, &l, strlen(post) / 2);
        add_to_str(&hdr, &l, "\r\n");
    }
    send_cookies(&hdr, &l, host);
    add_to_str(&hdr, &l, "\r\n");
    if (post) {
        while (post[0] && post[1]) {
            int h1, h2;
            h1 = post[0] <= '9' ? (unsigned)post[0] - '0' : post[0] >= 'A' ? upcase(post[0]) - 'A' + 10 : 0;
            if (h1 < 0 || h1 >= 16) h1 = 0;
            h2 = post[1] <= '9' ? (unsigned)post[1] - '0' : post[1] >= 'A' ? upcase(post[1]) - 'A' + 10 : 0;
            if (h2 < 0 || h2 >= 16) h2 = 0;
            add_chr_to_str(&hdr, &l, h1 * 16 + h2);
            post += 2;
        }
    }
    write_to_socket(c, c->sock1, hdr, l, http_get_header);
    mem_free(hdr);
    setcstate(c, S_SENT);
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
unsigned char *get_progress_msg( struct progress *progress, struct terminal *term, int wide, int full, unsigned char *separator )
{
  int eax;
  int edx;
  struct string msg;
  int newlines;
  newlines/*.1_1of4*/ = *(char*)(( separator + strlen( (char*)separator ) ) - 1);
  if ( init_string( &msg ) == 0 )
  {
    return msg.source;
  }
  if ( 0 != 82 )
  {
    if ( term && current_charset != get_terminal_codepage( term ) )
    {
      bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
      current_charset = get_terminal_codepage( term );
    }
    gettext( "Received" );
  }
  add_to_string( &msg, gettext( "Received" ) );
  add_char_to_string( &msg, 32 );
  add_xnum_to_string( &msg, progress->pos );
  if ( (int)(progress->size << 32) >= 0 )
  {
    add_char_to_string( &msg, 32 );
    if ( 0 != 111 )
    {
      if ( term && current_charset != get_terminal_codepage( term ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
        current_charset = get_terminal_codepage( term );
      }
      gettext( "of" );
    }
    add_to_string( &msg, gettext( "of" ) );
    add_char_to_string( &msg, 32 );
    add_xnum_to_string( &msg, progress->size );
  }
  newlines = newlines/*.1_1of4*/ == 10;
  add_to_string( &msg, &separator[0] );
  if ( wide )
  {
    if ( *(char*)(newlines != 0 ? "average speed" : "Average speed") )
    {
      if ( term && current_charset != get_terminal_codepage( term ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
        *ebp_48 = newlines != 0 ? "average speed" : "Average speed";
        current_charset = get_terminal_codepage( term );
      }
      return (unsigned char*)eax;
    }
    add_to_string( &ebx, &edx );
    add_char_to_string( &msg, 32 );
    add_xnum_to_string( &msg, progress->average_speed );
    add_to_string( &msg, "/s" );
    add_to_string( &msg, ", " );
    if ( *(char*)(full == 0 ? "current speed" : "cur") )
    {
      if ( term && current_charset != get_terminal_codepage( term ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
        *ebp_48 = full == 0 ? "current speed" : "cur";
        current_charset = get_terminal_codepage( term );
      }
      return (unsigned char*)eax;
    }
    add_to_string( &ebx, &edx );
    add_char_to_string( &msg, 32 );
    add_xnum_to_string( &msg, progress->current_speed );
    add_to_string( &msg, "/s" );
    add_to_string( &msg, &separator[0] );
    if ( *(char*)(newlines != 0 ? "elapsed time" : "Elapsed time") )
    {
      if ( term && current_charset != get_terminal_codepage( term ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
        current_charset = get_terminal_codepage( term );
      }
    }
    add_to_string( &ebx, &edi );
    add_char_to_string( &msg, 32 );
    add_timeval_to_string( &msg, &progress[0].elapsed );
  }
  else
  {
    if ( *(char*)(newlines != 0 ? "speed" : "Speed") )
    {
      if ( term && current_charset != get_terminal_codepage( term ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
        current_charset = get_terminal_codepage( term );
      }
      gettext( newlines != 0 ? "speed" : "Speed" );
    }
    add_to_string( &msg, gettext( newlines != 0 ? "speed" : "Speed" ) );
    add_char_to_string( &msg, 32 );
    add_xnum_to_string( &msg, progress->average_speed );
    add_to_string( &msg, "/s" );
  }
  if ( (int)(progress->size << 32) >= 0 && (int)(progress->loaded << 32) >= 0 )
  {
    if ( ccdep1 <= ccdep2 )
    {
      if ( (int)(progress->loaded & 0xFFFFFFFF) >= 1 )
      {
      }
    }
    add_to_string( &msg, ", " );
    if ( *(char*)(full == 0 ? "estimated time" : "ETA") )
    {
      if ( term && current_charset != get_terminal_codepage( term ) )
      {
        bind_textdomain_codeset( "elinks", get_cp_mime_name( get_terminal_codepage( term ) ) );
        current_charset = get_terminal_codepage( term );
      }
    }
    add_to_string( &ebx, &edi );
    add_char_to_string( &msg, 32 );
    add_timeval_to_string( &msg, &progress->estimated_time );
  }
  return msg.source;
}