// Note: this only works for local remote moves, cross filesystem moves // will not work bool FtpClient::MoveFile(const string& oldPath, const string& newPath) { bool rc = false; string from = "RNFR "; string to = "RNTO "; string replyString; int code, codeType; from += oldPath; to += newPath; if (_SendRequest(from)) { if (_GetReply(replyString, code, codeType)) { if (codeType == 3) { if (_SendRequest(to)) { if (_GetReply(replyString, code, codeType)) { if(codeType == 2) rc = true; } } } } } return rc; }
bool Wininet::_CallURL(CALLURLDATA *pcud, MEMDATA *pBuf) { bool r = false; HttpTools::URLDATA ud; if(HttpTools::_parseUrl(pcud->pstrURL, &ud)) { DWORD dwRequestFlags = pcud->SendRequest_dwFlags; if(ud.scheme == HttpTools::UDS_HTTPS)dwRequestFlags |= WISRF_IS_HTTPS; else dwRequestFlags &= ~(WISRF_IS_HTTPS); for(BYTE bi = 0; bi < pcud->bTryCount; bi++) { //Delay. if(bi > 0) { if(pcud->hStopEvent != NULL) { if(CWA(kernel32, WaitForSingleObject)(pcud->hStopEvent, pcud->dwRetryDelay) != WAIT_TIMEOUT)goto END; } else CWA(kernel32, Sleep)(pcud->dwRetryDelay); } DWORD dwConnectFlags = pcud->Connect_dwFlags; BYTE pp_m = 1; if(pcud->bAutoProxy) { dwConnectFlags |= WICF_USE_IE_PROXY; pp_m++; } for(BYTE pp = 0; pp < pp_m; pp++) { if(pp == 1)dwConnectFlags &= ~(WICF_USE_IE_PROXY); //Connection. HINTERNET hConnect = _Connect(pcud->pstrUserAgent, ud.host, ud.port, dwConnectFlags); if(hConnect) { HINTERNET hRequest = _SendRequest(hConnect, ud.uri, NULL, pcud->SendRequest_pPostData, pcud->SendRequest_dwPostDataSize, dwRequestFlags); if(hRequest) { if(pcud->DownloadData_pstrFileName)r = _DownloadDataToFile(hRequest, pcud->DownloadData_pstrFileName, pcud->DownloadData_dwSizeLimit, pcud->hStopEvent); else r = _DownloadData(hRequest, pBuf, pcud->DownloadData_dwSizeLimit, pcud->hStopEvent); CWA(wininet, InternetCloseHandle)(hRequest); } _CloseConnection(hConnect); if(r)goto END; } } } END: HttpTools::_freeUrlData(&ud); } return r; }
bool FtpClient::ListDirContents(string& listing) { bool rc = false; string cmd, replyString; int code, codeType, numRead; char buf[513]; cmd = "TYPE A"; if (_SendRequest(cmd)) _GetReply(replyString, code, codeType); if (_OpenDataConnection()) { cmd = "LIST"; if (_SendRequest(cmd)) { if (_GetReply(replyString, code, codeType)) { if (codeType <= 2) { if (_AcceptDataConnection()) { numRead = 1; while (numRead > 0) { memset(buf, 0, sizeof(buf)); numRead = fData->Receive(buf, sizeof(buf) - 1); listing += buf; printf(buf); } if (_GetReply(replyString, code, codeType)) { if (codeType <= 2) rc = true; } } } } } } delete fData; fData = 0; return rc; }
bool FtpClient::ChangeDir(const string& dir) { bool rc = false; int code, codeType; string cmd = "CWD ", replyString; cmd += dir; if (dir.length() == 0) cmd += '/'; if (_SendRequest(cmd) == true) { if (_GetReply(replyString, code, codeType) == true) { if (codeType == 2) rc = true; } } return rc; }
bool FtpClient::PrintWorkingDir(string& dir) { bool rc = false; int code, codeType; string cmd = "PWD", replyString; long i; if (_SendRequest(cmd) == true) { if (_GetReply(replyString, code, codeType) == true) { if (codeType == 2) { i = replyString.find('"'); if (i != -1) { i++; dir = replyString.substr(i, replyString.find('"') - i); rc = true; } } } } return rc; }
bool FtpClient::Chmod(const string& path, const string& mod) { bool rc = false; int code, codeType; string cmd = "SITE CHMOD ", replyString; cmd += mod; cmd += " "; cmd += path; if (path.length() == 0) cmd += '/'; printf(B_TRANSLATE("cmd: '%s'\n"), cmd.c_str()); if (_SendRequest(cmd) == true) { if (_GetReply(replyString, code, codeType) == true) { printf(B_TRANSLATE("reply: %d, %d\n"), code, codeType); if (codeType == 2) rc = true; } } return rc; }
status_t BHttpRequest::_MakeRequest() { delete fSocket; if (fSSL) fSocket = new(std::nothrow) CheckedSecureSocket(this); else fSocket = new(std::nothrow) BSocket(); if (fSocket == NULL) return B_NO_MEMORY; _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Connection to %s on port %d.", fUrl.Authority().String(), fRemoteAddr.Port()); status_t connectError = fSocket->Connect(fRemoteAddr); if (connectError != B_OK) { _EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR, "Socket connection error %s", strerror(connectError)); return connectError; } //! ProtocolHook:ConnectionOpened if (fListener != NULL) fListener->ConnectionOpened(this); _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Connection opened, sending request."); _SendRequest(); _SendHeaders(); fSocket->Write("\r\n", 2); _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Request sent."); _SendPostData(); fRequestStatus = kRequestInitialState; // Receive loop bool receiveEnd = false; bool parseEnd = false; bool readByChunks = false; bool decompress = false; status_t readError = B_OK; ssize_t bytesRead = 0; ssize_t bytesReceived = 0; ssize_t bytesTotal = 0; off_t bytesUnpacked = 0; char* inputTempBuffer = new(std::nothrow) char[kHttpBufferSize]; ssize_t inputTempSize = kHttpBufferSize; ssize_t chunkSize = -1; DynamicBuffer decompressorStorage; BDataIO* decompressingStream; ObjectDeleter<BDataIO> decompressingStreamDeleter; while (!fQuit && !(receiveEnd && parseEnd)) { if (!receiveEnd) { fSocket->WaitForReadable(); BStackOrHeapArray<char, 4096> chunk(kHttpBufferSize); bytesRead = fSocket->Read(chunk, kHttpBufferSize); if (bytesRead < 0) { readError = bytesRead; break; } else if (bytesRead == 0) receiveEnd = true; fInputBuffer.AppendData(chunk, bytesRead); } else bytesRead = 0; if (fRequestStatus < kRequestStatusReceived) { _ParseStatus(); //! ProtocolHook:ResponseStarted if (fRequestStatus >= kRequestStatusReceived && fListener != NULL) fListener->ResponseStarted(this); } if (fRequestStatus < kRequestHeadersReceived) { _ParseHeaders(); if (fRequestStatus >= kRequestHeadersReceived) { _ResultHeaders() = fHeaders; //! ProtocolHook:HeadersReceived if (fListener != NULL) fListener->HeadersReceived(this); // Parse received cookies if (fContext != NULL) { for (int32 i = 0; i < fHeaders.CountHeaders(); i++) { if (fHeaders.HeaderAt(i).NameIs("Set-Cookie")) { fContext->GetCookieJar().AddCookie( fHeaders.HeaderAt(i).Value(), fUrl); } } } if (BString(fHeaders["Transfer-Encoding"]) == "chunked") readByChunks = true; BString contentEncoding(fHeaders["Content-Encoding"]); // We don't advertise "deflate" support (see above), but we // still try to decompress it, if a server ever sends a deflate // stream despite it not being in our Accept-Encoding list. if (contentEncoding == "gzip" || contentEncoding == "deflate") { decompress = true; readError = BZlibCompressionAlgorithm() .CreateDecompressingOutputStream(&decompressorStorage, NULL, decompressingStream); if (readError != B_OK) break; decompressingStreamDeleter.SetTo(decompressingStream); } int32 index = fHeaders.HasHeader("Content-Length"); if (index != B_ERROR) bytesTotal = atoi(fHeaders.HeaderAt(index).Value()); else bytesTotal = -1; } } if (fRequestStatus >= kRequestHeadersReceived) { // If Transfer-Encoding is chunked, we should read a complete // chunk in buffer before handling it if (readByChunks) { if (chunkSize >= 0) { if ((ssize_t)fInputBuffer.Size() >= chunkSize + 2) { // 2 more bytes to handle the closing CR+LF bytesRead = chunkSize; if (inputTempSize < chunkSize + 2) { delete[] inputTempBuffer; inputTempSize = chunkSize + 2; inputTempBuffer = new(std::nothrow) char[inputTempSize]; } if (inputTempBuffer == NULL) { readError = B_NO_MEMORY; break; } fInputBuffer.RemoveData(inputTempBuffer, chunkSize + 2); chunkSize = -1; } else { // Not enough data, try again later bytesRead = -1; } } else { BString chunkHeader; if (_GetLine(chunkHeader) == B_ERROR) { chunkSize = -1; bytesRead = -1; } else { // Format of a chunk header: // <chunk size in hex>[; optional data] int32 semiColonIndex = chunkHeader.FindFirst(';', 0); // Cut-off optional data if present if (semiColonIndex != -1) { chunkHeader.Remove(semiColonIndex, chunkHeader.Length() - semiColonIndex); } chunkSize = strtol(chunkHeader.String(), NULL, 16); PRINT(("BHP[%p] Chunk %s=%ld\n", this, chunkHeader.String(), chunkSize)); if (chunkSize == 0) fRequestStatus = kRequestContentReceived; bytesRead = -1; } } // A chunk of 0 bytes indicates the end of the chunked transfer if (bytesRead == 0) receiveEnd = true; } else { bytesRead = fInputBuffer.Size(); if (bytesRead > 0) { if (inputTempSize < bytesRead) { inputTempSize = bytesRead; delete[] inputTempBuffer; inputTempBuffer = new(std::nothrow) char[bytesRead]; } if (inputTempBuffer == NULL) { readError = B_NO_MEMORY; break; } fInputBuffer.RemoveData(inputTempBuffer, bytesRead); } } if (bytesRead >= 0) { bytesReceived += bytesRead; if (fListener != NULL) { if (decompress) { readError = decompressingStream->WriteExactly( inputTempBuffer, bytesRead); if (readError != B_OK) break; ssize_t size = decompressorStorage.Size(); BStackOrHeapArray<char, 4096> buffer(size); size = decompressorStorage.Read(buffer, size); if (size > 0) { fListener->DataReceived(this, buffer, bytesUnpacked, size); bytesUnpacked += size; } } else if (bytesRead > 0) { fListener->DataReceived(this, inputTempBuffer, bytesReceived - bytesRead, bytesRead); } fListener->DownloadProgress(this, bytesReceived, std::max((ssize_t)0, bytesTotal)); } if (bytesTotal >= 0 && bytesReceived >= bytesTotal) receiveEnd = true; if (decompress && receiveEnd) { readError = decompressingStream->Flush(); if (readError == B_BUFFER_OVERFLOW) readError = B_OK; if (readError != B_OK) break; ssize_t size = decompressorStorage.Size(); BStackOrHeapArray<char, 4096> buffer(size); size = decompressorStorage.Read(buffer, size); if (fListener != NULL && size > 0) { fListener->DataReceived(this, buffer, bytesUnpacked, size); bytesUnpacked += size; } } } } parseEnd = (fInputBuffer.Size() == 0); } fSocket->Disconnect(); delete[] inputTempBuffer; if (readError != B_OK) return readError; return fQuit ? B_INTERRUPTED : B_OK; }
status_t BHttpRequest::_MakeRequest() { if (fSocket == NULL) return B_NO_MEMORY; _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Connection to %s on port %d.", fUrl.Authority().String(), fRemoteAddr.Port()); status_t connectError = fSocket->Connect(fRemoteAddr); if (connectError != B_OK) { _EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR, "Socket connection error %s", strerror(connectError)); return connectError; } //! ProtocolHook:ConnectionOpened if (fListener != NULL) fListener->ConnectionOpened(this); _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Connection opened, sending request."); _SendRequest(); _SendHeaders(); fSocket->Write("\r\n", 2); _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Request sent."); if (fRequestMethod == B_HTTP_POST && fOptPostFields != NULL) { if (fOptPostFields->GetFormType() != B_HTTP_FORM_MULTIPART) { BString outputBuffer = fOptPostFields->RawData(); _EmitDebug(B_URL_PROTOCOL_DEBUG_TRANSFER_OUT, "%s", outputBuffer.String()); fSocket->Write(outputBuffer.String(), outputBuffer.Length()); } else { for (BHttpForm::Iterator it = fOptPostFields->GetIterator(); const BHttpFormData* currentField = it.Next(); ) { _EmitDebug(B_URL_PROTOCOL_DEBUG_TRANSFER_OUT, it.MultipartHeader().String()); fSocket->Write(it.MultipartHeader().String(), it.MultipartHeader().Length()); switch (currentField->Type()) { default: case B_HTTPFORM_UNKNOWN: ASSERT(0); break; case B_HTTPFORM_STRING: fSocket->Write(currentField->String().String(), currentField->String().Length()); break; case B_HTTPFORM_FILE: { BFile upFile(currentField->File().Path(), B_READ_ONLY); char readBuffer[kHttpBufferSize]; ssize_t readSize; readSize = upFile.Read(readBuffer, sizeof(readBuffer)); while (readSize > 0) { fSocket->Write(readBuffer, readSize); readSize = upFile.Read(readBuffer, sizeof(readBuffer)); } break; } case B_HTTPFORM_BUFFER: fSocket->Write(currentField->Buffer(), currentField->BufferSize()); break; } fSocket->Write("\r\n", 2); } BString footer = fOptPostFields->GetMultipartFooter(); fSocket->Write(footer.String(), footer.Length()); } } else if ((fRequestMethod == B_HTTP_POST || fRequestMethod == B_HTTP_PUT) && fOptInputData != NULL) { for (;;) { char outputTempBuffer[kHttpBufferSize]; ssize_t read = fOptInputData->Read(outputTempBuffer, sizeof(outputTempBuffer)); if (read <= 0) break; if (fOptInputDataSize < 0) { // Chunked transfer char hexSize[16]; size_t hexLength = sprintf(hexSize, "%ld", read); fSocket->Write(hexSize, hexLength); fSocket->Write("\r\n", 2); fSocket->Write(outputTempBuffer, read); fSocket->Write("\r\n", 2); } else { fSocket->Write(outputTempBuffer, read); } } if (fOptInputDataSize < 0) { // Chunked transfer terminating sequence fSocket->Write("0\r\n\r\n", 5); } } fRequestStatus = kRequestInitialState; // Receive loop bool receiveEnd = false; bool parseEnd = false; bool readByChunks = false; bool decompress = false; status_t readError = B_OK; ssize_t bytesRead = 0; ssize_t bytesReceived = 0; ssize_t bytesTotal = 0; char* inputTempBuffer = new(std::nothrow) char[kHttpBufferSize]; ssize_t inputTempSize = kHttpBufferSize; ssize_t chunkSize = -1; DynamicBuffer decompressorStorage; BPrivate::ZlibDecompressor decompressor(&decompressorStorage); while (!fQuit && !(receiveEnd && parseEnd)) { if (!receiveEnd) { fSocket->WaitForReadable(); BNetBuffer chunk(kHttpBufferSize); bytesRead = fSocket->Read(chunk.Data(), kHttpBufferSize); if (bytesRead < 0) { readError = bytesRead; break; } else if (bytesRead == 0) receiveEnd = true; fInputBuffer.AppendData(chunk.Data(), bytesRead); } else bytesRead = 0; if (fRequestStatus < kRequestStatusReceived) { _ParseStatus(); //! ProtocolHook:ResponseStarted if (fRequestStatus >= kRequestStatusReceived && fListener != NULL) fListener->ResponseStarted(this); } if (fRequestStatus < kRequestHeadersReceived) { _ParseHeaders(); if (fRequestStatus >= kRequestHeadersReceived) { _ResultHeaders() = fHeaders; //! ProtocolHook:HeadersReceived if (fListener != NULL) fListener->HeadersReceived(this); // Parse received cookies if (fContext != NULL) { for (int32 i = 0; i < fHeaders.CountHeaders(); i++) { if (fHeaders.HeaderAt(i).NameIs("Set-Cookie")) { fContext->GetCookieJar().AddCookie( fHeaders.HeaderAt(i).Value(), fUrl); } } } if (BString(fHeaders["Transfer-Encoding"]) == "chunked") readByChunks = true; BString contentEncoding(fHeaders["Content-Encoding"]); if (contentEncoding == "gzip" || contentEncoding == "deflate") { decompress = true; decompressor.Init(); } int32 index = fHeaders.HasHeader("Content-Length"); if (index != B_ERROR) bytesTotal = atoi(fHeaders.HeaderAt(index).Value()); else bytesTotal = 0; } } if (fRequestStatus >= kRequestHeadersReceived) { // If Transfer-Encoding is chunked, we should read a complete // chunk in buffer before handling it if (readByChunks) { if (chunkSize >= 0) { if ((ssize_t)fInputBuffer.Size() >= chunkSize + 2) { // 2 more bytes to handle the closing CR+LF bytesRead = chunkSize; if (inputTempSize < chunkSize + 2) { delete[] inputTempBuffer; inputTempSize = chunkSize + 2; inputTempBuffer = new(std::nothrow) char[inputTempSize]; } if (inputTempBuffer == NULL) { readError = B_NO_MEMORY; break; } fInputBuffer.RemoveData(inputTempBuffer, chunkSize + 2); chunkSize = -1; } else { // Not enough data, try again later bytesRead = -1; } } else { BString chunkHeader; if (_GetLine(chunkHeader) == B_ERROR) { chunkSize = -1; bytesRead = -1; } else { // Format of a chunk header: // <chunk size in hex>[; optional data] int32 semiColonIndex = chunkHeader.FindFirst(';', 0); // Cut-off optional data if present if (semiColonIndex != -1) { chunkHeader.Remove(semiColonIndex, chunkHeader.Length() - semiColonIndex); } chunkSize = strtol(chunkHeader.String(), NULL, 16); PRINT(("BHP[%p] Chunk %s=%ld\n", this, chunkHeader.String(), chunkSize)); if (chunkSize == 0) fRequestStatus = kRequestContentReceived; bytesRead = -1; } } // A chunk of 0 bytes indicates the end of the chunked transfer if (bytesRead == 0) receiveEnd = true; } else { bytesRead = fInputBuffer.Size(); if (bytesRead > 0) { if (inputTempSize < bytesRead) { inputTempSize = bytesRead; delete[] inputTempBuffer; inputTempBuffer = new(std::nothrow) char[bytesRead]; } if (inputTempBuffer == NULL) { readError = B_NO_MEMORY; break; } fInputBuffer.RemoveData(inputTempBuffer, bytesRead); } } if (bytesRead > 0) { bytesReceived += bytesRead; if (fListener != NULL) { if (decompress) { decompressor.DecompressNext(inputTempBuffer, bytesRead); ssize_t size = decompressorStorage.Size(); BStackOrHeapArray<char, 4096> buffer(size); size = decompressorStorage.Read(buffer, size); if (size > 0) { fListener->DataReceived(this, buffer, size); } } else { fListener->DataReceived(this, inputTempBuffer, bytesRead); } fListener->DownloadProgress(this, bytesReceived, bytesTotal); } if (bytesTotal > 0 && bytesReceived >= bytesTotal) { receiveEnd = true; if (decompress) { decompressor.Finish(); ssize_t size = decompressorStorage.Size(); BStackOrHeapArray<char, 4096> buffer(size); size = decompressorStorage.Read(buffer, size); if (fListener != NULL && size > 0) { fListener->DataReceived(this, buffer, size); } } } } } parseEnd = (fInputBuffer.Size() == 0); } fSocket->Disconnect(); delete[] inputTempBuffer; if (readError != B_OK) return readError; return fQuit ? B_INTERRUPTED : B_OK; }
bool FtpClient::_OpenDataConnection() { string host, cmd, replyString; unsigned short port; BNetAddress addr; int i, code, codeType; bool rc = false; struct sockaddr_in sa; delete fData; fData = 0; fData = new BNetEndpoint; if (_TestState(ftp_passive)) { // Here we send a "pasv" command and connect to the remote server // on the port it sends back to us cmd = "PASV"; if (_SendRequest(cmd)) { if (_GetReply(replyString, code, codeType)) { if (codeType == 2) { // It should give us something like: // "227 Entering Passive Mode (192,168,1,1,10,187)" int paddr[6]; unsigned char ucaddr[6]; i = replyString.find('('); i++; replyString = replyString.substr(i, replyString.find(')') - i); if (sscanf(replyString.c_str(), "%d,%d,%d,%d,%d,%d", &paddr[0], &paddr[1], &paddr[2], &paddr[3], &paddr[4], &paddr[5]) != 6) { // cannot do passive. Do a little harmless rercursion here _ClearState(ftp_passive); return _OpenDataConnection(); } for (i = 0; i < 6; i++) ucaddr[i] = (unsigned char)(paddr[i] & 0xff); memcpy(&sa.sin_addr, &ucaddr[0], (size_t) 4); memcpy(&sa.sin_port, &ucaddr[4], (size_t) 2); addr.SetTo(sa); if (fData->Connect(addr) == B_NO_ERROR) rc = true; } } } else { // cannot do passive. Do a little harmless rercursion here _ClearState(ftp_passive); rc = _OpenDataConnection(); } } else { // Here we bind to a local port and send a PORT command if (fData->Bind() == B_NO_ERROR) { char buf[255]; fData->Listen(); addr = fData->LocalAddr(); addr.GetAddr(buf, &port); host = buf; i = 0; while (i >= 0) { i = host.find('.', i); if (i >= 0) host[i] = ','; } sprintf(buf, ",%d,%d", (port & 0xff00) >> 8, port & 0x00ff); cmd = "PORT "; cmd += host; cmd += buf; _SendRequest(cmd); _GetReply(replyString, code, codeType); // PORT failure is in the 500-range if (codeType == 2) rc = true; } }
bool FtpClient::GetFile(const string& remote, const string& local, ftp_mode mode) { bool rc = false; string cmd, replyString; int code, codeType, rlen, slen, i; BFile outfile(local.c_str(), B_READ_WRITE | B_CREATE_FILE); char buf[8192], sbuf[16384], *stmp; bool writeError = false; if (outfile.InitCheck() != B_NO_ERROR) return false; if (mode == binary_mode) cmd = "TYPE I"; else cmd = "TYPE A"; if (_SendRequest(cmd)) _GetReply(replyString, code, codeType); if (_OpenDataConnection()) { cmd = "RETR "; cmd += remote; if (_SendRequest(cmd)) { if (_GetReply(replyString, code, codeType)) { if (codeType <= 2) { if (_AcceptDataConnection()) { rlen = 1; rc = true; while (rlen > 0) { memset(buf, 0, sizeof(buf)); memset(sbuf, 0, sizeof(sbuf)); rlen = fData->Receive(buf, sizeof(buf)); if (rlen > 0) { slen = rlen; stmp = buf; if (mode == ascii_mode) { stmp = sbuf; slen = 0; for (i = 0; i < rlen; i++) { if (buf[i] == '\r') i++; *stmp = buf[i]; stmp++; slen++; } stmp = sbuf; } if (slen > 0) { if (outfile.Write(stmp, slen) < 0) writeError = true; } } } } } } } } delete fData; fData = 0; if (rc) { _GetReply(replyString, code, codeType); rc = (codeType <= 2 && writeError == false); } return rc; }
bool FtpClient::PutFile(const string& local, const string& remote, ftp_mode mode) { bool rc = false; string cmd, replyString; int code, codeType, rlen, slen, i; BFile infile(local.c_str(), B_READ_ONLY); char buf[8192], sbuf[16384], *stmp; if (infile.InitCheck() != B_NO_ERROR) return false; if (mode == binary_mode) cmd = "TYPE I"; else cmd = "TYPE A"; if (_SendRequest(cmd)) _GetReply(replyString, code, codeType); try { if (_OpenDataConnection()) { cmd = "STOR "; cmd += remote; if (_SendRequest(cmd)) { if (_GetReply(replyString, code, codeType)) { if (codeType <= 2) { if (_AcceptDataConnection()) { rlen = 1; while (rlen > 0) { memset(buf, 0, sizeof(buf)); memset(sbuf, 0, sizeof(sbuf)); rlen = infile.Read((void*)buf, sizeof(buf)); slen = rlen; stmp = buf; if (mode == ascii_mode) { stmp = sbuf; slen = 0; for (i = 0; i < rlen; i++) { if (buf[i] == '\n') { *stmp = '\r'; stmp++; slen++; } *stmp = buf[i]; stmp++; slen++; } stmp = sbuf; } if (slen > 0) { if (fData->Send(stmp, slen) < 0) throw "bail"; } } rc = true; } } } } } } catch(const char* errorString) { } delete fData; fData = 0; if (rc) { _GetReply(replyString, code, codeType); rc = codeType <= 2; } return rc; }
bool FtpClient::Connect(const string& server, const string& login, const string& passwd) { bool rc = false; int code, codeType; string cmd, replyString; BNetAddress addr; delete fControl; delete fData; fControl = new BNetEndpoint; if (fControl->InitCheck() != B_NO_ERROR) return false; addr.SetTo(server.c_str(), "tcp", "ftp"); if (fControl->Connect(addr) == B_NO_ERROR) { // read the welcome message, do the login if (_GetReply(replyString, code, codeType)) { if (code != 421 && codeType != 5) { cmd = "USER "; cmd += login; _SendRequest(cmd); if (_GetReply(replyString, code, codeType)) { switch (code) { case 230: case 202: rc = true; break; case 331: // password needed cmd = "PASS "; cmd += passwd; _SendRequest(cmd); if (_GetReply(replyString, code, codeType)) { if (codeType == 2) rc = true; } break; default: break; } } } } } if (rc == true) _SetState(ftp_connected); else { delete fControl; fControl = 0; } return rc; }
status_t BGopherRequest::_ProtocolLoop() { if (fSocket == NULL) return B_NO_MEMORY; if (!_ResolveHostName(fUrl.Host(), fUrl.HasPort() ? fUrl.Port() : 70)) { _EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR, "Unable to resolve hostname (%s), aborting.", fUrl.Host().String()); return B_SERVER_NOT_FOUND; } _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Connection to %s on port %d.", fUrl.Authority().String(), fRemoteAddr.Port()); status_t connectError = fSocket->Connect(fRemoteAddr); if (connectError != B_OK) { _EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR, "Socket connection error %s", strerror(connectError)); return connectError; } //! ProtocolHook:ConnectionOpened if (fListener != NULL) fListener->ConnectionOpened(this); _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Connection opened, sending request."); _SendRequest(); _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Request sent."); // Receive loop bool receiveEnd = false; status_t readError = B_OK; ssize_t bytesRead = 0; //ssize_t bytesReceived = 0; //ssize_t bytesTotal = 0; bool dataValidated = false; BStackOrHeapArray<char, 4096> chunk(kGopherBufferSize); while (!fQuit && !receiveEnd) { fSocket->WaitForReadable(); bytesRead = fSocket->Read(chunk, kGopherBufferSize); if (bytesRead < 0) { readError = bytesRead; break; } else if (bytesRead == 0) receiveEnd = true; fInputBuffer.AppendData(chunk, bytesRead); if (!dataValidated) { size_t i; // on error (file doesn't exist, ...) the server sends // a faked directory entry with an error message if (fInputBuffer.Size() && fInputBuffer.Data()[0] == '3') { int tabs = 0; bool crlf = false; // make sure the buffer only contains printable characters // and has at least 3 tabs before a CRLF for (i = 0; i < fInputBuffer.Size(); i++) { char c = fInputBuffer.Data()[i]; if (c == '\t') { if (!crlf) tabs++; } else if (c == '\r' || c == '\n') { if (tabs < 3) break; crlf = true; } else if (!isprint(fInputBuffer.Data()[i])) { crlf = false; break; } } if (crlf && tabs > 2 && tabs < 5) { // TODO: //if enough data // else continue fItemType = GOPHER_TYPE_DIRECTORY; readError = B_RESOURCE_NOT_FOUND; // continue parsing the error text anyway } } // special case for buggy(?) Gophernicus/1.5 static const char *buggy = "Error: File or directory not found!"; if (fInputBuffer.Size() > strlen(buggy) && !memcmp(fInputBuffer.Data(), buggy, strlen(buggy))) { fItemType = GOPHER_TYPE_DIRECTORY; readError = B_RESOURCE_NOT_FOUND; // continue parsing the error text anyway // but it won't look good } // now we probably have correct data dataValidated = true; //! ProtocolHook:ResponseStarted if (fListener != NULL) fListener->ResponseStarted(this); // we don't really have headers but well... //! ProtocolHook:HeadersReceived if (fListener != NULL) fListener->HeadersReceived(this); // now we can assign MIME type if we know it const char *mime = "application/octet-stream"; for (i = 0; gopher_type_map[i].type != GOPHER_TYPE_NONE; i++) { if (gopher_type_map[i].type == fItemType) { mime = gopher_type_map[i].mime; break; } } fResult.SetContentType(mime); } if (_NeedsParsing()) _ParseInput(receiveEnd); else if (fInputBuffer.Size()) { // send input directly if (fListener != NULL) { fListener->DataReceived(this, (const char *)fInputBuffer.Data(), fPosition, fInputBuffer.Size()); } fPosition += fInputBuffer.Size(); // XXX: this is plain stupid, we already copied the data // and just want to drop it... char *inputTempBuffer = new(std::nothrow) char[bytesRead]; if (inputTempBuffer == NULL) { readError = B_NO_MEMORY; break; } fInputBuffer.RemoveData(inputTempBuffer, fInputBuffer.Size()); delete[] inputTempBuffer; } } if (fPosition > 0) { fResult.SetLength(fPosition); if (fListener != NULL) fListener->DownloadProgress(this, fPosition, fPosition); } fSocket->Disconnect(); if (readError != B_OK) return readError; return fQuit ? B_INTERRUPTED : B_OK; }