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

📄 parse.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
			 * rare. */#define check_trailing_char(string, trailchar) \	((string)->length > 0 \	 && (string)->source[(string)->length - 1] == (trailchar))			switch (info->type) {			case FTP_FILE_DIRECTORY:				/* Check for trailing `/' */				if (check_trailing_char(&info->name, '/'))					info->name.length--;				break;			case FTP_FILE_SYMLINK:				/* If the file is a symbolic link, it should				 * have a ` -> ' somewhere. */				while (pos && pos + 3 < end) {					if (!memcmp(pos, " -> ", 4)) {						info->symlink.source = pos + 4;						info->symlink.length = end - pos - 4;						info->name.length = pos - src;						break;					}					pos = memchr(pos, ' ', end - pos);				}				if (!info->symlink.source)					return NULL;				/* Check for trailing `@' on link and trailing				 * `/' on the link target if it's a directory */				if (check_trailing_char(&info->name, '@'))					info->name.length--;				if (check_trailing_char(&info->symlink, '/'))					info->symlink.length--;				break;			case FTP_FILE_PLAINFILE:				/* Check for trailing `*' on files which are				 * executable. */				if ((info->permissions & 0111)				    && check_trailing_char(&info->name, '*'))					info->name.length--;			default:				break;			}			if (mtime.tm_year == 0) {				/* Get the current time.  */				time_t timenow = time(NULL);				struct tm *now = localtime(&timenow);				mtime.tm_year = now->tm_year;				/* Some listings will not specify the year if it				 * is "obvious" that the file was from the				 * previous year. E.g. if today is 97-01-12, and				 * you see a file of Dec 15th, its year is 1996,				 * not 1997. Thanks to Vladimir Volovich for				 * mentioning this! */				if (mtime.tm_mon > now->tm_mon)					mtime.tm_year--;			}			info->mtime = mktime(&mtime); /* store the time-stamp */			info->local_time_zone = 1;			return info;		}		skip_space_end(pos, end);	}	return NULL;}/* Parser for VMS-style MultiNet (some spaces removed from examples): */#ifdef DEBUG_FTP_PARSERstatic unsigned char ftp_vms_responses[] = "00README.TXT;1      2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE)\r\n" "CORE.DIR;1          1  8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE)\r\n" /* And non-MutliNet VMS: */ "CII-MANUAL.TEX;1  213/216  29-JAN-1996 03:33:12  [ANONYMOU,ANONYMOUS]   (RWED,RWED,,)\r\n" /* A garbage line which should fail: */ "EA95_0PS.GZ;1      No privilege for attempted operation\r\n";#endif/* Converts VMS symbolic permissions to number-style ones, e.g. string * RWED,RWE,RE to 755. "D" (delete) is taken to be equal to "W" (write). * Inspired by a patch of Stoyan Lekov <lekov@eda.bg>. */static intparse_ftp_vms_permissions(const unsigned char *src, int len){	int perms = 0;	int pos;	for (pos = 0; pos < len; pos++) {		switch (src[pos]) {		case ',': perms <<= 3; break;		case 'R': perms  |= 4; break;		case 'W':		case 'D': perms  |= 2; break;		case 'E': perms  |= 1; break;		default:			 /* Wrong VMS permissons! */			  return 0;		}	}	return perms;}static struct ftp_file_info *parse_ftp_vms_response(struct ftp_file_info *info, unsigned char *src, int len){	unsigned char *end = src + len;	unsigned char *pos;	/* First column: Name. A bit of black magic again. The name maybe either	 * ABCD.EXT or ABCD.EXT;NUM and it might be on a separate line.	 * Therefore we will first try to get the complete name until the first	 * space character; if it fails, we assume that the name occupies the	 * whole line. After that we search for the version separator ";", we	 * remove it and check the extension of the file; extension .DIR denotes	 * directory. */	pos = memchr(src, ';', end - src);	if (!pos) return NULL;	info->name.source = src;	info->name.length = pos - src;	/* If the name ends on .DIR or .DIR;#, it's a directory. We also	 * set the file size to zero as the listing does tell us only	 * the size in filesystem blocks - for an integrity check (when	 * mirroring, for example) we would need the size in bytes. */	if (info->name.length > 4 && !memcmp(&pos[-4], ".DIR", 4)) {		info->type  = FTP_FILE_DIRECTORY;		info->name.length -= 4;	} else {		info->type  = FTP_FILE_PLAINFILE;	}	skip_nonspace_end(pos, end);	skip_space_end(pos, end);	src = pos;	/* Second column, if exists, or the first column of the next line	 * contain file size in blocks. We will skip it. */	if (src >= end) {		/* FIXME: Handle multi-lined views. */		return NULL;	}	skip_nonspace_end(src, end);	skip_space_end(src, end);	if (src >= end) return NULL;	/* Third/Second column: Date DD-MMM-YYYY and	 * Fourth/Third column: Time hh:mm[:ss] */	/* If the server produces garbage like	 * 'EA95_0PS.GZ;1      No privilege for attempted operation'	 * parse_date() will fail. */	info->mtime = parse_date(&src, end, 1, 0);	if (info->mtime == 0)		return NULL;	/* Be more tolerant from here on ... */	/* Skip the fifth column */	skip_space_end(src, end);	skip_nonspace_end(src, end);	skip_space_end(src, end);	if (src >= end) return info;	/* Sixth column: Permissions */	src = memchr(src, '(', end - src);	if (!src || src >= end)		return info;	src++;	pos = memchr(src, ')', end - src);	if (!pos) return info;	/* Permissons have the format "RWED,RWED,RE" */	info->permissions = parse_ftp_vms_permissions(src, pos - src);	return info;}/* Parser for the MSDOS-style format: */#ifdef DEBUG_FTP_PARSERstatic unsigned char ftp_winnt_responses[] = "04-27-00  09:09PM       <DIR>          licensed\r\n" "07-18-00  10:16AM       <DIR>          pub\r\n" "04-14-00  03:47PM                  589 readme.htm\r\n";#endifstruct ftp_file_info *parse_ftp_winnt_response(struct ftp_file_info *info, unsigned char *src, int len){	struct tm mtime;	unsigned char *end = src + len;	/* Extracting name is a bit of black magic and we have to do it	 * before `strtok' inserted extra \0 characters in the line	 * string. For the moment let us just suppose that the name starts at	 * column 39 of the listing. This way we could also recognize	 * filenames that begin with a series of space characters (but who	 * really wants to use such filenames anyway?). */	if (len <= 39) return NULL;	info->name.source = src + 39;	info->name.length = end - src - 39;	/* First column: mm-dd-yy. Should number parsing of the month fail,	 * january will be assumed. */	memset(&mtime, 0, sizeof(mtime));	mtime.tm_isdst = -1;	mtime.tm_mon = parse_ftp_number(&src, end, 1, 12);	if (src + 2 >= end || *src != '-')		return NULL;	src++;	mtime.tm_mday = parse_day((const unsigned char **) &src, end);	if (src + 2 >= end || *src != '-')		return NULL;	src++;	mtime.tm_year = parse_year((const unsigned char **) &src, end);	if (src >= end || mtime.tm_year == -1)		return NULL;	skip_space_end(src, end);	if (src >= end) return NULL;	/* Second column: hh:mm[AP]M, listing does not contain value for	 * seconds */	if (!parse_time((const unsigned char **) &src, &mtime, end))		return NULL;	/* Store the time-stamp. */	info->mtime = mktime(&mtime);	skip_nonspace_end(src, end);	skip_space_end(src, end);	if (src >= end) return NULL;	/* Third column: Either file length, or <DIR>. We also set the	 * permissions (guessed as 0644 for plain files and 0755 for directories	 * as the listing does not give us a clue) and filetype here. */	if (*src == '<') {		info->type = FTP_FILE_DIRECTORY;		info->permissions = 0755;	} else if (isdigit(*src)) {		info->type = FTP_FILE_PLAINFILE;		info->size = parse_ftp_number(&src, end, 0, LONG_MAX);		info->permissions = 0644;	} else {		info->type = FTP_FILE_UNKNOWN;	}	return info;}#ifdef DEBUG_FTP_PARSERunsigned char *get_ftp_debug_parse_responses(unsigned char *buffer, int buflen){	struct string response;	if (!init_string(&response))		return NULL;	add_to_string(&response, ftp_eplf_responses);	add_to_string(&response, ftp_unix_responses);	add_to_string(&response, ftp_vms_responses);	add_to_string(&response, ftp_winnt_responses);	add_bytes_to_string(&response, buffer, buflen);	return response.source;}#endifstruct ftp_file_info *parse_ftp_file_info(struct ftp_file_info *info, unsigned char *src, int len){	assert(info && src && len > 0);	if_assert_failed return NULL;	switch (*src) {	case '+':		return parse_ftp_eplf_response(info, src, len);	case 'b':	case 'c':	case 'd':	case 'l':	case 'p':	case 's':	case '-':		break;	default:		if (memchr(src, ';', len))			return parse_ftp_vms_response(info, src, len);		if (isdigit(*src))			return parse_ftp_winnt_response(info, src, len);	}	return parse_ftp_unix_response(info, src, len);}

⌨️ 快捷键说明

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