unsigned char *get_auth_entry_info( struct listbox_item *item, struct terminal *term ) { int eax; int ecx; int edx; struct string info; if ( item->type != BI_FOLDER && init_string( &info ) ) { add_format_to_string( &info, "%s: " ); add_uri_to_string( &info, &item->udata[3], URI_HTTP_AUTH ); add_format_to_string( &info, "\n%s: " ); if ( item->udata[4] ) { if ( strlen( &item->udata[4] ) <= 511 ) add_bytes_to_string__( &info, &item->udata[4], strlen( &item->udata[4] ) ); else { add_bytes_to_string__( &info, &item->udata[4], 512 ); add_to_string( &info, "..." ); } } else { add_to_string( &info, _( "none", term ) ); } add_format_to_string( &info, "\n%s: %s\n" ); return info.source; } else { } }
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; }
static unsigned char * get_auth_entry_info(struct listbox_item *item, struct terminal *term) { struct auth_entry *auth_entry = (struct auth_entry *)item->udata; struct string info; if (item->type == BI_FOLDER) return NULL; if (!init_string(&info)) return NULL; add_format_to_string(&info, "%s: ", _("URL", term)); add_uri_to_string(&info, auth_entry->uri, URI_HTTP_AUTH); add_format_to_string(&info, "\n%s: ", _("Realm", term)); if (auth_entry->realm) { int len = strlen((const char *)auth_entry->realm); int maxlen = 512; /* Max. number of chars displayed for realm. */ if (len < maxlen) add_bytes_to_string(&info, auth_entry->realm, len); else { add_bytes_to_string(&info, auth_entry->realm, maxlen); add_to_string(&info, (const unsigned char *)"..."); } } else { add_to_string(&info, _("none", term)); } add_format_to_string(&info, "\n%s: %s\n", _("State", term), auth_entry->valid ? _("valid", term) : _("invalid", term)); return info.source; }
static unsigned char * get_nntp_title(struct connection *conn) { struct nntp_connection_info *nntp = conn->info; struct string title; if (!init_string(&title)) return NULL; switch (nntp->target) { case NNTP_TARGET_ARTICLE_RANGE: add_format_to_string(&title, "Articles in the range %ld to %ld", nntp->current_article, nntp->end_article); break; case NNTP_TARGET_ARTICLE_NUMBER: case NNTP_TARGET_MESSAGE_ID: case NNTP_TARGET_GROUP_MESSAGE_ID: { unsigned char *subject; subject = parse_header(conn->cached->head, "Subject", NULL); if (subject) { add_to_string(&title, subject); mem_free(subject); break; } add_format_to_string(&title, "Article "), add_string_to_string(&title, &nntp->message); if (nntp->target == NNTP_TARGET_MESSAGE_ID) break; add_format_to_string(&title, " in "); add_string_to_string(&title, &nntp->group); break; } case NNTP_TARGET_GROUP: add_format_to_string(&title, "Articles in "), add_string_to_string(&title, &nntp->group); break; case NNTP_TARGET_GROUPS: add_format_to_string(&title, "Newsgroups on "), add_uri_to_string(&title, conn->uri, URI_PUBLIC); break; case NNTP_TARGET_QUIT: break; } return title.source; }
struct string * add_mime_filename_to_string(struct string *string, struct uri *uri) { unsigned char *filename = get_content_filename(uri, NULL); assert(uri->data); if (filename) { add_shell_safe_to_string(string, filename, strlen(filename)); mem_free(filename); return string; } return add_uri_to_string(string, uri, URI_FILENAME); }
static unsigned char * get_cache_entry_info(struct listbox_item *item, struct terminal *term) { struct cache_entry *cached = item->udata; struct string msg; if (item->type == BI_FOLDER) return NULL; if (!init_string(&msg)) return NULL; add_to_string(&msg, _("URL", term)); add_to_string(&msg, ": "); add_uri_to_string(&msg, cached->uri, URI_PUBLIC); /* No need to use compare_uri() here we only want to check whether they * point to the same URI. */ if (cached->proxy_uri != cached->uri) { add_format_to_string(&msg, "\n%s: ", _("Proxy URL", term)); add_uri_to_string(&msg, cached->proxy_uri, URI_PUBLIC); } if (cached->redirect) { add_format_to_string(&msg, "\n%s: ", _("Redirect", term)); add_uri_to_string(&msg, cached->redirect, URI_PUBLIC); if (cached->redirect_get) { add_to_string(&msg, " (GET)"); } } add_format_to_string(&msg, "\n%s: %" OFF_T_FORMAT, _("Size", term), cached->length); add_format_to_string(&msg, "\n%s: %" OFF_T_FORMAT, _("Loaded size", term), cached->data_size); if (cached->content_type) { add_format_to_string(&msg, "\n%s: %s", _("Content type", term), cached->content_type); } if (cached->last_modified) { add_format_to_string(&msg, "\n%s: %s", _("Last modified", term), cached->last_modified); } if (cached->etag) { add_format_to_string(&msg, "\n%s: %s", "ETag", cached->etag); } if (cached->ssl_info) { add_format_to_string(&msg, "\n%s: %s", _("SSL Cipher", term), cached->ssl_info); } if (cached->encoding_info) { add_format_to_string(&msg, "\n%s: %s", _("Encoding", term), cached->encoding_info); } if (cached->incomplete || !cached->valid) { add_char_to_string(&msg, '\n'); add_to_string(&msg, _("Flags", term)); add_to_string(&msg, ": "); if (cached->incomplete) { add_to_string(&msg, _("incomplete", term)); add_char_to_string(&msg, ' '); } if (!cached->valid) add_to_string(&msg, _("invalid", term)); } #ifdef HAVE_STRFTIME if (cached->expire) { time_t expires = timeval_to_seconds(&cached->max_age); add_format_to_string(&msg, "\n%s: ", _("Expires", term)); add_date_to_string(&msg, get_opt_str("ui.date_format"), &expires); } #endif #ifdef CONFIG_DEBUG add_format_to_string(&msg, "\n%s: %d", "Refcount", get_object_refcount(cached)); add_format_to_string(&msg, "\n%s: %u", _("ID", term), cached->id); if (cached->head && *cached->head) { add_format_to_string(&msg, "\n%s:\n\n%s", _("Header", term), cached->head); } #endif return msg.source; }
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); }
static unsigned char * rewrite_uri(unsigned char *url, struct uri *current_uri, unsigned char *arg) { struct string n = NULL_STRING; unsigned char *args[MAX_URI_ARGS]; int argslen[MAX_URI_ARGS]; int argc = 0; int i; if (!init_string(&n)) return NULL; /* Extract space separated list of arguments */ args[argc] = arg; for (i = 0; ; i++) { if (args[argc][i] == ' ') { argslen[argc] = i; argc++; if (argc == MAX_URI_ARGS) break; args[argc] = &args[argc - 1][i]; i = 0; for (; *args[argc] == ' '; args[argc]++); } else if (!args[argc][i]) { argslen[argc] = i; argc++; break; } } while (*url) { int p; int value; for (p = 0; url[p] && url[p] != '%'; p++); add_bytes_to_string(&n, url, p); url += p; if (*url != '%') continue; url++; switch (*url) { case 'c': if (!current_uri) break; add_uri_to_string(&n, current_uri, URI_ORIGINAL); break; case 's': if (arg) encode_uri_string(&n, arg, -1, 1); break; case '%': add_char_to_string(&n, '%'); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': value = *url - '0'; if (value >= argc) break; encode_uri_string(&n, args[value], argslen[value], 1); break; default: add_bytes_to_string(&n, url - 1, 2); break; } if (*url) url++; } return n.source; }
static unsigned char * get_cache_entry_info(struct listbox_item *item, struct terminal *term) { struct cache_entry *cached = item->udata; struct string msg; if (item->type == BI_FOLDER) return NULL; if (!init_string(&msg)) return NULL; add_to_string(&msg, _("URL", term)); add_to_string(&msg, ": "); add_uri_to_string(&msg, cached->uri, URI_PUBLIC); /* No need to use compare_uri() here we only want to check whether they * point to the same URI. */ if (cached->proxy_uri != cached->uri) { add_format_to_string(&msg, "\n%s: ", _("Proxy URL", term)); add_uri_to_string(&msg, cached->proxy_uri, URI_PUBLIC); } if (cached->redirect) { add_format_to_string(&msg, "\n%s: ", _("Redirect", term)); add_uri_to_string(&msg, cached->redirect, URI_PUBLIC); if (cached->redirect_get) { add_to_string(&msg, " (GET)"); } } add_format_to_string(&msg, "\n%s: %" OFF_PRINT_FORMAT, _("Size", term), (off_print_T) cached->length); add_format_to_string(&msg, "\n%s: %" OFF_PRINT_FORMAT, _("Loaded size", term), (off_print_T) cached->data_size); if (cached->content_type) { add_format_to_string(&msg, "\n%s: %s", _("Content type", term), cached->content_type); } if (cached->last_modified) { add_format_to_string(&msg, "\n%s: %s", _("Last modified", term), cached->last_modified); } if (cached->etag) { add_format_to_string(&msg, "\n%s: %s", "ETag", cached->etag); } if (cached->ssl_info) { add_format_to_string(&msg, "\n%s: %s", _("SSL Cipher", term), cached->ssl_info); } if (cached->encoding_info) { add_format_to_string(&msg, "\n%s: %s", _("Encoding", term), cached->encoding_info); } if (cached->incomplete || !cached->valid) { add_char_to_string(&msg, '\n'); add_to_string(&msg, _("Flags", term)); add_to_string(&msg, ": "); if (cached->incomplete) { add_to_string(&msg, _("incomplete", term)); add_char_to_string(&msg, ' '); } if (!cached->valid) add_to_string(&msg, _("invalid", term)); } #ifdef HAVE_STRFTIME if (cached->expire) { time_t expires = timeval_to_seconds(&cached->max_age); add_format_to_string(&msg, "\n%s: ", _("Expires", term)); add_date_to_string(&msg, get_opt_str("ui.date_format", NULL), &expires); } #endif add_format_to_string(&msg, "\n%s: ", _("Cache mode", term)); switch (cached->cache_mode) { case CACHE_MODE_NEVER: add_to_string(&msg, _("never use cache entry", term)); break; case CACHE_MODE_ALWAYS: add_to_string(&msg, _("always use cache entry", term)); break; case CACHE_MODE_INCREMENT: case CACHE_MODE_NORMAL: case CACHE_MODE_CHECK_IF_MODIFIED: case CACHE_MODE_FORCE_RELOAD: /* Cache entries only use two values of enum cache_mode. */ INTERNAL("cached->cache_mode = %d", cached->cache_mode); break; } #ifdef CONFIG_DEBUG add_format_to_string(&msg, "\n%s: %d", "Refcount", get_object_refcount(cached)); add_format_to_string(&msg, "\n%s: %u", _("ID", term), cached->cache_id); if (cached->head && *cached->head) { add_format_to_string(&msg, "\n%s:\n\n%s", _("Header", term), cached->head); } #endif return msg.source; }
/* 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); }