void do_getabsolute(char* result, const char* value, const char* relative_to)
{
	int i;
	char* ch;
	char* prev;
	char buffer[0x4000] = { '\0' };

	/* if the path is not already absolute, base it on working dir */
	if (!do_isabsolute(value)) {
		if (relative_to) {
			strcpy(buffer, relative_to);
		}
		else {
			do_getcwd(buffer, 0x4000);
		}
		strcat(buffer, "/");
	}

	/* normalize the path */
	strcat(buffer, value);
	do_translate(buffer, '/');

	/* process it part by part */
	result[0] = '\0';
	if (buffer[0] == '/') {
		strcat(result, "/");
	}

	prev = NULL;
	ch = strtok(buffer, "/");
	while (ch) {
		/* remove ".." where I can */
		if (strcmp(ch, "..") == 0 && (prev == NULL || (prev[0] != '$' && prev[0] != '%' && strcmp(prev, "..") != 0))) {
			i = strlen(result) - 2;
			while (i >= 0 && result[i] != '/') {
				--i;
			}
			if (i >= 0) {
				result[i + 1] = '\0';
			}
			ch = NULL;
		}

		/* allow everything except "." */
		else if (strcmp(ch, ".") != 0) {
			strcat(result, ch);
			strcat(result, "/");
		}

		prev = ch;
		ch = strtok(NULL, "/");
	}

	/* remove trailing slash */
	i = strlen(result) - 1;
	if (result[i] == '/') {
		result[i] = '\0';
	}
}
Beispiel #2
0
int do_isabsolute(const char* path)
{
    char c;
    const char* closing;

    if (path[0] == '/' || path[0] == '\\')
        return 1;
    if (isalpha(path[0]) && path[1] == ':')
        return 1;
    if (path[0] == '"')
        return do_isabsolute(path + 1);

    // $(foo)
    if (path[0] == '$' && path[1] == '(')
    {
        path += 2;
        closing = strchr(path, ')');
        if (closing == NULL)
            return 0;

        // only alpha, digits, _ and . allowed inside $()
        while (path < closing) {
            c = *path++;
            if (!isalpha(c) && !isdigit(c) && c != '_' && c != '.')
                return 0;
        }

        return 1;
    }

    // $ORIGIN.
    if (path[0] == '$')
        return 1;

    // %foo%
    if (path[0] == '%')
    {
        // find the second closing %
        path += 1;
        closing = strchr(path, '%');
        if (closing == NULL)
            return 0;

        // need at least one character between the %%
        if (path == closing)
            return 0;

        // only alpha, digits and _ allowed inside %..%
        while (path < closing) {
            c = *path++;
            if (!isalpha(c) && !isdigit(c) && c != '_')
                return 0;
        }
        return 1;
    }

    return 0;
}
int path_isabsolute(lua_State* L)
{
	const char* path = luaL_checkstring(L, -1);
	lua_pushboolean(L, do_isabsolute(path));
	return 1;
}
Beispiel #4
0
int path_join(lua_State* L)
{
	int i;
	size_t len;
	const char* part;
	char buffer[0x4000];
	char* ptr = buffer;

	/* for each argument... */
	int argc = lua_gettop(L);
	for (i = 1; i <= argc; ++i) {
		/* if next argument is nil, skip it */
		if (lua_isnil(L, i)) {
			continue;
		}

		/* grab the next argument */
		part = luaL_checkstring(L, i);
		len = strlen(part);

		/* remove leading "./" */
		while (strncmp(part, "./", 2) == 0) {
			part += 2;
			len -= 2;
		}

		/* remove trailing slashes */
		while (len > 1 && part[len - 1] == '/') {
			--len;
		}

		/* ignore empty segments and "." */
		if (len == 0 || (len == 1 && part[0] == '.')) {
			continue;
		}

		/* if I encounter an absolute path, restart my result */
		if (do_isabsolute(part)) {
			ptr = buffer;
		}

		/* if source has a .. prefix then take off last dest path part
		   note that this doesn't guarantee a normalized result as this
		   code doesn't check for .. in the mid path, however .. occurring
		   mid path are much more likely to occur during path joins
		   and its faster if we handle here as we don't have to remove
		   substrings from the middle of the string. */

		while (ptr != buffer && len >= 2 && part[0] == '.' && part[1] == '.') {
			/* locate start of previous segment */
			char* start = strrchr(buffer, '/');
			if (!start) {
				start = buffer;
			}
			else {
				++start;
			}

			/* if I hit a segment I can't trim, bail out */
			if (*start == '$') {
				break;
			}

			/* otherwise trim segment and the ".." sequence */
			if (start != buffer) {
				--start;
			}
			*start = '\0';
			ptr = start;
			part += 2;
			len -= 2;
			if (len > 0 && part[0] == '/') {
				++part;
				--len;
			}
		}

		/* if the path is already started, split parts */
		if (ptr != buffer && *(ptr - 1) != '/') {
			*(ptr++) = '/';
		}

		/* append new part */
		strncpy(ptr, part, len);
		ptr += len;
		*ptr = '\0';
	}

	lua_pushstring(L, buffer);
	return 1;
}