示例#1
0
// FXPONE|HOST=127.0.0.1|PORT=8885|USER=admin|SSL=forced|TIMEFILE=name
void conf_fxpone(char **keys, char **values, int items,void *optarg)
{
	char *host, *port, *user, *pass, *ssl, *timefile;
	fxpone_t *fxpone;

	host     = parser_findkey(keys, values, items, "HOST");
	port     = parser_findkey(keys, values, items, "PORT");
	user     = parser_findkey(keys, values, items, "USER");
	pass     = parser_findkey(keys, values, items, "PASS");
	ssl      = parser_findkey(keys, values, items, "SSL");
	timefile = parser_findkey(keys, values, items, "TIMEFILE");

	if (!host) {
		printf("FXPONE Entry in conf without HOST= field\n");
		return;
	}

    // Don't need to save anymore
#if 0
	if (optarg) {
		// Saving
		lion_printf(optarg, "FXPONE|HOST=%s", host);
		if (port) lion_printf(optarg, "|PORT=%s", port);
		if (user) lion_printf(optarg, "|USER=%s", user);
		if (pass) lion_printf(optarg, "|PASS=%s", pass);
		if (ssl)  lion_printf(optarg, "|ssl=%s",  ssl);
		lion_printf(optarg, "\r\n");
		return;
	}
#endif

	// Create a new fxpone engine to connect to.
	fxpone = fxpone_newnode();
	if (!fxpone) return;


	SAFE_COPY(fxpone->host, host);
	SAFE_COPY(fxpone->user, user);
	SAFE_COPY(fxpone->pass, pass);
	if (port)
		fxpone->port = atoi(port);
	else
		fxpone->port = 8885;

	if (ssl)
		fxpone->ssl = atoi(ssl);

    SAFE_COPY(fxpone->timefile, timefile);
}
示例#2
0
文件: sites.c 项目: lundman/FXP.One
void sites_setkey(char *key)
{

	if (key && !*key)
		key = NULL;

	SAFE_COPY(sites_key, key);

}
示例#3
0
文件: file.c 项目: lundman/FXP.One
//
// Take src-file node AND
// dst-file node, to populate the dst-file node with
// appropriate information.
//
// If dst "fullpath" is set, we trust it. if not
// copy over the "name" from source, and build from that.
//
void file_makedest(file_t *dst, file_t *src, char *cwd)
{

	if (!dst->fullpath && !dst->name)
		SAFE_COPY(dst->name, src->name);

	file_makepath(dst, cwd);

	dst->directory = src->directory;
	dst->soft_link = src->soft_link;

}
示例#4
0
文件: file.c 项目: lundman/FXP.One
void file_dupe(file_t *dst, file_t *src)
{

	SAFE_COPY(dst->name,     src->name);
	SAFE_COPY(dst->fullpath, src->fullpath);
	SAFE_COPY(dst->dirname,  src->dirname);
	SAFE_COPY(dst->user,     src->user);
	SAFE_COPY(dst->group,    src->group);

	SAFE_COPY(dst->raw,      src->raw);

	memcpy(&dst->perm, src->perm, sizeof(dst->perm));

	dst->date      = src->date;
	dst->size      = src->size;
	dst->rest      = src->rest;
	dst->directory = src->directory;
	dst->soft_link = src->soft_link;

}
示例#5
0
文件: file.c 项目: lundman/FXP.One
//
// If "fullpath" is set, then we trust it is correct and fill in the
// "name" and "dirname" sections.
//
// If "fullpath" is not set, we combine "name" and "dirname" to be "fullpath".
//
void file_makepath(file_t *file, char *cwd)
{
	char *r;

	if (file->fullpath) {
		// Create name and dirname.

		r = strrchr(file->fullpath, '/');

		if (!r) { // Shouldn't happen as fullpath should be _full path_
			SAFE_COPY(file->dirname, "/");
			SAFE_COPY(file->name, file->fullpath);
			return;
		}

		*r = 0;
		if (*file->fullpath) {
			SAFE_COPY(file->dirname, file->fullpath);
		} else {
			SAFE_COPY(file->dirname, "/");
		}

		SAFE_COPY(file->name, &r[1]);

		*r = '/';
		return;
	}

	// fullpath not set.
	if (cwd && file->name) {
		SAFE_FREE(file->fullpath);
		file->fullpath = misc_strjoin(cwd, file->name);
		SAFE_COPY(file->dirname, cwd);
	} else if (file->dirname && file->name) {
		SAFE_FREE(file->fullpath);
		file->fullpath = misc_strjoin(file->dirname, file->name);
	} else {
		debugf("[file] can't file_makepath\n");
	}
}
示例#6
0
void arguments(int argc, char **argv)
{
	int opt;

	while ((opt=getopt(argc, argv,
					   "hf:a:i:I:qnvdC:")) != -1) {

		switch(opt) {

		case 'h':
			options(argv[0]);
			break;

		case 'f':
			SAFE_COPY(conf_file_name, optarg);
			break;

		case 'a':
			default_age = strtoul(optarg, NULL, 10);
			break;

		case 'i':
			SAFE_COPY(conf_incpattern, optarg);
			break;

		case 'I':
			SAFE_COPY(conf_autoqpattern, optarg);
			break;

		case 'q':
			conf_do_autoq ^= 1;
			break;

		case 'n':
			conf_do_save ^= 1;
			break;

		case 'v':
			conf_do_verbose ^= 1;
			break;

		case 'd':
			debug_on ^= 1;
			break;

		case 'C':
			lion_ssl_ciphers(optarg);
			break;

		default:
			printf("Unknown option.\n");
			break;
		}
	}

	argc -= optind;
	argv += optind;

	// argc and argv adjusted here.
	if (!conf_file_name)
		conf_file_name = strdup("clomps.conf");
}
示例#7
0
//SITE|NAME=foo|DIR=/tv/|USESKIP=1|INCTEST=%s-INCOMPLETE|LAST_CHECK=123123123
//NUKETEST=!NUKED-%s
void conf_site(char **keys, char **values, int items,void *optarg)
{
	char *name, *dir, *useskip, *inctest, *nuketest, *last_check, *hide;
	site_t *site, **tmp;
	char **dtmp;
    char *strtmp;
    int i;

	name       = parser_findkey(keys, values, items, "NAME");
	useskip    = parser_findkey(keys, values, items, "USESKIP");
	inctest    = parser_findkey(keys, values, items, "INCTEST");
	nuketest   = parser_findkey(keys, values, items, "NUKETEST");
	hide       = parser_findkey(keys, values, items, "HIDE");
	last_check = parser_findkey(keys, values, items, "LAST_CHECK");

	if (!name) {
		printf("SITE Entry in conf without NAME= field\n");
		return;
	}

    // Attempt to find a site already defined by name, if found, allow
    // HIDE to be concatenated.
    for (i = 0; i < num_sites; i++) {
        if (sites[i] && !mystrccmp(name, sites[i]->name)) {
            if (hide) {
                if (!sites[i]->hide) {
                    SAFE_COPY(sites[i]->hide, hide);
                } else {
                    strtmp = sites[i]->hide;
                    sites[i]->hide = misc_strjoin(strtmp?strtmp:"", hide);
                    SAFE_FREE(strtmp);
                }
            }
            return;
        }
    }

	site = calloc(1, sizeof(*site));
	if (!site) return;

	tmp = realloc(sites, sizeof(site_t *) * (num_sites + 1));
	if (!tmp) return;
	sites = tmp;

	sites[num_sites] = site;
	num_sites++;

	SAFE_COPY(site->name, name);

	while ((dir = parser_findkey_once(keys, values, items, "DIR"))) {
		dtmp = (char **) realloc(site->dirs,
								 sizeof(char *) * (site->num_dirs + 1));
		if (!dtmp) break;

		site->dirs = dtmp;

		site->dirs[ site->num_dirs ] = strdup(dir);
		site->num_dirs++;

	}

	SAFE_COPY(site->inctest, inctest);
	SAFE_COPY(site->nuketest, nuketest);
	SAFE_COPY(site->hide, hide);
	if (useskip)
		site->use_lists = atoi(useskip);
	if (last_check) {
		site->last_check = strtoul(last_check, NULL, 10);
		site->last_check -= default_age;
	} else {
		site->last_check = lion_global_time;
		site->last_check -= default_age;
	}


    site->num_files = 0;
}
static fz_error
evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr)
{
	fz_error error;
	int i1, i2;
	float r1, r2;
	int b1, b2;

	while (1)
	{
		switch (func->u.p.code[codeptr].type)
		{
		case PSINT:
			SAFE_PUSHINT(st, func->u.p.code[codeptr++].u.i);
			break;

		case PSREAL:
			SAFE_PUSHREAL(st, func->u.p.code[codeptr++].u.f);
			break;

		case PSOPERATOR:
			switch (func->u.p.code[codeptr++].u.op)
			{
			case PSOABS:
				if (pstopisint(st)) {
					SAFE_POPINT(st, &i1);
					SAFE_PUSHINT(st, abs(i1));
				}
				else {
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, fabs(r1));
				}
				break;

			case PSOADD:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHINT(st, i1 + i2);
				}
				else {
					SAFE_POPNUM(st, &r2);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, r1 + r2);
				}
				break;

			case PSOAND:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHINT(st, i1 & i2);
				}
				else {
					SAFE_POPBOOL(st, &b2);
					SAFE_POPBOOL(st, &b1);
					SAFE_PUSHBOOL(st, b1 && b2);
				}
				break;

			case PSOATAN:
				SAFE_POPNUM(st, &r2);
				SAFE_POPNUM(st, &r1);
				SAFE_PUSHREAL(st, atan2(r1, r2)*RADIAN);
				break;

			case PSOBITSHIFT:
				SAFE_POPINT(st, &i2);
				SAFE_POPINT(st, &i1);
				if (i2 > 0) {
					SAFE_PUSHINT(st, i1 << i2);
				}
				else if (i2 < 0) {
					SAFE_PUSHINT(st, (int)((unsigned int)i1 >> i2));
				}
				else {
					SAFE_PUSHINT(st, i1);
				}
				break;

			case PSOCEILING:
				if (!pstopisint(st)) {
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, ceil(r1));
				}
				break;

			case PSOCOPY:
				SAFE_POPINT(st, &i1);
				SAFE_COPY(st, i1);
				break;

			case PSOCOS:
				SAFE_POPNUM(st, &r1);
				SAFE_PUSHREAL(st, cos(r1/RADIAN));
				break;

			case PSOCVI:
				if (!pstopisint(st)) {
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHINT(st, (int)r1);
				}
				break;

			case PSOCVR:
				if (!pstopisreal(st)) {
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, r1);
				}
				break;

			case PSODIV:
				SAFE_POPNUM(st, &r2);
				SAFE_POPNUM(st, &r1);
				SAFE_PUSHREAL(st, r1 / r2);
				break;

			case PSODUP:
				SAFE_COPY(st, 1);
				break;

			case PSOEQ:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHBOOL(st, i1 == i2);
				}
				else if (pstoptwoarenums(st)) {
					SAFE_POPNUM(st, &r1);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHBOOL(st, r1 == r2);
				}
				else {
					SAFE_POPBOOL(st, &b2);
					SAFE_POPBOOL(st, &b2);
					SAFE_PUSHBOOL(st, b1 == b2);
				}
				break;

			case PSOEXCH:
				psroll(st, 2, 1);
				break;

			case PSOEXP:
				SAFE_POPNUM(st, &r2);
				SAFE_POPNUM(st, &r1);
				SAFE_PUSHREAL(st, pow(r1, r2));
				break;

			case PSOFALSE:
				SAFE_PUSHBOOL(st, 0);
				break;

			case PSOFLOOR:
				if (!pstopisint(st)) {
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, floor(r1));
				}
				break;

			case PSOGE:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHBOOL(st, i1 >= i2);
				}
				else {
					SAFE_POPNUM(st, &r2);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHBOOL(st, r1 >= r2);
				}
				break;

			case PSOGT:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHBOOL(st, i1 > i2);
				}
				else {
					SAFE_POPNUM(st, &r2);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHBOOL(st, r1 > r2);
				}
				break;

			case PSOIDIV:
				SAFE_POPINT(st, &i2);
				SAFE_POPINT(st, &i1);
				SAFE_PUSHINT(st, i1 / i2);
				break;

			case PSOINDEX:
				SAFE_POPINT(st, &i1);
				SAFE_INDEX(st, i1);
				break;

			case PSOLE:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHBOOL(st, i1 <= i2);
				}
				else {
					SAFE_POPNUM(st, &r2);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHBOOL(st, r1 <= r2);
				}
				break;

			case PSOLN:
				SAFE_POPNUM(st, &r1);
				SAFE_PUSHREAL(st, log(r1));
				break;

			case PSOLOG:
				SAFE_POPNUM(st, &r1);
				SAFE_PUSHREAL(st, log10(r1));
				break;

			case PSOLT:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHBOOL(st, i1 < i2);
				}
				else {
					SAFE_POPNUM(st, &r2);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHBOOL(st, r1 < r2);
				}
				break;

			case PSOMOD:
				SAFE_POPINT(st, &i2);
				SAFE_POPINT(st, &i1);
				SAFE_PUSHINT(st, i1 % i2);
				break;

			case PSOMUL:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					/* FIXME should check for out-of-range, and push a real instead */
					SAFE_PUSHINT(st, i1 * i2);
				}
				else {
					SAFE_POPNUM(st, &r2);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, r1 * r2);
				}
				break;

			case PSONE:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHBOOL(st, i1 != i2);
				}
				else if (pstoptwoarenums(st)) {
					SAFE_POPNUM(st, &r2);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHBOOL(st, r1 != r2);
				}
				else {
					SAFE_POPBOOL(st, &b2);
					SAFE_POPBOOL(st, &b1);
					SAFE_PUSHBOOL(st, b1 != b2);
				}
				break;

			case PSONEG:
				if (pstopisint(st)) {
					SAFE_POPINT(st, &i1);
					SAFE_PUSHINT(st, -i1);
				}
				else {
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, -r1);
				}
				break;

			case PSONOT:
				if (pstopisint(st)) {
					SAFE_POPINT(st, &i1);
					SAFE_PUSHINT(st, ~i1);
				}
				else {
					SAFE_POPBOOL(st, &b1);
					SAFE_PUSHBOOL(st, !b1);
				}
				break;

			case PSOOR:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHINT(st, i1 | i2);
				}
				else {
					SAFE_POPBOOL(st, &b2);
					SAFE_POPBOOL(st, &b1);
					SAFE_PUSHBOOL(st, b1 || b2);
				}
				break;

			case PSOPOP:
				SAFE_POP(st);
				break;

			case PSOROLL:
				SAFE_POPINT(st, &i2);
				SAFE_POPINT(st, &i1);
				psroll(st, i1, i2);
				break;

			case PSOROUND:
				if (!pstopisint(st)) {
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, (r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5));
				}
				break;

			case PSOSIN:
				SAFE_POPNUM(st, &r1);
				SAFE_PUSHREAL(st, sin(r1/RADIAN));
				break;

			case PSOSQRT:
				SAFE_POPNUM(st, &r1);
				SAFE_PUSHREAL(st, sqrt(r1));
				break;

			case PSOSUB:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHINT(st, i1 - i2);
				}
				else {
					SAFE_POPNUM(st, &r2);
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, r1 - r2);
				}
				break;

			case PSOTRUE:
				SAFE_PUSHBOOL(st, 1);
				break;

			case PSOTRUNCATE:
				if (!pstopisint(st)) {
					SAFE_POPNUM(st, &r1);
					SAFE_PUSHREAL(st, (r1 >= 0) ? floor(r1) : ceil(r1));
				}
				break;

			case PSOXOR:
				if (pstoptwoareints(st)) {
					SAFE_POPINT(st, &i2);
					SAFE_POPINT(st, &i1);
					SAFE_PUSHINT(st, i1 ^ i2);
				}
				else {
					SAFE_POPBOOL(st, &b2);
					SAFE_POPBOOL(st, &b1);
					SAFE_PUSHBOOL(st, b1 ^ b2);
				}
				break;

			case PSOIF:
				SAFE_POPBOOL(st, &b1);
				if (b1) {
					error = evalpostscriptfunc(func, st, codeptr + 2);
					if (error)
						return fz_rethrow(error, "runtime error in if-branch");
				}
				codeptr = func->u.p.code[codeptr + 1].u.block;
				break;

			case PSOIFELSE:
				SAFE_POPBOOL(st, &b1);
				if (b1) {
					error = evalpostscriptfunc(func, st, codeptr + 2);
					if (error)
						return fz_rethrow(error, "runtime error in if-branch");
				}
				else {
					error = evalpostscriptfunc(func, st, func->u.p.code[codeptr].u.block);
					if (error)
						return fz_rethrow(error, "runtime error in else-branch");
				}
				codeptr = func->u.p.code[codeptr + 1].u.block;
				break;

			case PSORETURN:
				return fz_okay;

			default:
				return fz_throw("foreign operator in calculator function");
			}
			break;

		default:
			return fz_throw("foreign object in calculator function");
		}
