コード例 #1
0
Boolean mp3ReaderCanHandle(const char *mimeType)
{
	const char *semi = FskStrChr(mimeType, ';');
	UInt32 length = semi ? (UInt32)(semi - mimeType) : FskStrLen(mimeType);

	if (0 == FskStrCompareCaseInsensitiveWithLength("audio/mpeg", mimeType, length))
		return true;

	if (0 == FskStrCompareCaseInsensitiveWithLength("audio/aac", mimeType, length))
		return true;

	if (0 == FskStrCompareCaseInsensitiveWithLength("audio/vnd.dlna.adts", mimeType, length))
		return true;

	return false;
}
コード例 #2
0
ファイル: kprHTTPClient.c プロジェクト: Kazu-zamasu/kinomajs
Boolean KprHTTPConnectionCandidate(KprHTTPConnection self, KprMessage message)
{
	Boolean result = false;
	if (!self->client)
		result = true;
	else if (!self->client->host)
		result = true;
	else {
		UInt32 hostLength = FskStrLen(self->client->host);
		result = (FskStrCompareCaseInsensitiveWithLength(self->client->host, message->parts.host, (hostLength > message->parts.hostLength) ? hostLength : message->parts.hostLength) == 0)
			&& (self->client->hostPort == (int)message->parts.port) 
			&& (self->client->priority == abs(message->priority));
		if (result && self->target) // only serialize if the message target is the same
			result = self->target->message->request.target == message->request.target;
	}
	return result;
}
コード例 #3
0
ファイル: kprURL.c プロジェクト: giapdangle/kinomajs
void KprURLSplit(char* url, KprURLParts parts)
{
	char c, *p, *q;
	FskMemSet(parts, 0, sizeof(KprURLPartsRecord));
	q = p = url;
	while ((c = *p)) {
		if ((c == ':') || (c == '/') || (c == '?') || (c == '#'))
			break;
		p++;
	}
	if (c == ':') {
		parts->scheme = q;
		parts->schemeLength = p - q;
		p++;
		q = p;
		c = *p;
	}
	if (c == '/') {
		p++;
		c = *p;
		if (c == '/') {
			char *semi = NULL;
			p++;
			parts->authority = q = p;
			while ((c = *p)) {
				if (c == '/')
					break;
				if (c == ':')
					semi = p;
				if (c == '@') {
					parts->host = p + 1;
					parts->user = q;
					if (semi) {
						parts->userLength = semi - q;
						parts->password = semi + 1;
						parts->passwordLength = p - semi - 1;
						semi = NULL;
					}
					else
						parts->userLength = p - q;
				}
				p++;
			}
			parts->authorityLength = p - q;
			if (parts->authorityLength) {
				if (!parts->host)
					parts->host = q;
				if (semi) {
					parts->hostLength = semi - parts->host;
					parts->port = FskStrToNum(semi + 1);
				}
				else {
					if (parts->schemeLength) {
						if (!FskStrCompareCaseInsensitiveWithLength(parts->scheme, "https", 5))
							parts->port = 443;
						else if (!FskStrCompareCaseInsensitiveWithLength(parts->scheme, "http", 4))
							parts->port = 80;
					}
					parts->hostLength = p - parts->host;
				}
			}
			q = p;
		}
		else if (c)
			parts->name = p;
	}
	while ((c = *p)) {
		if (c == '/')
			parts->name = p + 1;
		if ((c == '?') || (c == '#'))
			break;
		p++;
	}
	parts->path = q;
	parts->pathLength = p - q;
	if (parts->name)
		parts->nameLength = p - parts->name;
	if (c == '?') {
		p++;
		parts->query = q = p;
		while ((c = *p)) {
			if (c == '#')
				break;
			p++;
		}
		parts->queryLength = p - q;
	}
	if (c == '#') {
		p++;
		parts->fragment = q = p;
		while ((c = *p)) {
			p++;
		}
		parts->fragmentLength = p - q;
	}
}
コード例 #4
0
FskErr mp3RefillReadBuffer(mp3Reader state, UInt32 minimumBytesNeeded)
{
	FskErr err = kFskErrNone;
	UInt32 bytesInBuffer = (UInt32)(state->readBufferEnd - state->readBufferPtr);
	UInt32 bytesRead;
	void *buffer;
	Boolean firstTime = true;

	FskMemMove(state->readBuffer, state->readBufferPtr, bytesInBuffer);
	state->readBufferPtr = state->readBuffer;
	state->readBufferEnd = state->readBufferPtr + bytesInBuffer;

	while (true) {
		UInt32 bytesToRead = kMP3ReadBufferSize - bytesInBuffer;

		if (state->spoolerSize && ((state->position + bytesToRead) > state->spoolerSize)) {
			bytesToRead = (UInt32)(state->spoolerSize - state->position);
			if (0 == bytesToRead) {
				err = kFskErrEndOfFile;
				goto bail;
			}
		}

		if (0 != state->icy.metaInt) {
			if (0 != state->icy.metaBytesToCollect) {
				err = FskMediaSpoolerRead(state->spooler, state->position, state->icy.metaBytesToCollect, &buffer, &bytesRead);
				if (kFskErrNone != err) goto readErr;

				state->position += bytesRead;

				err = FskMemPtrRealloc(state->icy.metaBytesCollected + bytesRead + 1, &state->icy.metaBytes);
				if (err) return err;

				FskMemMove(state->icy.metaBytes + state->icy.metaBytesCollected, buffer, bytesRead);
				state->icy.metaBytes[state->icy.metaBytesCollected + bytesRead] = 0;

				state->icy.metaBytesCollected += bytesRead;
				state->icy.metaBytesToCollect -= bytesRead;
				if (0 == state->icy.metaBytesToCollect) {
					if (0 == FskStrCompareCaseInsensitiveWithLength((char *)state->icy.metaBytes, "StreamTitle=", 12)) {
						char *start = (char *)state->icy.metaBytes + 13;
						char *end = start;
						char *dash;
						FskMediaPropertyValueRecord prop;

						while (true) {
							end = FskStrChr(end, start[-1]);
							if (NULL == end) break;
							if ((0 != end[1]) && (';' != end[1])) {
								end += 1;
								continue;
							}
							break;
						}
						if (end)
							*end = 0;

						while (true) {
							if (kFskErrNone != FskMediaMetaDataRemove(state->mi.meta, "FullName", 0))
								break;
						}

						dash = FskStrStr(start, " - ");
						if (NULL != dash) {
							while (true) {
								if (kFskErrNone != FskMediaMetaDataRemove(state->mi.meta, "Artist", 0))
									break;
							}

							*dash = 0;

							prop.type = kFskMediaPropertyTypeString;
							prop.value.str = icyString(start);
							FskMediaMetaDataAdd(state->mi.meta, "Artist", NULL, &prop, kFskMediaMetaDataFlagOwnIt);

							prop.type = kFskMediaPropertyTypeString;
							prop.value.str = icyString(dash + 3);
							FskMediaMetaDataAdd(state->mi.meta, "FullName", NULL, &prop, kFskMediaMetaDataFlagOwnIt);
						}
						else {
							prop.type = kFskMediaPropertyTypeString;
							prop.value.str = icyString(start);
							FskMediaMetaDataAdd(state->mi.meta, "FullName", NULL, &prop, kFskMediaMetaDataFlagOwnIt);
						}

						FskMediaReaderSendEvent(state->reader, kFskEventMediaPlayerMetaDataChanged);
					}
					FskMemPtrDisposeAt((void**)(void*)(&state->icy.metaBytes));
				}
				continue;
			}
			else
			if (state->position == state->icy.nextMetaPosition) {
				err = FskMediaSpoolerRead(state->spooler, state->position, 1, &buffer, &bytesRead);
				if (kFskErrNone != err) goto readErr;

				state->position += 1;
				state->icy.metaBytesToCollect = ((unsigned char *)buffer)[0] * 16;
				state->icy.metaBytesCollected = 0;
				state->icy.nextMetaPosition += 1 + state->icy.metaBytesToCollect + state->icy.metaInt;
				continue;
			}
			else
			if ((state->position <= state->icy.nextMetaPosition) && (state->icy.nextMetaPosition < (state->position + bytesToRead)))
				bytesToRead = (UInt32)(state->icy.nextMetaPosition - state->position);
		}

		err = FskMediaSpoolerRead(state->spooler, state->position, bytesToRead, &buffer, &bytesRead);
readErr:
		if (err) {
			if (false == firstTime) {
				err = kFskErrNone;
				break;
			}
			goto bail;
		}

		FskMemMove(state->readBufferEnd, buffer, bytesRead);

		state->position += bytesRead;
		state->readBufferEnd += bytesRead;
		bytesInBuffer = (UInt32)(state->readBufferEnd - state->readBufferPtr);

		if ((kMP3ReadBufferSize == bytesInBuffer) || (bytesInBuffer >= minimumBytesNeeded))
			break;

		firstTime = false;
	}

	if (bytesInBuffer < minimumBytesNeeded) {
		err = kFskErrNeedMoreTime;
		goto bail;
	}

bail:
	return err;
}
コード例 #5
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
static void httpPrepareResponseHeaders(FskHTTPServerRequest request) {
	char	*str;
	int		requestProtocolVersion;

	requestProtocolVersion = FskHeaderHTTPVersion(request->requestHeaders);

	if (NULL == FskHeaderFind(kFskStrServer, request->responseHeaders))
		FskHeaderAddString(kFskStrServer, kHTTPServerIdentifier, request->responseHeaders);

	str = FskHeaderFind(kFskStrConnection, request->responseHeaders);
	if (str && FskStrCompareCaseInsensitiveWithLength(str, kFskStrClose, 5) == 0)
		request->keepAlive = false;

	str = FskHeaderFind(kFskStrTransferEncoding, request->responseHeaders);
	if (str && (FskStrCompareCaseInsensitiveWithLength(str, kFskStrChunked, FskStrLen(kFskStrChunked)) == 0)) {
		request->transferEncoding = kFskTransferEncodingChunked;
	}
	else {
		request->transferEncoding = kFskTransferEncodingNone;
		str = FskHeaderFind(kFskStrContentLength, request->responseHeaders);
		if (str) {
			request->stats.expectedBodyToSend = FskStrToNum(str);
		}
		else if (requestProtocolVersion >= kFskHTTPVersion1dot1) {
			// DHWG 7.8.1 - if http server is responding to 1.1 requests,
			// it must use connection:close if there's no content length
			// or chunked encoding
			FskHeaderRemove(kFskStrConnection, request->responseHeaders);
			FskHeaderAddString(kFskStrConnection, kFskStrClose, request->responseHeaders);
		}
	}
	
	if (requestProtocolVersion <= kFskHTTPVersion1dot0) {
		request->keepAlive = false;		// DHWG 7.8.21 (must ignore keepalive)
		FskHeaderRemove(kFskStrConnection, request->responseHeaders);
		FskHeaderAddString(kFskStrConnection, kFskStrClose, request->responseHeaders);
		FskMemPtrDispose(request->requestHeaders->protocol);

		request->requestHeaders->protocol = FskStrDoCopy("HTTP/1.0");

		if (0 == FskStrCompareCaseInsensitiveWithLength(FskHeaderFind(kFskStrTransferEncoding, request->responseHeaders), kFskStrChunked, FskStrLen(kFskStrChunked))) {
			FskHeaderRemove(kFskStrTransferEncoding, request->responseHeaders);
			request->transferEncoding = kFskTransferEncodingNone;
		}
		if (request->stats.expectedBodyToSend == 0) {
			FskHeaderRemove(kFskStrConnection, request->responseHeaders);
			FskHeaderAddString(kFskStrConnection, kFskStrClose, request->responseHeaders);
		}
	}

	if (request->requestHeaders->responseCode >= 400) {
		request->out.max = snprintf(request->out.buf, request->out.bufferSize, "%s %d %s\r\n", httpProtocolVersionString(request), request->requestHeaders->responseCode, FskFindResponse(request->requestHeaders->responseCode));
	}
	else if (request->responseHeaders->responseCode > 0) {
		str = FskFindResponse(request->responseHeaders->responseCode);
		request->out.max = snprintf(request->out.buf, request->out.bufferSize, "%s %d %s\r\n", httpProtocolVersionString(request), request->responseHeaders->responseCode, str ? str : "");
		if (request->keepAlive) {
			FskHeaderRemove(kFskStrConnection, request->responseHeaders);
			FskHeaderAddString(kFskStrConnection, kFskStrKeepAlive, request->responseHeaders);
		}
	}
	else {
		request->responseHeaders->responseCode = 500;
		request->out.max = snprintf(request->out.buf, request->out.bufferSize, "%s 500 Internal Sever Error\r\n", httpProtocolVersionString(request));
	}

	if (NULL == FskHeaderFind(kFskStrDate, request->responseHeaders)) {
		char dateString[32];
		FskTimeMakeDate(dateString, 31);
		FskHeaderAddString(kFskStrDate, dateString, request->responseHeaders);
	}

	// *** generate the response
	request->out.max += FskHeaderGenerateOutputBlob(&request->out.buf[request->out.max], request->out.bufferSize - request->out.max, true, request->responseHeaders);

	if ((!request->keepAlive) || (request->responseHeaders->responseCode >= 400))
		request->nextState = kHTTPDone;
}
コード例 #6
0
ファイル: FskHTTPServer.c プロジェクト: archite/kinomajs
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;
	}
}
コード例 #7
0
ファイル: FskHeaders.c プロジェクト: Kazu-zamasu/kinomajs
// ------------------------------------------------------------------------
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;
}
コード例 #8
0
ファイル: kprHTTPClient.c プロジェクト: Kazu-zamasu/kinomajs
Boolean KprHTTPClientPutTargetCache(KprHTTPTarget target)
{
	FskErr err = kFskErrNone;
	char* control = NULL;
	KprHTTPClient self = gKprHTTPClient;
	KprMessage message = target->message;
	
	UInt32 date = 0;
	UInt32 maxAge = 0;
	UInt32 lifetime = 0;
	char* start;
	char* next;
	char* end;
	Boolean foundAge = false;
	Boolean revalidate = false;
	KprHTTPCacheValue cached = NULL;
	
	bailIfError(message->error
				|| !FskStrCompareCaseInsensitiveWithLength(message->url, "https://", 8)
				|| ((message->status != 200) && (message->status != 203))
				|| (message->method && FskStrCompare(message->method, "GET")) // only caching GET method
				|| (message->user != NULL) // do not cache request with credentials
				|| (message->password != NULL) // do not cache request with credentials
				|| (message->response.size == 0) // only caching something
				|| (message->response.size > 384000)); // not caching big files

	if ((control = KprMessageGetResponseHeader(message, kFskStrCacheControl))) {
		start = control;
		end = control + FskStrLen(control);
		// split
		while (start < end) {
			if (*start == ',') *start = 0;
			start++;
		}
		start = control;
		while (start <= end) {
			next = start + FskStrLen(start) + 1;
			start = FskStrStripHeadSpace(start);
			if (!FskStrCompareCaseInsensitiveWithLength(start, "max-age", 7)) {
				bailIfError(!(start = FskStrStripHeadSpace(start + 7)));
				bailIfError(*start != '=');
				bailIfError(!(start = FskStrStripHeadSpace(start + 1)));
				maxAge = FskStrToNum(start);
				foundAge = true;
			}
			else if (!FskStrCompareCaseInsensitiveWithLength(start, "no-cache", 8)) {
				revalidate = true;
			}
			else if (!FskStrCompareCaseInsensitiveWithLength(start, "no-store", 8)) {
				BAIL(kFskErrInvalidParameter);
			}
			else if (!FskStrCompareCaseInsensitiveWithLength(start, "must-revalidate", 15)) {
				revalidate = true;
			}
			start = next;
		}
	}
	KprDateFromHTTP(KprMessageGetResponseHeader(message, kprHTTPHeaderDate), &date);
	if (foundAge)
		lifetime = maxAge;
	else {
		UInt32 expire = 0;
		KprDateFromHTTP(KprMessageGetResponseHeader(message, kFskStrExpires), &expire);
		if (date && expire)
			lifetime = (expire > date) ? expire - date : 0;
		else if (!KprMessageGetResponseHeader(message, kprHTTPHeaderETag)
			&& !KprMessageGetResponseHeader(message, kprHTTPHeaderLastModified))
			BAIL(kFskErrInvalidParameter); // not cached
	}
	if (KprMessageGetResponseHeader(message, kprHTTPHeaderVary))
		revalidate = true;
	if (!revalidate)
		lifetime += 180; // guess 3 minutes
//	put in cache
//	fprintf(stderr, "%p: CACHE %s for %d (%d)\n", message, message->url, lifetime, revalidate);
	bailIfError(KprHTTPCacheValueNew(&cached));
	KprDateFromHTTP(KprMessageGetResponseHeader(message, kprHTTPHeaderAge), &cached->age);
	cached->date = date;
	cached->lifetime = lifetime;
	cached->requestDate = target->requestDate;
	cached->responseDate = target->responseDate;
	cached->status = message->status;
	
	cached->headers = FskAssociativeArrayNew();
	{
		FskAssociativeArrayIterator iterate = FskAssociativeArrayIteratorNew(message->response.headers);
		while (iterate) {
			FskAssociativeArrayElementSet(cached->headers, iterate->name, iterate->value, 0, kFskStringType);
			iterate = FskAssociativeArrayIteratorNext(iterate);
		}
		FskAssociativeArrayIteratorDispose(iterate);
	}
	KprHTTPCacheValueCleanupHeaders(cached);
	
	cached->size = message->response.size;
	cached->body = message->response.body;
	target->cached = cached;
	bailIfError(KprHTTPCachePut(self->cache, message->url, cached));
	
bail:
	if (control) {
		// unsplit
		start = control;
		while (start < end) {
			if (*start == 0) *start = ',';
			start++;
		}
	}
	if (err == kFskErrNone) return true;
	target->cached = NULL;
	if (cached)
		KprMemPtrDispose(cached);
	return false;
}