char * Ns_ConfigGetPath(char *server, char *module, ...) { va_list ap; char *s; Ns_DString ds; Ns_Set *set; Ns_DStringInit(&ds); Ns_DStringAppend(&ds, "ns"); if (server != NULL) { Ns_DStringVarAppend(&ds, "/server/", server, NULL); } if (module != NULL) { Ns_DStringVarAppend(&ds, "/module/", module, NULL); } va_start(ap, module); while ((s = va_arg(ap, char *)) != NULL) { Ns_DStringAppend(&ds, "/"); while (*s != '\0' && ISSLASH(*s)) { ++s; } Ns_DStringAppend(&ds, s); while (ISSLASH(ds.string[ds.length - 1])) { ds.string[--ds.length] = '\0'; } } va_end(ap); set = Ns_ConfigGetSection(ds.string); Ns_DStringFree(&ds); return (set ? Ns_SetName(set) : NULL); }
void NsConfUpdate(void) { int stacksize; Ns_DString ds; Ns_DStringInit(&ds); Ns_HomePath(&ds, "modules", "tcl", NULL); nsconf.tcl.sharedlibrary = Ns_DStringExport(&ds); nsconf.shutdowntimeout = NsParamInt("shutdowntimeout", SHUTDOWNTIMEOUT); nsconf.sched.maxelapsed = NsParamInt("schedmaxelapsed", SCHED_MAXELAPSED); nsconf.backlog = NsParamInt("listenbacklog", LISTEN_BACKLOG); nsconf.http.major = (unsigned) NsParamInt("httpmajor", HTTP_MAJOR); nsconf.http.minor = (unsigned) NsParamInt("httpmajor", HTTP_MINOR); nsconf.tcl.lockoninit = NsParamBool("tclinitlock", TCL_INITLCK); if (!Ns_ConfigGetInt(NS_CONFIG_THREADS, "stacksize", &stacksize)) { stacksize = NsParamInt("stacksize", THREAD_STACKSIZE); } Ns_ThreadStackSize(stacksize); NsLogConf(); NsEnableDNSCache(); NsUpdateEncodings(); NsUpdateMimeTypes(); }
int Ns_ConnReadHeaders(Ns_Conn *conn, Ns_Set *set, int *nreadPtr) { Ns_DString ds; Conn *connPtr = (Conn *) conn; NsServer *servPtr = connPtr->servPtr; int status, nread, nline, maxhdr; Ns_DStringInit(&ds); nread = 0; maxhdr = connPtr->drvPtr->maxinput; status = NS_OK; while (nread < maxhdr && status == NS_OK) { Ns_DStringTrunc(&ds, 0); status = Ns_ConnReadLine(conn, &ds, &nline); if (status == NS_OK) { nread += nline; if (nread > maxhdr) { status = NS_ERROR; } else { if (ds.string[0] == '\0') { break; } status = Ns_ParseHeader(set, ds.string, servPtr->opts.hdrcase); } } } if (nreadPtr != NULL) { *nreadPtr = nread; } Ns_DStringFree(&ds); return status; }
char * Ns_GetMimeType(char *file) { char *start, *ext; Ns_DString ds; Tcl_HashEntry *hePtr; start = strrchr(file, '/'); if (start == NULL) { start = file; } ext = strrchr(start, '.'); if (ext == NULL) { return noextType; } Ns_DStringInit(&ds); ext = LowerDString(&ds, ext); hePtr = Tcl_FindHashEntry(&types, ext); if (hePtr == NULL) { return defaultType; } return Tcl_GetHashValue(hePtr); }
int Ns_ParseHeader(Ns_Set *set, char *line, Ns_HeaderCaseDisposition disp) { char *key, *sep; char *value; int index; Ns_DString ds; /* * Header lines are first checked if they continue a previous * header indicated by any preceeding white space. Otherwise, * they must be in well form key: value form. */ if (isspace(UCHAR(*line))) { index = Ns_SetLast(set); if (index < 0) { return NS_ERROR; /* Continue before first header. */ } while (isspace(UCHAR(*line))) { ++line; } if (*line != '\0') { value = Ns_SetValue(set, index); Ns_DStringInit(&ds); Ns_DStringVarAppend(&ds, value, " ", line, NULL); Ns_SetPutValue(set, index, ds.string); Ns_DStringFree(&ds); } } else { sep = strchr(line, ':'); if (sep == NULL) { return NS_ERROR; /* Malformed header. */ } *sep = '\0'; value = sep + 1; while (*value != '\0' && isspace(UCHAR(*value))) { ++value; } index = Ns_SetPut(set, line, value); key = Ns_SetKey(set, index); if (disp == ToLower) { while (*key != '\0') { if (isupper(UCHAR(*key))) { *key = tolower(UCHAR(*key)); } ++key; } } else if (disp == ToUpper) { while (*key != '\0') { if (islower(UCHAR(*key))) { *key = toupper(UCHAR(*key)); } ++key; } } *sep = ':'; } return NS_OK; }
void NsInitConf(void) { Ns_DString addr; static char cwd[PATH_MAX]; extern char *nsBuildDate; /* NB: Declared in stamp.c */ Ns_ThreadSetName("-main-"); /* * Set various core environment variables. */ nsconf.build = nsBuildDate; nsconf.name = NSD_NAME; nsconf.version = NSD_VERSION; nsconf.tcl.version = TCL_VERSION; nsconf.http.major = HTTP_MAJOR; nsconf.http.minor = HTTP_MINOR; time(&nsconf.boot_t); nsconf.pid = getpid(); nsconf.home = getcwd(cwd, sizeof(cwd)); if (gethostname(nsconf.hostname, sizeof(nsconf.hostname)) != 0) { strcpy(nsconf.hostname, "localhost"); } Ns_DStringInit(&addr); if (Ns_GetAddrByHost(&addr, nsconf.hostname)) { strcpy(nsconf.address, addr.string); } else { strcpy(nsconf.address, "0.0.0.0"); } Ns_DStringFree(&addr); /* * Set various default values. */ nsconf.shutdowntimeout = SHUTDOWNTIMEOUT; nsconf.sched.maxelapsed = SCHED_MAXELAPSED; nsconf.backlog = LISTEN_BACKLOG; nsconf.http.major = HTTP_MAJOR; nsconf.http.minor = HTTP_MINOR; nsconf.tcl.lockoninit = TCL_INITLCK; /* * At library load time the server is considered started. * Normally it's marked stopped immediately by Ns_Main unless * libnsd is being used for some other, non-server program. */ Ns_MutexSetName(&nsconf.state.lock, "nsd:state"); nsconf.state.started = 1; }
int NsAdpProc(void *arg, Ns_Conn *conn) { Ns_Time *ttlPtr = arg; Ns_DString file; int status; Ns_DStringInit(&file); Ns_UrlToFile(&file, Ns_ConnServer(conn), conn->request->url); status = Ns_AdpRequestEx(conn, file.string, ttlPtr); Ns_DStringFree(&file); return status; }
void Ns_SetRequestUrl(Ns_Request * request, char *url) { Ns_DString ds; Ns_MutexLock(&reqlock); FreeUrl(request); Ns_DStringInit(&ds); Ns_DStringAppend(&ds, url); SetUrl(request, ds.string, NULL); Ns_MutexUnlock(&reqlock); Ns_DStringFree(&ds); }
int NsTclQuoteHtmlCmd(ClientData dummy, Tcl_Interp *interp, int argc, char **argv) { Ns_DString ds; if (argc != 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " html\"", NULL); return TCL_ERROR; } Ns_DStringInit(&ds); Ns_QuoteHtml(&ds, argv[1]); Tcl_DStringResult(interp, &ds); return TCL_OK; }
static void php_ns_request_ctor(void) { char *server; Ns_DString ds; char *root; int index; char *tmp; server = Ns_ConnServer(NSG(conn)); #define safe_strdup(x) ((x)?strdup((x)):NULL) SG(request_info).query_string = safe_strdup(NSG(conn->request->query)); Ns_DStringInit(&ds); Ns_UrlToFile(&ds, server, NSG(conn->request->url)); /* path_translated is the absolute path to the file */ SG(request_info).path_translated = safe_strdup(Ns_DStringValue(&ds)); Ns_DStringFree(&ds); root = Ns_PageRoot(server); SG(request_info).request_uri = strdup(SG(request_info).path_translated + strlen(root)); SG(request_info).request_method = NSG(conn)->request->method; if(NSG(conn)->request->version > 1.0) SG(request_info).proto_num = 1001; else SG(request_info).proto_num = 1000; SG(request_info).content_length = Ns_ConnContentLength(NSG(conn)); index = Ns_SetIFind(NSG(conn)->headers, "content-type"); SG(request_info).content_type = index == -1 ? NULL : Ns_SetValue(NSG(conn)->headers, index); SG(sapi_headers).http_response_code = 200; tmp = Ns_ConnAuthUser(NSG(conn)); if (tmp) tmp = estrdup(tmp); SG(request_info).auth_user = tmp; tmp = Ns_ConnAuthPasswd(NSG(conn)); if (tmp) tmp = estrdup(tmp); SG(request_info).auth_password = tmp; NSG(data_avail) = SG(request_info).content_length; }
static void SetUrl(Ns_Request *request, char *url, Tcl_Encoding encoding) { Ns_Conn *conn; Ns_DString ds1, ds2; char *p; Ns_DStringInit(&ds1); Ns_DStringInit(&ds2); /* * Look for a query string at the end of the URL. */ p = strchr(url, '?'); if (p != NULL) { *p++ = '\0'; if (request->query != NULL) { ns_free(request->query); } request->query = ns_strdup(p); } /* * Decode and normalize the URL. If the encoding isn't specified, * use the encoding of the current connection, if any. */ if (encoding == NULL && (conn = Ns_GetConn()) != NULL) { encoding = Ns_ConnGetUrlEncoding(conn); } p = Ns_DecodeUrlWithEncoding(&ds1, url, encoding); if (p == NULL) { p = url; } Ns_NormalizePath(&ds2, p); Ns_DStringTrunc(&ds1, 0); /* * Append a trailing slash to the normalized URL if the original URL * ended in slash that wasn't also the leading slash. */ while (*url == '/') { ++url; } if (*url != '\0' && url[strlen(url) - 1] == '/') { Ns_DStringAppend(&ds2, "/"); } request->url = ns_strdup(ds2.string); Ns_DStringFree(&ds2); /* * Build the urlv and set urlc. */ p = ns_strdup(request->url + 1); Ns_DStringNAppend(&ds1, (char *) &p, sizeof(char *)); while (*p != '\0') { if (*p == '/') { *p++ = '\0'; if (*p == '\0') { /* * Stop on a trailing slash. */ break; } Ns_DStringNAppend(&ds1, (char *) &p, sizeof(char *)); } ++p; } request->urlc = ds1.length / (sizeof(char *)); p = NULL; Ns_DStringNAppend(&ds1, (char *) &p, sizeof(char *)); request->urlv = (char **) ns_malloc((size_t)ds1.length); memcpy(request->urlv, ds1.string, (size_t)ds1.length); Ns_DStringFree(&ds1); }
Ns_Request * Ns_ParseRequestEx(char *line, Tcl_Encoding encoding) { char *url; char *p; Ns_DString ds; Ns_Request *request; unsigned int major, minor; int i; request = ns_calloc(1, sizeof(Ns_Request)); Ns_DStringInit(&ds); /* * Make a copy of the line to chop up. Make sure it isn't blank. */ if (line == NULL) { goto done; } Ns_DStringAppend(&ds, line); line = Ns_StrTrim(ds.string); if (*line == '\0') { goto done; } /* * Save the trimmed line for logging purposes. */ request->line = ns_strdup(line); /* * Look for the minimum of method and url. */ url = line; while (*url != '\0' && !isspace(UCHAR(*url))) { ++url; } if (*url == '\0') { goto done; } *url++ = '\0'; while (*url != '\0' && isspace(UCHAR(*url))) { ++url; } if (*url == '\0') { goto done; } request->method = ns_strdup(line); /* * Look for a valid version. */ request->version = 0.0; p = NsFindVersion(url, &major, &minor); if (p != NULL) { *p = '\0'; i = 10; while ((minor / i) > 0) { i *= 10; } request->version = major + (double) minor / i; } url = Ns_StrTrim(url); if (*url == '\0') { goto done; } /* * Look for a protocol in the URL. */ request->protocol = NULL; request->host = NULL; request->port = 0; if (*url != '/') { p = url; while (*p != '\0' && *p != '/' && *p != ':') { ++p; } if (*p == ':') { /* * Found a protocol - copy it and search for host:port. */ *p++ = '\0'; request->protocol = ns_strdup(url); url = p; if ((strlen(url) > 3) && (*p++ == '/') && (*p++ == '/') && (*p != '\0') && (*p != '/')) { char *h; h = p; while (*p != '\0' && *p != '/') { ++p; } if (*p == '/') { *p++ = '\0'; } url = p; p = strchr(h, ':'); if (p != NULL) { *p++ = '\0'; if (Tcl_GetInt(NULL, p, &i) != TCL_OK) { goto done; } request->port = (unsigned short) i; } request->host = ns_strdup(h); } } } SetUrl(request, url, encoding); done: if (request->url == NULL) { Ns_FreeRequest(request); request = NULL; } Ns_DStringFree(&ds); return request; }
char * Ns_DecodeUrlWithEncoding(Ns_DString *dsPtr, char *string, Tcl_Encoding encoding) { register int i, j, n; register char *p, *q; char c; Ns_DString *outPtr, out; Tcl_DString ds; /* * If using an encoding, copy output to a scratch buffer instead * of directly to given dstring. */ if (encoding == NULL) { outPtr = dsPtr; } else { Ns_DStringInit(&out); outPtr = &out; } /* * Expand the output to the length of the input * string which will be the largest size required. */ n = strlen(string); i = dsPtr->length; Ns_DStringSetLength(outPtr, i + n); q = outPtr->string + i; p = string; while ((c = UCHAR(*p)) != '\0') { if (c == '%' && n > 2 && (i = enc[UCHAR(p[1])].hex) >= 0 && (j = enc[UCHAR(p[2])].hex) >= 0) { *q = (unsigned char) ((i << 4) + j); n -= 2; p += 2; } else if (c == '+') { *q = ' '; } else { *q = c; } --n, ++q, ++p; } /* * Terminate the dstring, decoding to utf8 if necessary. */ n = q - outPtr->string; if (outPtr == dsPtr) { Ns_DStringSetLength(dsPtr, n); } else { Tcl_ExternalToUtfDString(encoding, outPtr->string, n, &ds); Ns_DStringAppend(dsPtr, ds.string); Tcl_DStringFree(&ds); Ns_DStringFree(outPtr); } return dsPtr->string; }
int Ns_ExecArgv(char *exec, char *dir, int fdin, int fdout, char **argv, Ns_Set *env) { #ifdef _WIN32 /* * Win32 ExecArgv simply calls ExecArgblk. */ int pid; Ns_DString ads; char *args; int i; Ns_DStringInit(&ads); if (argv == NULL) { args = NULL; } else { for (i = 0; argv[i] != NULL; ++i) { Ns_DStringNAppend(&ads, argv[i], strlen(argv[i]) + 1); } args = ads.string; } pid = Ns_ExecArgblk(exec, dir, fdin, fdout, args, env); Ns_DStringFree(&ads); return pid; #else Ns_DString eds; char *argvSh[4], **envp; int i, pid; if (exec == NULL) { return -1; } if (argv == NULL) { argv = argvSh; argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = exec; argv[3] = NULL; exec = argv[0]; } Ns_DStringInit(&eds); if (env == NULL) { envp = Ns_CopyEnviron(&eds); } else { for (i = 0; i < Ns_SetSize(env); ++i) { Ns_DStringVarAppend(&eds, Ns_SetKey(env, i), "=", Ns_SetValue(env, i), NULL); Ns_DStringNAppend(&eds, "", 1); } Ns_DStringNAppend(&eds, "", 1); envp = Ns_DStringAppendArgv(&eds); } if (fdin < 0) { fdin = 0; } if (fdout < 0) { fdout = 1; } pid = ExecProc(exec, dir, fdin, fdout, argv, envp); Ns_DStringFree(&eds); return pid; #endif }
int Ns_ExecArgblk(char *exec, char *dir, int fdin, int fdout, char *args, Ns_Set *env) { #ifndef _WIN32 int pid; char **argv; Ns_DString vds; Ns_DStringInit(&vds); if (args == NULL) { argv = NULL; } else { while (*args != '\0') { Ns_DStringNAppend(&vds, (char *) &args, sizeof(args)); args += strlen(args) + 1; } args = NULL; Ns_DStringNAppend(&vds, (char *) &args, sizeof(args)); argv = (char **) vds.string; } pid = Ns_ExecArgv(exec, dir, fdin, fdout, argv, env); Ns_DStringFree(&vds); return pid; #else STARTUPINFO si; PROCESS_INFORMATION pi; HANDLE hCurrentProcess; int pid; Ns_DString cds, xds, eds; char *envp; OSVERSIONINFO oinfo; char *cmd; if (exec == NULL) { return -1; } oinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&oinfo) == TRUE && oinfo.dwPlatformId != VER_PLATFORM_WIN32_NT) { cmd = "command.com"; } else { cmd = "cmd.exe"; } /* * Setup STARTUPINFO with stdin, stdout, and stderr. */ memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdError = (HANDLE) _get_osfhandle(_fileno(stderr)); hCurrentProcess = GetCurrentProcess(); if (fdout < 0) { fdout = 1; } if (DuplicateHandle(hCurrentProcess, (HANDLE) _get_osfhandle(fdout), hCurrentProcess, &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS) != TRUE) { Ns_Log(Error, "exec: failed to duplicate handle: %s", NsWin32ErrMsg(GetLastError())); return -1; } if (fdin < 0) { fdin = 0; } if (DuplicateHandle(hCurrentProcess, (HANDLE) _get_osfhandle(fdin), hCurrentProcess, &si.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS) != TRUE) { Ns_Log(Error, "exec: failed to duplicate handle: %s", NsWin32ErrMsg(GetLastError())); (void) CloseHandle(si.hStdOutput); return -1; } /* * Setup the command line and environment block and create the new * subprocess. */ Ns_DStringInit(&cds); Ns_DStringInit(&xds); Ns_DStringInit(&eds); if (args == NULL) { /* NB: exec specifies a complete cmd.exe command string. */ Ns_DStringVarAppend(&cds, cmd, " /c ", exec, NULL); exec = NULL; } else { char *s; s = args; while (*s != '\0') { int len; len = strlen(s); Ns_DStringNAppend(&cds, s, len); s += len + 1; if (*s != '\0') { Ns_DStringNAppend(&cds, " ", 1); } } Ns_NormalizePath(&xds, exec); s = xds.string; while (*s != '\0') { if (*s == '/') { *s = '\\'; } ++s; } exec = xds.string; } if (env == NULL) { envp = NULL; } else { Set2Argv(&eds, env); envp = eds.string; } if (CreateProcess(exec, cds.string, NULL, NULL, TRUE, 0, envp, dir, &si, &pi) != TRUE) { Ns_Log(Error, "exec: failed to create process: %s: %s", exec ? exec : cds.string, NsWin32ErrMsg(GetLastError())); pid = -1; } else { CloseHandle(pi.hThread); pid = (int) pi.hProcess; } Ns_DStringFree(&cds); Ns_DStringFree(&xds); Ns_DStringFree(&eds); CloseHandle(si.hStdInput); CloseHandle(si.hStdOutput); return pid; #endif }