void ejsLexRestoreInputState(Ejs *ep, EjsInput *state) { EjsInput *ip; EjsToken *tp; int i; mprAssert(ep); mprAssert(state); ip = ep->input; mprAssert(ip); mprStrcpy(ip->tokbuf, sizeof(ip->tokbuf), state->tokbuf); ip->tokServp = state->tokServp; ip->tokEndp = state->tokEndp; ip->script = state->script; ip->scriptServp = state->scriptServp; ip->scriptSize = state->scriptSize; ip->putBackIndex = state->putBackIndex; for (i = 0; i <= ip->putBackIndex; i++) { tp = &ip->putBack[i]; tp->tid = state->putBack[i].tid; mprStrcpy(tp->tokbuf, sizeof(tp->tokbuf), state->putBack[i].tokbuf); } mprStrcpy(ip->line, sizeof(ip->line), state->line); ip->lineColumn = state->lineColumn; ip->lineNumber = state->lineNumber; }
void MprLogToFile::logEvent(char *module, int flags, int level, char *thread, char *msg) { char buf[MPR_MAX_LOG_STRING]; if (mprGetMpr() == 0) { mprStrcpy(buf, sizeof(buf), msg); } else if (timeStamps) { #if CYGWIN || LINUX || MACOSX || SOLARIS || VXWORKS || FREEBSD #if BLD_FEATURE_HIRES_TIME int64 elapsed = mprGetElapsedTime(); mprSprintf(buf, sizeof(buf), "%,14Ld %10s:%d %s %s", elapsed, module, level, thread, msg); #else static int last = 0; int now = mprGetTime(0); int elapsed = now - last; mprSprintf(buf, sizeof(buf), "%,14d %10s:%d %s %s", elapsed, module, level, thread, msg); last = now; #endif #endif // CYGWIN || LINUX || MACOSX || SOLARIS || VXWORKS || FREEBSD } else if (! (flags & MPR_RAW)) { mprSprintf(buf, sizeof(buf), "%10s:%d %4s %s", module, level, thread, msg); } else { // Raw output mprStrcpy(buf, sizeof(buf), msg); } if (logFd < 0) { if (level <= 1) { // // Always output fatal and error messages // mprFprintf(MPR_STDERR, buf); } return; } // OPT -- could get length above mprAssert(logFd >= 0); write(logFd, buf, strlen(buf)); if (logFd != MPR_STDOUT) { struct stat sbuf; if (maxSize <= 0 || fstat(logFd, &sbuf) < 0) { return; } // // Rotate logs when full // if (sbuf.st_mode & S_IFREG && (unsigned) sbuf.st_size > maxSize) { rotate(); } } }
int mprCtime(MprCtx ctx, char *buf, int bufsize, const time_t *timer) { char localBuf[80]; char *cp; int len; mprAssert(buf); mprGlobalLock(ctx); cp = ctime_r(timer, localBuf); if ((int) strlen(cp) >= bufsize) { mprStrcpy(buf, bufsize, "WONT FIT"); mprAssert(0); return MPR_ERR_WONT_FIT; } len = mprStrcpy(buf, bufsize, cp); if (buf[len - 1] == '\n') { buf[len - 1] = '\0'; } mprGlobalUnlock(ctx); return 0; }
/* * Simple wild-card matching */ static int match(char *file, char *pat) { char fileBuf[MPR_MAX_FNAME], patBuf[MPR_MAX_FNAME]; char *patExt; char *fileExt; mprStrcpy(fileBuf, sizeof(fileBuf), file); file = fileBuf; mprStrcpy(patBuf, sizeof(patBuf), pat); pat = patBuf; if (strcmp(file, pat) == 0) { return 1; } if ((fileExt = strrchr(file, '.')) != 0) { *fileExt++ = '\0'; } if ((patExt = strrchr(pat, '.')) != 0) { *patExt++ = '\0'; } if (*pat == '*' || strcmp(pat, file) == 0) { if (patExt && *patExt == '*') { return 1; } else { if (fileExt && strcmp(fileExt, patExt) == 0) { return 1; } } } return 0; }
void ejsLexSaveInputState(Ejs *ep, EjsInput *state) { EjsInput *ip; int i; mprAssert(ep); ip = ep->input; mprAssert(ip); *state = *ip; for (i = 0; i < ip->putBackIndex; i++) { state->putBack[i].token = mprStrdup(ip->putBack[i].token); state->putBack[i].id = ip->putBack[i].id; } for (; i < EJS_TOKEN_STACK; i++) { state->putBack[i].token = 0; } state->line = mprMalloc(ip->lineLength); mprStrcpy(state->line, ip->lineLength, ip->line); state->lineColumn = ip->lineColumn; state->lineNumber = ip->lineNumber; state->lineLength = ip->lineLength; }
void ejsLexRestoreInputState(Ejs *ep, EjsInput *state) { EjsInput *ip; int i; mprAssert(ep); mprAssert(state); ip = ep->input; mprAssert(ip); ip->tokbuf = state->tokbuf; ip->tokServp = state->tokServp; ip->tokEndp = state->tokEndp; ip->tokSize = state->tokSize; ip->script = state->script; ip->scriptServp = state->scriptServp; ip->scriptSize = state->scriptSize; ip->putBackIndex = state->putBackIndex; for (i = 0; i < ip->putBackIndex; i++) { mprFree(ip->putBack[i].token); ip->putBack[i].id = state->putBack[i].id; ip->putBack[i].token = mprStrdup(state->putBack[i].token); } mprFree(ip->line); ip->line = mprMalloc(state->lineLength); mprStrcpy(ip->line, state->lineLength, state->line); ip->lineColumn = state->lineColumn; ip->lineNumber = state->lineNumber; ip->lineLength = state->lineLength; }
static void printQueryData(MaQueue *q) { MaRequest *req; char buf[MPR_MAX_STRING], **keys, *value; int i, numKeys; req = q->conn->request; if (req->parsedUri->query == 0) { return; } mprStrcpy(buf, sizeof(buf), req->parsedUri->query); numKeys = getVars(q, &keys, buf, (int) strlen(buf)); if (numKeys == 0) { maWrite(q, "<H2>No Query Data Found</H2>\r\n"); } else { maWrite(q, "<H2>Decoded Query Data Variables</H2>\r\n"); for (i = 0; i < (numKeys * 2); i += 2) { value = keys[i+1]; maWrite(q, "<p>QVAR %s=%s</p>\r\n", keys[i], value ? value: ""); } } maWrite(q, "\r\n"); mprFree(keys); }
/* * Find an exact dir match. May be called with raw file names. ie. D:\myDir */ MaDir *maLookupDir(MaHost *host, cchar *path) { MaDir *dir; char *absPath, buf[MPR_MAX_FNAME]; int next, len; /* * Cannonicalize and ensure path has a trailing "/" */ absPath = mprGetAbsFilename(host, path); mprStrcpy(buf, sizeof(buf), absPath); len = (int) strlen(buf); if (buf[len - 1] != '/') { buf[len] = '/'; buf[++len] = '\0'; } for (next = 0; (dir = mprGetNextItem(host->dirs, &next)) != 0; ) { if (dir->path != 0) { #if WIN if (mprStrcmpAnyCase(dir->path, buf) == 0) #else if (strcmp(dir->path, buf) == 0) #endif return dir; } } return 0; }
/* * Convert a unicode string newly allocated C string */ char *mprUsToStr(uni *us) { char *str, *cp; mprAssert(us); str = cp = mprAlloc(us, us->length + 1); if (cp == 0) { return 0; } #if BLD_FEATURE_UTF16 { uniData *up; int i; up = us->str; for (i = 0; i < us->length; i++) { cp[i] = up[i]; } } #else mprStrcpy(cp, us->length, us->str); #endif return str; }
void mprWriteToOsLog(MprCtx ctx, cchar *message, int flags, int level) { HKEY hkey; void *event; long errorType; ulong exists; char buf[MPR_MAX_STRING], logName[MPR_MAX_STRING], *lines[9], *cp, *value; int type; static int once = 0; mprStrcpy(buf, sizeof(buf), message); cp = &buf[strlen(buf) - 1]; while (*cp == '\n' && cp > buf) { *cp-- = '\0'; } type = EVENTLOG_ERROR_TYPE; lines[0] = buf; lines[1] = 0; lines[2] = lines[3] = lines[4] = lines[5] = 0; lines[6] = lines[7] = lines[8] = 0; if (once == 0) { /* Initialize the registry */ once = 1; mprSprintf(logName, sizeof(logName), "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", mprGetAppName(ctx)); hkey = 0; if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, logName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, &exists) == ERROR_SUCCESS) { value = "%SystemRoot%\\System32\\netmsg.dll"; if (RegSetValueEx(hkey, "EventMessageFile", 0, REG_EXPAND_SZ, (uchar*) value, (int) strlen(value) + 1) != ERROR_SUCCESS) { RegCloseKey(hkey); return; } errorType = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; if (RegSetValueEx(hkey, "TypesSupported", 0, REG_DWORD, (uchar*) &errorType, sizeof(DWORD)) != ERROR_SUCCESS) { RegCloseKey(hkey); return; } RegCloseKey(hkey); } } event = RegisterEventSource(0, mprGetAppName(ctx)); if (event) { /* * 3299 is the event number for the generic message in netmsg.dll. * "%1 %2 %3 %4 %5 %6 %7 %8 %9" -- thanks Apache for the tip */ ReportEvent(event, EVENTLOG_ERROR_TYPE, 0, 3299, NULL, sizeof(lines) / sizeof(char*), 0, (LPCSTR*) lines, 0); DeregisterEventSource(event); } }
int Mpr::loadDll(char *path, char *fnName, void *arg, void **handlePtr) { MprDllEntryProc fn; char localPath[MPR_MAX_FNAME], dir[MPR_MAX_FNAME]; void *handle; char *cp; int rc; mprAssert(path && *path); mprAssert(fnName && *fnName); mprGetDirName(dir, sizeof(dir), path); mprSetModuleSearchPath(dir); mprStrcpy(localPath, sizeof(localPath), path); // TODO - good to have a x-platform method for this. for (cp = localPath; *cp; cp++) { if (*cp == '/') { *cp = '\\'; } } if ((handle = GetModuleHandle(mprGetBaseName(localPath))) == 0) { if ((handle = LoadLibraryEx(localPath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) { char cwd[1024], *env; getcwd(cwd, sizeof(cwd) - 1); env = getenv("PATH"); mprLog(0, "ERROR %d\n", GetLastError()); mprLog(0, "Can't load %s\nReason: \"%d\"\n", path, mprGetOsError()); mprLog(0, "CWD %s\n PATH %s\n", cwd, env); return MPR_ERR_CANT_OPEN; } } fn = (MprDllEntryProc) GetProcAddress((HINSTANCE) handle, fnName); if (fn == 0) { FreeLibrary((HINSTANCE) handle); mprLog(0, "Can't load %s\nReason: can't find function \"%s\"\n", localPath, fnName); return MPR_ERR_NOT_FOUND; } mprLog(MPR_INFO, "Loading DLL %s\n", path); if ((rc = (fn)(arg)) < 0) { FreeLibrary((HINSTANCE) handle); mprError(MPR_L, MPR_LOG, "Initialization for %s failed.", path); return MPR_ERR_CANT_INITIALIZE; } if (handlePtr) { *handlePtr = handle; } return rc; }
int MprSocketService::start() { Mpr *mpr; char hostName[MPR_MAX_IP_NAME]; char serverName[MPR_MAX_IP_NAME]; char domainName[MPR_MAX_IP_NAME]; char *dp; mpr = mprGetMpr(); serverName[0] = '\0'; domainName[0] = '\0'; hostName[0] = '\0'; if (gethostname(serverName, sizeof(serverName)) < 0) { mprStrcpy(serverName, sizeof(serverName), "localhost"); mprError(MPR_L, MPR_USER, "Can't get host name"); // Keep going } if ((dp = strchr(serverName, '.')) != 0) { mprStrcpy(hostName, sizeof(hostName), serverName); *dp++ = '\0'; mprStrcpy(domainName, sizeof(domainName), dp); } else { mprStrcpy(hostName, sizeof(hostName), serverName); } lock(); mpr->setServerName(serverName); mpr->setDomainName(domainName); mpr->setHostName(hostName); #if DEPRECATED getInterfaces(); #endif unlock(); return 0; }
int mprAsctime(MprCtx ctx, char *buf, int bufsize, const struct tm *timeptr) { char *cp; char localBuf[80]; cp = asctime_r(timeptr, localBuf); if ((int) strlen(cp) >= bufsize) { mprAssert(0); return MPR_ERR_WONT_FIT; } mprStrcpy(buf, bufsize, cp); return strlen(buf); }
static char *getPassword(char *passBuf, int passLen) { char *password, *confirm; #if LINUX || WIN || MACOSX || SOLARIS password = getpass("New password: "******"Confirm password: "******"%s: Error: Password not verified\n", programName); return 0; #endif }
void ejsLexSaveInputState(Ejs *ep, EjsInput *state) { EjsInput *ip; int i; mprAssert(ep); ip = ep->input; mprAssert(ip); *state = *ip; for (i = 0; i <= ip->putBackIndex; i++) { mprStrcpy(state->putBack[i].tokbuf, EJS_MAX_TOKEN, ip->putBack[i].tokbuf); state->putBack[i].tid = ip->putBack[i].tid; } mprStrcpy(state->line, sizeof(state->line), ip->line); state->lineColumn = ip->lineColumn; state->lineNumber = ip->lineNumber; }
/* * Can be called multiple times */ static int openMonitorIcon() { NOTIFYICONDATA data; HICON iconHandle; HBITMAP go, stop; static int doOnce = 0; int rc; if (monitorMenu == NULL) { monitorMenu = LoadMenu(appInst, "monitorMenu"); if (! monitorMenu) { mprError(mpr, "Can't locate monitorMenu"); return MPR_ERR_CANT_OPEN; } } if (subMenu == NULL) { subMenu = GetSubMenu(monitorMenu, 0); go = LoadBitmap(appInst, MAKEINTRESOURCE(IDB_GO)); rc = GetLastError(); stop = LoadBitmap(appInst, MAKEINTRESOURCE(IDB_STOP)); SetMenuItemBitmaps(subMenu, MA_MENU_STATUS, MF_BYCOMMAND, stop, go); } iconHandle = (HICON) LoadImage(appInst, APPWEB_ICON, IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); if (iconHandle == 0) { mprError(mpr, "Can't load icon %s", APPWEB_ICON); return MPR_ERR_CANT_INITIALIZE; } data.uID = APPWEB_MONITOR_ID; data.hWnd = appHwnd; data.hIcon = iconHandle; data.cbSize = sizeof(NOTIFYICONDATA); data.uCallbackMessage = APPWEB_MONITOR_MESSAGE; data.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE; mprStrcpy(data.szTip, sizeof(data.szTip), mprGetAppTitle(mpr)); Shell_NotifyIcon(NIM_ADD, &data); if (iconHandle) { DestroyIcon(iconHandle); } return 0; }
void ejsLexPutbackToken(Ejs *ep, int tid, char *string) { EjsInput *ip; EjsToken *tp; int idx; mprAssert(ep); ip = ep->input; mprAssert(ip); ip->putBackIndex += 1; mprAssert(ip->putBackIndex < EJS_TOKEN_STACK); idx = ip->putBackIndex; tp = &ip->putBack[idx]; tp->tid = tid; mprStrcpy(tp->tokbuf, sizeof(tp->tokbuf), string); }
static int openTrayIcon() { NOTIFYICONDATA data; HICON iconHandle; static int doOnce = 0; if (trayMenu == NULL) { trayMenu = LoadMenu(appInst, "trayMenu"); if (! trayMenu) { mprError(MPR_L, MPR_LOG, "Can't locate trayMenu"); return MPR_ERR_CANT_OPEN; } } if (subMenu == NULL) { subMenu = GetSubMenu(trayMenu, 0); } iconHandle = (HICON) LoadImage(appInst, APPWEB_ICON, IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); if (iconHandle == 0) { mprError(MPR_L, MPR_LOG, "Can't load icon %s", APPWEB_ICON); return MPR_ERR_CANT_INITIALIZE; } data.uID = APPWEB_TRAY_ID; data.hWnd = appHwnd; data.hIcon = iconHandle; data.cbSize = sizeof(NOTIFYICONDATA); data.uCallbackMessage = APPWEB_TRAY_MESSAGE; data.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE; mprStrcpy(data.szTip, sizeof(data.szTip), mp->getAppTitle()); Shell_NotifyIcon(NIM_ADD, &data); if (iconHandle) { DestroyIcon(iconHandle); } return 0; }
static bool authGet(MprTestGroup *gp, char *uri, char *realm, char *user, char *password, int expectCode) { MprHttp *http; char uriBuf[MPR_MAX_STRING]; cchar *content; int rc, code, contentLength; http = getHttp(gp); if (authType) { mprSprintf(uriBuf, sizeof(uriBuf), "/%s%s", authType, uri); mprSetHttpCredentials(http, user, password); } else { mprStrcpy(uriBuf, sizeof(uriBuf), uri); mprResetHttpCredentials(http); } rc = httpRequest(http, "GET", uriBuf); if (!assert(rc == 0)) { return 0; } code = mprGetHttpCode(http); assert(code == expectCode); if (code != expectCode) { mprLog(gp, 0, "Client failed for %s, response code: %d, expected %d, msg %s\n", uriBuf, code, expectCode, mprGetHttpMessage(http)); return 0; } if (expectCode != 200) { contentLength = mprGetHttpContentLength(http); content = mprGetHttpContent(http); if (! assert(content != 0 && contentLength > 0)) { return 0; } } return 1; }
int Mpr::loadDll(char *path, char *fnName, void *arg, void **handlePtr) { MprEntryProc fn; char localPath[MPR_MAX_FNAME]; void *handle; char *cp; int rc; mprAssert(path && *path); mprAssert(fnName && *fnName); mprStrcpy(localPath, sizeof(localPath), path); for (cp = localPath; *cp; cp++) { if (*cp == '/') { *cp = '\\'; } } if ((handle = GetModuleHandle(mprGetBaseName(localPath))) == 0) { if ((handle = LoadLibrary(localPath)) == 0) { mprLog(0, "Can't load %s\nReason: \"%d\"\n", path, mprGetOsError()); return MPR_ERR_CANT_OPEN; } } if ((fn = (MprEntryProc) GetProcAddress((HINSTANCE) handle, fnName)) == 0) { FreeLibrary((HINSTANCE) handle); mprLog(0, "Can't load %s\nReason: can't find function \"%s\"\n", localPath, fnName); return MPR_ERR_NOT_FOUND; } if ((rc = (fn)(arg)) < 0) { FreeLibrary((HINSTANCE) handle); return MPR_ERR_CANT_INITIALIZE; } mprLog(MPR_INFO, "Loading DLL %s\n", path); if (handlePtr) { *handlePtr = handle; } return rc; }
void MprLogService::traceCore(int level, int flags, MprLogModule *mod, char *fmt, va_list args) { char buf[MPR_MAX_LOG_STRING]; int len; if (mod == 0) { mod = defaultModule; } // // Test the level here first up to quickly eliminate verbose trace levels // if ((level & MPR_LOG_MASK) <= mod->getLevel()) { int max = sizeof(buf) - 12; len = mprVsprintf(buf, max, fmt, args); if (len >= (max - 1)) { mprStrcpy(&buf[len], 12, " TRUNCATED\n"); } output(mod, flags, level, buf); } }
char *MaHost::makePath(char *buf, int buflen, char *file, bool validate) { char tmp[MPR_MAX_FNAME]; mprAssert(file); if (replaceReferences(buf, buflen, file) == 0) { // Overflow return 0; } if (*buf == '\0' || strcmp(buf, ".") == 0) { mprStrcpy(tmp, sizeof(tmp), server->getServerRoot()); #if WIN } else if (*buf != '/' && buf[1] != ':' && buf[2] != '/') { mprSprintf(tmp, buflen, "%s/%s", server->getServerRoot(), buf); #elif WINCE } else if (*buf != '\\' && *buf != '/')) { mprSprintf(tmp, buflen, "%s/%s", server->getServerRoot(), buf); #elif VXWORKS } else if (strchr((buf), ':') == 0 && *buf != '/') {
static char *getHive(char *keyPath, HKEY *hive) { char key[MPR_MAX_STRING], *cp; int len; mprAssert(keyPath && *keyPath); *hive = 0; mprStrcpy(key, sizeof(key), keyPath); key[sizeof(key) - 1] = '\0'; if (cp = strchr(key, '\\')) { *cp++ = '\0'; } if (cp == 0 || *cp == '\0') { return 0; } if (!mprStrCmpAnyCase(key, "HKEY_LOCAL_MACHINE")) { *hive = HKEY_LOCAL_MACHINE; } else if (!mprStrCmpAnyCase(key, "HKEY_CURRENT_USER")) { *hive = HKEY_CURRENT_USER; } else if (!mprStrCmpAnyCase(key, "HKEY_USERS")) { *hive = HKEY_USERS; } else if (!mprStrCmpAnyCase(key, "HKEY_CLASSES_ROOT")) { *hive = HKEY_CLASSES_ROOT; } else { mprError(MPR_L, MPR_LOG, "Bad hive key: %s", key); } if (*hive == 0) { return 0; } len = strlen(key) + 1; return keyPath + len; }
/* * Parse the request headers. Return true if the header parsed. */ static bool parseHeaders(MaConn *conn, MaPacket *packet) { MaHostAddress *address; MaRequest *req; MaHost *host, *hp; MaLimits *limits; MprBuf *content; char keyBuf[MPR_MAX_STRING]; char *key, *value, *cp, *tok; int count, keepAlive; req = conn->request; host = req->host; content = packet->content; conn->request->headerPacket = packet; limits = &conn->http->limits; keepAlive = 0; strcpy(keyBuf, "HTTP_"); mprAssert(strstr((char*) content->start, "\r\n")); for (count = 0; content->start[0] != '\r' && !conn->connectionFailed; count++) { if (count >= limits->maxNumHeaders) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Too many headers"); return 0; } if ((key = getToken(conn, ":")) == 0 || *key == '\0') { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad header format"); return 0; } value = getToken(conn, "\r\n"); while (isspace((int) *value)) { value++; } if (conn->requestFailed) { continue; } mprStrUpper(key); for (cp = key; *cp; cp++) { if (*cp == '-') { *cp = '_'; } } mprLog(req, 8, "Key %s, value %s", key, value); if (strspn(key, "%<>/\\") > 0) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad header key value"); continue; } /* * Define the header with a "HTTP_" prefix */ mprStrcpy(&keyBuf[5], sizeof(keyBuf) - 5, key); mprAddDuplicateHash(req->headers, keyBuf, value); switch (key[0]) { case 'A': if (strcmp(key, "AUTHORIZATION") == 0) { value = mprStrdup(req, value); req->authType = mprStrTok(value, " \t", &tok); req->authDetails = tok; } else if (strcmp(key, "ACCEPT_CHARSET") == 0) { req->acceptCharset = value; } else if (strcmp(key, "ACCEPT") == 0) { req->accept = value; } else if (strcmp(key, "ACCEPT_ENCODING") == 0) { req->acceptEncoding = value; } break; case 'C': if (strcmp(key, "CONTENT_LENGTH") == 0) { if (req->length >= 0) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Mulitple content length headers"); continue; } req->length = mprAtoi(value, 10); if (req->length < 0) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad content length"); continue; } if (req->length >= host->limits->maxBody) { maFailConnection(conn, MPR_HTTP_CODE_REQUEST_TOO_LARGE, "Request content length %Ld is too big. Limit %Ld", req->length, host->limits->maxBody); continue; } mprAssert(req->length >= 0); req->remainingContent = req->length; req->contentLengthStr = value; } else if (strcmp(key, "CONTENT_RANGE") == 0) { /* * This headers specifies the range of any posted body data * Format is: Content-Range: bytes n1-n2/length * Where n1 is first byte pos and n2 is last byte pos */ char *sp; int start, end, size; start = end = size = -1; sp = value; while (*sp && !isdigit((int) *sp)) { sp++; } if (*sp) { start = (int) mprAtoi(sp, 10); if ((sp = strchr(sp, '-')) != 0) { end = (int) mprAtoi(++sp, 10); } if ((sp = strchr(sp, '/')) != 0) { /* * Note this is not the content length transmitted, but the original size of the input of which * the client is transmitting only a portion. */ size = (int) mprAtoi(++sp, 10); } } if (start < 0 || end < 0 || size < 0 || end <= start) { maFailRequest(conn, MPR_HTTP_CODE_RANGE_NOT_SATISFIABLE, "Bad content range"); continue; } req->inputRange = maCreateRange(conn, start, end); } else if (strcmp(key, "CONTENT_TYPE") == 0) { req->mimeType = value; req->form = strstr(value, "application/x-www-form-urlencoded") != 0; } else if (strcmp(key, "COOKIE") == 0) { if (req->cookie && *req->cookie) { req->cookie = mprStrcat(req, -1, req->cookie, "; ", value, NULL); } else { req->cookie = value; } } else if (strcmp(key, "CONNECTION") == 0) { req->connection = value; if (mprStrcmpAnyCase(value, "KEEP-ALIVE") == 0) { keepAlive++; } else if (mprStrcmpAnyCase(value, "CLOSE") == 0) { conn->keepAliveCount = 0; } if (!host->keepAlive) { conn->keepAliveCount = 0; } } break; case 'F': req->forwarded = value; break; case 'H': if (strcmp(key, "HOST") == 0) { req->hostName = value; address = conn->address; if (maIsNamedVirtualHostAddress(address)) { hp = maLookupVirtualHost(address, value); if (hp == 0) { maFailRequest(conn, 404, "No host to serve request. Searching for %s", value); mprLog(conn, 1, "Can't find virtual host %s", value); continue; } req->host = hp; /* * Reassign this request to a new host */ maRemoveConn(host, conn); host = hp; conn->host = hp; maAddConn(hp, conn); } } break; case 'I': if ((strcmp(key, "IF_MODIFIED_SINCE") == 0) || (strcmp(key, "IF_UNMODIFIED_SINCE") == 0)) { MprTime newDate = 0; char *cp; bool ifModified = (key[3] == 'M'); if ((cp = strchr(value, ';')) != 0) { *cp = '\0'; } if (mprParseTime(conn, &newDate, value, MPR_UTC_TIMEZONE, NULL) < 0) { mprAssert(0); break; } if (newDate) { setIfModifiedDate(conn, newDate, ifModified); req->flags |= MA_REQ_IF_MODIFIED; } } else if ((strcmp(key, "IF_MATCH") == 0) || (strcmp(key, "IF_NONE_MATCH") == 0)) { char *word, *tok; bool ifMatch = key[3] == 'M'; if ((tok = strchr(value, ';')) != 0) { *tok = '\0'; } req->ifMatch = ifMatch; req->flags |= MA_REQ_IF_MODIFIED; value = mprStrdup(conn, value); word = mprStrTok(value, " ,", &tok); while (word) { addMatchEtag(conn, word); word = mprStrTok(0, " ,", &tok); } } else if (strcmp(key, "IF_RANGE") == 0) { char *word, *tok; if ((tok = strchr(value, ';')) != 0) { *tok = '\0'; } req->ifMatch = 1; req->flags |= MA_REQ_IF_MODIFIED; value = mprStrdup(conn, value); word = mprStrTok(value, " ,", &tok); while (word) { addMatchEtag(conn, word); word = mprStrTok(0, " ,", &tok); } } break; case 'P': if (strcmp(key, "PRAGMA") == 0) { req->pragma = value; } break; case 'R': if (strcmp(key, "RANGE") == 0) { if (!parseRange(conn, value)) { maFailRequest(conn, MPR_HTTP_CODE_RANGE_NOT_SATISFIABLE, "Bad range"); } } else if (strcmp(key, "REFERER") == 0) { /* NOTE: yes the header is misspelt in the spec */ req->referer = value; } break; case 'T': if (strcmp(key, "TRANSFER_ENCODING") == 0) { mprStrLower(value); if (strcmp(value, "chunked") == 0) { req->flags |= MA_REQ_CHUNKED; /* * This will be revised by the chunk filter as chunks are processed and will be set to zero when the * last chunk has been received. */ req->remainingContent = MAXINT; } } break; #if BLD_DEBUG case 'X': if (strcmp(key, "X_APPWEB_CHUNK_SIZE") == 0) { mprStrUpper(value); conn->response->chunkSize = atoi(value); if (conn->response->chunkSize <= 0) { conn->response->chunkSize = 0; } else if (conn->response->chunkSize > conn->http->limits.maxChunkSize) { conn->response->chunkSize = conn->http->limits.maxChunkSize; } } break; #endif case 'U': if (strcmp(key, "USER_AGENT") == 0) { req->userAgent = value; } break; } } if (conn->protocol == 0 && !keepAlive) { conn->keepAliveCount = 0; } if (!(req->flags & MA_REQ_CHUNKED)) { /* * Step over "\r\n" after headers. As an optimization, don't do this if chunked so chunking can parse a single * chunk delimiter of "\r\nSIZE ...\r\n" */ mprAdjustBufStart(content, 2); } mprLog(conn, 3, "Select host \"%s\"", conn->host->name); if (maSetRequestUri(conn, req->url, "") < 0) { maFailConnection(conn, MPR_HTTP_CODE_BAD_REQUEST, "Bad URI format"); return 0; } if (conn->host->secure) { req->parsedUri->scheme = mprStrdup(req, "https"); } req->parsedUri->port = conn->sock->port; req->parsedUri->host = req->hostName ? req->hostName : conn->host->name; return 1; }
int MaHost::mapToStorage(MaRequest *rq, char *path, int pathLen, char *uri, int flags) { MaAlias *ap; MaDir *dir; char urlBuf[MPR_HTTP_MAX_URL]; char *base, *aliasName, *prefix; int len, redirectCode, prefixLen; mprAssert(path); mprAssert(pathLen > 0); *path = '\0'; lock(); // // FUTURE - Could optimize by having a hash lookup for alias prefixes. // ap = (MaAlias*) aliases.getFirst(); while (ap) { aliasName = ap->getName(); prefix = ap->getPrefix(); prefixLen = ap->getPrefixLen(); // // Note that for Aliases with redirects, the aliasName is a URL and // not a document path. // if (strncmp(prefix, uri, prefixLen) == 0) { redirectCode = ap->getRedirectCode(); if (redirectCode) { if (flags & MPR_HTTP_REDIRECT) { rq->redirect(redirectCode, aliasName); rq->flushOutput(MPR_HTTP_FOREGROUND_FLUSH, MPR_HTTP_FINISH_REQUEST); } else { mprStrcpy(path, pathLen, aliasName); } unlock(); return 0; } base = &uri[prefixLen]; while (*base == '/') { base++; } if (aliasName[strlen(aliasName) - 1] == '/') { len = mprSprintf(path, pathLen, "%s%s", aliasName, base); } else if (*base) { len = mprSprintf(path, pathLen, "%s/%s", aliasName, base); } else { len = mprStrcpy(path, pathLen, aliasName); } dir = 0; if (*base != '\0') { // // There was some extra URI past the matching alias prefix // portion // #if WIN // // Windows will ignore trailing "." and " ". We must reject // here as the URL probably won't match due to the trailing // character and the copyHandler will return the unprocessed // content to the user. Bad. // int lastc = base[strlen(base) - 1]; if (lastc == '.' || lastc == ' ') { unlock(); return MPR_ERR_CANT_ACCESS; } #endif unlock(); return 0; } else { if (*prefix == '\0') { prefix = "/"; } // // The URL matched the alias exactly so we change the URI // to match the prefix as we may have changed the extension // mprStrcpy(urlBuf, sizeof(urlBuf), prefix); MaUrl *url = rq->getUrl(); if (strcmp(urlBuf, url->uri) != 0) { if (url->query && *url->query) { mprStrcat(urlBuf, sizeof(urlBuf), "?", url->query, (void*) 0); } if (flags & MPR_HTTP_REMATCH) { rq->setUri(urlBuf); rq->parseUri(); } } } if (flags & MPR_HTTP_REMATCH) { rq->deleteHandlers(); } unlock(); return 0; } ap = (MaAlias*) aliases.getNext(ap); } unlock(); return MPR_ERR_NOT_FOUND; }
void maLogRequest(MaConn *conn) { MaHost *logHost, *host; MaResponse *resp; MaRequest *req; MprBuf *buf; char keyBuf[80], *timeText, *fmt, *cp, *qualifier, *value, c; int len; resp = conn->response; req = conn->request; host = req->host; logHost = host->logHost; if (logHost == 0) { return; } fmt = logHost->logFormat; if (fmt == 0) { return; } if (req->method == 0) { return; } len = MPR_MAX_URL + 256; buf = mprCreateBuf(resp, len, len); while ((c = *fmt++) != '\0') { if (c != '%' || (c = *fmt++) == '%') { mprPutCharToBuf(buf, c); continue; } switch (c) { case 'a': /* Remote IP */ mprPutStringToBuf(buf, conn->remoteIpAddr); break; case 'A': /* Local IP */ mprPutStringToBuf(buf, conn->sock->listenSock->ipAddr); break; case 'b': if (resp->bytesWritten == 0) { mprPutCharToBuf(buf, '-'); } else { mprPutIntToBuf(buf, resp->bytesWritten); } break; case 'B': /* Bytes written (minus headers) */ mprPutIntToBuf(buf, resp->bytesWritten - resp->headerSize); break; case 'h': /* Remote host */ mprPutStringToBuf(buf, conn->remoteIpAddr); break; case 'n': /* Local host */ mprPutStringToBuf(buf, req->parsedUri->host); break; case 'l': /* Supplied in authorization */ mprPutStringToBuf(buf, req->user ? req->user : "******"); break; case 'O': /* Bytes written (including headers) */ mprPutIntToBuf(buf, resp->bytesWritten); break; case 'r': /* First line of request */ mprPutFmtToBuf(buf, "%s %s %s", req->methodName, req->parsedUri->originalUri, req->httpProtocol); break; case 's': /* Response code */ mprPutIntToBuf(buf, resp->code); break; case 't': /* Time */ mprPutCharToBuf(buf, '['); timeText = mprFormatLocalTime(conn, mprGetTime(conn)); mprPutStringToBuf(buf, timeText); mprFree(timeText); mprPutCharToBuf(buf, ']'); break; case 'u': /* Remote username */ mprPutStringToBuf(buf, req->user ? req->user : "******"); break; case '{': /* Header line */ qualifier = fmt; if ((cp = strchr(qualifier, '}')) != 0) { fmt = &cp[1]; *cp = '\0'; c = *fmt++; mprStrcpy(keyBuf, sizeof(keyBuf), "HTTP_"); mprStrcpy(&keyBuf[5], sizeof(keyBuf) - 5, qualifier); mprStrUpper(keyBuf); switch (c) { case 'i': value = (char*) mprLookupHash(req->headers, keyBuf); mprPutStringToBuf(buf, value ? value : "-"); break; default: mprPutStringToBuf(buf, qualifier); } *cp = '}'; } else { mprPutCharToBuf(buf, c); } break; case '>': if (*fmt == 's') { fmt++; mprPutIntToBuf(buf, resp->code); } break; default: mprPutCharToBuf(buf, c); break; } } mprPutCharToBuf(buf, '\n'); mprAddNullToBuf(buf); mprWrite(logHost->accessLog, mprGetBufStart(buf), mprGetBufLength(buf)); }
int MprCmd::start(char *program, char **argv, char **envp, MprCmdProc fn, void *fnData, int userFlags) { PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; char dirBuf[MPR_MAX_FNAME]; char *envBuf, **ep, *cmdBuf, **ap, *destp, *cp, *dir; char progBuf[MPR_MAX_STRING], *localArgv[2], *saveArg0; int argc, i, len, inheritFiles; mprAssert(program); mprAssert(argv); flags &= ~(MPR_CMD_WAITED | MPR_CMD_RUNNING); flags |= (userFlags & MPR_CMD_USER_FLAGS); exitStatus = -1; mprStrcpy(progBuf, sizeof(progBuf), program); progBuf[sizeof(progBuf) - 1] = '\0'; program = progBuf; // // Sanitize the command line (program name only) // for (cp = program; *cp; cp++) { if (*cp == '/') { *cp = '\\'; } else if (*cp == '\r' || *cp == '\n') { *cp = ' '; } } if (*program == '"') { if ((cp = strrchr(++program, '"')) != 0) { *cp = '\0'; } } saveArg0 = argv[0]; if (argv == 0) { argv = localArgv; argv[1] = 0; } argv[0] = program; // // Determine the command line length and arg count // argc = 0; for (len = 0, ap = argv; *ap; ap++) { len += strlen(*ap) + 1 + 2; // Space and possible quotes argc++; } cmdBuf = (char*) mprMalloc(len + 1); cmdBuf[len] = '\0'; // // Add quotes to all args that have spaces in them including "program" // destp = cmdBuf; for (ap = &argv[0]; *ap; ) { cp = *ap; if ((strchr(cp, ' ') != 0) && cp[0] != '\"') { *destp++ = '\"'; strcpy(destp, cp); destp += strlen(cp); *destp++ = '\"'; } else { strcpy(destp, cp); destp += strlen(cp); } if (*++ap) { *destp++ = ' '; } } *destp = '\0'; mprAssert((int) strlen(destp) < (len - 1)); mprAssert(cmdBuf[len] == '\0'); argv[0] = saveArg0; envBuf = 0; if (envp) { for (len = 0, ep = envp; *ep; ep++) { len += strlen(*ep) + 1; } envBuf = (char*) mprMalloc(len + 2); // Win requires two nulls destp = envBuf; for (ep = envp; *ep; ep++) { strcpy(destp, *ep); mprLog(6, log, "Set CGI variable: %s\n", destp); destp += strlen(*ep) + 1; } *destp++ = '\0'; *destp++ = '\0'; // WIN requires two nulls } memset(&startInfo, 0, sizeof(startInfo)); startInfo.cb = sizeof(startInfo); startInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; if (flags & MPR_CMD_SHOW) { startInfo.wShowWindow = SW_SHOW; } else { startInfo.wShowWindow = SW_HIDE; } if (files.clientFd[MPR_CMD_IN] > 0) { startInfo.hStdInput = (HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_IN]); } if (files.clientFd[MPR_CMD_OUT] > 0) { startInfo.hStdOutput = (HANDLE)_get_osfhandle(files.clientFd[MPR_CMD_OUT]); } if (files.clientFd[MPR_CMD_ERR] > 0) { startInfo.hStdError = (HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_ERR]); } #if UNUSED SECURITY_ATTRIBUTES secAtt; memset(&secAtt, 0, sizeof(secAtt)); secAtt.nLength = sizeof(SECURITY_ATTRIBUTES); secAtt.bInheritHandle = TRUE; #endif if (userFlags & MPR_CMD_CHDIR) { if (cwd) { dir = cwd; } else { mprGetDirName(dirBuf, sizeof(dirBuf), argv[0]); dir = dirBuf; } } else { dir = 0; } inheritFiles = (flags & MPR_CMD_STDIO_MADE) ? 1 : 0; mprLog(5, log, "Running: %s\n", cmdBuf); if (! CreateProcess(0, cmdBuf, 0, 0, inheritFiles, CREATE_NEW_CONSOLE, envBuf, dir, &startInfo, &procInfo)) { mprError(MPR_L, MPR_LOG, "Can't create process: %s, %d", cmdBuf, mprGetOsError()); return MPR_ERR_CANT_CREATE; } handle = (long) procInfo.hProcess; pid = procInfo.dwProcessId; if (procInfo.hThread != 0) { CloseHandle(procInfo.hThread); } for (i = 0; i < MPR_CMD_MAX_FD; i++) { if (files.clientFd[i] >= 0) { close(files.clientFd[i]); files.clientFd[i] = -1; } } if (cmdBuf) { mprFree(cmdBuf); } if (envBuf) { mprFree(envBuf); } if (userFlags & MPR_CMD_WAIT) { waitForChild(INT_MAX); for (i = 0; i < MPR_CMD_MAX_FD; i++) { if (files.serverFd[i] >= 0) { close(files.serverFd[i]); files.serverFd[i] = -1; } } return exitStatus; } lock(); outputDataProc = fn; data = fnData; flags |= MPR_CMD_RUNNING; if (1 || ! mpr->getAsyncSelectMode()) { timer = new MprTimer(MPR_TIMEOUT_CMD_WAIT, singleThreadedOutputData, (void*) this); #if FUTURE // // Want non blocking reads if we are in single-threaded mode. // Can't use this yet as we are holding a Request lock and so blocking // in a read stops everything. Need proper Async I/O in windows. // if (mprGetMpr()->poolService->getMaxPoolThreads() == 0) { } else { task = new MprTask(multiThreadedOutputData, (void*) this); task->start(); } #endif } unlock(); return 0; }
void Mpr::writeToOsLog(char *message, int flags) { HKEY hkey; void *event; long errorType; char buf[MPR_MAX_STRING], msg[MPR_MAX_STRING]; char logName[MPR_MAX_STRING]; char *lines[9]; char *cp, *value; int type; ulong exists; static int once = 0; mprStrcpy(buf, sizeof(buf), message); cp = &buf[strlen(buf) - 1]; while (*cp == '\n' && cp > buf) { *cp-- = '\0'; } if (flags & MPR_INFO) { type = EVENTLOG_INFORMATION_TYPE; mprSprintf(msg, MPR_MAX_STRING, "%s information: ", Mpr::getAppName()); } else if (flags == MPR_WARN) { type = EVENTLOG_WARNING_TYPE; mprSprintf(msg, MPR_MAX_STRING, "%s warning: ", Mpr::getAppName()); } else { type = EVENTLOG_ERROR_TYPE; mprSprintf(msg, MPR_MAX_STRING, "%s error: %d", Mpr::getAppName(), GetLastError()); } lines[0] = msg; lines[1] = buf; lines[2] = lines[3] = lines[4] = lines[5] = 0; lines[6] = lines[7] = lines[8] = 0; if (once == 0) { // Initialize the registry once = 1; mprSprintf(logName, sizeof(logName), "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", Mpr::getAppName()); hkey = 0; if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, logName, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, &exists) == ERROR_SUCCESS) { value = "%SystemRoot%\\System32\\netmsg.dll"; if (RegSetValueEx(hkey, "EventMessageFile", 0, REG_EXPAND_SZ, (uchar*) value, strlen(value) + 1) != ERROR_SUCCESS) { RegCloseKey(hkey); return; } errorType = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; if (RegSetValueEx(hkey, "TypesSupported", 0, REG_DWORD, (uchar*) &errorType, sizeof(DWORD)) != ERROR_SUCCESS) { RegCloseKey(hkey); return; } RegCloseKey(hkey); } } event = RegisterEventSource(0, Mpr::getAppName()); if (event) { // // 3299 is the event number for the generic message in netmsg.dll. // "%1 %2 %3 %4 %5 %6 %7 %8 %9" -- thanks Apache for the tip // ReportEvent(event, EVENTLOG_ERROR_TYPE, 0, 3299, NULL, sizeof(lines) / sizeof(char*), 0, (LPCSTR*) lines, 0); DeregisterEventSource(event); } }
static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg) { EspParse parse; char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME], incPath[MPR_MAX_FNAME]; char *incBuf, *incText; int state, tid, len, rc, maxScriptSize, incSize; mprAssert(ep); mprAssert(jsBuf); mprAssert(input); rc = 0; len = 0; state = ESP_STATE_BEGIN; if (errMsg) { *errMsg = 0; } memset(&parse, 0, sizeof(parse)); parse.token = (char*) mprMalloc(ESP_TOK_INCR); if (parse.token == 0) { return MPR_ERR_CANT_ALLOCATE; } parse.token[0] = '\0'; parse.tokLen = ESP_TOK_INCR; parse.endp = &parse.token[parse.tokLen - 1]; parse.tokp = parse.token; parse.inBuf = input; parse.inp = parse.inBuf; maxScriptSize = esp->maxScriptSize; tid = getEspToken(state, &parse); while (tid != ESP_TOK_EOF && len >= 0) { switch (tid) { default: case ESP_TOK_ERR: mprFree(parse.token); return MPR_ERR_BAD_SYNTAX; case ESP_TOK_LITERAL: len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"", parse.token, "\");\n", (void*) 0); break; case ESP_TOK_ATAT: /* * Trick to get undefined variables to evaluate to "". * Catenate with "" to cause toString to run. */ len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"\" + ", parse.token, ");\n", (void*) 0); break; case ESP_TOK_EQUALS: len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, "write(\"\" + ", parse.token, ");\n", (void*) 0); state = ESP_STATE_IN_ESP_TAG; break; case ESP_TOK_START_ESP: state = ESP_STATE_IN_ESP_TAG; tid = getEspToken(state, &parse); while (tid != ESP_TOK_EOF && tid != ESP_TOK_EOF && tid != ESP_TOK_END_ESP && len >= 0) { len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, parse.token, (void*) 0); tid = getEspToken(state, &parse); } state = ESP_STATE_BEGIN; break; case ESP_TOK_END_ESP: state = ESP_STATE_BEGIN; break; case ESP_TOK_INCLUDE: if (parse.token[0] == '/') { mprStrcpy(incPath, sizeof(incPath), parse.token); } else { mprGetDirName(dir, sizeof(dir), ep->uri); mprSprintf(incPath, sizeof(incPath), "%s/%s", dir, parse.token); } if (esp->mapToStorage(ep->requestHandle, path, sizeof(path), incPath, 0) < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Can't find include file: %s", path); rc = MPR_ERR_CANT_OPEN; break; } if (esp->readFile(ep->requestHandle, &incText, &incSize, path) < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Can't read include file: %s", path); rc = MPR_ERR_CANT_READ; break; } incText[incSize] = '\0'; /* * Recurse and process the include script */ incBuf = 0; if ((rc = buildScript(ep, &incBuf, incText, errMsg)) < 0) { mprFree(incText); mprFree(parse.token); return rc; } len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, incBuf, (void*) 0); mprFree(incText); mprFree(incBuf); state = ESP_STATE_IN_ESP_TAG; break; } tid = getEspToken(state, &parse); } mprFree(parse.token); if (len < 0) { mprAllocSprintf(errMsg, MPR_MAX_STRING, "Script token is too big in %s.\nConfigured maximum is %d.", path, maxScriptSize); return MPR_ERR_WONT_FIT; } return rc; }
// // Algorithm originally in the GoAhead WebServer. // int MaUrl::parse(char *url) { char *tok, *cp, *portStr, *last_delim, *hostbuf, *portbuf; char *htmlExt = "html"; int c, len, ulen; mprAssert(url && *url); if (parsedUrlBuf) { mprFree(parsedUrlBuf); } ulen = strlen(url); // // Allocate a single buffer to hold all the cracked fields. // Store host, port and url strings (3 nulls). // len = ulen * 2 + MAX_PORT_LEN + 3; parsedUrlBuf = (char*) mprMalloc(len * sizeof(char)); portbuf = &parsedUrlBuf[len - MAX_PORT_LEN - 1]; hostbuf = &parsedUrlBuf[ulen+1]; strcpy(parsedUrlBuf, url); url = parsedUrlBuf; // // Defaults for missing ULR fields // strcpy(portbuf, "80"); portStr = portbuf; uri = "/"; proto = "http"; host = "localhost"; query = ""; ext = htmlExt; if (strncmp(url, "http://", 7) == 0) { tok = &url[7]; tok[-3] = '\0'; proto = url; host = tok; for (cp = tok; *cp; cp++) { if (*cp == '/') { break; } if (*cp == ':') { *cp++ = '\0'; portStr = cp; tok = cp; } } if ((cp = strchr(tok, '/')) != NULL) { c = *cp; *cp = '\0'; mprStrcpy(hostbuf, ulen + 1, host); mprStrcpy(portbuf, MAX_PORT_LEN, portStr); *cp = c; host = hostbuf; portStr = portbuf; uri = cp; tok = cp; } } else { uri = url; tok = url; } // // Split off the query string. // if ((cp = strchr(tok, '?')) != NULL) { *cp++ = '\0'; query = cp; uri = tok; tok = query; } // // Split off fragment identifier. // if ((cp = strchr(tok, '#')) != NULL) { *cp++ = '\0'; if (*query == 0) { uri = tok; } } // // FUTURE -- this logic could be improved // if ((cp = strrchr(uri, '.')) != NULL) { if ((last_delim = strrchr(uri, '/')) != NULL) { if (last_delim > cp) { ext = htmlExt; } else { ext = cp + 1; #if WIN mprStrLower(ext); #endif } } else { ext = cp + 1; #if WIN mprStrLower(ext); #endif } } else { if (uri[strlen(uri) - 1] == '/') { ext = htmlExt; } } port = atoi(portStr); return 0; }