CString CAeonInterface::EncodeFilePathComponent (const CString &sValue) // EncodeFilePathComponent // // Encodes a file path component by replacing any invalid characters with ~hh // (where hh is the hexcode). { char *pPos = sValue.GetParsePointer(); char *pEndPos = pPos + sValue.GetLength(); CStringBuffer Output; while (pPos < pEndPos) { if (!strIsASCIIAlpha(pPos) // alpha && !strIsDigit(pPos) // numbers && *pPos != '-' && *pPos != '_' && *pPos != '.' && *pPos != '~' && !strIsASCIIHigh(pPos)) // unicode characters { CString sChar = strPattern("~%x", (DWORD)(BYTE)*pPos); Output.Write(sChar); } else Output.Write(pPos, 1); pPos++; } // Done return CString::CreateFromHandoff(Output); }
bool CComplexDateTime::CreateFromString (const CString &sString, CDateTime *retDateTime) // CreateFromString // // Reverse of AsString { char *pPos = sString.GetParsePointer(); int iYear = strParseInt(pPos, 0, &pPos); if (iYear < 1 || iYear > 30827) return false; if (*pPos++ != '-') return false; int iMonth = strParseInt(pPos, 0, &pPos); if (iMonth < 1 || iMonth > 12) return false; if (*pPos++ != '-') return false; int iDay = strParseInt(pPos, 0, &pPos); if (iDay < 1 || iDay > CDateTime::GetDaysInMonth(iMonth, iYear)) return false; if (*pPos++ != 'T') return false; int iHour = strParseInt(pPos, -1, &pPos); if (iHour < 0 || iHour > 23) return false; if (*pPos++ != ':') return false; int iMinute = strParseInt(pPos, -1, &pPos); if (iMinute < 0 || iMinute > 59) return false; if (*pPos++ != ':') return false; int iSecond = strParseInt(pPos, -1, &pPos); if (iSecond < 0 || iSecond > 59) return false; if (*pPos++ != '.') return false; int iMillisecond = strParseInt(pPos, -1, &pPos); if (iMillisecond < 0 || iMillisecond > 999) return false; // Done *retDateTime = CDateTime(iDay, iMonth, iYear, iHour, iMinute, iSecond, iMillisecond); return true; }
void CAeonRowValue::SerializeKey (IByteStream &Stream, const CString &sKey, DWORD *retdwSize) // SerializeKey // // Serializes a key and returns the serialized size. // // DWORD key size // BYTES[] key (padded to DWORD align) { DWORD dwKeySize = sKey.GetLength(); // Write out the key length Stream.Write(&dwKeySize, sizeof(DWORD)); // Write out the key (add 1 for NULL termination) Stream.Write(sKey.GetParsePointer(), dwKeySize + 1); // Save padding DWORD dwZero = 0; DWORD dwAlignedKeySize = AlignUp(dwKeySize + 1, (DWORD)sizeof(DWORD)); Stream.Write(&dwZero, dwAlignedKeySize - (dwKeySize + 1)); // Done if (retdwSize) *retdwSize = sizeof(DWORD) + dwAlignedKeySize; }
bool CAeonInterface::ParseTableFilePath (const CString &sPath, CString *retsTable, CString *retsFilePath, CString *retsError) // ParseTableFilePath // // Parses a filePath { char *pPos = sPath.GetParsePointer(); char *pEndPos = pPos + sPath.GetLength(); // First character must be a slash because we need an absolute path if (*pPos != '/') { if (retsError) *retsError = STR_ERROR_ABSOLUTE_PATH_REQUIRED; return false; } pPos++; // The first segment is the table name char *pStart = pPos; while (pPos < pEndPos && *pPos != '/') pPos++; CString sTable(pStart, pPos - pStart); if (sTable.IsEmpty()) { if (retsError) *retsError = STR_ERROR_NO_TABLE_IN_PATH; return false; } // We have the table name if (retsTable) *retsTable = sTable; // If we've reached the end, then we have an empty path if (pPos >= pEndPos) { if (retsFilePath) *retsFilePath = CString("/", 1); return true; } // filePath starts with a slash and goes to the end. if (retsFilePath) *retsFilePath = CString(pPos, (int)(pEndPos - pPos)); // Done return true; }
void htmlWriteText (const CString &sText, IByteStream &Output) // htmlWriteText // // Writes text, escaping all appropriate HTML characters. // // NOTE: This is only for the text content of HTML element; for escaping // attribute values, use htmlWriteAttributeValue { char *pPos = sText.GetParsePointer(); char *pPosEnd = pPos + sText.GetLength(); htmlWriteText(pPos, pPosEnd, Output); }
CString ExecuteUploadCertificate (CSocket &theSocket, const CString &sCmd) { char *pPos = sCmd.GetParsePointer() + STR_UPLOAD_CERTIFICATE_PREFIX.GetLength(); // Skip whitespace while (*pPos == ' ') pPos++; // Get the filespec char *pStart = pPos; while (*pPos != '\0') pPos++; CString sFilespec(pStart, pPos - pStart); // Upload return UploadFile(theSocket, CMD_UPLOAD, CString("/Arc.certificates"), sFilespec); }
CString ExecuteUpload (CSocket &theSocket, const CString &sCmd) { char *pPos = sCmd.GetParsePointer() + STR_UPLOAD_PREFIX.GetLength(); // Get the filePath if (*pPos == '\"') pPos++; char *pStart = pPos; while (*pPos != ' ' && *pPos != '\"' && *pPos != '\0') pPos++; CString sFilePath(pStart, pPos - pStart); if (*pPos != '\0') pPos++; if (*pPos == '\"') pPos++; // Skip whitespace while (*pPos == ' ') pPos++; // Get the filespec pStart = pPos; while (*pPos != '\0') pPos++; CString sFilespec(pStart, pPos - pStart); // Load the file return UploadFile(theSocket, CMD_UPLOAD, sFilePath, sFilespec); }
CString CAeonInterface::FilespecToFilePath (const CString &sFilespec) // FilespecToFilePath // // Converts a filespec to an Aeon filePath. We convert \ to / and escape all // characters that are not valid Aeon path characters. { char *pPos = sFilespec.GetParsePointer(); char *pEndPos = pPos + sFilespec.GetLength(); CStringBuffer Output; while (pPos < pEndPos) { if (*pPos == '\\') Output.Write("/", 1); else if (!strIsASCIIAlpha(pPos) // alpha && !strIsDigit(pPos) // numbers && *pPos != '-' && *pPos != '_' && *pPos != '.' && *pPos != '~' && !strIsASCIIHigh(pPos)) // unicode characters { CString sChar = strPattern("_%x_", (DWORD)(BYTE)*pPos); Output.Write(sChar); } else Output.Write(pPos, 1); pPos++; } // Done return CString::CreateFromHandoff(Output); }
void CMnemosynthDb::ParseEndpointName (const CString &sEndpoint, CString *retsMachine, CString *retsModule) // ParseEndpointName // // Parses out an endpoint name into machine and module { char *pPos = sEndpoint.GetParsePointer(); char *pStart = pPos; while (*pPos != '/' && *pPos != '\0') pPos++; if (*pPos == '\0') return; if (retsMachine) *retsMachine = CString(pStart, pPos - pStart); pPos++; if (retsModule) *retsModule = CString(pPos); }
CString ResolveEntity (ParserCtx *pCtx, const CString &sName, bool *retbFound) // ResolveEntity // // Resolves the entity from the parser table { *retbFound = true; CString sResult; // Check to see if the name is one of the standard entities CString sNameLC = strToLower(sName); if (strEquals(sNameLC, ENTITY_AMP)) return ENTITY_AMP_SUB; else if (strEquals(sNameLC, ENTITY_LT)) return ENTITY_LT_SUB; else if (strEquals(sNameLC, ENTITY_GT)) return ENTITY_GT_SUB; else if (strEquals(sNameLC, ENTITY_QUOT)) return ENTITY_QUOT_SUB; else if (strEquals(sNameLC, ENTITY_APOS)) return ENTITY_APOS_SUB; // If the entity is a hex number, then this is a character char *pPos = sName.GetParsePointer(); if (*pPos == '#') { pPos++; if (*pPos == 'x' || *pPos == 'X') { *pPos++; char chChar = (char)strParseIntOfBase(pPos, 16, 0x20, NULL, NULL); return CString(&chChar, 1); } else { char chChar = (char)strParseInt(pPos, 0x20); return CString(&chChar, 1); } } // Otherwise, it is a general attribute bool bFound; CString sValue = pCtx->LookupEntity(sName, &bFound); if (bFound) { // Parse the value to resolve embedded entities ParserCtx SubCtx(pCtx, sValue); ParseToken(&SubCtx, ParseEntityState); if (SubCtx.iToken == tkText) sResult = SubCtx.sToken; else { bFound = false; sResult = sName; } } if (retbFound) *retbFound = bFound; return sResult; }
bool CCryptosaurEngine::ValidateUsername (const CString &sUsername, CString *retsError) // ValidateUsername // // Make sure that the username is valid. Usernames can have any character // except ASCII control codes and must have at least one printable character. // // Also, usernames may not start with '#', '&', '@', '$', '%', or '['. // // If valid we return TRUE. { bool bLeadingWhitespace = false; bool bTrailingWhitespace = false; bool bDoubleWhitespace = false; bool bHasPrintableChars = false; char *pPos = sUsername.GetParsePointer(); char *pPosEnd = pPos + sUsername.GetLength(); // Can't lead with certain symbols if (*pPos == '[' || *pPos == '#' || *pPos == '&' || *pPos == '$' || *pPos == '@' || *pPos == '%') { *retsError = ERR_INVALID_LEADING_CHAR; return false; } // Check the rest of the name int iCount = 0; while (pPos < pPosEnd) { if (strIsASCIIControl(pPos)) { *retsError = ERR_CANT_HAVE_CONTROL_CHARS; return false; } // Is this a printable char? UTF32 dwCodePoint = strParseUTF8Char(&pPos, pPosEnd); bool bIsPrintableChar = strIsPrintableChar(dwCodePoint); // If this is not printable and we haven't yet seen a printable char // then we have a leading whitespace if (!bIsPrintableChar && !bHasPrintableChars) bLeadingWhitespace = true; // We have at least one printable char if (bIsPrintableChar) bHasPrintableChars = true; // If the previous character was also whitespace, then that's an error else if (bTrailingWhitespace) bDoubleWhitespace = true; bTrailingWhitespace = !bIsPrintableChar; if (bIsPrintableChar) iCount++; } // Printable characters if (iCount < 3) { *retsError = ERR_MUST_HAVE_PRINTABLE_CHARS; return false; } // Leading or trailing whitespace if (bLeadingWhitespace || bTrailingWhitespace) { *retsError = ERR_INVALID_WHITESPACE; return false; } // Double whitespace if (bDoubleWhitespace) { *retsError = ERR_TOO_MUCH_WHITESPACE; return false; } // Done return true; }
CString ExecuteHTTPGet (const CString &sInput) { // Parse the input char *pPos = sInput.GetParsePointer() + STR_HTTP_GET_PREFIX.GetLength(); // Parse the URL CString sHost; CString sPath; if (!urlParse(pPos, NULL, &sHost, &sPath)) return CString("Invalid URL."); // If no host, then local host if (sHost.IsEmpty()) sHost = CString("localhost"); // Connect CSocket theSocket; if (!theSocket.Connect(sHost, 80)) return strPattern("Unable to connect to: %s.", sHost); // Compose a request CHTTPMessage Request; Request.InitRequest(CString("GET"), sPath); Request.AddHeader(HEADER_HOST, sHost); Request.AddHeader(HEADER_CONNECTION, CString("keep-alive")); #ifdef DEBUG_REQUEST_FRAGMENT_X Request.AddHeader(HEADER_USER_AGENT, CString("AI1/1.0 (This is a test of the header parsing system in Hexarc. There is probably a bug in which splitting the header across packets will cause failure of the HTTP parsing engine.)")); #else Request.AddHeader(HEADER_USER_AGENT, CString("AI1/1.0")); #endif // Send the request CBuffer Buffer(4096); Request.WriteToBuffer(Buffer); #ifdef DEBUG_REQUEST_FRAGMENT int iTotalLen = Buffer.GetLength(); int iSplit = 105; if (iSplit < iTotalLen) { printf("Split at %d bytes\n", iSplit); CString sPart(Buffer.GetPointer(), iSplit); printf("%s\n", (LPSTR)sPart); theSocket.Write(Buffer.GetPointer(), iSplit); ::Sleep(10); theSocket.Write(Buffer.GetPointer() + iSplit, iTotalLen - iSplit); } else theSocket.Write(Buffer.GetPointer(), Buffer.GetLength()); #else theSocket.Write(Buffer.GetPointer(), Buffer.GetLength()); #endif // Now read the response. We build up a buffer to hold it. CHTTPMessage Response; CBuffer ResponseBuff; // Keep reading until we've got enough (or until the connection drops) while (!Response.IsMessageComplete()) { CBuffer TempBuffer(8192); // Read int iBytesRead = theSocket.Read(TempBuffer.GetPointer(), 8192); TempBuffer.SetLength(iBytesRead); // If we're no making progress, then we're done if (iBytesRead == 0) return strPattern("Unable to read entire message."); // Add to entire buffer ResponseBuff.Write(TempBuffer.GetPointer(), iBytesRead); // Parse to see if we're done if (!Response.InitFromPartialBuffer(TempBuffer)) return strPattern("Unable to parse HTTP message."); } // Done theSocket.Disconnect(); return CString(ResponseBuff.GetPointer(), ResponseBuff.GetLength()); }
bool CSSLEnvelopeKey::InitFromPEM (IMemoryBlock &Data, const CString &sPassphrase, bool bKeepRaw, CString *retsError) // InitFromPEM // // Loads the first key from the given PEM file. { CleanUp(); // Make sure OpenSSL is initialized. if (!g_SSLGlobal.Init()) return false; // Keep parsing until we find a key int iPos = 0; while (CSSLCert::HasPEMSection(Data, iPos)) { CString sData; CString sType; if (!CSSLCert::ParsePEMSection(Data, iPos, &sData, &sType, &iPos)) { if (retsError) *retsError = ERR_CANT_PARSE_PEM; return false; } // We skip any types that we don't understand. This is not an error, // since we often store private keys and other things in a PEM file. if (!IsKeyPEMSection(sType)) continue; // Create BIO stream for the section CMemoryBIO SectionData(sData); // Create the key EVP_PKEY *pKey = PEM_read_bio_PrivateKey(SectionData, NULL, NULL, sPassphrase.GetParsePointer()); if (!pKey) { if (retsError) *retsError = ERR_CANT_PARSE_KEY; return false; } // Create m_pData = new SEKey; m_pData->pKey = pKey; if (bKeepRaw) m_pData->sPEMData = sData; // We load the first key we find, so we're done. break; } // If we didn't find a key, then we return an error if (m_pData == NULL) { if (retsError) *retsError = ERR_NO_KEY_FOUND; return false; } // Success return true; }
CString ExecuteUploadPackage (CSocket &theSocket, const CString &sCmd) { int i; char *pPos = sCmd.GetParsePointer() + STR_UPLOAD_PACKAGE_PREFIX.GetLength(); // Get the package name if (*pPos == '\"') pPos++; char *pStart = pPos; while (*pPos != ' ' && *pPos != '\"' && *pPos != '\0') pPos++; CString sPackageName(pStart, pPos - pStart); if (*pPos != '\0') pPos++; if (*pPos == '\"') pPos++; // Skip whitespace while (*pPos == ' ') pPos++; // Get the filespec pStart = pPos; while (*pPos != '\0') pPos++; CString sFilespec(pStart, pPos - pStart); // Get the directory CString sPackageFolder = fileGetPath(sFilespec); CString sPackageDescFilespec = fileGetFilename(sFilespec); // Upload the package descriptor CString sPackageDesc = strPattern("/Arc.services/%s.ars", sPackageName); printf("Uploading %s to /Arc.services/%s.ars...", (LPSTR)sFilespec, (LPSTR)sPackageName); CString sResult = UploadFile(theSocket, CMD_UPLOAD, sPackageDesc, sFilespec); printf("%s\n", (LPSTR)sResult); // Now loop over all files in the directory TArray<CString> Files; if (!fileGetFileList(fileAppend(sPackageFolder, CString("*.*")), FFL_FLAG_RELATIVE_FILESPEC | FFL_FLAG_RECURSIVE, &Files)) { printf("ERROR: Unable to list directory: %s\\*.*\n", (LPSTR)sPackageFolder); return NULL_STR; } for (i = 0; i < Files.GetCount(); i++) { if (!strEquals(Files[i], sPackageDescFilespec)) { CString sFilePath = strPattern("/Arc.services/%s/%s", sPackageName, CAeonInterface::FilespecToFilePath(Files[i])); printf("Uploading %s to %s...", (LPSTR)fileAppend(sPackageFolder, Files[i]), (LPSTR)sFilePath); CString sResult = UploadFile(theSocket, CMD_UPLOAD, sFilePath, fileAppend(sPackageFolder, Files[i])); printf("%s\n", (LPSTR)sResult); } } // Refresh printf("Refreshing Hyperion..."); return ExecuteArcologyCommand(theSocket, CMD_REFRESH_PACKAGES); }
CDatum::Types CDatum::GetStringValueType (const CString &sValue) // GetStringValueType // // Returns one of the following: // // typeNil if sValue is empty // typeInteger32 if sValue is a 32-bit integer // typeIntegerIP if sValue is an integer (which may or may not be > 64-bits) // typeDouble if sValue is a double // typeString otherwise. { enum EStates { stateStart, stateHex0, stateHex, stateInteger, stateDoubleFrac, stateDoubleExp, stateDoubleExpSign, }; char *pPos = sValue.GetParsePointer(); char *pPosEnd = pPos + sValue.GetLength(); int iState = stateStart; while (pPos < pPosEnd) { switch (iState) { case stateStart: { // If 0 then we might be a hex number if (*pPos == '0') iState = stateHex0; // If -, +, or a digit, we might be an integer else if (*pPos == '-' || *pPos == '+' || strIsDigit(pPos)) iState = stateInteger; // If . then we might be a double else if (*pPos == '.') iState = stateDoubleFrac; // Otherwise, we are a string else return typeString; break; } case stateHex0: { if (*pPos == 'x' || *pPos == 'X') iState = stateHex; else if (strIsDigit(pPos)) iState = stateInteger; else if (*pPos == '.') iState = stateDoubleFrac; else if (*pPos == 'e' || *pPos == 'E') iState = stateDoubleExp; else return typeString; break; } case stateHex: { if (strIsDigit(pPos) || (*pPos >= 'A' && *pPos <= 'F') || (*pPos >= 'a' && *pPos <= 'f')) NULL; else return typeString; break; } case stateInteger: { if (strIsDigit(pPos)) NULL; else if (*pPos == '.') iState = stateDoubleFrac; else if (*pPos == 'e' || *pPos == 'E') iState = stateDoubleExp; else return typeString; break; } case stateDoubleFrac: { if (strIsDigit(pPos)) NULL; else if (*pPos == 'e' || *pPos == 'E') iState = stateDoubleExp; else return typeString; break; } case stateDoubleExp: { if (*pPos == '+' || *pPos == '-' || strIsDigit(pPos)) iState = stateDoubleExpSign; else return typeString; break; } case stateDoubleExpSign: { if (strIsDigit(pPos)) NULL; else return typeString; break; } } pPos++; } switch (iState) { case stateStart: return typeNil; case stateHex: // LATER: return typeString; case stateInteger: if (strOverflowsInteger32(sValue)) return typeIntegerIP; else return typeInteger32; case stateDoubleFrac: case stateDoubleExpSign: return typeDouble; default: return typeString; } }
bool CHexeMarkupEvaluator::ProcessHeader (SHTTPRequestCtx &Ctx, CDatum dResult) // ProcessHeader // // Outputs the given header { // Check for error if (dResult.IsError()) { m_Output.Write(strPattern(ERR_PROCESSING_HEADER, dResult.AsString())); return true; } // Processing depends on result type switch (dResult.GetBasicType()) { case CDatum::typeNil: return true; // If this is a string or anything else, we expect both field and value // are in the same string and we need to parse it. default: { CString sData = dResult.AsString(); // Parse into field and value char *pPos = sData.GetParsePointer(); while (strIsWhitespace(pPos)) pPos++; // Look for the field name char *pStart = pPos; while (*pPos != ':' && *pPos != '\0') pPos++; CString sField(pStart, pPos - pStart); if (sField.IsEmpty()) { m_Output.Write(strPattern(ERR_NO_HEADER_FIELD, sData)); return true; } // Look for the value CString sValue; if (*pPos == ':') { pPos++; while (strIsWhitespace(pPos)) pPos++; sValue = CString(pPos); } // Done CHTTPMessage::SHeader *pNewHeader = m_Headers.Insert(); pNewHeader->sField = sField; pNewHeader->sValue = sValue; } } return true; }
void htmlWriteAttributeValue (const CString &sText, IByteStream &Output) // htmlWriteAttributeValue // // Writes attribute value text, escaping all appropriate characters. { char *pPos = sText.GetParsePointer(); char *pPosEnd = pPos + sText.GetLength(); char *pStart = pPos; while (pPos < pPosEnd) { if (*pPos == '<') { Output.Write(pStart, pPos - pStart); pPos++; pStart = pPos; Output.Write("<", 4); } else if (*pPos == '>') { Output.Write(pStart, pPos - pStart); pPos++; pStart = pPos; Output.Write(">", 4); } else if (*pPos == '&') { Output.Write(pStart, pPos - pStart); pPos++; pStart = pPos; Output.Write("&", 5); } else if (*pPos == '\"') { Output.Write(pStart, pPos - pStart); pPos++; pStart = pPos; Output.Write(""", 6); } else if (*pPos == '\'') { Output.Write(pStart, pPos - pStart); pPos++; pStart = pPos; Output.Write("'", 6); } else if (*pPos == '`') { Output.Write(pStart, pPos - pStart); pPos++; pStart = pPos; Output.Write("`", 6); } else // LATER: Should check for lower-ASCII characters pPos++; } Output.Write(pStart, pPos - pStart); }
bool CArchonProcess::TransformAddress (const CString &sAddress, const CString &sMsg, CDatum dPayload, CString *retsDestMsgAddress, CString *retsDestMsg, CDatum *retdPayload, CString *retsError) // TransformAddress // // Transforms a Transpace Address. { CString sNamespace; if (!CTranspaceInterface::ParseAddress(sAddress, &sNamespace)) { *retsError = strPattern(ERR_BAD_TRANSPACE_ADDRESS, sAddress); return false; } // Is this a message namespace? char *pPos = sNamespace.GetParsePointer(); if (*pPos == '@') { // Send the message directly to the port specified by the namespace *retsDestMsgAddress = CString(pPos + 1); *retsDestMsg = sMsg; *retdPayload = dPayload; } // Is this a service namespace? else if (*pPos == '#') { // Parse the service endpoint CString sService(pPos + 1); // Encode into the proper payload CComplexArray *pPayload = new CComplexArray; pPayload->Append(sService); pPayload->Append(sMsg); pPayload->Append(dPayload); // Done *retsDestMsgAddress = ADDRESS_HYPERION_COMMAND; *retsDestMsg = MSG_HYPERION_SERVICE_MSG; *retdPayload = CDatum(pPayload); } // If this is a slash, then convert to Aeon else if (*pPos == '/') { *retsDestMsgAddress = ADDRESS_AEON_COMMAND; *retsDestMsg = sMsg; *retdPayload = dPayload; } // Otherwise, can't parse else { *retsError = strPattern(ERR_BAD_TRANSPACE_ADDRESS, sAddress); return false; } return true; }
CString ExecuteUpgrade (CSocket &theSocket, const CString &sCmd) { int i; CString sRoot = fileGetPath(fileGetExecutableFilespec()); // Make a list of all executable files to upgrade TArray<CString> FileList; if (!fileGetFileList(sRoot, NULL_STR, CString("*.exe"), FFL_FLAG_RELATIVE_FILESPEC, &FileList)) return CString("ERROR: Unable to obtain a list of executable files to upgrade."); // Prepare a request upgrade command CStringBuffer Output; Output.Write("requestUpgrade (", 16); for (i = 0; i < FileList.GetCount(); i++) { CString sFilespec = fileAppend(sRoot, FileList[i]); // Version SFileVersionInfo Info; if (!fileGetVersionInfo(sFilespec, &Info)) { printf("ERROR: Unable to get file version: %s\n", (LPSTR)sFilespec); continue; } CIPInteger Version(Info.dwProductVersion); CString sVersion = Version.AsString(); // Checksum DWORD dwChecksum = fileChecksumAdler32(sFilespec); if (dwChecksum == 0) { printf("ERROR: Unable to get file checksum: %s\n", (LPSTR)sFilespec); continue; } CString sOutput = strPattern("{filename:\"%s\" version:%s checksum:%d} ", FileList[i], sVersion, dwChecksum); Output.Write(sOutput); } Output.Write(")", 1); // Send the command CString sSend = CString::CreateFromHandoff(Output); CString sResult; CDatum dResult; ExecuteArcologyCommand(theSocket, sSend, &sResult, &dResult); if (strEquals(sResult, CString("ERROR"))) return dResult.AsString(); // Show all the files to upgrade CDatum dUpgradeDesc = dResult.GetElement(0).GetElement(FIELD_UPGRADE_DESC); for (i = 0; i < dUpgradeDesc.GetCount(); i++) { CDatum dFileDesc = dUpgradeDesc.GetElement(i); printf("Upgrading %s\n", (LPSTR)dFileDesc.GetElement(FIELD_FILENAME).AsString()); } // Confirm CString sConfirm = GetInputLine(CString("\nAre you sure you want to upgrade the arcology? [y/n] : ")); if (*sConfirm.GetParsePointer() != 'y' && *sConfirm.GetParsePointer() != 'Y') return NULL_STR; // Upload the new files. for (i = 0; i < dUpgradeDesc.GetCount(); i++) { CDatum dFileDesc = dUpgradeDesc.GetElement(i); const CString &sFilename = dFileDesc.GetElement(FIELD_FILENAME); CString sFilespec = fileAppend(sRoot, sFilename); CString sResult = UploadFile(theSocket, CMD_UPLOAD_UPGRADE, sFilename, sFilespec); printf("%s\n", (LPSTR)sResult); } // Complete the upgrade return ExecuteArcologyCommand(theSocket, CMD_COMPLETE_UPGRADE); }
bool CAeonInterface::ParseFilePath (const CString &sFilePath, const CString &sRoot, int iOffset, const CDateTime &IfModifiedAfter, CString *retsAddr, CString *retsMsg, CDatum *retdPayload) // ParseFilePath // // Parses a filePath of the form: // // @Aeon.command/Arc.services/TransPackage.ars // /Arc.services/TransPackage.ars // ./TransPackage.ars // // Returns FALSE if error. { char *pPos = sFilePath.GetParsePointer(); char *pPosEnd = pPos + sFilePath.GetLength(); // Create a fileDownloadDesc to specify that we not read more than 100K // at a time (so that we don't overload our IPC buffer). CComplexStruct *pFDDesc = new CComplexStruct; pFDDesc->SetElement(FIELD_PARTIAL_MAX_SIZE, 100000); pFDDesc->SetElement(FIELD_PARTIAL_POS, iOffset); if (IfModifiedAfter.IsValid()) pFDDesc->SetElement(FIELD_IF_MODIFIED_AFTER, IfModifiedAfter); CDatum dFileDownloadDesc(pFDDesc); // If the path starts with @ then this is an absolute path CString sParsedPath; if (*pPos == '@') { // LATER return false; } // Is this a service namespace? else if (*pPos == '#') { CString sNamespace; if (!CTranspaceInterface::ParseAddress(sFilePath, &sNamespace)) return false; // Compose a proper download command payload CComplexArray *pPayload = new CComplexArray; pPayload->Append(sFilePath); pPayload->Append(sFilePath); pPayload->Append(dFileDownloadDesc); CDatum dPayload(pPayload); // Parse the service endpoint CString sService(sNamespace.GetParsePointer() + 1); // Encode into the proper payload CComplexArray *pPayload2 = new CComplexArray; pPayload2->Append(sService); pPayload2->Append(MSG_TRANSPACE_DOWNLOAD); pPayload2->Append(dPayload); // Done *retsAddr = ADDRESS_HYPERION_COMMAND; *retsMsg = MSG_HYPERION_SERVICE_MSG; *retdPayload = CDatum(pPayload2); return true; } // If it starts with a slash then it is an Aeon path else if (*pPos == '/') { sParsedPath = sFilePath; *retsAddr = ADDR_AEON; *retsMsg = MSG_AEON_FILE_DOWNLOAD; // Generate a message for Aeon to load the file CComplexArray *pPayload = new CComplexArray; pPayload->Insert(sParsedPath); pPayload->Insert(dFileDownloadDesc); // Done *retdPayload = CDatum(pPayload); } // If it starts with a ./ then this is a relative path else if (*pPos == '.') { pPos++; if (pPos == pPosEnd || *pPos != '/') return false; // Root must be valid if (sRoot.IsEmpty()) return false; // If the root already ends in '/' then skip. if (*(sRoot.GetParsePointer() + sRoot.GetLength() - 1) == '/') pPos++; sParsedPath = sRoot + CString(pPos); *retsAddr = ADDR_AEON; *retsMsg = MSG_AEON_FILE_DOWNLOAD; // Generate a message for Aeon to load the file CComplexArray *pPayload = new CComplexArray; pPayload->Insert(sParsedPath); pPayload->Insert(dFileDownloadDesc); // Done *retdPayload = CDatum(pPayload); } // Otherwise this is a relative path. else { // Root must be valid if (sRoot.IsEmpty()) return false; // Add '/' separator if (*(sRoot.GetParsePointer() + sRoot.GetLength() - 1) == '/') sParsedPath = sRoot + sFilePath; else sParsedPath = sRoot + SEPARATOR_SLASH, sFilePath; *retsAddr = ADDR_AEON; *retsMsg = MSG_AEON_FILE_DOWNLOAD; // Generate a message for Aeon to load the file CComplexArray *pPayload = new CComplexArray; pPayload->Insert(sParsedPath); pPayload->Insert(dFileDownloadDesc); // Done *retdPayload = CDatum(pPayload); } return true; }