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

📄 parse.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Parsing of FTP `ls' directory output. *//* $Id: parse.c,v 1.38.2.1 2005/04/06 09:30:31 jonas Exp $ *//* Parts of this file was part of GNU Wget * Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <errno.h>#include <stdio.h>#include <stdlib.h>#ifdef HAVE_STRING_H# include <string.h>#else# include <strings.h>#endif#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#include <sys/stat.h>#include <sys/types.h>#include "elinks.h"#include "osdep/ascii.h"#include "protocol/date.h"#include "protocol/ftp/parse.h"#include "util/conv.h"#include "util/string.h"#include "util/ttime.h"#define skip_space_end(src, end) \	do { while ((src) < (end) && isspace(*(src))) (src)++; } while (0)#define skip_nonspace_end(src, end) \	do { while ((src) < (end) && !isspace(*(src))) (src)++; } while (0)static longparse_ftp_number(unsigned char **src, unsigned char *end, long from, long to){	long number = 0;	unsigned char *pos = *src;	for (; pos < end && isdigit(*pos); pos++)		number = (*pos - '0') + 10 * number;	*src = pos;	if (number < from || to < number)		return -1;	return number;}/* Parser for the EPLF format (see http://pobox.com/~djb/proto/eplf.txt). * * Lines end with \r\n (CR-LF), but that is handled elsewhere. * * Some example EPLF response, with the filename separator (tab) displayed as a * space: */#ifdef DEBUG_FTP_PARSERstatic unsigned char ftp_eplf_responses[] = "+i8388621.48594,m825718503,r,s280,\tdjb.html\r\n" "+i8388621.50690,m824255907,/,\t514\r\n" "+i8388621.48598,m824253270,r,s612,\t514.html\r\n";#endifenum ftp_eplf {	FTP_EPLF_FILENAME	= ASCII_TAB,	/* Filename follows */	FTP_EPLF_PLAINFILE	= 'r',		/* RETR is possible */	FTP_EPLF_DIRECTORY	= '/',		/* CWD is possible */	FTP_EPLF_SIZE		= 's',		/* File size follows */	FTP_EPLF_MTIME		= 'm',		/* Modification time follows */	FTP_EPLF_ID		= 'i',		/* Unique file id follows */};static struct ftp_file_info *parse_ftp_eplf_response(struct ftp_file_info *info, unsigned char *src, int len){	/* Skip the '+'-char which starts the line. */	unsigned char *end = src + len;	unsigned char *pos = src++;	/* Handle the series of facts about the file. */	for (; src < end && pos; src = pos + 1) {		/* Find the end of the current fact. */		pos = memchr(src, ',', end - src);		if (!pos) pos = end;		switch (*src++) {		case FTP_EPLF_FILENAME:			if (src >= end) break;			info->name.source = src;			info->name.length = end - src;			return info;		case FTP_EPLF_DIRECTORY:			info->type = FTP_FILE_DIRECTORY;			break;		case FTP_EPLF_PLAINFILE:			info->type = FTP_FILE_PLAINFILE;			break;		case FTP_EPLF_SIZE:			if (src >= pos) break;			info->size = parse_ftp_number(&src, pos, 0, LONG_MAX);			break;		case FTP_EPLF_MTIME:			if (src >= pos) break;			info->mtime = (time_t) parse_ftp_number(&src, pos, 0, LONG_MAX);			break;		case FTP_EPLF_ID:			/* Not used */			break;		}	}	return NULL;}/* Parser for UNIX-style listing: */#ifdef DEBUG_FTP_PARSERstatic unsigned char ftp_unix_responses[] =  /* UNIX-style listing, without inum and without blocks: */ "-rw-r--r--   1 root     other        531 Jan 29 03:26 README\r\n" "dr-xr-xr-x   2 root     other        512 Apr  8  1994 etc\r\n" "dr-xr-xr-x   2 root     512 Apr  8  1994 et\r\nc" "lrwxrwxrwx   1 root     other          7 Jan 25 00:17 bin -> usr/bin\r\n" /* Also produced by Microsoft's FTP servers for Windows: */ "----------   1 owner    group         1803128 Jul 10 10:18 ls-lR.Z\r\n" "d---------   1 owner    group               0 May  9 19:45 Softlib\r\n" /* Also WFTPD for MSDOS: */ "-rwxrwxrwx   1 noone    nogroup      322 Aug 19  1996 message.ftp\r\n" /* Also NetWare: */ "d [R----F--] supervisor            512       Jan 16 18:53    login\r\n" "- [R----F--] rhesus             214059       Oct 20 15:27    cx.exe\r\n" /* Also NetPresenz for the Mac: */ "-------r--         326  1391972  1392298 Nov 22  1995 MegaPhone.sit\r\n" "drwxrwxr-x               folder        2 May 10  1996 network\r\n";#endifenum ftp_unix {	FTP_UNIX_PERMISSIONS,	FTP_UNIX_SIZE,	FTP_UNIX_DAY,	FTP_UNIX_TIME,	FTP_UNIX_NAME};/* Converts Un*x-style symbolic permissions to number-style ones, e.g. string * rwxr-xr-x to 755. * Borrowed from lftp source code by Alexander V. Lukyanov. * On parse error, it returns 0. */static intparse_ftp_unix_permissions(const unsigned char *src, int len){	int perms = 0;	if (len != 9	    && !(len == 10 && src[9] == '+'))   /* ACL tag */		return 0;	/* User permissions */	switch (src[0]) {	case('r'): perms |= S_IRUSR; break;	case('-'): break;	default: return 0;	}	switch (src[1]) {	case('w'): perms |= S_IWUSR; break;	case('-'): break;	default: return 0;	}	switch (src[2]) {	case('S'): perms |= S_ISUID; break;	case('s'): perms |= S_ISUID; /* fall-through */	case('x'): perms |= S_IXUSR; break;	case('-'): break;	default: return 0;	}	/* Group permissions */	switch (src[3]) {	case('r'): perms |= S_IRGRP; break;	case('-'): break;	default: return 0;	}	switch (src[4]) {	case('w'): perms |= S_IWGRP; break;	case('-'): break;	default: return 0;	}	switch (src[5]) {	case('S'): perms |= S_ISGID; break;	case('s'): perms |= S_ISGID; /* fall-through */	case('x'): perms |= S_IXGRP; break;	case('-'): break;	default: return 0;	}	/* Others permissions */	switch (src[6]) {	case('r'): perms |= S_IROTH; break;	case('-'): break;	default: return 0;	}	switch (src[7]) {	case('w'): perms |= S_IWOTH; break;	case('-'): break;	default: return 0;	}	switch (src[8]) {	case('T'): perms |= S_ISVTX; break;	case('t'): perms |= S_ISVTX; /* fall-through */	case('x'): perms |= S_IXOTH; break;	case('l'):	case('L'): perms |= S_ISGID; perms &= ~S_IXGRP; break;	case('-'): break;	default: return 0;	}	return perms;}static struct ftp_file_info *parse_ftp_unix_response(struct ftp_file_info *info, unsigned char *src, int len){	unsigned char *end = src + len;	enum ftp_file_type type = *src++;	unsigned char *pos = src;	struct tm mtime;	enum ftp_unix fact;	/* Decide the file type. */	switch (type) {	case FTP_FILE_PLAINFILE:	case FTP_FILE_DIRECTORY:	case FTP_FILE_SYMLINK:		info->type = type;		break;	default:		info->type = FTP_FILE_UNKNOWN;	}	memset(&mtime, 0, sizeof(mtime));	mtime.tm_isdst = -1;	skip_space_end(src, end);	fact = FTP_UNIX_PERMISSIONS;	for (pos = src; src < end; src = pos) {		skip_nonspace_end(pos, end);		switch (fact) {		case FTP_UNIX_PERMISSIONS:			/* We wanna know permissions as well! And I decided to			 * completely ignore the NetWare perms, they are very			 * rare and of some nonstandart format.  If you want			 * them, though, I'll accept patch enabling them.			 * --pasky */			if (pos - src == 9)	/* 9 is length of "rwxrwxrwx". */				info->permissions = parse_ftp_unix_permissions(src, 9);			fact = FTP_UNIX_SIZE;			break;		case FTP_UNIX_SIZE:			/* Search for the size and month name combo: */			if (info->size != FTP_SIZE_UNKNOWN			    && pos - src == 3) {				int month = parse_month((const unsigned char **) &src, pos);				if (month != -1) {					fact = FTP_UNIX_DAY;					mtime.tm_mon = month;					break;				}			}			if (!isdigit(*src)) {				info->size = FTP_SIZE_UNKNOWN;				break;			}			info->size = parse_ftp_number(&src, pos, 0, LONG_MAX);			break;		case FTP_UNIX_DAY:			mtime.tm_mday = parse_day((const unsigned char **) &src, pos);			fact = FTP_UNIX_TIME;			break;		case FTP_UNIX_TIME:			/* This ought to be either the time, or the			 * year. Let's be flexible! */			fact = FTP_UNIX_NAME;			/* We must deal with digits.  */			if (!isdigit (*src))				break;			/* If we have a number x, it's a year. If we have x:y,			 * it's hours and minutes. */			if (!memchr(src, ':', pos - src)) {				mtime.tm_year = parse_year((const unsigned char **) &src, pos);				break;			}			if (!parse_time((const unsigned char **) &src, &mtime, pos)) {				mtime.tm_hour = mtime.tm_min = mtime.tm_sec = 0;			}			break;		case FTP_UNIX_NAME:			/* Since the file name may contain spaces use @end as the			 * token ending and not @pos. */			info->name.source = src;			info->name.length = end - src;			/* Some FTP sites choose to have ls -F as their default			 * LIST output, which marks the symlinks with a trailing			 * `@', directory names with a trailing `/' and			 * executables with a trailing `*'. This is no problem			 * unless encountering a symbolic link ending with `@',			 * or an executable ending with `*' on a server without			 * default -F output. I believe these cases are very

⌨️ 快捷键说明

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