Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
int main(int argc, char *argv[])
{
	char	*password, *passFile, *userName;
	char	*encodedPassword, *argp, *realm;
	char	passBuf[MPR_HTTP_MAX_PASS], buf[MPR_HTTP_MAX_PASS * 2];
	int		c, errflg, create, nextArg;
	bool	enable;

	programName = mprGetBaseName(argv[0]);
	userName = 0;
	create = errflg = 0;
	password = 0;
	enable = 1;

#if BLD_FEATURE_LOG
	MprLogService *ls = new MprLogService();
	ls->addListener(new MprLogToFile());
	ls->setLogSpec("stdout:0");
#endif

	MprCmdLine cmdLine(argc, argv, "cdep:");
	while ((c = cmdLine.next(&argp)) != EOF) {
		switch(c) {
		case 'c':
			create++;
			break;

		case 'e':
			enable = 1;
			break;

		case 'd':
			enable = 0;
			break;

		case 'p':
			password = argp;
			break;

		default:
			errflg++;
			break;
		}
	}
	nextArg = cmdLine.firstArg();
	if ((nextArg + 3) > argc) {
		errflg++;
	}

	if (errflg) {
		printUsage(argv[0]);
		exit(2);
	}	

	passFile = argv[nextArg++];
	realm = argv[nextArg++];
	userName = argv[nextArg++];

	if (!create) {
		if (readPassFile(passFile) < 0) {
			exit(2);
		}
		if (access(passFile, R_OK) != 0) {
			mprError(MPR_L, MPR_USER, "Can't find %s\n", passFile);
			exit(3);
		}
		if (access(passFile, W_OK) < 0) {
			mprError(MPR_L, MPR_USER, "Can't write to %s\n", passFile);
			exit(4);
		}
	} else {
		if (access(passFile, R_OK) == 0) {
			mprError(MPR_L, MPR_USER, "Can't create %s, already exists\n", 
				passFile);
			exit(5);
		}
	}

	if (password == 0) {
		password = getPassword(passBuf, sizeof(passBuf));
		if (password == 0) {
			exit(1);
		}
	}

	mprSprintf(buf, sizeof(buf), "%s:%s:%s", userName, realm, password);
	encodedPassword = maMD5(buf);

	addUser(userName, realm, encodedPassword, enable);

	if (updatePassFile(passFile) < 0) {
		exit(6);
	}
	mprFree(encodedPassword);
	
	return 0;
}