CDatum CAeonView::ComputeColumns (CHexeProcess &Process, CDatum dRowData) // ComputeColumns // // Returns a new row struct containing any computed columns. { if (m_ComputedColumns.IsNil() || !m_ComputedColumns.CanInvoke()) return dRowData; // Compute columns. We should get back a struct of all new columns. TArray<CDatum> Args; Args.Insert(dRowData); CDatum dResult; CHexeProcess::ERunCodes iRun = Process.Run(m_ComputedColumns, Args, &dResult); switch (iRun) { case CHexeProcess::runOK: { // dResult is a struct containing zero or more columns CDatum dNewRowData(new CComplexStruct(dRowData)); dNewRowData.Append(dResult); return dNewRowData; } case CHexeProcess::runError: { CDatum dNewRowData(new CComplexStruct(dRowData)); dNewRowData.SetElement(FIELD_ERROR, strPattern("ERROR: %s", dResult.AsString())); return dNewRowData; } default: { CDatum dNewRowData(new CComplexStruct(dRowData)); dNewRowData.SetElement(FIELD_ERROR, ERR_COMPUTED_COLUMN); return dNewRowData; } } }
CString ExecuteLispCommand (const CString &sInput) { CString sOutput; CDatum dExpression; if (!CHexeDocument::ParseLispExpression(sInput, &dExpression, &sOutput)) return sOutput; CDatum dResult; CHexeProcess::ERunCodes iRun = g_Process.Run(dExpression, &dResult); switch (iRun) { case CHexeProcess::runOK: case CHexeProcess::runError: return dResult.AsString(); default: return CString("Unable to complete run."); } }
void CHexeMarkupEvaluator::OutputDatum (CDatum dValue) // OutputDatum // // Outputs a datum to the resulting HTML page. NOTE: We expect the values to be // HTML compatible (i.e., caller is responsible for escaping). { int i; if (dValue.GetBasicType() == CDatum::typeArray) { for (i = 0; i < dValue.GetCount(); i++) OutputDatum(dValue.GetElement(i)); } else { m_Output.Write(dValue.AsString()); } }
void CHexeMarkupEvaluator::AddHeader (const CString &sField, CDatum dValue) // AddHeader // // Adds the header { CHTTPMessage::SHeader *pNewHeader; switch (dValue.GetBasicType()) { case CDatum::typeString: pNewHeader = m_Headers.Insert(); pNewHeader->sField = sField; pNewHeader->sValue = dValue; break; default: pNewHeader = m_Headers.Insert(); pNewHeader->sField = sField; pNewHeader->sValue = dValue.AsString(); } }
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 CAeonView::CreateSecondaryKeys (CHexeProcess &Process, CDatum dData, SEQUENCENUMBER RowID, TArray<CRowKey> *retKeys) // CreateSecondaryKeys // // Creates a secondary key from the data and rowID. We return TRUE if all of // the key values are non-nil. FALSE if one or more values are nil. { int i; bool bAllValid = true; // Pull the dimensions from the data TArray<CDatum> KeyData; for (i = 0; i < m_Keys.GetCount(); i++) { CDatum dValue; CDatum dKeyDesc = m_Keys[i]; // If this is a function then we need to evaluate it. if (dKeyDesc.CanInvoke()) { TArray<CDatum> Args; Args.Insert(dData); CHexeProcess::ERunCodes iRun = Process.Run(dKeyDesc, Args, &dValue); switch (iRun) { case CHexeProcess::runOK: // dValue is a valid value for a key break; case CHexeProcess::runError: dValue = CDatum(strPattern("(%s)", dValue.AsString())); break; default: dValue = CDatum(STR_ERROR_KEY); } } // Otherwise this specifies a field in the data to use as a key else dValue = dData.GetElement((const CString &)dKeyDesc); // We don't support Nil keys, so we have to replace these with a // a special value. if (dValue.IsNil()) { dValue = CDatum(STR_EMPTY_KEY); // If we're not valid if we're excluding nil keys if (m_bExcludeNil) bAllValid = false; } // Add to list KeyData.Insert(dValue); } // Generate the keys. // If we use list keys then we need to create permuted keys retKeys->DeleteAll(); if (m_bUsesListKeys) CreatePermutedKeys(KeyData, 0, TArray<CDatum>(), RowID, retKeys); // Otherwise we just create the key normally else { CRowKey *pNewKey = retKeys->Insert(); CRowKey::CreateFromDatumAndRowID(m_Dims, KeyData, RowID, pNewKey); } // Done return bAllValid; }
bool CHexeMarkupEvaluator::ProcessResult (SHTTPRequestCtx &Ctx, CHexeProcess::ERunCodes iRun, CDatum dResult) // ProcessResult // // Process the result of an evaluation. Returns TRUE if processing should // continue; FALSE if we need RPC or are done processing. { // If we have more async calls then return if (iRun == CHexeProcess::runAsyncRequest) { Ctx.iStatus = pstatRPCReady; Ctx.sRPCAddr = dResult.GetElement(0); Ctx.RPCMsg.sMsg = dResult.GetElement(1); Ctx.RPCMsg.dPayload = dResult.GetElement(2); Ctx.RPCMsg.dwTicket = 0; Ctx.RPCMsg.sReplyAddr = NULL_STR; return false; } // Otherwise, process the result based on the directive that we're // evaluating. bool bResult = true; switch (m_iProcessing) { case tagEval: OutputDatum(dResult); break; case tagFile: // If this is an error, then we return with 404 if (iRun == CHexeProcess::runError) { Ctx.iStatus = pstatResponseReady; Ctx.Response.InitResponse(http_NOT_FOUND, dResult.AsString()); bResult = false; } // If the result is a list then we expect a fileDesc and fileData. else if (dResult.GetCount() >= 2) { Ctx.iStatus = pstatFileDataReady; Ctx.dFileDesc = dResult.GetElement(0); Ctx.dFileData = dResult.GetElement(1); Ctx.AdditionalHeaders = m_Headers; bResult = false; } // Otherwise we expect a filePath else { Ctx.iStatus = pstatFilePathReady; Ctx.sFilePath = dResult; Ctx.AdditionalHeaders = m_Headers; bResult = false; } break; case tagHeader: bResult = ProcessHeader(Ctx, dResult); break; case tagIf: m_iIfLevel++; if (dResult.IsNil()) m_iIfLevelEnd = m_iIfLevel; break; case tagRedirect: // If this is an error, then we return with 404 if (iRun == CHexeProcess::runError) { Ctx.iStatus = pstatResponseReady; Ctx.Response.InitResponse(http_NOT_FOUND, dResult.AsString()); bResult = false; } // Otherwise, we expect a string containing the new address. else if (!dResult.IsNil()) { m_dwResponseCode = http_MOVED_PERMANENTLY; m_sResponseMsg = STR_MOVED_PERMANENTLY; AddHeader(HEADER_LOCATION, dResult); } break; default: ASSERT(false); } m_iProcessing = tagNone; return bResult; }
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; }
bool CAeonEngine::ParseTableAndView (const SArchonMessage &Msg, const CHexeSecurityCtx *pSecurityCtx, CDatum dTableAndView, CAeonTable **retpTable, DWORD *retdwViewID, CDatum dKey, CRowKey *retKey) // ParseTableAndView // // Parses a datum as follows: // // If a single string, it specifies a table and the default view. // If an array with two strings, the first is the table name; the second is the view name. { CString sError; // If we're not ready, then error if (!m_bReady) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, ERR_NOT_READY, Msg); return false; } // Parse the table names CString sTable; CString sView; if (dTableAndView.GetCount() < 2) sTable = dTableAndView.AsString(); else { sTable = dTableAndView.GetElement(0).AsString(); sView = dTableAndView.GetElement(1).AsString(); } // Make sure we have access if (pSecurityCtx && !pSecurityCtx->IsNamespaceAccessible(sTable)) { SendMessageReplyError(MSG_ERROR_NOT_ALLOWED, strPattern(ERR_NOT_IN_SANDBOX, sTable, pSecurityCtx->GetSandboxName()), Msg); return false; } // Get the table CAeonTable *pTable; if (!FindTable(sTable, &pTable)) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, strPattern(STR_ERROR_UNKNOWN_TABLE, sTable), Msg); return false; } // Get the view. If we want a key, take this opportunity to parse it. DWORD dwViewID; if (retKey) { if (!pTable->FindViewAndPath(sView, &dwViewID, dKey, retKey, &sError)) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, sError, Msg); return false; } } // Otherwise just get the view. else { if (!pTable->FindView(sView, &dwViewID)) { SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, strPattern(ERR_UNKNOWN_VIEW, sTable, sView), Msg); return false; } } // Done if (retpTable) *retpTable = pTable; if (retdwViewID) *retdwViewID = dwViewID; return true; }