⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smb.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Internal SMB protocol implementation *//* $Id: smb.c,v 1.66.4.2 2005/05/01 21:15:32 jonas Exp $ */#ifndef _GNU_SOURCE#define _GNU_SOURCE /* Needed for asprintf() */#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef HAVE_SYS_TIME_H#include <sys/time.h> /* FreeBSD needs this before resource.h */#endif#include <sys/types.h> /* FreeBSD needs this before resource.h */#ifdef HAVE_SYS_RESOURCE_H#include <sys/resource.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h> /* OS/2 needs this after sys/types.h */#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "elinks.h"#include "cache/cache.h"#include "config/options.h"#include "intl/gettext/libintl.h"#include "lowlevel/connect.h"#include "lowlevel/select.h"#include "modules/module.h"#include "osdep/osdep.h"#include "protocol/protocol.h"#include "protocol/smb/smb.h"#include "protocol/uri.h"#include "sched/connection.h"#include "util/memory.h"#include "util/snprintf.h"#include "util/string.h"/* XXX: Nice cleanup target --pasky *//* FIXME: we rely on smbclient output which may change in future, * so i think we should use libsmbclient instead (or better in addition) * This stuff is a quick hack, but it works ;). --Zas */enum smb_list_type {	SMB_LIST_NONE,	SMB_LIST_SHARES,	SMB_LIST_DIR,};struct smb_connection_info {	enum smb_list_type list_type;	/* If this is 1, it means one socket is already off. The second one	 * should call end_smb_connection() when it goes off as well. */	int closing;	int textlen;	unsigned char text[1];};static void end_smb_connection(struct connection *conn);struct option_info smb_options[] = {	INIT_OPT_TREE("protocol", N_("SMB"),		"smb", 0,		N_("SAMBA specific options.")),	INIT_OPT_STRING("protocol.smb", N_("Credentials"),		"credentials", 0, "",		N_("Credentials file passed to smbclient via -A option.")),	NULL_OPTION_INFO,};struct module smb_protocol_module = struct_module(	/* name: */		N_("SMB"),	/* options: */		smb_options,	/* hooks: */		NULL,	/* submodules: */	NULL,	/* data: */		NULL,	/* init: */		NULL,	/* done: */		NULL);/* Return 0 if @conn->cached was set. */static intsmb_get_cache(struct connection *conn){	if (conn->cached) return 0;	conn->cached = get_cache_entry(conn->uri);	if (conn->cached) return 0;	abort_conn_with_state(conn, S_OUT_OF_MEM);	return -1;}#define READ_SIZE	4096static intsmb_read_data(struct connection *conn, int sock, unsigned char *dst){	int r;	struct smb_connection_info *si = conn->info;	r = read(sock, dst, READ_SIZE);	if (r == -1) {		retry_conn_with_state(conn, -errno);		return -1;	}	if (r == 0) {		if (!si->closing) {			si->closing = 1;			clear_handlers(sock);			return 0;		}		end_smb_connection(conn);		return 0;	}	return r;}static voidsmb_read_text(struct connection *conn, int sock){	int r;	struct smb_connection_info *si = conn->info;	/* We add 2 here to handle LF and NUL chars that are added in	 * smb_end_connection(). */	si = mem_realloc(si, sizeof(*si) + si->textlen			     + READ_SIZE + 2);	if (!si) {		abort_conn_with_state(conn, S_OUT_OF_MEM);		return;	}	conn->info = si;	r = smb_read_data(conn, sock, si->text + si->textlen);	if (r <= 0) return;	if (!conn->from) set_connection_state(conn, S_GETH);	si->textlen += r;}static voidsmb_got_data(struct connection *conn){	struct smb_connection_info *si = conn->info;	unsigned char buffer[READ_SIZE];	int r;	if (si->list_type != SMB_LIST_NONE) {		smb_read_text(conn, conn->data_socket.fd);		return;	}	r = smb_read_data(conn, conn->data_socket.fd, buffer);	if (r <= 0) return;	set_connection_state(conn, S_TRANS);	if (smb_get_cache(conn)) return;	conn->received += r;	if (add_fragment(conn->cached, conn->from, buffer, r) == 1)		conn->tries = 0;	conn->from += r;}#undef READ_SIZEstatic voidsmb_got_text(struct connection *conn){	smb_read_text(conn, conn->socket.fd);} /* Search for @str1 followed by @str2 in @line.  * It returns NULL if not found, or pointer to start  * of @str2 in @line if found.  */static unsigned char *find_strs(unsigned char *line, unsigned char *str1,	  unsigned char *str2){	unsigned char *p = strstr(line, str1);	if (!p) return NULL;	p = strstr(p + strlen(str1), str2);	return p;}static voidparse_smbclient_output(struct uri *uri, struct smb_connection_info *si,		       struct string *page){	unsigned char *line_start, *line_end;	enum {		SMB_TYPE_NONE,		SMB_TYPE_SHARE,		SMB_TYPE_SERVER,		SMB_TYPE_WORKGROUP	} type = SMB_TYPE_NONE;	int pos = 0;	int stop;	assert(uri && si && page);	if_assert_failed return;	add_to_string(page, "<html><head><title>/");	add_bytes_to_string(page, uri->data, uri->datalen);	add_to_string(page, "</title></head><body><pre>");	line_start = si->text;	stop = !si->textlen;	/* Nothing to parse. */	while (!stop && (line_end = strchr(line_start, ASCII_LF))) {		unsigned char *line = line_start;		int line_len;		int start_offset = 0;		/* Handle \r\n case. Normally, do not occur on *nix. */		if (line_end > line_start && line_end[-1] == ASCII_CR)			 line_end--, start_offset++;		line_len = line_end - line_start;		/* Here we modify si->text content, this should not be		 * a problem as it is only used here. This prevents		 * allocation of memory for the line. */		*line_end = '\0';		/* And I got bored here with cleaning it up. --pasky */		if (si->list_type == SMB_LIST_SHARES) {			unsigned char *ll, *lll, *found;			if (!*line) type = SMB_TYPE_NONE;			found = find_strs(line, "Sharename", "Type");			if (found) {				pos = found - line;				type = SMB_TYPE_SHARE;				goto print_as_is;			}			found = find_strs(line, "Server", "Comment");			if (found) {				type = SMB_TYPE_SERVER;				goto print_as_is;			}			found = find_strs(line, "Workgroup", "Master");			if (found) {				pos = found - line;				type = SMB_TYPE_WORKGROUP;				goto print_as_is;			}			if (type == SMB_TYPE_NONE)				goto print_as_is;			for (ll = line; *ll; ll++)				if (!isspace(*ll) && *ll != '-')					goto print_next;			goto print_as_is;print_next:			for (ll = line; *ll; ll++)				if (!isspace(*ll))					break;			for (lll = ll; *lll; lll++)				if (isspace(*lll))					break;			switch (type) {			case SMB_TYPE_SHARE:			{				unsigned char *llll;				if (!strstr(lll, "Disk"))					goto print_as_is;				if (pos && pos < line_len				    && isspace(*(llll = line + pos - 1))				    && llll > ll) {					while (llll > ll && isspace(*llll))						llll--;					if (!isspace(*llll))						lll = llll + 1;				}				add_bytes_to_string(page, line, ll - line);				add_to_string(page, "<a href=\"");				add_bytes_to_string(page, ll, lll - ll);				add_to_string(page, "/\">");				add_bytes_to_string(page, ll, lll - ll);				add_to_string(page, "</a>");				add_to_string(page, lll);				break;			}			case SMB_TYPE_WORKGROUP:				if (pos < line_len && pos				    && isspace(line[pos - 1])				    && !isspace(line[pos])) {					ll = line + pos;				} else {					for (ll = lll; *ll; ll++)						if (!isspace(*ll))							break;				}				for (lll = ll; *lll; lll++)					if (isspace(*lll))						break;				/* Fall-through */			case SMB_TYPE_SERVER:				add_bytes_to_string(page, line, ll - line);				add_to_string(page, "<a href=\"smb://");				add_bytes_to_string(page, ll, lll - ll);				add_to_string(page, "/\">");				add_bytes_to_string(page, ll, lll - ll);				add_to_string(page, "</a>");				add_to_string(page, lll);				break;			case SMB_TYPE_NONE:				goto print_as_is;			}		} else if (si->list_type == SMB_LIST_DIR) {			if (strstr(line, "NT_STATUS")) {				/* Error, stop after message. */				stop = 1;				goto print_as_is;			}			if (line_end - line_start >= 5			    && line_start[0] == ' '			    && line_start[1] == ' '			    && line_start[2] != ' ') {				int dir = 0;				int may_be_dir = 0;				unsigned char *p = line_end;				unsigned char *url = line_start + 2;				/* smbclient list parser				 * The boring thing is that output is				 * ambiguous in many ways:				 * filenames with more than one space,				 * etc...				 * This bloated code tries to do a not				 * so bad job. --Zas *//* directory                      D        0  Fri May  7 11:23:18 2004 *//* filename                             2444  Thu Feb 19 15:52:46 2004 */				/* Skip end of line */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -