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

📄 bookmark.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* bookmark.c
 *
 * Copyright (c) 1992-2001 by Mike Gleason.
 * All rights reserved.
 *
 */

#include "syshdrs.h"

#include "bookmark.h"
#include "util.h"

/*
 * The ~/.ncftp/bookmarks file contains a list of sites
 * the user wants to remember.
 *
 * Unlike previous versions of the program, we now open/close
 * the file every time we need it;  That way we can have
 * multiple ncftp processes changing the file.  There is still
 * a possibility that two different processes could be modifying
 * the file at the same time.
 */

Bookmark gBm;
int gLoadedBm = 0;
int gBookmarkMatchMode = 0;
int gNumBookmarks = 0;
BookmarkPtr gBookmarkTable = NULL;

extern char gOurDirectoryPath[];

/* Converts a pre-loaded Bookmark structure into a RFC 1738
 * Uniform Resource Locator.
 */
void
BookmarkToURL(BookmarkPtr bmp, char *url, size_t urlsize)
{
	char pbuf[32];

	/* //<user>:<password>@<host>:<port>/<url-path> */
	/* Note that if an absolute path is given,
	 * you need to escape the first entry, i.e. /pub -> %2Fpub
	 */
	(void) Strncpy(url, "ftp://", urlsize);
	if (bmp->user[0] != '\0') {
		(void) Strncat(url, bmp->user, urlsize);
		if (bmp->pass[0] != '\0') {
			(void) Strncat(url, ":", urlsize);
			(void) Strncat(url, "PASSWORD", urlsize);
		}
		(void) Strncat(url, "@", urlsize);
	}
	(void) Strncat(url, bmp->name, urlsize);
	if (bmp->port != 21) {
		(void) sprintf(pbuf, ":%u", (unsigned int) bmp->port);
		(void) Strncat(url, pbuf, urlsize);
	}
	if (bmp->dir[0] == '/') {
		/* Absolute URL path, must escape first slash. */
		(void) Strncat(url, "/%2F", urlsize);
		(void) Strncat(url, bmp->dir + 1, urlsize);
		(void) Strncat(url, "/", urlsize);
	} else if (bmp->dir[0] != '\0') {
		(void) Strncat(url, "/", urlsize);
		(void) Strncat(url, bmp->dir, urlsize);
		(void) Strncat(url, "/", urlsize);
	}
}	/* BookmarkToURL */




void
SetBookmarkDefaults(BookmarkPtr bmp)
{
	(void) memset(bmp, 0, sizeof(Bookmark));

	bmp->xferType = 'I';
	bmp->xferMode = 'S';	/* Use FTP protocol default as ours too. */
	bmp->hasSIZE = kCommandAvailabilityUnknown;
	bmp->hasMDTM = kCommandAvailabilityUnknown;
	bmp->hasUTIME = kCommandAvailabilityUnknown;
	bmp->hasPASV = kCommandAvailabilityUnknown;
	bmp->isUnix = 1;
	bmp->lastCall = (time_t) 0;
	bmp->deleted = 0;
}	/* SetBookmarkDefaults */




/* Used when converting hex strings to integral types. */
static int
HexCharToNibble(int c)
{
	switch (c) {
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			return (c - '0');
		case 'a':
		case 'b':
		case 'c':
		case 'd':
		case 'e':
		case 'f':
			return (c - 'a' + 10);
		case 'A':
		case 'B':
		case 'C':
		case 'D':
		case 'E':
		case 'F':
			return (c - 'A' + 10);

	}
	return (-1);	/* Error. */
}	/* HexCharToNibble */





/* Fills in a Bookmark structure based off of a line from the NcFTP
 * "bookmarks" file.
 */
