FskErr KprURLMerge(char* base, char* reference, char** result) { FskErr err = kFskErrNone; KprURLPartsRecord parts; KprURLPartsRecord baseParts; char* path = NULL; UInt32 length; KprURLSplit(reference, &parts); if (!parts.scheme) { KprURLSplit(base, &baseParts); parts.scheme = baseParts.scheme; parts.schemeLength = baseParts.schemeLength; if (!parts.authority) { parts.authority = baseParts.authority; parts.authorityLength = baseParts.authorityLength; if (!parts.pathLength) { if (baseParts.authority && !baseParts.pathLength) { bailIfError(FskMemPtrNew(1, &path)); FskMemMove(path, "/", 1); parts.path = path; parts.pathLength = 1; } else { parts.path = baseParts.path; parts.pathLength = baseParts.pathLength; } if (!parts.query) { parts.query = baseParts.query; parts.queryLength = baseParts.queryLength; } } else if (*parts.path != '/') { if (baseParts.authority && !baseParts.pathLength) { bailIfError(FskMemPtrNew(1 + parts.pathLength, &path)); FskMemMove(path, "/", 1); FskMemMove(path + 1, parts.path, parts.pathLength); parts.path = path; parts.pathLength++; } else if (baseParts.name) { length = baseParts.name - baseParts.path; bailIfError(FskMemPtrNew(length + parts.pathLength, &path)); FskMemMove(path, baseParts.path, length); FskMemMove(path + length, parts.path, parts.pathLength); parts.path = path; parts.pathLength += length; } } } } bailIfError(KprURLJoin(&parts, result)); bail: FskMemPtrDispose(path); return err; }
FskErr KprMessageNew(KprMessage *it, char* url) { FskErr err = kFskErrNone; KprMessage self; bailIfError(FskMemPtrNewClear(sizeof(KprMessageRecord), it)); self = *it; FskInstrumentedItemNew(self, NULL, &KprMessageInstrumentation); self->url = FskStrDoCopy(url); bailIfNULL(self->url); KprURLSplit(self->url, &self->parts); self->priority = 256; bail: return err; }
void KPR_parseURI(xsMachine *the) { xsStringValue url = xsToString(xsArg(0)); KprURLPartsRecord parts; xsStringValue target; char c; xsThrowIfFskErr(FskMemPtrNew(FskStrLen(url) + 1, &target)); FskStrCopy(target, url); KprURLSplit(target, &parts); xsResult = xsNewInstanceOf(xsObjectPrototype); if (parts.scheme) { c = *(parts.scheme + parts.schemeLength); *(parts.scheme + parts.schemeLength) = 0; xsNewHostProperty(xsResult, xsID_scheme, xsString(parts.scheme), xsDefault, xsDontScript); *(parts.scheme + parts.schemeLength) = c; } if (parts.authority) { c = *(parts.authority + parts.authorityLength); *(parts.authority + parts.authorityLength) = 0; xsNewHostProperty(xsResult, xsID_authority, xsString(parts.authority), xsDefault, xsDontScript); *(parts.authority + parts.authorityLength) = c; } if (parts.path) { c = *(parts.path + parts.pathLength); *(parts.path + parts.pathLength) = 0; xsNewHostProperty(xsResult, xsID_path, xsString(parts.path), xsDefault, xsDontScript); *(parts.path + parts.pathLength) = c; } if (parts.name) { c = *(parts.name + parts.nameLength); *(parts.name + parts.nameLength) = 0; xsNewHostProperty(xsResult, xsID_name, xsString(parts.name), xsDefault, xsDontScript); *(parts.name + parts.nameLength) = c; } if (parts.query) { c = *(parts.query + parts.queryLength); *(parts.query + parts.queryLength) = 0; xsNewHostProperty(xsResult, xsID_query, xsString(parts.query), xsDefault, xsDontScript); *(parts.query + parts.queryLength) = c; } if (parts.fragment) { c = *(parts.fragment + parts.fragmentLength); *(parts.fragment + parts.fragmentLength) = 0; xsNewHostProperty(xsResult, xsID_fragment, xsString(parts.fragment), xsDefault, xsDontScript); *(parts.fragment + parts.fragmentLength) = c; } FskMemPtrDispose(target); }
void KprMessageComplete(KprMessage self) { char* url; FskThread thread = KprShellGetThread(gShell); if (!thread) return; // @@ happens on exit if (thread != FskThreadGetCurrent()) { FskThreadPostCallback(thread, (FskThreadCallback)KprMessageComplete, self, NULL, NULL, NULL); return; } FskInstrumentedItemSendMessageDebug(self, kprInstrumentedMessageComplete, self); if (FskListRemove(&gShell->messages, self)) { self->usage--; // message queue self->waiting = false; url = KprMessageGetResponseHeader(self, "location"); if (url && (!FskStrCompareWithLength(self->url, "xkpr", 4)) && ((!self->sniffing) || (!FskStrCompareWithLength(url, "xkpr", 4)))) { FskMemPtrDispose(self->url); self->url = FskStrDoCopy(url); //bailIfNULL(self->url); KprURLSplit(self->url, &self->parts); FskAssociativeArrayDispose(self->response.headers); self->response.headers = NULL; FskMemPtrDispose(self->response.body); self->response.body = NULL; self->response.size = 0; if (self->request.target) self->usage--; // @@ request if (kFskErrNone == KprMessageInvoke(self, self->request.callback, self->request.dispose, self->request.target)) return; } if (self->request.target) { if (self->request.callback) (*self->request.callback)(self, self->request.target); if (self->request.dispose) (*self->request.dispose)(self->request.target); self->request.callback = NULL; self->request.dispose = NULL; self->request.target = NULL; self->usage--; // request } if (!self->usage) KprMessageDispose(self); } }
FskErr KprMessageURL(KprContext context, char* url, char** result) { FskErr err = kFskErrNone; KprURLPartsRecord parts; KprURLSplit(url, &parts); if (!parts.scheme) { parts.scheme = "xkpr"; parts.schemeLength = 4; if (!parts.authority) { parts.authority = context->id; parts.authorityLength = FskStrLen(parts.authority); } bailIfError(KprURLJoin(&parts, result)); } else { *result = FskStrDoCopy(url); bailIfNULL(*result); } bail: return err; }
FskErr KprLibraryServerRequestConditionCallback(FskHTTPServerRequest request, UInt32 condition, void *refCon) { FskErr err = kFskErrNone; KprLibraryServer self = request->http->refCon; KprLibrarySession session = refCon; switch (condition) { case kFskHTTPConditionConnectionInitialized: case kFskHTTPConditionNoSocket: case kFskHTTPConditionRequestReceivedRequestHeaders: break; case kFskHTTPConditionRequestRequestFinished: { FskHeaders *headers; UInt32 queryIndex; KprLibraryQuery query; bailIfError(KprLibrarySessionNew(&session, request)); FskInstrumentedItemSetOwner(session, self); headers = FskHTTPServerRequestGetRequestHeaders(request); queryIndex = FskStrToNum(headers->filename); FskMutexAcquire(self->queryMutex); query = self->queries[queryIndex % kQueryCount]; if (query && (query->index == queryIndex)) { session->info = FskStrDoCopy(query->info); session->kind = query->kind; session->mime = FskStrDoCopy(query->mime); session->url = FskStrDoCopy(query->url); if (query->authorization) session->authorization = FskStrDoCopy(query->authorization); } else err = kFskErrNotFound; FskMutexRelease(self->queryMutex); if (kFskErrNone == err) { KprURLSplit(session->url, &session->parts); if (0 == FskStrCompareWithLength(session->url, "file", 4)) err = KprFileServerOpen(session); else if (0 == FskStrCompareWithLength(session->url, "http", 4)) { session->http.location = FskStrDoCopy(session->url); err = KprProxyServerOpen(session); } else err = KprDataServerOpen(session); } if (kFskErrNeedMoreTime == err) FskHTTPServerRequestSuspend(request); else session->error = err; err = kFskErrNone; } break; case kFskHTTPConditionRequestGenerateResponseHeaders: if (session) { FskHeaders *responseHeaders = FskHTTPServerRequestGetResponseHeaders(request); if (session->error) { if (kFskErrNotFound == session->error) responseHeaders->responseCode = 404; else responseHeaders->responseCode = 500; FskHeaderAddString(kFskStrContentLength, "0", responseHeaders); FskInstrumentedItemPrintfNormal(session, "response headers error %ld", session->error); } else if (session->file.file) KprFileServerGenerateResponseHeaders(session, responseHeaders); else if (session->http.client) KprProxyServerGenerateResponseHeaders(session, responseHeaders); else KprDataServerGenerateResponseHeaders(session, responseHeaders); } break; case kFskHTTPConditionConnectionTerminating: err = kFskErrUnimplemented; //@@ or hang on exit... weird. case kFskHTTPConditionRequestResponseFinished: case kFskHTTPConditionRequestErrorAbort: if (session) KprLibrarySessionDispose(session); break; default: err = kFskErrUnimplemented; break; } bail: return err; }