Ejemplo n.º 1
0
static FskErr KprWebSocketEndpointUpgradeConnection(KprWebSocketEndpoint self)
{
	FskErr err = kFskErrNone;
	FskHeaders *request;
	char buffer[1024], tmp[1024], portStr[10];
	int len, port;
	
	bailIfError(FskHeaderStructNew(&request));
	
	port = (self->parts->port ? port = self->parts->port : 80);
	
	if (port == 80) {
		FskHeaderAddString("Host", self->parts->host, request);
	} else {
		FskStrCopy(tmp, self->parts->host);
		FskStrCat(tmp, ":");
		FskStrNumToStr(port, portStr, 10);
		FskStrCat(tmp, portStr);
		FskHeaderAddString("Host", tmp, request);
	}
	
	if (self->origin) {
		FskHeaderAddString("Origin", self->origin, request);
	} else {
		FskStrCopy(tmp, "http://");
		FskStrCat(tmp, self->parts->host);
		FskHeaderAddString("Origin", tmp, request);
	}
	
	FskHeaderAddString("Upgrade", "websocket", request);
	FskHeaderAddString("Connection", "Upgrade", request);
	
	KprWebSocketCreateKey(&self->key);
	FskHeaderAddString("Sec-WebSocket-Key", self->key, request);
	FskHeaderAddInteger("Sec-WebSocket-Version", 13, request);
	
	FskStrCopy(buffer, "GET ");
	if (self->parts->path[0] != '/') FskStrCat(buffer, "/");
	FskStrCat(buffer, self->parts->path);
	FskStrCat(buffer, " HTTP/1.1\r\n");
	
	len = FskStrLen(buffer);
	FskHeaderGenerateOutputBlob(&buffer[len], 1024 - len, true, request);
	
	KprSocketWriterSendBytes(self->writer, buffer, FskStrLen(buffer));
	
bail:
	
	return err;
}
Ejemplo n.º 2
0
FskErr FskFSFileRenameDirectory(const char *fullPath, const char *newName)
{
	int err, len;
	char *p, newPath[PATH_MAX];
	FskFileInfo itemInfo;

	err = sCheckFullPath(fullPath, kFskPathIsDirectory);
	BAIL_IF_ERR(err);

	len = FskStrLen(fullPath);
	if (len < 2)
		BAIL(kFskErrOperationFailed);			// can't rename root

	err = FskFSFileGetFileInfo(fullPath, &itemInfo);
	BAIL_IF_ERR(err);

	if (itemInfo.filetype != kFskDirectoryItemIsDirectory)
		BAIL(kFskErrNotDirectory);

	p = FskStrRChr((char *)newName, '/');
	if (p)
		BAIL(kFskErrOperationFailed);	// newName contains path elements

	FskStrCopy(newPath, fullPath);

	if (newPath[len - 1] == '/')
		newPath[len - 1] = '\0';		// remove trailing slash

	p = FskStrRChr(newPath, '/');
	if (p)
		*++p = '\0';
	FskStrCat(newPath, newName);

	err = rename(fullPath, newPath);
	if (err == -1)
		BAIL(errnoToFskErr(errno));

	 err = kFskErrNone;

bail:
	return err;
}
Ejemplo n.º 3
0
void fxReadAddressAutomatic(txMachine* the)
{
	/* read debugAddress and debugAutomatic from a file... */
#if TARGET_OS_ANDROID
	char *folder = NULL;
	char *file = FskStrDoCat(folder, "/sdcard/debug.txt");
	{
#else
	char *folder;
	if (kFskErrNone == FskDirectoryGetSpecialPath(kFskDirectorySpecialTypeApplicationPreference, true, NULL, &folder)) {
		char *file = FskStrDoCat(folder, "debug.txt");
#endif
		char *data;

		if (kFskErrNone == FskFileLoad(file, (FskMemPtr *)&data, NULL)) {
			char *lf = FskStrChr(data, 10);
			if ((NULL != lf) && (FskStrLen(data) < sizeof(debugAddress))) {
				*lf = 0;
				FskStrCopy(debugAddress, data);
				debugAutomatic = '1' == lf[1];
			}
			FskMemPtrDispose(data);
		}
		else {
			FskECMAScriptGetDebug(&data, NULL, NULL);
			if (data) {
				FskStrCopy(debugAddress, data);
				FskStrCat(debugAddress, ":5002");
				debugAutomatic = 1;
			}
		}

		FskMemPtrDispose(file);
		FskMemPtrDispose(folder);
	}
}

void fxSetAddress(txMachine* the, char* theAddress)
{
	c_strcpy(debugAddress, theAddress);
	fxWriteAddressAutomatic(the);
}
Ejemplo n.º 4
0
FskErr KplFileRenameDirectory(const char *fullPath, const char *newName)
{
	int err, len;
	char *p, newPath[PATH_MAX];
	KplFileInfo itemInfo;

	err = sCheckFullPath(fullPath, kKplPathIsDirectory);
	if (err) return err;

	len = FskStrLen(fullPath);
	if (len < 2) return kFskErrOperationFailed;			// can't rename root

	err = KplFileGetFileInfo(fullPath, &itemInfo);
	if (err) return err;

	if (itemInfo.filetype != kKplDirectoryItemIsDirectory)
		return kFskErrNotDirectory;

	p = FskStrRChr((char *)newName, '/');
	if (p) return kFskErrOperationFailed;	// newName contains path elements

	FskStrCopy(newPath, fullPath);

	if (newPath[len - 1] == '/')
		newPath[len - 1] = '\0';		// remove trailing slash

	p = FskStrRChr(newPath, '/');
	if (p)
		*++p = '\0';
	FskStrCat(newPath, newName);

	err = rename(fullPath, newPath);
	if (err == -1)
		return errnoToFskErr(errno);
	else
		return kFskErrNone;
}
Ejemplo n.º 5
0
// text
void KPR_canvasRenderingContext2D_get_font(xsMachine *the)
{
	FskCanvas2dContext ctx = xsGetHostData(xsThis);
	const struct FskFontAttributes* font = FskCanvas2dGetFont(ctx);
	char buffer[1024] = "";
	if (font->style == kFskFontStyleItalic)
		FskStrCat(buffer, "italic ");
	else if (font->style == kFskFontStyleOblique)
		FskStrCat(buffer, "oblique ");
	if (font->weight == kFskFontWeightBold)
		FskStrCat(buffer, "bold ");
	else if (font->weight != kFskFontWeightNormal) {
		FskStrNumToStr(font->weight, buffer + FskStrLen(buffer), sizeof(buffer) - FskStrLen(buffer));
		FskStrCat(buffer, " ");
	}
	if (font->variant == kFskFontVariantSmallCaps)
		FskStrCat(buffer, "small-caps ");
	FskStrNumToStr((SInt32)(font->size), buffer + FskStrLen(buffer), sizeof(buffer) - FskStrLen(buffer));
	FskStrCat(buffer, "px ");
	FskStrCat(buffer, font->family);
	xsResult = xsString(buffer);
}
Ejemplo n.º 6
0
void KprFILEServiceInvoke(KprService service UNUSED, KprMessage message)
{
	FskErr err = kFskErrNone;
	char* path = NULL;
	FskFileInfo info;
	FskDirectoryIterator iterator = NULL;
	char* pathName = NULL;
	char* sniff = NULL;
	FskFile fref = NULL;
	char *name = NULL;
	if (KprMessageContinue(message)) {
		if (!message->method || FskStrCompare(message->method, "GET")) {
			bailIfError(KprURLToPath(message->url, &path));
			bailIfError(FskFileGetFileInfo(path, &info));
			if (kFskDirectoryItemIsDirectory == info.filetype) {
				unsigned char buffer[4096];
				UInt32 itemType;
				double date;
				UInt32 size;
				xsBeginHostSandboxCode(gFILEService.machine, NULL);
				{
					xsVars(3);
					{
						xsTry {
							xsVar(0) = xsGet(xsGlobal, xsID("Files"));
							xsResult = xsNewInstanceOf(xsArrayPrototype);
							bailIfError(FskDirectoryIteratorNew(path, &iterator, 0));
							while (kFskErrNone == FskDirectoryIteratorGetNext(iterator, &name, &itemType)) {
								if (name[0] == '.') {
									FskMemPtrDisposeAt(&name);
									continue;
								}
								if (kFskDirectoryItemIsFile == itemType) {
									pathName = FskStrDoCat(path, name);
									bailIfError(FskFileGetFileInfo(pathName, &info));
									bailIfError(FskFileOpen(pathName, kFskFilePermissionReadOnly, &fref));
									bailIfError(FskFileRead(fref, sizeof(buffer), buffer, &size));
									FskFileClose(fref);
									fref = NULL;
									if (kFskErrNone == FskMediaPlayerSniffForMIME(buffer, size, NULL, pathName, &sniff)) {
									}
									else if (kFskErrNone == FskImageDecompressSniffForMIME(buffer, size, NULL, pathName, &sniff)) {
									}
									FskMemPtrDispose(pathName);
									pathName = NULL;
								}
								xsVar(1) = xsNewInstanceOf(xsObjectPrototype);
								xsNewHostProperty(xsVar(1), xsID("name"), xsString(name), xsDefault, xsDontScript);
								xsNewHostProperty(xsVar(1), xsID("path"), xsString(name), xsDefault, xsDontScript);
								FskStrCopy((char*)buffer, message->url);
								FskStrCat((char*)buffer, name);
								if (kFskDirectoryItemIsDirectory == itemType) {
									xsVar(2) = xsGet(xsVar(0), xsID("directoryType"));
									FskStrCat((char*)buffer, "/");
								}
								else if (kFskDirectoryItemIsFile == itemType) {
									xsVar(2) = xsGet(xsVar(0), xsID("fileType"));
									if (info.fileModificationDate > info.fileCreationDate)
										date = info.fileModificationDate * 1000.0;	
									else
										date = info.fileCreationDate * 1000.0;
									xsNewHostProperty(xsVar(1), xsID("date"), xsNumber(date), xsDefault, xsDontScript);
									xsNewHostProperty(xsVar(1), xsID("size"), xsNumber(info.filesize), xsDefault, xsDontScript);
									if (sniff) {
										xsNewHostProperty(xsVar(1), xsID("mime"), xsString(sniff), xsDefault, xsDontScript);
										FskMemPtrDispose(sniff);
										sniff = NULL;
									}
								}
								else
									xsVar(2) = xsGet(xsVar(0), xsID("linkType"));
								xsNewHostProperty(xsVar(1), xsID("type"), xsVar(2), xsDefault, xsDontScript);
								xsNewHostProperty(xsVar(1), xsID("url"), xsString((char*)buffer), xsDefault, xsDontScript);
								(void)xsCall1(xsResult, xsID("push"), xsVar(1));
								FskMemPtrDisposeAt(&name);
							}
							xsResult = xsCall1(xsGet(xsGlobal, xsID("JSON")), xsID("stringify"), xsResult);
							message->response.body = FskStrDoCopy(xsToString(xsResult));
							message->response.size = FskStrLen(message->response.body);
							KprMessageTransform(message, gFILEService.machine);
						}
						xsCatch {
						}
					}
				}
				xsEndHostSandboxCode();
			}
			else if (kFskDirectoryItemIsFile == info.filetype) {
Ejemplo n.º 7
0
static void httpProcessRequestHeaders(FskHTTPServerRequest request) {
	char 		*str;
	FskHeaders* headers = request->requestHeaders;
	UInt32 version = FskHeaderHTTPVersion(headers);
	char* host = FskHeaderFind(kFskStrHost, headers);
	char* uri = FskHeaderURI(headers);
	char* filename = FskHeaderFilename(headers);
	
	request->state = kHTTPReadRequestBody;

	if (FskStrCompareWithLength(uri, "http://", 7) == 0) {
		// remove host from filename
		char* p = FskStrStr(filename, "://") + 3;
		p = FskStrChr(p, '/') + 1;
		FskMemMove(filename, p, FskStrLen(p) + 1);
	}
	else {
		if (host) {
			if (FskMemPtrNewClear(FskStrLen(host) + FskStrLen(uri) + 9, &str) != kFskErrNone)
				headers->responseCode = 500;
			else {
				FskStrCat(str, "http://");
				FskStrCat(str, host);
				FskStrCat(str, "/");
				FskStrCat(str, headers->URI);
				FskMemPtrDispose(headers->URI);
				headers->URI = str;
			}
		}
		else if (version >= kFskHTTPVersion1dot1)
			headers->responseCode = 400;
		else if (version == kFskHTTPVersion1dot0) {
			if (FskMemPtrNewClear(FskStrLen(uri) + 9, &str) != kFskErrNone)
				headers->responseCode = 500;
			else {
				FskStrCat(str, "http:///");
				FskStrCat(str, headers->URI);
				FskMemPtrDispose(headers->URI);
				headers->URI = str;
			}
		}
	}
	
	str = FskHeaderFind(kFskStrConnection, request->requestHeaders);
	if (str && FskStrCompareCaseInsensitiveWithLength(str, kFskStrClose, 5) == 0) 
		request->keepAlive = false;
	else
		request->keepAlive = true;

	str = FskHeaderFind(kFskStrContentLength, request->requestHeaders);
	if (str) {
		request->requestBodyContentLength = FskStrToNum(str);
		request->stats.expectedBytesToReceive = FskStrToNum(str);
	}
	else
		request->stats.expectedBytesToReceive = 0;

	str = FskHeaderFind(kFskStrTransferEncoding, request->requestHeaders);
	if (str && (FskStrCompareCaseInsensitiveWithLength(str, kFskStrChunked, FskStrLen(kFskStrChunked)) == 0))
		request->requestBodyChunked = true;
	else
		request->requestBodyChunked = false;
	
	doCallCondition(request->http->callbacks->requestCondition, request, kFskHTTPConditionRequestReceivedRequestHeaders, request->refCon);

	if (NULL != (str = FskHeaderFind(kFskStrExpect, request->requestHeaders))) {
		if (0 == FskStrCompareCaseInsensitive(kFskStr100Continue, str))
			request->state = kHTTPFulfillExpectation;
		else
			request->state = kHTTPDenyExpectation;
	}
}
Ejemplo n.º 8
0
// ------------------------------------------------------------------------
static int sParseStartLine(char *startLine, UInt16 headerType, FskHeaders *headers)
{
	FskErr	err;
	int		l;
	const char *p;
	char *c = startLine;
	char *firstPart;

	// Get method or protocol
	p = c;
	c = FskStrChr(c, ' ');
	if (!c) return -1;
	
	l = (c++) - p;
	err = FskMemPtrNew(l+1, &firstPart);
	if (err != kFskErrNone)
		return -1;
	FskStrNCopy(firstPart, p, l);
	firstPart[l] = '\0';
	if (kFskHeaderTypeResponse == headerType)
		headers->protocol = firstPart;
	else 
		headers->method = firstPart;

	c = FskStrStripHeadSpace(c);	// skip over space

	headers->headerType = headerType;
	if (kFskHeaderTypeResponse == headerType) {
		// Get response code and message (if message not in HTTP_Responses)
		headers->responseCode = FskStrToNum(c);
		if (headers->flags & kFskHeadersNonStandardResponseReasonPhrase) {
			c = FskStrChr(c, ' ');
			if (c) {
				char *r, *s;
				s = FskStrStripHeadSpace(c);
				r = FskFindResponse(headers->responseCode);
				if (!r || (0 != FskStrCompareCaseInsensitiveWithLength(s, r, FskStrLen(r)))) {
					headers->responseReasonPhrase = FskStrDoCopy(s);
					if (NULL != headers->responseReasonPhrase)
						FskStrStripTailSpace(headers->responseReasonPhrase);
				}
			}
		}
	}
	else {
		char 	*s, *t = NULL;
		char	*uri = NULL;

		// Get URI
		if ((*c == '/') && !(headers->flags & kFskHeadersDoNotStripURILeadingSlash))
			c++;
		s = FskStrChr(c, ' ');
		if (!s) {
			headers->responseCode = 400;
			return -1;
		}
		headers->protocol = FskStrDoCopy(s + 1);
		if (NULL != headers->protocol)
			FskStrStripTailSpace(headers->protocol);

		BAIL_IF_ERR(FskMemPtrNew((s-c)+1, &uri));
		BAIL_IF_ERR(FskMemPtrNew((s-c)+1, &t));
		FskMemCopy(uri, c, s-c);
		uri[s-c] = '\0';
		s = FskStrChr(uri, '?');
        if (s) *s = 0;
        FskStrDecodeEscapedChars(uri, t);
        if (s) {
            *s = '?';
            FskStrCat(t, s);
        }
		headers->URI = FskStrDoCopy(t);

		// Break URI into filename and parameters
		s = FskStrChr(t, '?');
		if (!s) {
			headers->filename = FskStrDoCopy(t);
		}
		else {		// URI has parameters
			*s++ = '\0';	// cap off the filename
			headers->filename = FskStrDoCopy(t);
			
			headers->parameters = FskAssociativeArrayNew();
			while (s) {
				char *name = s;		
				char *value = FskStrChr(name, '=');
				if (!value)
					break;
				s = FskStrChr(value, '&');
				*value++ = '\0';		// cap off the name
				if (s)
					*s++ = '\0';		// cap off the value
				FskAssociativeArrayElementSetString(headers->parameters, name, value);
			}
		}		

bail:
		FskMemPtrDispose(uri);
		FskMemPtrDispose(t);

	}

	return headers->headerType;
}
Ejemplo n.º 9
0
FskErr FskEnvironmentInitialize(void)
{
	char *appPath;

	gEnvironment = FskAssociativeArrayNew();

	appPath = FskGetApplicationPath();
	FskEnvironmentSet("applicationPath", appPath);
	FskMemPtrDispose(appPath);

#if TARGET_OS_KPL
	KplEnvironmentInitialize(gEnvironment);
#elif TARGET_OS_ANDROID
	FskEnvironmentSet("application", "PLAY");
#elif TARGET_OS_WIN32 || TARGET_OS_MAC || TARGET_OS_LINUX
	FskEnvironmentSet("application", FSK_APPLICATION);
#else
	FskEnvironmentSet("application", "PLAY");
#endif

#if TARGET_OS_WIN32
	{
	char name[256], *nameTemp = NULL;
	UInt16 nameW[256];
	char num[32];
	DWORD nameSize = sizeof(nameW) / sizeof(UInt16);
	EXTENDED_NAME_FORMAT exNameFormat = NameSamCompatible;

	if (GetUserNameExW(exNameFormat, (LPWSTR)nameW, &nameSize)) {
		FskTextUnicode16LEToUTF8(nameW, nameSize * 2, &nameTemp, NULL);
		FskStrCopy(name, nameTemp);
		FskEnvironmentSet("loginName", name);
		FskMemPtrDispose(nameTemp);
	}

	FskEnvironmentSet("OS", "Windows");
	FskStrNumToStr(gWindowsVersionInfo.dwMajorVersion, name, sizeof(name));
	FskStrCat(name, ".");
	FskStrNumToStr(gWindowsVersionInfo.dwMinorVersion, num, sizeof(num));
	FskStrCat(name, num);
	FskEnvironmentSet("OSVersion", name);
	}
#elif TARGET_OS_MAC
	{
		struct utsname un;
		char name[256], *model;
		SInt32 gen;
	#if TARGET_OS_IPHONE
		FskEnvironmentSet("OS", "iPhone");
	#else
		FskEnvironmentSet("OS", "Mac");
	#endif
		FskCocoaSystemGetVersion(name);
		FskEnvironmentSet("OSVersion", name);
		if (uname(&un) == 0) {
			model = un.machine;
			if (FskStrCompareWithLength(model, "iPhone", 6) == 0)
				gen = FskStrToNum(model + 6);
			else if (FskStrCompareWithLength(model, "iPad", 4) == 0) {
				gen = FskStrToNum(model + 4);
				if (gen == 3) {
					SInt32 minor = FskStrToNum(model + 6);
					if (minor == 4)	/* 4th gen */
						gen = 5;
					else
						gen = 4;	/* Only the 3rd gen iPad doesn't follow the numbering system */
				}
				else
					gen += 2;
			}
			else if (FskStrCompareWithLength(model, "iPod", 4) == 0) {
				gen = FskStrToNum(model + 4);
				if (gen > 1)
					--gen;
			}
			else
				gen = 99;
		}
		else {
			model = "unknown";
			gen = 99;
		}
		FskEnvironmentSet("Model", model);
		FskStrNumToStr(gen, name, sizeof(name));
		FskEnvironmentSet("Generation", name);
	}
		
#elif TARGET_OS_LINUX
	{
	struct utsname name;
	uname(&name);

	if (getlogin())
		FskEnvironmentSet("loginName", getlogin());
	else
		FskEnvironmentSet("loginName", "User");
	FskEnvironmentSet("OS", name.sysname);
	FskEnvironmentSet("OSVersion", name.release);		//@@
	}
#endif

	return kFskErrNone;
}
Ejemplo n.º 10
0
char *FskEnvironmentApply(char *input)
{
	FskErr err;
	char *p;
	char *out = NULL;
	char *start, *end;
	UInt32 outCount = 0;
	char tempName[256];
	UInt32 nameLen;
	char *value;
	Boolean doApply = false;

	if (NULL == input)
		goto bail;

	if ('"' == *input) {
		// special case for string literal - useful when there is leading or trailing white space or [ or ] in the string
		UInt32 len = FskStrLen(input);
		if ('"' == input[len - 1]) {
			err = FskMemPtrNew(len - 1, &out);
			BAIL_IF_ERR(err);
			out[len - 2] = 0;
			FskMemMove(out, input + 1, len - 2);
			goto bail;
		}
	}

	// scan
	p = input;
	while (true) {
		start = FskStrChr(p, '[');
		if (NULL == start) {
			outCount += FskStrLen(p);
			break;
		}
		outCount += start - p;
		end = FskStrChr(start + 1, ']');
		if (NULL == end) {
			outCount += FskStrLen(start);
			break;
		}

		nameLen = end - start - 1;
		if (nameLen > (sizeof(tempName) - 1))
			goto bail;
		FskMemMove(tempName, start + 1, nameLen);
		tempName[nameLen] = 0;

		value = FskEnvironmentGet(tempName);
		outCount += FskStrLen(value);

		doApply = true;
		p = end + 1;
	}

	if (!doApply)
		goto bail;

	// replace
	err = FskMemPtrNew(outCount + 1, &out);
	BAIL_IF_ERR(err);

	out[0] = 0;
	p = input;
	while (true) {
		start = FskStrChr(p, '[');
		if (NULL == start) {
			FskStrCat(out, p);
			break;
		}
		outCount += start - p;
		end = FskStrChr(start + 1, ']');
		if (NULL == end) {
			FskStrCat(out, start);
			break;
		}

		FskStrNCat(out, p, start - p);

		nameLen = end - start - 1;
		FskMemMove(tempName, start + 1, nameLen);
		tempName[nameLen] = 0;
		FskStrCat(out, FskEnvironmentGet(tempName));

		p = end + 1;
	}

bail:
	return out;
}
Ejemplo n.º 11
0
FskErr FskFSDirectoryGetSpecialPath(UInt32 type, const Boolean create, const char *volumeName, char **fullPath)
{
	FskErr	err = kFskErrFileNotFound;
	FskFileInfo finfo;
	char *tmp = NULL, *specialDir = NULL;
	char *dataDir = gAndroidCallbacks->getStaticDataDirCB();
	char *externalDir = gAndroidCallbacks->getStaticExternalDirCB();
	Boolean doCreate = create;

	*fullPath = NULL;

	FskAndroidFilesPrintfDebug("for SpecialPath - type %d, use dataDir as %s (volumeName %s)\n", type, dataDir, volumeName);

	switch (type & ~kFskDirectorySpecialTypeSharedFlag) {
		case kFskDirectorySpecialTypeDownload:
			if (androidSystemDownloadsDir)
				tmp = FskStrDoCat(androidSystemDownloadsDir, "/");
			else if (externalDir)
				tmp = FskStrDoCat(externalDir, "/Kinoma/Downloads/");
			else
				BAIL(kFskErrNotDirectory);
			break;
		case kFskDirectorySpecialTypeDocument:
			doCreate = true;
			if (externalDir)
				tmp = FskStrDoCat(externalDir, "/");
			else if (androidSystemDownloadsDir)
				tmp = FskStrDoCat(androidSystemDownloadsDir, "/");
			else
				specialDir = "Download";
			break;
		case kFskDirectorySpecialTypePhoto:
			if (androidSystemPicturesDir)
				tmp = FskStrDoCat(androidSystemPicturesDir, "/");
			else
				specialDir = "Pictures";
			break;
		case kFskDirectorySpecialTypeMusic:
			if (androidSystemMusicDir)
				tmp = FskStrDoCat(androidSystemMusicDir, "/");
			else
				specialDir = "Music";
			break;
		case kFskDirectorySpecialTypeVideo:
			if (androidSystemMoviesDir)
				tmp = FskStrDoCat(androidSystemMoviesDir, "/");
			else
				specialDir = "Movies";
			break;
		case kFskDirectorySpecialTypeTV:
			specialDir = "TV";
			break;
		case kFskDirectorySpecialTypeApplicationPreference:
			*fullPath = FskStrDoCat(dataDir, "kinoma/");
			err = FskFSFileCreateDirectory(*fullPath);
			err = kFskErrNone;
			goto makeit;
		case kFskDirectorySpecialTypeTemporary:
			*fullPath = FskStrDoCat(dataDir, "tmp/");
			err = FskFSFileCreateDirectory(*fullPath);
			err = kFskErrNone;
			goto makeit;
		case kFskDirectorySpecialTypeCache:
			*fullPath = FskStrDoCat(dataDir, "tmp/");
			err = FskFSFileCreateDirectory(*fullPath);
			err = kFskErrNone;
			goto makeit;
		default:
			FskAndroidFilesPrintfDebug("SpecialDirectory - bad special directory\n");
			BAIL(kFskErrInvalidParameter);
	}

	if (specialDir)
		tmp = FskStrDoCopy(FskEnvironmentGet(specialDir));

	if (!tmp) {
		char *home;
		home = dataDir;
		err = FskMemPtrNewClear(FskStrLen(home) + FskStrLen(specialDir) + 3, (FskMemPtr*)(void*)&tmp);
		BAIL_IF_ERR(err);
		FskStrCopy(tmp, home);
		if (tmp[FskStrLen(tmp)-1] != '/')
			FskStrCat(tmp, "/");
		if (specialDir) {
			FskStrCat(tmp, specialDir);
			FskStrCat(tmp, "/");
		}
	}
	FskAndroidFilesPrintfDebug("looking for %s - got %s", specialDir, tmp);
	*fullPath = tmp;

makeit:
	if (doCreate) {
		err = FskFSFileCreateDirectory(*fullPath);
	}
	else {
		err = FskFSFileGetFileInfo(*fullPath, &finfo);
		if (kFskErrNone == err) {
			if (kFskDirectoryItemIsDirectory != finfo.filetype)
				BAIL(kFskErrNotDirectory);
		}
	}

bail:
	if (kFskErrFileExists == err) {
		err = kFskErrNone;
		FskAndroidFilesPrintfDebug("DIRECTORY EXISTS specialDirectory - looking for type %d - got [%s]", type, *fullPath);
	}
	else if (kFskErrNone != err) {
		FskAndroidFilesPrintfDebug("DIRECGOTRY DIDN'T EXIST - specialDirectory - looking for type %d - got [%s] err: %d", type, *fullPath, err);
	}

	return err;
}