int
ParseHostLine(char *line, BookmarkPtr bmp)
{
	char token[128];
	char pass[128];
	char *s, *d;
	char *tokenend;
	long L;
	int i;
	int result;
	int n, n1, n2;

	SetBookmarkDefaults(bmp);
	s = line;
	tokenend = token + sizeof(token) - 1;
	result = -1;
	for (i=1; ; i++) {
		if (*s == '\0')
			break;
		/* Some tokens may need to have a comma in them.  Since this is a
		 * field delimiter, these fields use \, to represent a comma, and
		 * \\ for a backslash.  This chunk gets the next token, paying
		 * attention to the escaped stuff.
		 */
		for (d = token; *s != '\0'; ) {
			if ((*s == '\\') && (s[1] != '\0')) {
				if (d < tokenend)
					*d++ = s[1];
				s += 2;
			} else if (*s == ',') {
				++s;
				break;
			} else if ((*s == '$') && (s[1] != '\0') && (s[2] != '\0')) {
				n1 = HexCharToNibble(s[1]);
				n2 = HexCharToNibble(s[2]);
				if ((n1 >= 0) && (n2 >= 0)) {
					n = (n1 << 4) | n2;
					if (d < tokenend)
						*(unsigned char *)d++ = (unsigned int) n;
				}
				s += 3;
			} else {
				if (d < tokenend)
					*d++ = *s;
				++s;
			}
		}
		*d = '\0';
		switch(i) {
			case 1: (void) STRNCPY(bmp->bookmarkName, token); break;
			case 2: (void) STRNCPY(bmp->name, token); break;
			case 3: (void) STRNCPY(bmp->user, token); break;
			case 4: (void) STRNCPY(bmp->pass, token); break;
			case 5: (void) STRNCPY(bmp->acct, token); break;
			case 6: (void) STRNCPY(bmp->dir, token);
					result = 0;		/* Good enough to have these fields. */
					break;
			case 7:
				if (token[0] != '\0')
					bmp->xferType = (int) token[0];
				break;
			case 8:
				/* Most of the time, we won't have a port. */
				if (token[0] == '\0')
					bmp->port = (unsigned int) kDefaultFTPPort;
				else
					bmp->port = (unsigned int) atoi(token);
				break;
			case 9:
				(void) sscanf(token, "%lx", &L);
				bmp->lastCall = (time_t) L;
				break;
			case 10: bmp->hasSIZE = atoi(token); break;
			case 11: bmp->hasMDTM = atoi(token); break;
			case 12: bmp->hasPASV = atoi(token); break;
			case 13: bmp->isUnix = atoi(token);
					result = 3;		/* Version 3 had all fields to here. */
					break;
			case 14: (void) STRNCPY(bmp->lastIP, token); break;
			case 15: (void) STRNCPY(bmp->comment, token); break;
			case 16:
			case 17:
			case 18:
			case 19:
				break;
			case 20: bmp->xferMode = token[0];
					result = 7;		/* Version 7 has all fields to here. */
					break;
			case 21: bmp->hasUTIME = atoi(token);
					break;
			case 22: (void) STRNCPY(bmp->ldir, token);
					result = 8;		/* Version 8 has all fields to here. */
					break;
			default:
					result = 99;	/* Version >8 ? */
					goto done;
		}
	}
done:

	/* Decode password, if it was base-64 encoded. */
	if (strncmp(bmp->pass, kPasswordMagic, kPasswordMagicLen) == 0) {
		FromBase64(pass, bmp->pass + kPasswordMagicLen, strlen(bmp->pass + kPasswordMagicLen), 1);
		(void) STRNCPY(bmp->pass, pass);
	}
	return (result);
}	/* ParseHostLine */




void
CloseBookmarkFile(FILE *fp)
{
	if (fp != NULL)
		(void) fclose(fp);
}	/* CloseBookmarkFile */





int
GetNextBookmark(FILE *fp, Bookmark *bmp)
{
	char line[512];

	while (FGets(line, sizeof(line), fp) != NULL) {
		if (ParseHostLine(line, bmp) >= 0)
			return (0);
	}
	return (-1);
}	/* GetNextBookmark */




/* Opens a NcFTP 2.x or 3.x style bookmarks file, and sets the file pointer
 * so that it is ready to read the first data line.
 */
