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; }
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; }