Esempio n. 1
0
int MaEgiHandler::run(MaRequest *rq)
{
	MaEgiForm		*form;
	MaDataStream	*dynBuf;
	MaHeader		*header;
	char			*uri;
	int				flags;

	flags = rq->getFlags();
	if (flags & MPR_HTTP_POST_REQUEST && rq->getRemainingContent() > 0) {
		//
		//	When all the post data is received the run method will be recalled
		//	by the postData method.
		//
		header = rq->getHeader();
		if (mprStrCmpAnyCase(header->contentMimeType, 
				"application/x-www-form-urlencoded") == 0) {
			egiFlags |= MPR_EGI_URL_ENCODED;
		}
		return MPR_HTTP_HANDLER_FINISHED_PROCESSING;
	}

	hitCount++;
	rq->setResponseCode(200);
	rq->setResponseMimeType("text/html");
	rq->setHeaderFlags(MPR_HTTP_DONT_CACHE, 0);
	rq->insertDataStream(rq->getDynBuf());

	uri = rq->getUri();
	mprLog(4, log, "%d: serving: %s\n", rq->getFd(), uri);

	form = (MaEgiForm*) forms->lookup(uri);
	if (form == 0) {
		rq->requestError(404, "EGI Form: \"%s\" is not defined", uri);
		rq->finishRequest();

	} else {
		form->run(rq, uri, rq->getOriginalUri(), rq->getQueryString(), 
			postBuf->getStart(), postBuf->getLength());
		if (rq->getState() == MPR_HTTP_RUNNING) {
			dynBuf = rq->getDynBuf();

			//
			//	This flag is only used by the GoAhead compatibility layer.
			//	Users needing this functionality should create their own 
			//	custom handler
			//
			if (rq->getFlags() & MPR_HTTP_DONT_FINISH) {
				rq->flushOutput(MPR_HTTP_BACKGROUND_FLUSH, 0);
			} else {
				rq->flushOutput(MPR_HTTP_BACKGROUND_FLUSH, 
					MPR_HTTP_FINISH_REQUEST);
			}
		}
	}
	return MPR_HTTP_HANDLER_FINISHED_PROCESSING;
}
Esempio n. 2
0
int MaCgiHandler::parseConfig(char *key, char *value, MaServer *server, 
	MaHost *host, MaAuth *auth, MaDir *dir, MaLocation *location)
{
	char	*program, *mimeType;

	if (mprStrCmpAnyCase(key, "Action") == 0) {
		if (server->splitValue(&mimeType, &program, value, 1) < 0) {
			return MPR_ERR_BAD_SYNTAX;
		}
		host->setMimeActionProgram(mimeType, program);
		return 1;
	}
	return 0;
}
Esempio n. 3
0
File: os.cpp Progetto: OPSF/uClinux
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;
}
Esempio n. 4
0
static int fetch(MaClient *client, char *method, char *url, char *data, int len)
{
	struct stat	sbuf;
	FILE		*fp;
	MaUrl		*parsedUrl;
	char		*header, *content, *diffBuf, *msg;
	char		path[MPR_MAX_PATH], dir[MPR_MAX_PATH], urlBuf[MPR_HTTP_MAX_URL];
	char		tmp[MPR_MAX_PATH];
	int			i, code, rc, contentLen, mark, elapsed, c;

	fp = 0;

	lock();
	fetchCount++;
	unlock();

	if (url == 0) {
		return MPR_ERR_BAD_ARGS;
	}
	if (*url == '/') {
		mprSprintf(urlBuf, sizeof(urlBuf), "http://127.0.0.1%s", url);
		url = urlBuf;
	} else if ((strstr(url, "http://")) == 0) {
		mprSprintf(urlBuf, sizeof(urlBuf), "http://%s", url);
		url = urlBuf;
	}
	mprLog(MPR_DEBUG, tMod, "fetch: %s %s\n", method, url);
	mark = mprGetTime(0);

	if (mprStrCmpAnyCase(method, "GET") == 0) {
		rc = client->getRequest(url);

	} else if (mprStrCmpAnyCase(method, "HEAD") == 0) {
		rc = client->headRequest(url);

	} else if (mprStrCmpAnyCase(method, "OPTIONS") == 0) {
		rc = client->optionsRequest(url);

	} else if (mprStrCmpAnyCase(method, "POST") == 0) {
		rc = client->postRequest(url, data, len);

	} else if (mprStrCmpAnyCase(method, "TRACE") == 0) {
		rc = client->traceRequest(url);
	}

	if (rc < 0) {
		return MPR_ERR_CANT_OPEN;
	}

	code = client->getResponseCode();
	content = client->getResponseContent(&contentLen);
	header = client->getResponseHeader();
	msg = client->getResponseMessage();

	elapsed = mprGetTime(0) - mark;

	if (code == 200 || code == 302) {
		mprLog(6, tMod, "Response code %d, content len %d, header: \n%s\n", 
			code, contentLen, header);
	} else {
		mprLog(2, tMod, "Response code %d, content len %d, header: \n%s\n%s", 
			code, contentLen, header, content);
		mprError(MPR_L, MPR_USER, "Can't retrieve \"%s\" (%d), %s",
			url, code, msg);
		return MPR_ERR_CANT_READ;
	}

	if (cmpDir) {
		client->getParsedUrl(&parsedUrl);
		mprSprintf(path, sizeof(path), "%s%s", cmpDir, parsedUrl->uri);
		if (path[strlen(path) - 1] == '/') {
			path[strlen(path) - 1] = '\0';
		}
		if (stat(path, &sbuf) < 0) {
			mprError(MPR_L, MPR_USER, "Can't access %s", path);
			return MPR_ERR_CANT_ACCESS;
		}
		if (sbuf.st_mode & S_IFDIR) {
			strcpy(tmp, path);
			mprSprintf(path, sizeof(path), "%s/_DEFAULT_.html", tmp);
		}
		if (stat(path, &sbuf) < 0) {
			mprError(MPR_L, MPR_USER, "Can't access %s", path);
			return MPR_ERR_CANT_ACCESS;
		}
		if ((int) sbuf.st_size != contentLen) {
			mprError(MPR_L, MPR_USER, "Failed comparison for %s"
				"ContentLen %d, size %d\n", url, contentLen, sbuf.st_size);
			return MPR_ERR_CANT_ACCESS;
		}
		if ((fp = fopen(path, "r" MPR_BINARY)) == 0) {
			mprError(MPR_L, MPR_USER, "Can't open %s", path);
			return MPR_ERR_CANT_OPEN;
		}
		diffBuf = (char*) mprMalloc(contentLen);
		if ((int) fread(diffBuf, 1, contentLen, fp) != contentLen) {
			mprError(MPR_L, MPR_USER, "Can't read content from %s", path);
			return MPR_ERR_CANT_READ;
		}
		for (i = 0; i < contentLen; i++) {
			if (diffBuf[i] != content[i]) {
				mprError(MPR_L, MPR_USER, "Failed comparison for %s"
					"At byte %d: %x vs %x\n", i, 
					(uchar) diffBuf[i], (uchar) content[i]);
				return MPR_ERR_GENERAL;
			}
		}
		fclose(fp);
		mprFree(diffBuf);
	}

	if (writeDir) {
		client->getParsedUrl(&parsedUrl);
		mprSprintf(path, sizeof(path), "%s%s", writeDir, parsedUrl->uri);
		if (path[strlen(path) - 1] == '/') {
			path[strlen(path) - 1] = '\0';
		}
		mprGetDirName(dir, sizeof(dir), path);
		mprMakeDir(dir);
		if (stat(path, &sbuf) == 0 && sbuf.st_mode & S_IFDIR) {
			strcpy(tmp, path);
			mprSprintf(path, sizeof(path), "%s/_DEFAULT_.html", tmp);
		}

		if ((fp = fopen(path, "w" MPR_BINARY)) == 0) {
			mprError(MPR_L, MPR_USER, "Can't open %s", path);
			return MPR_ERR_CANT_OPEN;
		}
		
		if (outputHeader) {
			if (fputs(header, fp) != EOF) {
				mprError(MPR_L, MPR_USER, "Can't write header to %s", path);
				return MPR_ERR_CANT_WRITE;
			}
			fputc('\n', fp);
		}
		if ((int) fwrite(content, 1, contentLen, fp) != contentLen) {
			mprError(MPR_L, MPR_USER, "Can't write content to %s", path);
			return MPR_ERR_CANT_WRITE;
		}
		fclose(fp);
	}

	lock();
	if (trace) {
		if (strstr(url, "http://") != 0) {
			url += 7;
		}
		if ((fetchCount % 100) == 1) {
			if (fetchCount == 1 || (fetchCount % 2500) == 1) {
				if (fetchCount > 1) {
					mprPrintf("\n");
				}
				mprPrintf(
					"   Count   Fd  Thread   Op  Code   Bytes  Time Url\n");
			}
			mprPrintf("%8d %4d %7s %4s %5d %7d %5.2f %s\n", fetchCount - 1,
				client->getFd(), 
#if BLD_FEATURE_MULTITHREAD
				mprGetCurrentThreadName(),
#else
				"",
#endif
				method, code, contentLen, elapsed / 1000.0, url);
		}
	}
	if (outputHeader) {
		mprPrintf("%s\n", header);
	}
	if (!quietMode) {
		for (i = 0; i < contentLen; i++) {
			if (!isprint((uchar) content[i]) && content[i] != '\n' && content[i] != '\r' && content[i] != '\t') {
				break;
			}
		}
		if (contentLen > 0) {
			if (i != contentLen && 0) {
				mprPrintf("Content has non-printable data\n");
			} else {
				// mprPrintf("Length of content %d\n", contentLen);
				for (i = 0; i < contentLen; i++) {
					c = (uchar) content[i];
					if (isprint((uchar) c) || isspace((uchar) c)) {
						putchar(content[i]);
					} else {
						mprPrintf("0x%x", c);
					}
				}
				fflush(stdout);
			}
		}
	}
	unlock();

	if (singleStep) {
		mprPrintf("Pause: ");
		read(0, (char*) &rc, 1);
	}

	return 0;
}
Esempio n. 5
0
int MaSslModule::parseConfig(char *key, char *value, MaServer *server, 
	MaHost *host, MaAuth *auth, MaDir *dir, MaLocation *location)
{
	MaSslConfig	*config;
	char		pathBuf[MPR_MAX_FNAME], prefix[MPR_MAX_FNAME];
	char		*tok, *word, *enable, *provider;
	int			protoMask, mask;

	mprStrcpy(prefix, sizeof(prefix), key);
	prefix[3] = '\0';
	if (mprStrCmpAnyCase(prefix, "SSL") != 0) {
		return 0;
	}

	if (mprStrCmpAnyCase(key, "SSLEngine") == 0) {
		enable = mprStrTok(value, " \t", &tok);
		provider = mprStrTok(0, " \t", &tok);
		if (mprStrCmpAnyCase(value, "on") == 0) {
			if (sslProvider == 0) {
				mprError(MPR_L, MPR_LOG, "Missing an SSL Provider\n");
				return MPR_ERR_BAD_SYNTAX;
			}
			config = (MaSslConfig*) sslConfigTable->lookup(host->getName());
			if (config == 0) {
				config = sslProvider->newConfig(host);
				mprAssert(config);
				sslConfigTable->insert(config);
			}
			host->setSecure(1);
			host->server->setSslListeners(host, config);
		}
		return 1;
	}

	config = (MaSslConfig*) sslConfigTable->lookup(host->getName());
	if (config == 0) {
		mprError(MPR_L, MPR_LOG, "Missing SSLEngine directive\n");
		return MPR_ERR_BAD_SYNTAX;
	}

	if (host->makePath(pathBuf, sizeof(pathBuf), mprStrTrim(value, '\"')) 
			== 0) {
		mprError(MPR_L, MPR_LOG, "SSL path is too long");
		return MPR_ERR_BAD_SYNTAX;
    }

	if (mprStrCmpAnyCase(key, "SSLCACertificatePath") == 0) {
		config->setCaPath(pathBuf);
		return 1;

	} else if (mprStrCmpAnyCase(key, "SSLCACertificateFile") == 0) {
		config->setCaFile(pathBuf);
		return 1;

	} else if (mprStrCmpAnyCase(key, "SSLCertificateFile") == 0) {
		config->setCertFile(pathBuf);
		return 1;

	} else if (mprStrCmpAnyCase(key, "SSLCertificateKeyFile") == 0) {
		config->setKeyFile(pathBuf);
		return 1;

	} else if (mprStrCmpAnyCase(key, "SSLCipherSuite") == 0) {
		config->setCipherSuite(value);
		return 1;

	} else if (mprStrCmpAnyCase(key, "SSLVerifyClient") == 0) {
		if (mprStrCmpAnyCase(value, "require") == 0) {
			config->setVerifyClient(1);
		} else if (mprStrCmpAnyCase(value, "none") == 0) {
			config->setVerifyClient(0);
		} else {
			return -1;
		}
		return 1;

	} else if (mprStrCmpAnyCase(key, "SSLProtocol") == 0) {
		protoMask = 0;
		word = mprStrTok(value, " \t", &tok);
		while (word) {
			mask = -1;
			if (*word == '-') {
				word++;
				mask = 0;
			} else if (*word == '+') {
				word++;
			}
			if (mprStrCmpAnyCase(word, "SSLv2") == 0) {
				protoMask &= ~(MPR_HTTP_PROTO_SSLV2 & ~mask);
				protoMask |= (MPR_HTTP_PROTO_SSLV2 & mask);

			} else if (mprStrCmpAnyCase(word, "SSLv3") == 0) {
				protoMask &= ~(MPR_HTTP_PROTO_SSLV3 & ~mask);
				protoMask |= (MPR_HTTP_PROTO_SSLV3 & mask);

			} else if (mprStrCmpAnyCase(word, "TLSv1") == 0) {
				protoMask &= ~(MPR_HTTP_PROTO_TLSV1 & ~mask);
				protoMask |= (MPR_HTTP_PROTO_TLSV1 & mask);

			} else if (mprStrCmpAnyCase(word, "ALL") == 0) {
				protoMask &= ~(MPR_HTTP_PROTO_ALL & ~mask);
				protoMask |= (MPR_HTTP_PROTO_ALL & mask);
			}
			word = mprStrTok(0, " \t", &tok);
		}
		config->setSslProto(protoMask);
		return 1;
	}
	return 0;
}
Esempio n. 6
0
int MaClient::parseHeader(char *line)
{
	char	*key, *value, *tok, *tp;

	mprAssert(line && *line);

	if ((key = mprStrTok(line, ": \t\n", &tok)) == 0) {
		formatError("Bad HTTP header");
		responseCode = MPR_HTTP_CLIENT_ERROR;
		finishRequest(1);
		return MPR_ERR_BAD_STATE;
	}
	if ((value = mprStrTok(0, "\n", &tok)) == 0) {
		value = "";
	}
	while (isspace((uchar) *value)) {
		value++;
	}

	//	Upper to be consistent with Request?
	mprStrLower(key);
	headerValues->insert(new MprStringHashEntry(key, value));

	if (strcmp("www-authenticate", key) == 0) {
		tp = value;
		while (*value && !isspace((uchar) *value)) {
			value++;
		}
		*value++ = '\0';
		mprStrLower(tp);
		mprFree(serverAuthType);
		serverAuthType = mprStrdup(tp);

		if (parseAuthenticate(value) < 0) {
			formatError("Bad Authenticate header");
			responseCode = MPR_HTTP_CLIENT_ERROR;
			finishRequest(1);
			return MPR_ERR_BAD_STATE;
		}

	} else if (strcmp("content-length", key) == 0) {
		contentLength = atoi(value);
		if (mprStrCmpAnyCase(method, "HEAD") != 0) {
			contentRemaining = atoi(value);
		}

	} else if (strcmp("connection", key) == 0) {
		mprStrLower(value);
		if (strcmp(value, "close") == 0) {
			flags &= ~MPR_HTTP_KEEP_ALIVE;
#if BLD_FEATURE_KEEP_ALIVE
		} else if (strcmp(value, "keep-alive") == 0) {
			if (userFlags & MPR_HTTP_KEEP_ALIVE) {
				flags |= MPR_HTTP_KEEP_ALIVE;
			}
#endif
		}
	} else if (strcmp("transfer-encoding", key) == 0) {
		mprStrLower(value);
		if (strcmp(value, "chunked") == 0) {
			flags |= MPR_HTTP_INPUT_CHUNKED;
		}
	}
	return 0;
}
Esempio n. 7
0
int MaClient::processResponseData()
{
	char		*line, *cp;
	int			nbytes;

	mprLog(6, tMod, "READ DATA: %s\n", inBuf->getStart());
	timestamp = mprGetTime(0);

	line = 0;
	while (state != MPR_HTTP_CLIENT_DONE && inBuf->getLength() > 0) {

		line = inBuf->getStart();
		if (state != MPR_HTTP_CLIENT_CONTENT) {
			if ((cp = strchr(line, '\n')) == 0) {
				//	Wait for more data
				return 0;
			}
			*cp = '\0';
			if (cp[-1] == '\r') {
				nbytes = cp - line;
				*--cp = '\0';
			} else {
				nbytes = cp - line;
			}
			inBuf->adjustStart(nbytes + 1);

		} else {
			if (contentLength <= 0) {
				nbytes = inBuf->getLength();
			} else {
				nbytes = min(contentRemaining, inBuf->getLength());
			}
			inBuf->adjustStart(nbytes);
		}

		switch(state) {
		case MPR_HTTP_CLIENT_START:
			mprLog(3, tMod, "processResponseData: %s\n", line);
			if (line[0] == '\0') {
				return 0;
			}
			responseHeader->put(line);
			responseHeader->put('\n');
			if (parseFirst(line) < 0) {
				return MPR_ERR_BAD_STATE;
			}
			state = MPR_HTTP_CLIENT_HEADER;
			break;
		
		case MPR_HTTP_CLIENT_HEADER:
			if (nbytes > 1) {
				mprLog(3, tMod, "processResponseData: %s\n", line);
				responseHeader->put(line);
				responseHeader->put('\n');
				if (parseHeader(line) < 0) {
					return MPR_ERR_BAD_STATE;
				}
			} else {
				//
				//	Blank line means end of headers
				//
				if (flags & MPR_HTTP_INPUT_CHUNKED) {
					if (flags & MPR_HTTP_END_CHUNK_DATA) {
						finishRequest(0);
					} else {
						state = MPR_HTTP_CLIENT_CHUNK;
					}
				} else {
					state = MPR_HTTP_CLIENT_CONTENT;
					//
					//	This means there was an explicit zero content length
					//
					if (contentRemaining == 0) {
						finishRequest(0);
					} else if (mprStrCmpAnyCase(method, "HEAD") == 0) {
						finishRequest(0);
					}
				}
			}
			break;

		case MPR_HTTP_CLIENT_CHUNK:
			mprLog(3, tMod, "processResponseData: %s\n", line);
			contentRemaining = contentLength = mprAtoi(line, 16);
			if (contentLength <= 0) {
				flags |= MPR_HTTP_END_CHUNK_DATA;
				state = MPR_HTTP_CLIENT_HEADER;
			} else {
				state = MPR_HTTP_CLIENT_CONTENT;
			}
			if (contentLength > MPR_HTTP_CLIENT_BUFSIZE) {
				delete responseContent;
				responseContent = new MprBuf(contentLength + 1, -1);
			}
			break;

		case MPR_HTTP_CLIENT_CONTENT:
			responseContent->put((uchar*) line, nbytes);
			responseContent->addNull();
			mprLog(3, tMod, 
				"processResponseData: %d bytes, %d remaining, %d sofar\n", 
				nbytes, contentRemaining, responseContent->getLength());
			if (contentRemaining > 0 || nbytes <= 0) {
				contentRemaining -= nbytes;
				if (contentRemaining <= 0) {
					/* if (!(flags & MPR_HTTP_INPUT_CHUNKED)) */
					finishRequest(0);
				}
			}
			break;

		default:
			formatError("Bad state");
			responseCode = MPR_HTTP_CLIENT_ERROR;
			finishRequest(1);
			return MPR_ERR_BAD_STATE;
		}
	}
	return 0;
}
Esempio n. 8
0
int MaClient::sendCore(char *method, char *requestUrl, char *postData, 
	int postLen)
{
	char	abuf[MPR_HTTP_MAX_PASS * 2], encDetails[MPR_HTTP_MAX_PASS * 2];
	char	*host;
	int		port, len, rc, nbytes;

	mprAssert(requestUrl && *requestUrl);

	lock();
	reset();

	mprLog(3, tMod, "sendCore: %s %s\n", method, requestUrl);

	this->method = mprStrdup(method);
	timestamp = mprGetTime(0);
	if (timeoutPeriod < 0) {
		timeoutPeriod = MPR_HTTP_CLIENT_TIMEOUT;
	}
	if (timeoutPeriod > 0) {
		if (!mprGetDebugMode()) {
			timer = new MprTimer(MPR_HTTP_TIMER_PERIOD, timeoutWrapper, 
				(void *) this);
		}
	}
	
	if (*requestUrl == '/') {
		url.parse(requestUrl);
		host = (proxyHost) ? proxyHost : defaultHost;
		port = (proxyHost) ? proxyPort : defaultPort;
	} else {
		url.parse(requestUrl);
		host = (proxyHost) ? proxyHost : url.host;
		port = (proxyHost) ? proxyPort : url.port;
	}

	if (sock) {
		if (port != currentPort || strcmp(host, currentHost) != 0) {
			//
			//	This request is for a different host or port. Must close socket.
			//
			sock->close(0);
			sock->dispose();
			sock = 0;
		}
	}

	if (sock == 0) {
		sock = new MprSocket();
		mprLog(3, tMod, "Opening new socket on: %s:%d\n", host, port);
		rc = sock->openClient(host, port, MPR_SOCKET_NODELAY);
		if (rc < 0) {
			mprLog(MPR_ERROR, tMod, "Can't open socket on %s:%d, %d\n", 
				host, port, rc);
			unlock();
			sock->dispose();
			sock = 0;
			return rc;
		}
		sock->setBufSize(-1, MPR_HTTP_CLIENT_BUFSIZE);
		currentHost = mprStrdup(host);
		currentPort = port;

	} else {
		mprLog(3, tMod, "Reusing Keep-Alive socket on: %s:%d\n", host, port);
	}

	//
	//	Remove this flush when pipelining is supported
	//
	inBuf->flush();
	fd = sock->getFd();

	if (proxyHost && *proxyHost) {
		if (url.query && *url.query) {
			outBuf->putFmt("%s http://%s:%d%s?%s HTTP/1.1\r\n",
				method, proxyHost, proxyPort, url.uri, url.query);
		} else {
			outBuf->putFmt("%s http://%s:%d%s HTTP/1.1\r\n",
				method, proxyHost, proxyPort, url.uri);
		}
	} else {
		if (url.query && *url.query) {
			outBuf->putFmt("%s %s?%s HTTP/1.1\r\n", method, url.uri, url.query);
		} else {
			outBuf->putFmt("%s %s HTTP/1.1\r\n", method, url.uri);
		}
	}

	if (serverAuthType) {
		if (strcmp(serverAuthType, "basic") == 0) {
			mprSprintf(abuf, sizeof(abuf), "%s:%s", user, password);
			maEncode64(encDetails, sizeof(encDetails), abuf);
			outBuf->putFmt("Authorization: %s %s\r\n", serverAuthType, 
				encDetails);

#if BLD_FEATURE_DIGEST
		} else if (strcmp(serverAuthType, "digest") == 0) {
			char	a1Buf[256], a2Buf[256], digestBuf[256];
			char	*ha1, *ha2, *digest, *qop;

			authNc++;
			if (secret == 0) {
				if (createSecret() < 0) {
					mprLog(MPR_ERROR, tMod, "Can't create secret\n");
					return MPR_ERR_CANT_INITIALIZE;
				}
			}
			mprFree(authCnonce);
			maCalcNonce(&authCnonce, secret, 0, realm);

			mprSprintf(a1Buf, sizeof(a1Buf), "%s:%s:%s", user, realm, password);
			ha1 = maMD5(a1Buf);

			mprSprintf(a2Buf, sizeof(a2Buf), "%s:%s", method, url.uri);
			ha2 = maMD5(a2Buf);

			qop = (serverQop) ? serverQop : (char*) "";
			if (mprStrCmpAnyCase(serverQop, "auth") == 0) {
				mprSprintf(digestBuf, sizeof(digestBuf), "%s:%s:%08x:%s:%s:%s", 
					ha1, serverNonce, authNc, authCnonce, serverQop, ha2);

			} else if (mprStrCmpAnyCase(serverQop, "auth-int") == 0) {
				mprSprintf(digestBuf, sizeof(digestBuf), "%s:%s:%08x:%s:%s:%s", 
					ha1, serverNonce, authNc, authCnonce, serverQop, ha2);

			} else {
				qop = "";
				mprSprintf(digestBuf, sizeof(digestBuf), "%s:%s:%s", ha1, 
					serverNonce, ha2);
			}

			mprFree(ha1);
			mprFree(ha2);
			digest = maMD5(digestBuf);

			if (*qop == '\0') {
				outBuf->putFmt("Authorization: Digest "
					"username=\"%s\", realm=\"%s\", nonce=\"%s\", "
					"uri=\"%s\", response=\"%s\"\r\n",
					user, realm, serverNonce, url.uri, digest);

			} else if (strcmp(qop, "auth") == 0) {
				outBuf->putFmt("Authorization: Digest "
					"username=\"%s\", realm=\"%s\", domain=\"%s\", "
					"algorithm=\"MD5\", qop=\"%s\", cnonce=\"%s\", "
					"nc=\"%08x\", nonce=\"%s\", opaque=\"%s\", "
					"stale=\"FALSE\", uri=\"%s\", response=\"%s\"\r\n",
					user, realm, serverDomain, serverQop, authCnonce, authNc, 
					serverNonce, serverOpaque, url.uri, digest);

			} else if (strcmp(qop, "auth-int") == 0) {
				;
			}
			mprFree(digest);
#endif // BLD_FEATURE_HTTP_DIGEST
		}
	}

	outBuf->putFmt("Host: %s\r\n", host);
	outBuf->putFmt("User-Agent: %s\r\n", MPR_HTTP_CLIENT_NAME);
	if (userFlags & MPR_HTTP_KEEP_ALIVE) {
		outBuf->putFmt("Connection: Keep-Alive\r\n");
	} else {
		outBuf->putFmt("Connection: close\r\n");
	}
	if (postLen > 0) {
		outBuf->putFmt("Content-Length: %d\r\n", postLen);
	}
	if (postData) {
		outBuf->putFmt("Content-Type: application/x-www-form-urlencoded\r\n");
	}
	if (userHeaders) {
		outBuf->put(userHeaders);
	}
	outBuf->put("\r\n");
	outBuf->addNull();

	//
	//	Flush to the socket with any post data. Writes can fail because the
	//	server prematurely closes a keep-alive connection.
	//
	len = outBuf->getLength();
	if ((rc = sock->write(outBuf->getStart(), len)) != len) {
		flags |= MPR_HTTP_TERMINATED;
		unlock();
		mprLog(MPR_ERROR, tMod, 
			"Can't write to socket on %s:%d, %d\n", host, port, rc);
		return rc;
	}

#if BLD_DEBUG
	mprLog(3, MPR_RAW, tMod, "Request >>>>\n%s\n", outBuf->getStart());
#endif

	if (postData) {
		sock->setBlockingMode(1);
		for (len = 0; len < postLen; ) {
			nbytes = postLen - len;
			rc = sock->write(&postData[len], nbytes);
#if BLD_DEBUG
			mprLog(3, MPR_RAW, tMod, "POST DATA %s\n", &postData[len]);
#endif
			if (rc < 0) {
				unlock();
				mprLog(MPR_ERROR, tMod, 
					"Can't write post data to socket on %s:%d, %d\n", 
					host, port, rc);
				flags |= MPR_HTTP_TERMINATED;
				sock->dispose();
				sock = 0;
				return rc;
			}
			len += rc;
		}
		sock->setBlockingMode(0);
	}
	sock->setCallback(readEventWrapper, (void*) this, 0, MPR_READABLE);

	//
	//	If no callback, then we must block
	//
	if (callback == 0) {
		unlock();
		while (state != MPR_HTTP_CLIENT_DONE) {
			//
			//	If multithreaded and the events thread is not yet running,
			//	we still want to work.
			//
#if BLD_FEATURE_MULTITHREAD
			if (mprGetMpr()->isRunningEventsThread() &&
					mprGetMpr()->poolService->getMaxPoolThreads() > 0) {
				completeCond->waitForCond(250);
			} else
#endif
				mprGetMpr()->serviceEvents(1, 100);
		}
	} else {
		unlock();
	}
	return 0;
}
Esempio n. 9
0
int MaClient::parseAuthenticate(char *authDetails)
{
	char	*value, *tok, *key, *dp, *sp;
	int		seenComma;

	key = authDetails;

	while (*key) {
		while (*key && isspace((uchar) *key)) {
			key++;
		}
		tok = key;
		while (*tok && !isspace((uchar) *tok) && *tok != ',' && *tok != '=') {
			tok++;
		}
		*tok++ = '\0';

		while (isspace((uchar) *tok)) {
			tok++;
		}
		seenComma = 0;
		if (*tok == '\"') {
			value = ++tok;
			while (*tok != '\"' && *tok != '\0') {
				tok++;
			}
		} else {
			value = tok;
			while (*tok != ',' && *tok != '\0') {
				tok++;
			}
			seenComma++;
		}
		*tok++ = '\0';

		//
		//	Handle back-quoting
		//
		if (strchr(value, '\\')) {
			for (dp = sp = value; *sp; sp++) {
				if (*sp == '\\') {
					sp++;
				}
				*dp++ = *sp++;
			}
			*dp = '\0';
		}

		//
		//	algorithm, domain, nonce, oqaque, realm, qop, stale
		//	
		switch (tolower((uchar) *key)) {
		case 'a':
			if (mprStrCmpAnyCase(key, "algorithm") == 0) {
				mprFree(serverAlgorithm);
				serverAlgorithm = mprStrdup(value);
				break;
//			} else if (mprStrCmpAnyCase(key, "server-param") == 0) {
//				break;
			}
			break;

		case 'd':
			if (mprStrCmpAnyCase(key, "domain") == 0) {
				mprFree(serverDomain);
				serverDomain = mprStrdup(value);
				break;
			}
			break;

		case 'n':
			if (mprStrCmpAnyCase(key, "nonce") == 0) {
				mprFree(serverNonce);
				serverNonce = mprStrdup(value);
				authNc = 0;
			}
			break;

		case 'o':
			if (mprStrCmpAnyCase(key, "opaque") == 0) {
				mprFree(serverOpaque);
				serverOpaque = mprStrdup(value);
			}
			break;

		case 'q':
			if (mprStrCmpAnyCase(key, "qop") == 0) {
				mprFree(serverQop);
				serverQop = mprStrdup(value);
			}
			break;

		case 'r':
			if (mprStrCmpAnyCase(key, "realm") == 0) {
				mprFree(serverRealm);
				serverRealm = mprStrdup(value);
			}
			break;

		case 's':
			if (mprStrCmpAnyCase(key, "stale") == 0) {
				mprFree(serverStale);
				serverStale = mprStrdup(value);
				break;
			}
		
		default:
			//	For upward compatibility --  ignore keywords we don't understand
			;
		}
		key = tok;
		if (!seenComma) {
			while (*key && *key != ',') {
				key++;
			}
			if (*key) {
				key++;
			}
		}
	}
	if (strcmp(serverAuthType, "basic") == 0) {
		if (serverRealm == 0) {
			return MPR_ERR_BAD_ARGS;
		} else {
			return 0;
		}
	}
	if (serverRealm == 0 || serverNonce == 0) {
		return MPR_ERR_BAD_ARGS;
	}
	if (serverQop) {
		//	FUTURE -- add checking for auth-int here
		if (serverDomain == 0 || serverOpaque == 0 || 
				serverAlgorithm == 0 || serverStale == 0) {
			return MPR_ERR_BAD_ARGS;
		}
	}
	return 0;
}