FILE *
OpenBookmarkFile(int *numBookmarks0)
{
	char pathName[256], path2[256];
	char line[256];
	FILE *fp;
	int version;
	int numBookmarks;
	Bookmark junkbm;

	if (gOurDirectoryPath[0] == '\0')
		return NULL;		/* Don't create in root directory. */
	(void) OurDirectoryPath(pathName, sizeof(pathName), kBookmarkFileName);
	fp = fopen(pathName, FOPEN_READ_TEXT);
	if (fp == NULL) {
		/* See if it exists under the old name. */
		(void) OurDirectoryPath(path2, sizeof(path2), kOldBookmarkFileName);
		if (rename(path2, pathName) == 0) {
			/* Rename succeeded, now open it. */
			fp = fopen(pathName, FOPEN_READ_TEXT);
			if (fp == NULL)
				return NULL;
		}
		return NULL;		/* Okay to not have one yet. */
	}

	(void) chmod(pathName, 00600);
	if (FGets(line, sizeof(line), fp) == NULL) {
		(void) fprintf(stderr, "%s: invalid format.\n", pathName);
		(void) fclose(fp);
		return NULL;
	}

	/* Sample line we're looking for:
	 * "NcFTP bookmark-file version: 8"
	 */
	version = -1;
	(void) sscanf(line, "%*s %*s %*s %d", &version);
	if (version < kBookmarkMinVersion) {
		if (version < 0) {
			(void) fprintf(stderr, "%s: invalid format, or bad version.\n", pathName);
			(void) fclose(fp);
			return NULL;
		}
		(void) STRNCPY(path2, pathName);
		(void) sprintf(line, ".v%d", version);
		(void) STRNCAT(path2, line);
		(void) rename(pathName, path2);
		(void) fprintf(stderr, "%s: old version.\n", pathName);
		(void) fclose(fp);
		return NULL;
	}

	/* Sample line we're looking for:
	 * "Number of entries: 28" or "# # # 1"
	 */
	numBookmarks = -1;

	/* At the moment, we can't trust the number stored in the
	 * file.  It's there for future use.
	 */
	if (FGets(line, sizeof(line), fp) == NULL) {
		(void) fprintf(stderr, "%s: invalid format.\n", pathName);
		(void) fclose(fp);
		return NULL;
	}

	if (numBookmarks0 == (int *) 0) {
		/* If the caller doesn't care how many bookmarks are *really*
		 * in the file, then we can return now.
		 */
		return(fp);
	}

	/* Otherwise, we have to read through the whole file because
	 * unfortunately the header line can't be trusted.
	 */
	for (numBookmarks = 0; ; numBookmarks++) {
		if (GetNextBookmark(fp, &junkbm) < 0)
			break;
	}

	/* Now we have to re-open and re-position the file.
	 * We don't use rewind() because it doesn't always work.
	 * This introduces a race condition, but the bookmark
	 * functionality wasn't designed to be air-tight.
	 */
	CloseBookmarkFile(fp);
	fp = fopen(pathName, FOPEN_READ_TEXT);
	if (fp == NULL)
		return (NULL);
	if (FGets(line, sizeof(line), fp) == NULL) {
		(void) fprintf(stderr, "%s: invalid format.\n", pathName);
		(void) fclose(fp);
		return NULL;
	}

	if (FGets(line, sizeof(line), fp) == NULL) {
		(void) fprintf(stderr, "%s: invalid format.\n", pathName);
		(void) fclose(fp);
		return NULL;
	}

	/* NOW we're done. */
	*numBookmarks0 = numBookmarks;
	return (fp);
}	/* OpenBookmarkFile */




/* Looks for a saved bookmark by the abbreviation given. */
int
GetBookmark(const char *const bmabbr, Bookmark *bmp)
{
	FILE *fp;
	char line[512];
	Bookmark byHostName;
	Bookmark byHostAbbr;
	Bookmark byBmAbbr;
	size_t byBmNameFlag = 0;
	size_t byBmAbbrFlag = 0;
	size_t byHostNameFlag = 0;
	size_t byHostAbbrFlag = 0;
	int result = -1;
	int exactMatch = 0;
	size_t bmabbrLen;
	char *cp;

	fp = OpenBookmarkFile(NULL);
	if (fp == NULL)
		return (-1);

	bmabbrLen = strlen(bmabbr);
	while (FGets(line, sizeof(line), fp) != NULL) {
		if (ParseHostLine(line, bmp) < 0)
			continue;
		if (ISTREQ(bmp->bookmarkName, bmabbr)) {
			/* Exact match, done. */
			byBmNameFlag = bmabbrLen;
			exactMatch = 1;
			break;
		} else if (ISTRNEQ(bmp->bookmarkName, bmabbr, bmabbrLen)) {
			/* Remember this one, it matched an abbreviated
			 * bookmark name.
			 */
			byBmAbbr = *bmp;
			byBmAbbrFlag = bmabbrLen;
		} else if (ISTREQ(bmp->name, bmabbr)) {
			/* Remember this one, it matched a full

⌨️ 快捷键说明

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