示例#9
0
void TCLinkSend(TCLinkHandle handle)
{
	param *p, *next;
	char buf[TC_BUFF_MAX], destbuf[TC_LINE_MAX];
	char buf2[1024];
	int host_hash = 1;
	int retval = 0;

	TCLinkCon *c = (TCLinkCon *)handle;

	ClearRecvList(c);

	/* build most of the string we will send to the processor */
	sprintf(buf, "BEGIN\nversion=%s\n", tclink_version);

	for (p = c->send_param_list; p; p = next)
	{
		next = p->next;
		SAFE_COPY(buf2, p->name);
		SAFE_APPEND(buf2, "=");
		SAFE_APPEND(buf2, p->value);
		SAFE_APPEND(buf2, "\n");
		SAFE_APPEND(buf, buf2);
		if (!strcasecmp(p->name, "custid")) {
			host_hash = atoi(p->value);
			host_hash = (host_hash / 100) + (host_hash % 100);
		}
		free(p->name);
		free(p->value);
		free(p);
	}

	c->send_param_list = c->send_param_tail = NULL;

	/* try to make the connection */
	if (!Connect(c, host_hash))
	{
		Close(c);  /* clean up any memory Connect() may have left lying around */
		AddRecvParam(c, "status", "error");
		AddRecvParam(c, "errortype", "cantconnect");
		return;
	}

	/* append some data about the connection */
	sprintf(buf+strlen(buf), "pass=%d\ntime=%ld\n", c->pass, time(0) - c->start_time);
	if (c->dns != 1) SAFE_APPEND(buf, "dns=n\n");
	SAFE_APPEND(buf, "END\n");

	/* send the data */
	if (Send(c, buf))
	{
		int state = 0;
		buf[0] = destbuf[0] = 0;          /* recycle buf */
		c->is_error = 0;
		while (1)
		{
			int len = ReadLine(c, buf, destbuf);
			if (len == 0) continue;
			if (len < 0) break;
			if (strcasecmp(destbuf, "BEGIN") == 0)
			{
				if (state != 0)
					{ state = -1; break; }
				state = 1;
			}
			else if (strcasecmp(destbuf, "END") == 0)
			{
				if (state != 1)
					state = -1;
				else
					state = 2;
				break;
			}
			else
			{
				if (state != 1 || !AddRecvString(c, destbuf))
					{ state = -1; break; }
			}
		}
		if (state == 2)
			retval = 1;
	}

	Close(c);

	if (!retval)
	{
		ClearRecvList(c);
		AddRecvParam(c, "status", "error");
		AddRecvParam(c, "errortype", "linkfailure");
	}
}
示例#10
0
文件: sites.c 项目: lundman/FXP.One
//
// Take a argc/argv pair, parse out the required fields for a site
// then save any optional fields for GUIs.
//
// Return standard error codes, or 0 for success.
//
int sites_parsekeys(char **keys, char **values, int items, sites_t *node)
{
	int i, len;
	int xitems;
	unsigned long set = 0;  // make sure we have seen all required fields.

	xitems = items;

#ifdef DEBUG_VERBOSE
	debugf("[sites_parsekeys] parsing for %p\n", node);
#endif

	for (i = 0; i < items; i++) {

		// Empty key, just loop
		if (!keys[i]) continue;

		len = strlen(keys[i]);

#define tester(X) ((sizeof((X))-1 == len) && !strcasecmp(keys[i], (X)))

		// REQUIRED
		if (tester("name")) {
			if (!values[i]) return 1504; // Missing required field
			SAFE_COPY(node->name, values[i]);
			keys[i] = NULL;
			xitems--;
			set |= 1;
		} else if (tester("host")) {
			if (!values[i]) return 1504;
			SAFE_COPY(node->host, values[i]);
			keys[i] = NULL;
			xitems--;
			set |= 2;
		} else if (tester("user")) {
			if (!values[i]) return 1504;
			SAFE_COPY(node->user, values[i]);
			keys[i] = NULL;
			xitems--;
			set |= 4;
		} else if (tester("pass")) {
			if (!values[i]) return 1504;
			SAFE_COPY(node->pass, values[i]);
			keys[i] = NULL;
			xitems--;
			set |= 8;

			// OPTIONAL
		} else if (tester("port")) {
			if (!values[i]) continue;
			node->port = atoi(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("passive")) {
			if (!values[i]) continue;
			node->passive = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("fxp_passive")) {
			if (!values[i]) continue;
			node->fxp_passive = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("control_TLS")) {
			if (!values[i]) continue;
			node->control_TLS = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("data_TLS")) {
			if (!values[i]) continue;
			node->data_TLS = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("iface")) {  // FIXME!! Use char *
			if (!values[i]) continue;
			node->iface = lion_addr(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("iport")) {
			if (!values[i]) continue;
			node->iport = atoi(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("desired_type")) {
			if (!values[i]) continue;
			node->desired_type = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("resume")) {
			if (!values[i]) continue;
			node->resume = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("resume_last")) {
			if (!values[i]) continue;
			node->resume_last = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("pret")) {
			if (!values[i]) continue;
			node->pret = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("fskiplist")) {
			if (!values[i]) {
				SAFE_FREE(node->file_skiplist);
				continue;
			}
			SAFE_COPY(node->file_skiplist, values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("dskiplist")) {
			if (!values[i]) {
				SAFE_FREE(node->directory_skiplist);
				continue;
			}
			SAFE_COPY(node->directory_skiplist, values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("fpasslist")) {
			if (!values[i]) {
				SAFE_FREE(node->file_passlist);
				continue;
			}
			SAFE_COPY(node->file_passlist, values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("dpasslist")) {
			if (!values[i]) {
				SAFE_FREE(node->directory_passlist);
				continue;
			}
			SAFE_COPY(node->directory_passlist, values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("fskipempty")) {
			if (!values[i]) continue;
			node->file_skipempty = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("dskipempty")) {
			if (!values[i]) continue;
			node->directory_skipempty = str2yna(values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("fmovefirst")) {
			if (!values[i]) {
				SAFE_FREE(node->file_movefirst);
				continue;
			}
			SAFE_COPY(node->file_movefirst, values[i]);
			keys[i] = NULL;
			xitems--;
		} else if (tester("dmovefirst")) {
			if (!values[i]) {
				SAFE_FREE(node->directory_movefirst);
				continue;
			}
			SAFE_COPY(node->directory_movefirst, values[i]);
			keys[i] = NULL;
			xitems--;


			// Parser adds the "type" field to say what command we were
			// so we had better take it out.
		} else if (tester("type")) {
			keys[i] = NULL;
			xitems--;
		} else if (tester("SITEID")) {
			keys[i] = NULL;
			xitems--;
		}


#undef tester

	}


#ifdef DEBUG_VERBOSE
	debugf("[sites_parsekeys] saw fields %lu.\n", set);
#endif

	// Check if we saw all required fields.
	// name, host, user and pass.

	// Save any left over fields
	// Subtract the number of matched fields, and allocate the arrays to
	// hold the remainding.

	if (xitems) {

#ifdef DEBUG_VERBOSE
		debugf("[sites] %d items remaining..\r\n", xitems);
#endif

		// We want to keep/copy the old key/pairs, and check against fields
		// given to remove some, or add new.

		// Find key/value to delete.
		if (node->items && node->keys) {
			for (i = 0; i < items; i++) {
				if (keys[i] && (!values[i] || !values[i][0])) {

					// Look for keys[i] in the site's keys. If it finds it
					// it sets it to NULL. (Delete). We also wipe it from
					// keys to not consider it as an addition.
					parser_findkey_once(node->keys, node->values,
										node->items,
										keys[i]);

					keys[i] = NULL;
					xitems--;
				}
			}
		}

		// All other remaining key/pairs are either changes, or, additions.
		// Do we need to allocate more space?
		if (xitems > node->items) {
			char **tmp;

			tmp  = (char **) realloc(node->keys,
									 sizeof(char *) * xitems);
			if (!tmp) return 401; // Out of memory
			node->keys = tmp;

			tmp  = (char **) realloc(node->values,
									 sizeof(char *) * xitems);
			if (!tmp) return 401; // Out of memory
			node->values = tmp;
		}

		//node->items = xitems;

		// Assign in...
		for (i = 0; i < items; i++) {
			int j, empty;

			if (keys[i] && values[i]) {

				// Still set, we should save it.
				// Attempt to find it, in node->keys
				for (j = 0, empty = -1;
					 j < node->items; j++) {

					// If a key position is empty, remember it
					if (!node->keys[j]) {
						if (empty < 0) empty = j;
						continue; // It's empty, don't bother comparing below
					}

					if (!strcasecmp(keys[i], node->keys[j])) {
						// Key exists, just copy over the new value.
						SAFE_DUPE(node->values[j], values[i]);
						break;
					}
				}

				// Didn't find it? If so add it.
				if (j >= node->items) {
					// Did we not find an empty slot?
					if (empty == -1) {
						empty = node->items;

						// Add more space.
						node->items++;
						char **tmp;

						tmp  = (char **) realloc(node->keys,
							sizeof(char *) * node->items);
						if (!tmp) return 401; // Out of memory
						node->keys = tmp;

						tmp  = (char **) realloc(node->values,
							sizeof(char *) * node->items);
						if (!tmp) return 401; // Out of memory
						node->values = tmp;
					}
					// Ok, there is space.

					SAFE_DUPE(node->keys[empty],   keys[i]);
					SAFE_DUPE(node->values[empty], values[i]);

				} // Added node

			} // both keys and values set.

		} // for all remaining items.

		// We could update node->items when there was deletion.. But they
		// should not be saved to disk if they are NULL, and so, next load
		// they are set correctly.


		// xitems should be 0 here, or something went wrong, but we
		// can just adjust out value and not panic about it.

	} // xitems





	// This check is only for siteadd, not sitemod
	if ((set & (15)) != 15)
		return 1504;





	return 0;

}
示例#11
0
文件: handler.c 项目: lundman/FXP.One
//
// Main session handler when we have a user as the owner.
//
void handler_queue(session_t *session, int event, int id, int reply,
				   char *line)
{
	lion_t *huser = NULL;
	manager_t *node = NULL;
	queue_t *queue;
	int i;

	// If this session doesnt have a manager, do we care?
	if (!(node = manager_find_fromsession(session)))
		return;

	if (node->user && node->user->handle)
		huser = node->user->handle;

	// Find queue
	queue = queue_findbyqid(node->qid);
	if (!queue) return;


	switch(event) {

	case SESSION_EVENT_LOST:
		debugf("[handler_queue] lost event.\n");

		// We no longer have a session.
		node->old_session = node->session;
		node->session = NULL;
		if (queue) {
		  if (node->id == queue->north_sid)
		    queue->north_sid = 0;
		  if (node->id == queue->south_sid)
		    queue->south_sid = 0;
		}
		//node->id = 0;
		//queue->state = QUEUE_ITEM_FAILED;

		break;

	case SESSION_EVENT_IDLE:
		debugf("[handler_queue] idle event\n");
#ifndef SLOW_QUEUE
		engine_nodelay = 1;
#endif
		break;

	case SESSION_EVENT_CMD:
		if ((id != QUEUE_EVENT_DIRECTORY_PHASE_2_SRC_DIRLIST) &&
			(id != QUEUE_EVENT_DIRECTORY_PHASE_2_DST_DIRLIST)) {
			debugf("[handler_queue] cmd event %d %d '%s'\n",
				   id, reply, line);
		} else {
			debugf("[handler_queue] dirlist event %d %d %p\n",
				   id, reply, line);
		}

		switch (id) {

		case QUEUE_EVENT_PHASE_1_SRC_CWD:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 250) {
				// Success
				// We want a way to know if we actually CD. Look for
				// "cached"? Kinda lame.
				if (!strstr(line, "cached"))
					if (queue->num_users) {
						char *name;
						name = misc_url_encode(queue->items->src.dirname);

						for (i = 0; i < queue->num_users; i++)
							if (queue->users[i] && queue->users[i]->handle)
								lion_printf(queue->users[i]->handle,
											"QS|QID=%u|SRCCWD=%s\r\n",
											queue->id,
											name);
						SAFE_FREE(name);
					}

			} else {
				// Initiate failure.
				queue_adderr_src(queue->items, line);
			}
			break;


		case QUEUE_EVENT_PHASE_1_DST_CWD:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 250) {
				// Success

				if (!strstr(line, "cached"))
					if (queue->num_users) {
						char *name;
						name = misc_url_encode(queue->items->dst.dirname);
						for (i = 0; i < queue->num_users; i++)
							if (queue->users[i] && queue->users[i]->handle)
								lion_printf(queue->users[i]->handle,
											"QS|QID=%u|DSTCWD=%s\r\n",
											queue->id,
											name);
						SAFE_FREE(name);
					}

			} else if ((reply >= 500)) {


				// Failed. Add error, but also try to create
				// the directory, if that succeeds, clear error.
				queue_adderr_dst(queue->items, line);

				debugf("QS|QID=%u|DSTMKD=%s\n",
					   queue->id,
					   queue->items->dst.dirname);

				// Try MKD, we fall-through down to trying
				// to send MKD.
				debugf("[handler] starting MKD with depth %d\n",
					   queue->mkd_depth);
				session_cmdq_newf(session,
								  0,
								  QUEUE_EVENT_PHASE_1_DST_MKD,
								  "MKD %s\r\n",
								  get_mkdname_by_depth(queue, 1));
			}

			break;


		case QUEUE_EVENT_PHASE_1_DST_MKD:
			if ((reply >= 200) && (reply <= 299)) {
				// Success

				if (queue->num_users) {
					char *name;
					name = misc_url_encode(get_mkdname_by_depth(queue, 0));

					for (i = 0; i < queue->num_users; i++)
						if (queue->users[i] && queue->users[i]->handle)
							lion_printf(queue->users[i]->handle,
										"QS|QID=%u|MKD=%s\r\n",
										queue->id,
										name);
					SAFE_FREE(name);
				}

				// Clear error.
				queue->items->dst_failure = 0;

				// Try CWD again.
				session_cwd(session, 0, QUEUE_EVENT_PHASE_1_DST_CWD2,
							get_mkdname_by_depth(queue, 0));

			} else if ((reply >= 500)) {

				// Failed

				queue_adderr_dst(queue->items, line);

			}
			break;

		case QUEUE_EVENT_PHASE_1_DST_CWD2:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 250) {

				// Success
				debugf("[handler] 2ND mkd of depth %d\n", queue->mkd_depth);
				if (queue->mkd_depth > 0) {
					session_cmdq_newf(session,
									  0,
									  QUEUE_EVENT_PHASE_1_DST_MKD,
									  "MKD %s\r\n",
									  get_mkdname_by_depth(queue, 1));
					break;
				}

			} else if ((reply >= 500)) {

				// Failure
				queue_adderr_dst(queue->items, line);

			}
			break;

		case QUEUE_EVENT_PHASE_2_SRC_SECURE:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 200) {
				// Success
				queue->secure_data = 1;
			} else {
				// Failure
				queue_adderr_src(queue->items, line);
			}
			break;

		case QUEUE_EVENT_PHASE_2_DST_SECURE:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 200) {
				// Success
				queue->secure_data = 1;
			} else {
				// Failure
				queue_adderr_dst(queue->items, line);
			}
			break;


		case QUEUE_EVENT_PHASE_2_DISABLE:
			// Do we care if we failed here? Disabling
			// CCSN/SSCN should never fail to disable.
			// We would need to disconnect session instead.
			// TODO
			break;

		case QUEUE_EVENT_PHASE_3_SRC_PROT:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 200) {
				// Success
			} else {
				// Failure
				queue_adderr_src(queue->items, line);
			}
			break;

		case QUEUE_EVENT_PHASE_3_DST_PROT:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 200) {
				// Success
			} else {
				// Failure
				queue_adderr_dst(queue->items, line);
			}
			break;



		case QUEUE_EVENT_PHASE_4_TYPE:
			break;

		case QUEUE_EVENT_PHASE_5_SRC_SIZE:
			if (reply == 213) {
				lion64_t newsize = 0;

				if (line &&
					sscanf((char *)line,
						   "213 %"PRIu64,
						   &newsize)
					== 1) {

					if (newsize != queue->items->src.size) {
						debugf("[handler] Updating src.size to %"PRIu64"\n",
							   newsize);
						queue->items->src.size = newsize;

					}

				} // scanf

			} // 213
			break;

		case QUEUE_EVENT_PHASE_5_DST_SIZE:
			if (reply == 213) {
				lion64_t newsize = 0;

				if (line &&
					sscanf((char *)line,
						   "213 %"PRIu64,
						   &newsize)
					== 1) {

					if (newsize != queue->items->dst.size) {
						debugf("[handler] Updating dst.size to %"PRIu64"\n",
							   newsize);
						queue->items->dst.size = newsize;

					}

				} // scanf

			} // 213
			break;


		case QUEUE_EVENT_PHASE_6_PRET:
			break;

		case QUEUE_EVENT_PHASE_7_PASV:
			if (reply == 227) {
				// 227 Entering Passive Mode (127,0,0,1,226,180)
				// 229 Entering Extended Passive Mode (|||58028|)
				// Look for () and safe inbetween. If that failed, we fail.
				char *r;

				if ((r = strchr(line, '('))) {

					line = &r[1];

					if ((r = strchr(line, ')'))) {

						*r = 0;

						SAFE_COPY(queue->pasv_line, line);

						return;
					}

				}

			}

			// Wrong reply, or couldn't parse, fail.
			if (queue->srcpasv)
				queue_adderr_src(queue->items, line);
			else
				queue_adderr_dst(queue->items, line);

			break;

		case QUEUE_EVENT_PHASE_8_PORT:
			if (reply == 200)
				break;

			if (!queue->srcpasv)
				queue_adderr_src(queue->items, line);
			else
				queue_adderr_dst(queue->items, line);

			break;

		case QUEUE_EVENT_PHASE_9_SRC_REST:
			if (reply == 350) {
				// REST ok
			} else {
				queue_adderr_src(queue->items, line);
			}
			break;

		case QUEUE_EVENT_PHASE_9_DST_REST:
			if (reply == 350) {
				// REST ok
			} else {
				queue_adderr_dst(queue->items, line);
			}
			break;

		case QUEUE_EVENT_PHASE_9_SRC_REST2:
		case QUEUE_EVENT_PHASE_9_DST_REST2:
			break;



		case QUEUE_EVENT_PHASE_10_STOR:

			if (reply == -1) {
				// LOG reply, in case we are looking for X-DUPE
				if (session->status & STATUS_ON_XDUPE) {
					// Look for X-DUPE lines, remember these are url
					// encoded.
					if (!strncasecmp("226-+X-DUPE%3A+", line, 15))
						queue_xdupe_item(queue, &line[15]);
				}
				break;
			}


			if ((reply == 150) ||  // Unix
				(reply == 125)) {  // Windows

				queue->items->src_transfer++;
				break;
			}
			queue_adderr_dst(queue->items, line);
			break;



		case QUEUE_EVENT_PHASE_11_RETR:
			if ((reply == 150) ||  // Unix
				(reply == 125)) {  // Windows

				queue->items->dst_transfer++;
				gettimeofday(&queue->xfr_start, NULL);
				break;
			}
			queue_adderr_src(queue->items, line);
			break;


		case QUEUE_EVENT_PHASE_11_ABOR:
			break;


		case QUEUE_EVENT_PHASE_12_SRC_226:
			if (queue->items) queue->items->src_transfer++;
			if (reply == 226)
				break;
			queue_adderr_src(queue->items, line);
			break;

		case QUEUE_EVENT_PHASE_12_DST_226:
			if (queue->items) queue->items->dst_transfer++;
			if (reply == 226)
				break;
			queue_adderr_dst(queue->items, line);
			break;




		case QUEUE_EVENT_PHASE_12_NOOP:
			break;











		case QUEUE_EVENT_DIRECTORY_PHASE_1_SRC_CWD:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 250) {
				// Success
				if (!strstr(line, "cached"))
					if (queue->num_users) {
						char *name;
						name = misc_url_encode(queue->items->src.fullpath);

						for (i = 0; i < queue->num_users; i++)
							if (queue->users[i] && queue->users[i]->handle)
								lion_printf(queue->users[i]->handle,
											"QS|QID=%u|SRCCWD=%s\r\n",
											queue->id,
											name);
						SAFE_FREE(name);
					}

			} else {
				// Initiate failure.
				queue_adderr_src(queue->items, line);
			}
			break;


		case QUEUE_EVENT_DIRECTORY_PHASE_1_DST_CWD:
			if ((reply >= 200) && (reply <= 299)) {
				//if (reply == 250) {

				// Success
				debugf("[handler] CLEARing depth**********\n");
				queue->mkd_depth = 0;

				if (!strstr(line, "cached"))
					if (queue->num_users) {
						char *name;
						name = misc_url_encode(queue->items->dst.fullpath);

						for (i = 0; i < queue->num_users; i++)
							if (queue->users[i] && queue->users[i]->handle)
								lion_printf(queue->users[i]->handle,
											"QS|QID=%u|DSTCWD=%s\r\n",
											queue->id,
											name);
						SAFE_FREE(name);
					}

			} else {
				// Initiate failure.
				queue_adderr_dst(queue->items, line);

				// Increase the depth that we've failed at, for MKDs.
				queue->mkd_depth++;
				debugf("[handler] INCreasing depth %d\n",queue->mkd_depth);
			}
			break;



		case QUEUE_EVENT_DIRECTORY_PHASE_2_SRC_DIRLIST:
			if (!line || !reply) {
				// No files. Empty dir. We have no FAILURE event in dirlist!!
				// FIXME!!
			}
			queue->items->src_transfer = 1;
			break;

		case QUEUE_EVENT_DIRECTORY_PHASE_2_DST_DIRLIST:
			if (!line || !reply) {
				// No files. Empty dir. We have no FAILURE event in dirlist!!
				// FIXME!!
			}
			queue->items->dst_transfer = 1;
			break;



		case QUEUE_EVENT_DIRECTORY_PHASE_2_DST_MKD:
			if ((reply >= 200) && (reply <= 299)) {
				// Success

				if (queue->num_users) {
					char *name;
					name = misc_url_encode(get_mkdname_by_depth(queue, 0));

					for (i = 0; i < queue->num_users; i++)
						if (queue->users[i] && queue->users[i]->handle)
							lion_printf(queue->users[i]->handle,
										"QS|QID=%u|MKD=%s\r\n",
										queue->id,
										name);
					SAFE_FREE(name);
				}

				// Clear error.
				queue->items->dst_failure = 0;

			} else if ((reply >= 500)) {

				// Failed

				queue_adderr_dst(queue->items, line);

			}
			break;


		} // switch EVENT_CMD (inner switch)


		break;


	}


}
示例#12
0
文件: site.c 项目: lundman/FXP.One
//<< DIRLIST|SID=1|FID=0|NAME=giana_sounds|DATE=1057590000|SIZE=512|USER=nobody|GROUP=nobody|PERM=drwxrwxrwx|type=directory
void site_cmd_dirlist(char **keys, char **values, int items,void *optarg)
{
	fxpone_t *the_engine = optarg;
	char *sid, *name, *fid, *date, *size, *type, *end, *begin;
	int i;
	unsigned int id;
	site_t *site;
	file_t *file, **tmp;

	sid    = parser_findkey(keys, values, items, "SID");
	name   = parser_findkey(keys, values, items, "NAME");
	fid    = parser_findkey(keys, values, items, "FID");
	date   = parser_findkey(keys, values, items, "DATE");
	size   = parser_findkey(keys, values, items, "SIZE");
	type   = parser_findkey(keys, values, items, "FTYPE");
	begin  = parser_findkey(keys, values, items, "BEGIN");
	end    = parser_findkey(keys, values, items, "END");

	if (!sid) return;

	if (begin) return;

	id = atoi(sid);

	for (i = 0; i < num_sites; i++) {

		if (!sites[i]) continue;

		if (sites[i]->sid == id) {

			site = sites[i];

			if (end) {

				site->current_dir++;
				if (site->current_dir >= site->num_dirs) {
					site_ready(the_engine->handle, site);
					return;
				}

				printf("Site %s processing dir '%s'\n", sites[i]->name,
					   sites[i]->dirs[sites[i]->current_dir]);

				lion_printf(the_engine->handle, "CWD|SID=%u|PATH=%s\r\n",
							sites[i]->sid,
							sites[i]->dirs[sites[i]->current_dir]);

				return;

			}


            // Don't show entries in HIDE
            if (sites[i]->hide && file_listmatch(sites[i]->hide, name)) return;


			//			SAFE_COPY(sites[i]->name, name);
			file = file_new();
			if (!file) return;

			tmp = realloc(site->files, sizeof(file_t *)*(site->num_files + 1));
			if (!tmp) {
				file_free(file);
				return;
			}

			site->files = tmp;

			site->files[ site->num_files ] = file;
			site->num_files++;

			SAFE_COPY(file->name, name);
            if (date)
                file->date = strtoul(date, NULL, 10);
            if (size)
                file->size = strtoull(size, NULL, 10);
			if (type && !mystrccmp("directory", type))
				file->type = 1;

			// Remember the source path we came from
			file->current_dir = site->current_dir;

		}

	}

}
示例#13
0
文件: site.c 项目: lundman/FXP.One
// >> SITELIST|SITEID=1|NAME=localhost|HOST=127.0.0.1|PORT=21|USER=mp3|PASS=mp3|PASSIVE=1|FXP_PASSIVE=2|CONTROL_TLS=2|DATA_TLS=2|optional_variable=roger moore
void site_cmd_sitelist(char **keys, char **values, int items,void *optarg)
{
	fxpone_t *the_engine = optarg;
	char *name, *siteid, *end;
	char *dskiplist, *dpasslist, *fskiplist, *fpasslist, *fskipempty;
	int i;

	end    = parser_findkey(keys, values, items, "END");
	name   = parser_findkey(keys, values, items, "NAME");
	siteid = parser_findkey(keys, values, items, "SITEID");

	if (end) {

		// num_sitelist has how many sites we found and connected to
		// num_sites is how many we are waiting for before processing.
		num_sites = num_sitelist;
		return;

	}




	if (!name || !siteid) return;

	dskiplist = parser_findkey(keys, values, items, "DSKIPLIST");
	dpasslist = parser_findkey(keys, values, items, "DPASSLIST");
	fskiplist = parser_findkey(keys, values, items, "FSKIPLIST");
	fpasslist = parser_findkey(keys, values, items, "FPASSLIST");
	fskipempty = parser_findkey(keys, values, items, "FSKIPEMPTY");


	for (i = 0; i < num_sites; i++) {

		if (!sites[i]) continue;

		if (!mystrccmp(sites[i]->name, name)) {

			sites[i]->siteid = atoi(siteid);

			SAFE_COPY(sites[i]->dskiplist, dskiplist);
			SAFE_COPY(sites[i]->dpasslist, dpasslist);
			SAFE_COPY(sites[i]->fskiplist, fskiplist);
			SAFE_COPY(sites[i]->fpasslist, fpasslist);

			if (fskipempty && (atoi(fskipempty) == 0))
				sites[i]->fskipempty = 0;
			else
				sites[i]->fskipempty = 1;

			num_sitelist++;

            // IRC sets skip, so we dont do initial login
            if (!sites[i]->skip)
                lion_printf(the_engine->handle, "SESSIONNEW|SITEID=%u\r\n",
                            atoi(siteid));

		}

	}

}
示例#14
0
文件: root.c 项目: lundman/llink
//
// This takes the "virtual path" ->path sent over by the HTTP request, and
// attempts to match it to one of the roots we have setup from conf file.
// If there is a valid match, ->disk_path is assigned.
//
// Note that if "disk_path" is already set, we don't do anything, and assume
// it is good. Only place that sets it apart from this function, is when we
// copy over the temporary filename, which is strictly controlled in
// request_action()
//
int root_setpath(request_t *node)
{
	char *tmpname, *subdir, *skin_root = NULL;
	char *str;
	int i;

	// If disk_path is set, we need not do anything.
	if (node->disk_path && node->disk_path) {
		debugf("[root] trusting that '%s' is valid.\n",
			   node->disk_path);
		// However, if the path is "/", or stat to a directory we
		// call dirlist.
		stat(node->disk_path, &node->stat);
		return 0;
	}


	// Reduce away any naughty "../../../" parts.
	root_undot(node->path);


	// If its "/" we just leave it as that.
	if (!mystrccmp("/", node->path)) {
		// Strictly not needed. We dont expand "/" to the real root as
		// we may have multiple real roots. So it is left as a secret
		// match strict which starts listing of all roots.
		SAFE_COPY(node->disk_path, node->path);
		return 0;
	}

	// Anything else, we need to find the "right" root, and
	// set full path. Any multiple hits are ignored as we just
	// settle for first come.

	// First we check if it is in the skin directory.
    if ((skin_root = skin_get_root(node->skin_type))) {
        tmpname = misc_strjoin(skin_root, node->path);

        debugf("[root] testing path '%s'\n", tmpname);

        // Windows does not like "directory/" in stat.
        misc_stripslash(tmpname);

        if (!stat(tmpname, &node->stat)) {

            // misc_strjoin allocates string, so we can just assign it.
            node->disk_path = tmpname;

            // Caveat, if the target is a directory, we have to ensure
            // it has a trailing "/" for dirlist's precat in ->path
            if (S_ISDIR(node->stat.st_mode) &&
                node->path[ strlen(node->path) ] != '/') {
                tmpname = misc_strjoin(node->path, "");
                SAFE_FREE(node->path);
                node->path = tmpname;
            }

            return 0;

        }

        SAFE_FREE(tmpname);
    } // skin


#if 0
    // The above (identical) code uses skin_get_root() which should return
    // the root of the current skin, which should be set to the upnp skin
    // in skin_set_skin().

	// First we check if it is in the upnpskin directory.
    if (skin_upnp_root) {

        tmpname = misc_strjoin(skin_upnp_root, node->path);

        debugf("[root] testing path '%s'\n", tmpname);

        // Windows does not like "directory/" in stat.
        misc_stripslash(tmpname);

        if (!stat(tmpname, &node->stat)) {

            // misc_strjoin allocates string, so we can just assign it.
            node->disk_path = tmpname;

            // Caveat, if the target is a directory, we have to ensure
            // it has a trailing "/" for dirlist's precat in ->path
            if (S_ISDIR(node->stat.st_mode) &&
                node->path[ strlen(node->path) ] != '/') {
                tmpname = misc_strjoin(node->path, "");
                SAFE_FREE(node->path);
                node->path = tmpname;
            }

            return 0;

        }

        SAFE_FREE(tmpname);
    } //upnp skin
#endif



	// Now try all the roots defined.

	for (i = 0; i < root_count; i++) {

		// Check for exact http ROOT matches
		if (root_array[i].http_host) {

			// If its a proxy request (file mode)

			if (node->cgi_host && node->cgi_file) {
				node->root_index = i;
				node->stat.st_mode = S_IFREG;
				node->disk_path = strdup("http-proxy");
				return 0;
			}

			// it will start with a slash, so skip it
			str = node->path;
			while (*str == '/') str++;

			// Compare it
			if (!mystrccmp(root_array[i].path, str)) {
				debugf("[root] ROOT|http match '%s'\n", str);
				node->root_index = i;
				// Due to stat()s, we need to send a real dir here.
				// Don't worry, "/" means dirlist, not that it lists from root
				node->disk_path = strdup("http-listing");
				//Fake a stat of a dirlist
				node->stat.st_mode = S_IFDIR;

				return 0;
			}
		}


		tmpname = misc_strjoin(root_array[i].path, node->path);
		misc_stripslash(tmpname);

		debugf("[root] testing path '%s'\n", tmpname);

		if (!stat(tmpname, &node->stat)) {


			// misc_strjoin allocates string, so we can just assign it.
			node->disk_path = tmpname;

			// Caveat, if the target is a directory, we have to ensure
			// it has a trailing "/" for dirlist's precat in ->path
			if (S_ISDIR(node->stat.st_mode) &&
				node->path[ strlen(node->path) ] != '/') {
				tmpname = misc_strjoin(node->path, "");
				SAFE_FREE(node->path);
				node->path = tmpname;
			}

			node->root_index = i;

			return 0;

		}

		SAFE_FREE(tmpname);

	}





	// This test destroys node->path, so it needs to be last

	debugf("[root] testing for SUBDIR type: '%s'\n", node->path);

	// it might be using a SUBDIR style syntax.
	str = node->path;
	while (*str == '/') str++;

	// Might be the root of SUBDIR, or deeper request.
	if ((subdir = strchr(str, '/'))) {

		*subdir = 0;
		subdir++;
	} else {
		subdir = "";
	}



	debugf("[root] looking for '%s' rest '%s'\n", str, subdir);

	for (i = 0; i < root_count; i++) {
		if (root_array[i].subdir &&
			!mystrccmp(root_array[i].subdir, str)) {

			node->disk_path = misc_strjoin(root_array[i].path, subdir);

			debugf("[root] testing subdir path '%s'\n", node->disk_path);

			misc_stripslash(node->disk_path);

			if (!stat(node->disk_path, &node->stat)) {

				// Caveat, if the target is a directory, we have to ensure
				// it has a trailing "/" for dirlist's precat in ->path
				// path = path + subdir
				tmpname = misc_strjoin(node->path, subdir);
				SAFE_FREE(node->path);
				node->path = tmpname;

				if (S_ISDIR(node->stat.st_mode) &&
					node->path[ strlen(node->path) ] != '/') {
					tmpname = misc_strjoin(node->path, "");
					SAFE_FREE(node->path);
					node->path = tmpname;
				}

				node->root_index = i;
				debugf("[root] returning subdir: '%s':%d\n", node->disk_path,
					   node->root_index);
				return 0;


			} // stat
		} // mystrccmp
	} // for roots


	debugf("[root] giving up, path not valid.\n");
	// we've trashed the path anyway?
	SAFE_FREE(node->path);

	// Invalid path. Do we ensure it will fail later here? Or just assume
	// that the stat will fail later on.
	return -1;

}