int main(int argc, char** argv) { std::map<std::string, std::string> args = ProcessArgs(argc, argv); if (args.size() != 5 || !ValidateArgs(args)) { ShowHelp(); return -5; } DesuraId id(args["-i"].c_str(), args["-t"].c_str()); if (!Login(args["-u"], args["-p"])) return -1; if (!CreateMcf(id, args["-f"])) return -2; if (!StartUpload(id)) return -3; if (!UploadMcf()) return -4; return 0; }
virtual int performAction(std::vector<std::string> &args) { DesuraId id(args[3].c_str(), args[4].c_str()); if (!Login(args[0], args[1])) return -1; if (!CreateMcf(id, args[2])) return -2; if (!StartUpload(id)) return -3; if (!UploadMcf()) return -4; return 0; }
void CGnuUpload::Send_HttpOK() { if((CGnuUpload*) m_pShell->m_Socket != this) return; CString HttpOK; //HTTP Version if (m_pShell->m_HTTPVersion == "HTTP/1.1") HttpOK = "HTTP/1.1 "; else HttpOK = "HTTP "; //200 or 206 if (m_pShell->m_StartPos == 0 && m_pShell->m_StopPos == m_pShell->m_FileLength) HttpOK += "200 OK\r\n"; else HttpOK += "206 Partial Content\r\n"; // Server HttpOK += "Server: " + m_pNet->m_pCore->GetUserAgent() + "\r\n"; // Content-Type HttpOK += "Content-type: application/octet-stream\r\n"; //I think octet-stream is more correct than binary //HttpOK += "Content-type: application/zip\r\n"; // Accept-Ranges HttpOK += "Accept-Ranges: bytes\r\n"; // Conent-Range, it is "bytes x-y/z" not "bytes=x-y/z" HttpOK += "Content-Range: bytes " + NumtoStr(m_pShell->m_StartPos) + "-" + NumtoStr(m_pShell->m_StopPos - 1) + "/" + NumtoStr(m_pShell->m_FileLength) + "\r\n"; // Content-Length HttpOK += "Content-Length: " + NumtoStr(m_pShell->m_StopPos - m_pShell->m_StartPos) + "\r\n"; // Connection if (m_pShell->m_KeepAlive) HttpOK += "Connection: Keep-Alive\r\n"; //Even on 1.1 where keep-alive is assumed else if (m_pShell->m_HTTPVersion == "HTTP/1.1") HttpOK += "Connection: Close\r\n"; //Only in 1.1. Close is assumed in 1.0 std::map<int, CGnuDownloadShell*>::iterator itPart; // X-Available-Ranges if (m_pShell->m_IsPartial) { itPart = m_pTrans->m_DownloadMap.find(m_pShell->m_PartialID); if(itPart != m_pTrans->m_DownloadMap.end()) HttpOK += "X-Available-Ranges: bytes " + itPart->second->AvailableRangesCommaSeparated() + "\r\n"; } // X-Gnutella-Content-URN if (!m_pShell->m_Sha1Hash.IsEmpty()) { if( m_pShell->m_Network == NETWORK_GNUTELLA ) HttpOK += "X-Gnutella-Content-URN: urn:sha1:" + m_pShell->m_Sha1Hash + "\r\n"; else if( m_pShell->m_Network == NETWORK_G2 ) HttpOK += "Content-URN: urn:sha1:" + m_pShell->m_Sha1Hash + "\r\n"; // X-TigerTree-Path if (!m_pShell->m_TigerHash.IsEmpty()) { CString Client = m_pShell->m_RemoteClient; Client.MakeLower(); // handle a million implementations if( Client.Find("dna") != -1) HttpOK += "X-TigerTree-Path: /gnutella/tigertree/v3?urn:tree:tiger/:" + m_pShell->m_TigerHash + "\r\n"; else if( Client.Find("bearshare") != -1 || Client.Find("shareaza") != -1) HttpOK += "X-Thex-URI: /gnutella/thex/v1?urn:tree:tiger/:" + m_pShell->m_TigerHash + "\r\n"; else HttpOK += "X-Thex-URI: /uri-res/N2X?urn:sha1:" + m_pShell->m_Sha1Hash + ";" + m_pShell->m_TigerHash + "\r\n"; } // X-Alt if (!m_pShell->m_IsPartial) HttpOK += m_pShare->GetShareAltLocHeader(m_pShell->m_Sha1Hash, m_pShell->m_Host); else { itPart = m_pTrans->m_DownloadMap.find(m_pShell->m_PartialID); if(itPart != m_pTrans->m_DownloadMap.end()) HttpOK += itPart->second->GetAltLocHeader( m_pShell->m_Host ); } } // X-Push-Proxy if(m_Push && m_pShell->m_Network == NETWORK_GNUTELLA && m_pNet->m_pGnu) HttpOK += m_pNet->m_pGnu->GetPushProxyHeader(); // X-Filename if(m_pShell->m_RequestURI.Left(9) == "/uri-res/") HttpOK += "X-Filename: " + m_pShell->m_Name + "\r\n"; // Authentication if( !m_Authorized ) { if(m_pNet->m_pCore->m_dnaCore->m_dnaEvents) m_pNet->m_pCore->m_dnaCore->m_dnaEvents->UploadAuthenticate(m_pShell->m_UploadID); if(m_pShell->m_Challenge == "ERROR") { Close(); return; } if(!m_pShell->m_Challenge.IsEmpty() && !m_pShell->m_ChallengeAnswer.IsEmpty()) HttpOK += "X-Auth-Challenge: " + m_pShell->m_Challenge + "\r\n"; else m_Authorized = true; } // End header HttpOK += "\r\n"; // Send header m_pSocket->Send(HttpOK, HttpOK.GetLength()); m_pShell->m_Handshake += HttpOK; if(m_Authorized) StartUpload(); }
void CGnuUpload::OnReceive(int nErrorCode) { byte pBuff[6000]; int dwBuffLength = m_pSocket->Receive(pBuff, 4096); switch (dwBuffLength) { case 0: m_pShell->m_Error = "Bad Push"; Close(); return; break; case SOCKET_ERROR: m_pShell->m_Error = "Bad Push"; Close(); return; break; } pBuff[dwBuffLength] = 0; CString Header(pBuff); // Clear old GetRequest when new one comes in if(m_GetRequest.Find("\r\n\r\n") != -1) { m_GetRequest = ""; m_pShell->m_Handshake = ""; } m_pShell->m_Handshake += Header; m_GetRequest += Header; // New Upload if(m_GetRequest.Find("\r\n\r\n") != -1) { if(m_GetRequest.Left(4) == "GET " || m_GetRequest.Left(5) == "HEAD ") { // Get Node info CString Host; UINT nPort; m_pSocket->GetPeerName(Host, nPort); // Check if it's a blocked Host if (m_pPrefs->BlockedIP(StrtoIP(Host)) == true) { m_pShell->m_Error = "Blocked"; Send_ClientBlock(Host); Close(); } else { // Set Variables m_pShell->m_Host = StrtoIP(Host); m_pShell->m_Port = 0; m_pShell->m_RequsetPending = true; } } else if( m_GetRequest.Left(4) == "AUTH" && !m_pShell->m_Challenge.IsEmpty() ) { CParsedHeaders ParsedHeaders(m_pShell->m_Handshake); if(m_pShell->m_ChallengeAnswer.Compare( ParsedHeaders.FindHeader("X-Auth-Response") ) == 0 ) { m_Authorized = true; StartUpload(); } else { m_pShell->m_Error = "Authentication Failed"; Close(); } } else { m_pShell->m_Error = "Bad Push"; Close(); } } }
// Process the first fragment of input from the client. // Return true if the session should be kept open. bool Webserver::ProcessFirstFragment(HttpSession& session, const char* command, bool isOnlyFragment) { // Process connect messages first if (StringEquals(command, "connect") && GetKeyValue("password") != nullptr) { OutputBuffer *response; if (OutputBuffer::Allocate(response)) { if (session.isAuthenticated || reprap.CheckPassword(GetKeyValue("password"))) { // Password is OK, see if we can update the current RTC date and time const char *timeVal = GetKeyValue("time"); if (timeVal != nullptr && !platform->IsDateTimeSet()) { struct tm timeInfo; memset(&timeInfo, 0, sizeof(timeInfo)); if (strptime(timeVal, "%Y-%m-%dT%H:%M:%S", &timeInfo) != nullptr) { time_t newTime = mktime(&timeInfo); platform->SetDateTime(newTime); } } // Client has logged in session.isAuthenticated = true; response->printf("{\"err\":0,\"sessionTimeout\":%u,\"boardType\":\"%s\"}", httpSessionTimeout, platform->GetBoardString()); } else { // Wrong password response->copy("{\"err\":1}"); } network->SendReply(session.ip, 200 | rcJson, response); } else { // If we failed to allocate an output buffer, send back an error string network->SendReply(session.ip, 200 | rcJson, "{\"err\":2}"); } return false; } if (StringEquals(command, "disconnect")) { network->SendReply(session.ip, 200 | rcJson, "{\"err\":0}"); DeleteSession(session.ip); return false; } // Try to authorise the user automatically to retain compatibility with the old web interface if (!session.isAuthenticated && reprap.NoPasswordSet()) { session.isAuthenticated = true; } // If the client is still not authenticated, stop here if (!session.isAuthenticated) { network->SendReply(session.ip, 500, "Not authorized"); return false; } if (StringEquals(command, "reply")) { SendGCodeReply(session); return false; } // rr_configfile sends the config as plain text well if (StringEquals(command, "configfile")) { const char *configPath = platform->GetMassStorage()->CombineName(platform->GetSysDir(), platform->GetConfigFile()); char fileName[FILENAME_LENGTH]; strncpy(fileName, configPath, FILENAME_LENGTH); SendFile(fileName, session); return false; } if (StringEquals(command, "download") && GetKeyValue("name") != nullptr) { SendFile(GetKeyValue("name"), session); return false; } if (StringEquals(command, "upload")) { const char* nameVal = GetKeyValue("name"); const char* lengthVal = GetKeyValue("length"); const char* timeVal = GetKeyValue("time"); if (nameVal != nullptr && lengthVal != nullptr) { // Try to obtain the last modified time time_t fileLastModified = 0; struct tm timeInfo; memset(&timeInfo, 0, sizeof(timeInfo)); if (timeVal != nullptr && strptime(timeVal, "%Y-%m-%dT%H:%M:%S", &timeInfo) != nullptr) { fileLastModified = mktime(&timeInfo); } // Deal with file upload request uint32_t fileLength = atol(lengthVal); StartUpload(session, nameVal, fileLength, fileLastModified); if (session.uploadState == uploading) { if (isOnlyFragment) { FinishUpload(session); return false; } else { network->DiscardMessage(); // no reply needed yet return true; // expecting more data } } } network->SendReply(session.ip, 200 | rcJson, "{\"err\":1}"); // TODO return the cause of the error return false; } if (StringEquals(command, "move")) { const char* response = "{\"err\":1}"; // assume failure const char* const oldVal = GetKeyValue("old"); const char* const newVal = GetKeyValue("new"); if (oldVal != nullptr && newVal != nullptr) { const bool success = platform->GetMassStorage()->Rename(oldVal, newVal); if (success) { response = "{\"err\":0}"; } } network->SendReply(session.ip, 200 | rcJson, response); return false; } if (StringEquals(command, "mkdir")) { const char* response = "{\"err\":1}"; // assume failure const char* dirVal = GetKeyValue("dir"); if (dirVal != nullptr) { bool ok = (platform->GetMassStorage()->MakeDirectory(dirVal)); if (ok) { response = "{\"err\":0}"; } } network->SendReply(session.ip, 200 | rcJson, response); return false; } if (StringEquals(command, "delete")) { const char* response = "{\"err\":1}"; // assume failure const char* nameVal = GetKeyValue("name"); if (nameVal != nullptr) { bool ok = platform->GetMassStorage()->Delete("0:/", nameVal); if (ok) { response = "{\"err\":0}"; } } network->SendReply(session.ip, 200 | rcJson, response); return false; } // The remaining commands use an OutputBuffer for the response OutputBuffer *response = nullptr; if (StringEquals(command, "status")) { const char* typeVal = GetKeyValue("type"); if (typeVal != nullptr) { // New-style JSON status responses int type = atoi(typeVal); if (type < 1 || type > 3) { type = 1; } response = reprap.GetStatusResponse(type, ResponseSource::HTTP); } else { response = reprap.GetLegacyStatusResponse(1, 0); } } else if (StringEquals(command, "gcode")) { const char* gcodeVal = GetKeyValue("gcode"); if (gcodeVal != nullptr) { RegularGCodeInput * const httpInput = reprap.GetGCodes()->GetHTTPInput(); httpInput->Put(HTTP_MESSAGE, gcodeVal); if (OutputBuffer::Allocate(response)) { response->printf("{\"buff\":%u}", httpInput->BufferSpaceLeft()); } } else { network->SendReply(session.ip, 200 | rcJson, "{\"err\":1}"); return false; } } else if (StringEquals(command, "filelist") && GetKeyValue("dir") != nullptr) { response = reprap.GetFilelistResponse(GetKeyValue("dir")); } else if (StringEquals(command, "files")) { const char* dir = GetKeyValue("dir"); if (dir == nullptr) { dir = platform->GetGCodeDir(); } const char* const flagDirsVal = GetKeyValue("flagDirs"); const bool flagDirs = flagDirsVal != nullptr && atoi(flagDirsVal) == 1; response = reprap.GetFilesResponse(dir, flagDirs); } else if (StringEquals(command, "fileinfo")) { const char* const nameVal = GetKeyValue("name"); if (reprap.GetPrintMonitor()->GetFileInfoResponse(nameVal, response)) { processingDeferredRequest = false; } else { processingDeferredRequest = true; } } else if (StringEquals(command, "config")) { response = reprap.GetConfigResponse(); } else { platform->MessageF(HOST_MESSAGE, "KnockOut request: %s not recognised\n", command); network->SendReply(session.ip, 400, "Unknown rr_ command"); return false; } if (response != nullptr) { network->SendReply(session.ip, 200 | rcJson, response); } else if (!processingDeferredRequest) { network->SendReply(session.ip, 500, "No buffer available"); } return processingDeferredRequest; }