1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF) */
3 /* (C) Copyright IBM Corp. 2001, 2004, 2005 */
4 /* */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */
6 /*****************************************************************************/
7
8 #include "STAF.h"
9 #include <map>
10 #include <queue>
11 #include "STAFLogService.h"
12 #include "STAF_fstream.h"
13 #include "STAF_iostream.h"
14 #include "STAFString.h"
15 #include "STAFException.h"
16 #include "STAFRefPtr.h"
17 #include "STAFMutexSem.h"
18 #include "STAFCommandParser.h"
19 #include "STAFServiceInterface.h"
20 #include "STAFTimestamp.h"
21 #include "STAFUtil.h"
22 #include "STAFInternalUtil.h"
23 #include "STAFFileSystem.h"
24 #include "STAFRWSem.h"
25
26 //#define STAF_DO_TIMING
27 #include "STAFTiming.h"
28
29 // Note: The handleXXX functions for the Log service behave slightly differently
30 // from other services. They parse the input before checking the trust
31 // of the requester. This is necessary since requests may be forwarded
32 // from another system. These requests may contain RMTMACHINE options,
33 // which specify the originating system.
34
35 // Type definitions
36
37 // The STAFLogFileLocks class represents the necessary locks needed to access
38 // a specific log file. The static acquireLocks() method is used to obtain
39 // access to the appropriate locks.
40 //
41 // Internally, this class maintains a map of all the locks for "active" logs.
42 // An "active" log is one for which there is a request currently being
43 // processed. Once no more requests are working on a log, the log is no
44 // longer "active" and is removed from the map. This is handled by maintaining
45 // a "count" of all requests using the locks for a given log. When the lock
46 // structure is deleted, the count is decremented, and, if it is zero, the
47 // lock structure is removed from the map.
48 //
49 // This internal mechanism is used so that the map of log locks doesn't continue
50 // to grow, which could lead to resource exhaustion (more likely OS semaphores
51 // than memory). With this, the map stays very small, which also aids in
52 // performance (of lookups).
53
54 class STAFLogFileLocks;
55 typedef STAFRefPtr<STAFLogFileLocks> STAFLogFileLocksPtr;
56
57 class STAFLogFileLocks
58 {
59 public:
60
61 // This is the method used to get access to the locks for a given
62 // log file.
63 static STAFLogFileLocksPtr acquireLocks(const STAFString &logFile);
64
65 // DEBUG
66 static void dumpLockData();
67
68 // The logAccess sem allows general access to the log.
69 // A read lock should be obtained for any general read/write operation.
70 // A write lock should be obtainef for any destructive type of change, such
71 // as a purge/delete
72 STAFRWSemPtr logAccess;
73
74 // The recordAccess sem allows access to individual records. You should
75 // acquire this sem before attempting to read or write any log records
76 // from/to the file.
77 // Note: You should already have a logAccess lock before acquiring this lock
78 STAFMutexSemPtr recordAccess;
79
~STAFLogFileLocks()80 ~STAFLogFileLocks()
81 {
82 releaseLocks(logFile);
83 }
84
85 private:
86
87 // This is private so that users must go through acquireLocks()
STAFLogFileLocks(STAFRWSemPtr theLogAccess,STAFMutexSemPtr theRecordAccess,const STAFString & theLogFile)88 STAFLogFileLocks(STAFRWSemPtr theLogAccess,
89 STAFMutexSemPtr theRecordAccess,
90 const STAFString &theLogFile) :
91 logAccess(theLogAccess),
92 recordAccess(theRecordAccess),
93 logFile(theLogFile)
94 { /* Do nothing */ }
95
96 STAFString logFile;
97
98 // This is private so that is only called by the destructor
99 static void releaseLocks(const STAFString &logFile);
100
101 // This structure holds the real semaphores and access count
102 struct LogLocks
103 {
LogLocksSTAFLogFileLocks::LogLocks104 LogLocks() : logAccess(new STAFRWSem, STAFRWSemPtr::INIT),
105 recordAccess(new STAFMutexSem, STAFMutexSemPtr::INIT),
106 count(1)
107 { /* Do nothing */ }
108
109 STAFRWSemPtr logAccess;
110 STAFMutexSemPtr recordAccess;
111 unsigned int count;
112 };
113
114 typedef std::map<STAFString, LogLocks> LogLocksMap;
115
116 static STAFMutexSem logLocksMutex;
117 static std::map<STAFString, LogLocks> logLocks;
118 };
119
120 STAFMutexSem STAFLogFileLocks::logLocksMutex;
121 STAFLogFileLocks::LogLocksMap STAFLogFileLocks::logLocks;
122
dumpLockData()123 void STAFLogFileLocks::dumpLockData()
124 {
125 STAFMutexSemLock lock(logLocksMutex);
126
127 for (LogLocksMap::iterator iter = logLocks.begin();
128 iter != logLocks.end();
129 ++iter)
130 {
131 cout << iter->first << ": " << iter->second.count << endl;
132 }
133 }
134
acquireLocks(const STAFString & logFile)135 STAFLogFileLocksPtr STAFLogFileLocks::acquireLocks(const STAFString &logFile)
136 {
137 STAFString logFileName = logFile.toLowerCase();
138 STAFMutexSemLock lock(logLocksMutex);
139
140 LogLocksMap::iterator iter = logLocks.find(logFileName);
141
142 if (iter != logLocks.end())
143 {
144 ++iter->second.count;
145
146 return STAFLogFileLocksPtr(new STAFLogFileLocks(
147 iter->second.logAccess,
148 iter->second.recordAccess,
149 logFileName),
150 STAFLogFileLocksPtr::INIT);
151 }
152 else
153 {
154 LogLocks theLogLocks;
155 logLocks[logFileName] = theLogLocks;
156
157 return STAFLogFileLocksPtr(new STAFLogFileLocks(
158 theLogLocks.logAccess,
159 theLogLocks.recordAccess,
160 logFileName),
161 STAFLogFileLocksPtr::INIT);
162 }
163 }
164
releaseLocks(const STAFString & logFile)165 void STAFLogFileLocks::releaseLocks(const STAFString &logFile)
166 {
167 STAFMutexSemLock lock(logLocksMutex);
168 LogLocksMap::iterator iter = logLocks.find(logFile);
169
170 if ((iter != logLocks.end()) && (--iter->second.count == 0))
171 {
172 logLocks.erase(iter);
173 }
174 }
175
176 typedef STAFRefPtr<STAFCommandParser> STAFCommandParserPtr;
177
178 struct LogServiceData
179 {
180 unsigned int fDebugMode; // Not used, currently
181 STAFString fName; // Registered service name
182 STAFString fShortName; // Short service name
183 STAFString fResolveLogMaskString; // String for resolve log mask
184 STAFString fResolveMessageString; // String for resolve message var
185 STAFString fRoot; // Root of log directory
186 STAFString fRemoteLogServer; // Name of remote log server
187 STAFString fRemoteLogService; // Name of remote log service
188 STAFHandlePtr fHandle; // Log service's STAF handle
189 unsigned int fDefaultResolveMessage; // Default for resolving messages
190 unsigned int fMaxRecordSize; // Maximum log record size
191 unsigned int fDefaultMaxQueryRecords; // Default maximum records to return
192 // on a generic QUERY request
193 unsigned int fUseResolveMessageVar; // Honor S/S/Log/ResolveMessage
194 unsigned int fRLogMode; // Are we in RLog mode?
195 STAFCommandParserPtr fParmsParser;
196 STAFCommandParserPtr fLogParser;
197 STAFCommandParserPtr fQueryParser;
198 STAFCommandParserPtr fListParser;
199 STAFCommandParserPtr fDeleteParser;
200 STAFCommandParserPtr fPurgeParser;
201 STAFCommandParserPtr fSetParser;
202 STAFString fDefaultAuthenticator; // Default Authenticator
203 STAFString fLocalMachineName;
204
205 // Map Class Definitions for marshalled results
206 STAFMapClassDefinitionPtr fLogRecordClass;
207 STAFMapClassDefinitionPtr fLogRecordLongClass;
208 STAFMapClassDefinitionPtr fQueryStatsClass;
209 STAFMapClassDefinitionPtr fPurgeStatsClass;
210 STAFMapClassDefinitionPtr fListLocalSettingsClass;
211 STAFMapClassDefinitionPtr fListRemoteSettingsClass;
212 STAFMapClassDefinitionPtr fListLogsClass;
213 };
214
215 struct LogRecord
216 {
LogRecordLogRecord217 LogRecord() : recordFormatID(0), date(0), secondsPastMidnight(0),
218 logLevel(0), handle(0), recordNumber(0)
219 { /* Do Nothing */ }
220
LogRecordLogRecord221 LogRecord(unsigned int aDate, unsigned int seconds, unsigned int level,
222 const STAFString &aMachine, const STAFString &aHandleName,
223 STAFHandle_t aHandle, const STAFString(&aUser),
224 const STAFString(&aEndpoint), const STAFString &aMessage)
225 : recordFormatID(0), date(aDate), secondsPastMidnight(seconds),
226 logLevel(level), machine(aMachine), handleName(aHandleName),
227 handle(aHandle), user(aUser), endpoint(aEndpoint), message(aMessage),
228 recordNumber(0)
229 { /* Do Nothing */ }
230
231 unsigned int recordFormatID;
232 unsigned int date;
233 unsigned int secondsPastMidnight;
234 unsigned int logLevel;
235 STAFString machine;
236 STAFString handleName;
237 STAFHandle_t handle;
238 STAFString user;
239 STAFString endpoint;
240 STAFString message;
241
242 // Note: Record number is not stored in the logfile
243 unsigned int recordNumber;
244 };
245
246
247 typedef std::deque<STAFString> StringList;
248 typedef std::deque<STAFHandle_t> HandleList;
249 typedef struct
250 {
251 unsigned int date;
252 unsigned int seconds;
253 } LogTimestamp;
254
255 struct LogRecordFilter
256 {
LogRecordFilterLogRecordFilter257 LogRecordFilter() : useLevelMask(false), useFrom(false), useAfter(false),
258 useBefore(false), useTo(false)
259 { /* Do Nothing */ }
260
261 StringList contains;
262 StringList cscontains;
263 StringList startswith;
264 StringList csstartswith;
265 StringList qMachines;
266 StringList names;
267 StringList users;
268 StringList endpoints;
269 HandleList qHandles;
270 bool useLevelMask;
271 unsigned int levelMask;
272 bool useFrom;
273 LogTimestamp fromTimestamp;
274 bool useAfter;
275 LogTimestamp afterTimestamp;
276 bool useBefore;
277 LogTimestamp beforeTimestamp;
278 bool useTo;
279 LogTimestamp toTimestamp;
280 };
281
282
283 enum ReadLogRecordRC
284 {
285 kReadLogOk = 0,
286 kReadLogEndOfFile = 1,
287 kReadLogInvalidFormat = 2
288 };
289
290 struct LogStats
291 {
292 unsigned int fatal;
293 unsigned int error;
294 unsigned int warning;
295 unsigned int info;
296 unsigned int trace;
297 unsigned int trace2;
298 unsigned int trace3;
299 unsigned int debug;
300 unsigned int debug2;
301 unsigned int debug3;
302 unsigned int start;
303 unsigned int stop;
304 unsigned int pass;
305 unsigned int fail;
306 unsigned int status;
307 unsigned int user1;
308 unsigned int user2;
309 unsigned int user3;
310 unsigned int user4;
311 unsigned int user5;
312 unsigned int user6;
313 unsigned int user7;
314 unsigned int user8;
315 };
316
317 // Some global variables
318
319 static STAFString sHelpMsg;
320 static STAFString sLineSep;
321 static const STAFString sVersionInfo("3.4.2");
322 static const STAFString sZeroOne("01");
323 static const STAFString sOne("1");
324 static const STAFString sLogExt("log");
325 static const STAFString sTmpExt("tmp");
326 static const STAFString sLeftCurly(kUTF8_LCURLY);
327 static const STAFString sSpace(kUTF8_SPACE);
328 static const STAFString sEqual(kUTF8_EQUAL);
329 static const STAFString sSlash(kUTF8_SLASH);
330 static const STAFString sColon(kUTF8_COLON);
331 static const STAFString sSpecSeparator(sColon + sSlash + sSlash);
332 static const STAFString sTimestampSeps("-@");
333 static const STAFString sLocal("LOCAL");
334 static const STAFString sVar("VAR");
335 static const STAFString sResStrResolve("RESOLVE REQUEST ");
336 static const STAFString sString(" STRING ");
337 static const STAFString sTrust("TRUST");
338 static const STAFString sMisc("MISC");
339 static const STAFString sRESOLVE("RESOLVE");
340 static const STAFString sEverythingLogMask("11111111111111111111111111111111");
341 static const STAFString sOldSep(kUTF8_VBAR);
342 static const STAFString sEOLString("RESOLVE STRING {STAF/Config/Sep/Line}");
343 static const STAFString sResMachineString("RESOLVE STRING {STAF/Config/Machine}");
344 static const STAFString sDefAuthString(
345 "RESOLVE STRING {STAF/Config/DefaultAuthenticator}");
346 static const STAFString sListDots("........................................");
347 static const STAFString sSizeEquals("Size=");
348 static const STAFString sGetMachine("GET MACHINE ");
349 static const STAFString sGetUser(" USER ");
350 static const STAFString sMachine("MACHINE ");
351 static const STAFString sLOG("LOG");
352 static const STAFString sQUERY("QUERY");
353 static const STAFString sLIST("LIST");
354 static const STAFString sPURGE("PURGE");
355 static const STAFString sDELETE("DELETE");
356 static const STAFString sHELP("HELP");
357 static const STAFString sSET("SET");
358 static const STAFString sVERSION("VERSION");
359 static const STAFString sGLOBAL("GLOBAL");
360 static const STAFString sMACHINE("MACHINE");
361 static const STAFString sMACHINES("MACHINES");
362 static const STAFString sHANDLE("HANDLE");
363 static const STAFString sHANDLES("HANDLES");
364 static const STAFString sLOGNAME("LOGNAME");
365 static const STAFString sLEVEL("LEVEL");
366 static const STAFString sMESSAGE("MESSAGE");
367 static const STAFString sRESOLVEMESSAGE("RESOLVEMESSAGE");
368 static const STAFString sNORESOLVEMESSAGE("NORESOLVEMESSAGE");
369 static const STAFString sCONTAINS("CONTAINS");
370 static const STAFString sCSCONTAINS("CSCONTAINS");
371 static const STAFString sSTARTSWITH("STARTSWITH");
372 static const STAFString sCSSTARTSWITH("CSSTARTSWITH");
373 static const STAFString sQMACHINE("QMACHINE");
374 static const STAFString sQHANDLE("QHANDLE");
375 static const STAFString sNAME("NAME");
376 static const STAFString sUSER("USER");
377 static const STAFString sENDPOINT("ENDPOINT");
378 static const STAFString sLEVELMASK("LEVELMASK");
379 static const STAFString sFROM("FROM");
380 static const STAFString sAFTER("AFTER");
381 static const STAFString sFROMRECORD("FROMRECORD");
382 static const STAFString sTORECORD("TORECORD");
383 static const STAFString sBEFORE("BEFORE");
384 static const STAFString sTO("TO");
385 static const STAFString sLEVELBITSTRING("LEVELBITSTRING");
386 static const STAFString sFIRST("FIRST");
387 static const STAFString sLAST("LAST");
388 static const STAFString sALL("ALL");
389 static const STAFString sSTATS("STATS");
390 static const STAFString sTOTAL("TOTAL");
391 static const STAFString sLONG("LONG");
392 static const STAFString sCONFIRMALL("CONFIRMALL");
393 static const STAFString sDIRECTORY("DIRECTORY");
394 static const STAFString sRMTMACHINE("RMTMACHINE");
395 static const STAFString sRMTNICKNAME("RMTNICKNAME");
396 static const STAFString sRMTHANDLE("RMTHANDLE");
397 static const STAFString sRMTNAME("RMTNAME");
398 static const STAFString sRMTUSER("RMTUSER");
399 static const STAFString sRMTMACH("RMTMACH");
400 static const STAFString sMAXRECORDSIZE("MAXRECORDSIZE");
401 static const STAFString sDEFAULTMAXQUERYRECORDS("DEFAULTMAXQUERYRECORDS");
402 static const STAFString sENABLERESOLVEMESSAGEVAR("ENABLERESOLVEMESSAGEVAR");
403 static const STAFString sDISABLERESOLVEMESSAGEVAR("DISABLERESOLVEMESSAGEVAR");
404 static const STAFString sSETTINGS("SETTINGS");
405 static const STAFString sENABLEREMOTELOGGING("ENABLEREMOTELOGGING");
406 static const STAFString sREMOTELOGSERVER("REMOTELOGSERVER");
407 static const STAFString sREMOTELOGSERVICE("REMOTELOGSERVICE");
408 static const STAFString sTODAY("TODAY");
409
410 static const STAFString sFATAL("FATAL");
411 static const STAFString sERROR("ERROR");
412 static const STAFString sWARNING("WARNING");
413 static const STAFString sINFO("INFO");
414 static const STAFString sTRACE("TRACE");
415 static const STAFString sTRACE2("TRACE2");
416 static const STAFString sTRACE3("TRACE3");
417 static const STAFString sDEBUG("DEBUG");
418 static const STAFString sDEBUG2("DEBUG2");
419 static const STAFString sDEBUG3("DEBUG3");
420 static const STAFString sSTART("START");
421 static const STAFString sSTOP("STOP");
422 static const STAFString sPASS("PASS");
423 static const STAFString sFAIL("FAIL");
424 static const STAFString sSTATUS("STATUS");
425 static const STAFString sUSER1("USER1");
426 static const STAFString sUSER2("USER2");
427 static const STAFString sUSER3("USER3");
428 static const STAFString sUSER4("USER4");
429 static const STAFString sUSER5("USER5");
430 static const STAFString sUSER6("USER6");
431 static const STAFString sUSER7("USER7");
432 static const STAFString sUSER8("USER8");
433
434 static STAFString sFATALPretty("Fatal");
435 static STAFString sERRORPretty("Error");
436 static STAFString sWARNINGPretty("Warning");
437 static STAFString sINFOPretty("Info");
438 static STAFString sTRACEPretty("Trace");
439 static STAFString sTRACE2Pretty("Trace2");
440 static STAFString sTRACE3Pretty("Trace3");
441 static STAFString sDEBUGPretty("Debug");
442 static STAFString sDEBUG2Pretty("Debug2");
443 static STAFString sDEBUG3Pretty("Debug3");
444 static STAFString sSTARTPretty("Start");
445 static STAFString sSTOPPretty("Stop");
446 static STAFString sPASSPretty("Pass");
447 static STAFString sFAILPretty("Fail");
448 static STAFString sSTATUSPretty("Status");
449 static STAFString sUSER1Pretty("User1");
450 static STAFString sUSER2Pretty("User2");
451 static STAFString sUSER3Pretty("User3");
452 static STAFString sUSER4Pretty("User4");
453 static STAFString sUSER5Pretty("User5");
454 static STAFString sUSER6Pretty("User6");
455 static STAFString sUSER7Pretty("User7");
456 static STAFString sUSER8Pretty("User8");
457 static STAFString sUNKNOWNPretty("Unknown");
458
459 static STAFString sFATALBits ("00000000000000000000000000000001");
460 static STAFString sERRORBits ("00000000000000000000000000000010");
461 static STAFString sWARNINGBits("00000000000000000000000000000100");
462 static STAFString sINFOBits ("00000000000000000000000000001000");
463 static STAFString sTRACEBits ("00000000000000000000000000010000");
464 static STAFString sTRACE2Bits ("00000000000000000000000000100000");
465 static STAFString sTRACE3Bits ("00000000000000000000000001000000");
466 static STAFString sDEBUGBits ("00000000000000000000000010000000");
467 static STAFString sDEBUG2Bits ("00000000000000000000000100000000");
468 static STAFString sDEBUG3Bits ("00000000000000000000001000000000");
469 static STAFString sSTARTBits ("00000000000000000000010000000000");
470 static STAFString sSTOPBits ("00000000000000000000100000000000");
471 static STAFString sPASSBits ("00000000000000000001000000000000");
472 static STAFString sFAILBits ("00000000000000000010000000000000");
473 static STAFString sSTATUSBits ("00000000000000000100000000000000");
474 static STAFString sUSER1Bits ("00000001000000000000000000000000");
475 static STAFString sUSER2Bits ("00000010000000000000000000000000");
476 static STAFString sUSER3Bits ("00000100000000000000000000000000");
477 static STAFString sUSER4Bits ("00001000000000000000000000000000");
478 static STAFString sUSER5Bits ("00010000000000000000000000000000");
479 static STAFString sUSER6Bits ("00100000000000000000000000000000");
480 static STAFString sUSER7Bits ("01000000000000000000000000000000");
481 static STAFString sUSER8Bits ("10000000000000000000000000000000");
482 static STAFString sUNKNOWNBits("00000000000000000000000000000000");
483
484 static const STAFString sUnauthenticatedUser = "none" +
485 sSpecSeparator + "anonymous";
486
487 static const unsigned int sCurrRecordFormatID = 4;
488
489
490 // Prototypes
491
492 static STAFResultPtr handleLog(STAFServiceRequestLevel30 *, LogServiceData *);
493 static STAFResultPtr handleQuery(STAFServiceRequestLevel30 *, LogServiceData *);
494 static STAFResultPtr handlePurge(STAFServiceRequestLevel30 *, LogServiceData *);
495 static STAFResultPtr handleList(STAFServiceRequestLevel30 *, LogServiceData *);
496 static STAFResultPtr handleDelete(STAFServiceRequestLevel30 *, LogServiceData *);
497 static STAFResultPtr handleSet(STAFServiceRequestLevel30 *, LogServiceData *);
498 static STAFResultPtr handleHelp(STAFServiceRequestLevel30 *, LogServiceData *);
499 static STAFResultPtr handleRemoteLog(STAFServiceRequestLevel30 *,
500 LogServiceData *);
501 static STAFResultPtr handleRemoteLogGeneral(STAFServiceRequestLevel30 *,
502 LogServiceData *);
503
504 static bool isValidLogLevel(const STAFString &levelString,
505 unsigned int &outputLevel);
506
507 static bool convertLogLevelToUInt(const STAFString &levelString,
508 unsigned int &outputLevel);
509
510 static STAFString &convertLogLevelToString(unsigned int logLevel,
511 bool levelAsBits = false);
512
513 static bool convertLogMaskToUInt(const STAFString &logmaskString,
514 unsigned int &logMask);
515
516 void readUIntFromFile(istream &input, unsigned int &data,
517 unsigned int length = 4);
518
519 void writeUIntToFile(ostream &output, unsigned int data,
520 unsigned int length = 4);
521
522 void readStringFromFile(istream &input, STAFString &inString);
523
524 void writeStringToFile(ostream &output, const STAFString &outString);
525
526 STAFResultPtr resolveStr(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData,
527 const STAFString &theString);
528
529 STAFResultPtr resolveOp(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData,
530 STAFCommandParseResultPtr &parsedResult,
531 const STAFString &fOption,
532 unsigned int optionIndex = 1);
533
534 STAFResultPtr resolveOpLocal(LogServiceData *pData,
535 STAFCommandParseResultPtr &parsedResult,
536 const STAFString &fOption,
537 unsigned int optionIndex = 1);
538
539 static STAFResultPtr convertStringToUInt(
540 const STAFString &theString,
541 unsigned int &number,
542 const unsigned int minValue = 0,
543 const unsigned int maxValue = UINT_MAX);
544
545 static STAFResultPtr convertOptionStringToUInt(
546 const STAFString &theString,
547 const STAFString &optionName,
548 unsigned int &number,
549 const unsigned int minValue = 0,
550 const unsigned int maxValue = UINT_MAX);
551
552 bool generateQueryPurgeDeleteLogFilePath(STAFFSPath &logfilePath,
553 STAFResultPtr &errorResult, STAFServiceRequestLevel30 *pInfo,
554 LogServiceData *pData, STAFCommandParseResultPtr &parsedResult);
555
556 bool updateQueryPurgeLogFilter(LogRecordFilter &logFilter,
557 STAFResultPtr &errorResult, STAFServiceRequestLevel30 *pInfo,
558 LogServiceData *pData, STAFCommandParseResultPtr &parsedResult);
559
560 unsigned int readLogRecordFromFile(istream &input, LogRecord &logRecord,
561 unsigned int recordNumber);
562
563 void writeLogRecordToFile(ostream &output, LogRecord &logRecord);
564
565 void addLogRecordToList(STAFObjectPtr &logList,
566 STAFMapClassDefinitionPtr &logRecordClass,
567 const LogRecord &logRecord, bool levelAsBits,
568 bool longFormat);
569
570 void printLogRecord(const LogRecord &logRecord);
571
572 bool logRecordMatchesFilter(const LogRecord &logRecord,
573 const LogRecordFilter &logFilter,
574 const STAFString &defaultAuthenticator);
575
576 void updateLogStats(LogStats &logStats, unsigned int logLevel);
577
578 void addLogStatsToMap(STAFObjectPtr &queryStatsMap, const LogStats &logStats);
579
580 static void registerHelpData(LogServiceData *pData, unsigned int errorNumber,
581 const STAFString &shortInfo,
582 const STAFString &longInfo);
583
584 static void unregisterHelpData(LogServiceData *pData, unsigned int errorNumber);
585
586
587 // Begin implementation
588
STAFServiceGetLevelBounds(unsigned int levelID,unsigned int * minimum,unsigned int * maximum)589 STAFRC_t STAFServiceGetLevelBounds(unsigned int levelID,
590 unsigned int *minimum,
591 unsigned int *maximum)
592 {
593 switch (levelID)
594 {
595 case kServiceInfo:
596 {
597 *minimum = 30;
598 *maximum = 30;
599 break;
600 }
601 case kServiceInit:
602 {
603 *minimum = 30;
604 *maximum = 30;
605 break;
606 }
607 case kServiceAcceptRequest:
608 {
609 *minimum = 30;
610 *maximum = 30;
611 break;
612 }
613 case kServiceTerm:
614 case kServiceDestruct:
615 {
616 *minimum = 0;
617 *maximum = 0;
618 break;
619 }
620 default:
621 {
622 return kSTAFInvalidAPILevel;
623 }
624 }
625
626 return kSTAFOk;
627 }
628
629
STAFServiceConstruct(STAFServiceHandle_t * pServiceHandle,void * pServiceInfo,unsigned int infoLevel,STAFString_t * pErrorBuffer)630 STAFRC_t STAFServiceConstruct(STAFServiceHandle_t *pServiceHandle,
631 void *pServiceInfo, unsigned int infoLevel,
632 STAFString_t *pErrorBuffer)
633 {
634 STAFRC_t rc = kSTAFUnknownError;
635
636 try
637 {
638 if (infoLevel != 30) return kSTAFInvalidAPILevel;
639
640 STAFServiceInfoLevel30 *pInfo =
641 reinterpret_cast<STAFServiceInfoLevel30 *>(pServiceInfo);
642 LogServiceData data;
643
644 data.fDebugMode = 0;
645 data.fRLogMode = 0;
646 data.fMaxRecordSize = 100000;
647 data.fDefaultMaxQueryRecords = 100;
648 data.fDefaultResolveMessage = 0;
649 data.fUseResolveMessageVar = 0;
650 data.fRemoteLogService = sLOG;
651 data.fShortName = STAFString(pInfo->name).toUpperCase();
652 data.fName = "STAF/Service/";
653 data.fName += pInfo->name;
654 data.fResolveLogMaskString = sLeftCurly + data.fName + "/Mask}";
655 data.fResolveMessageString = sLeftCurly + data.fName +
656 "/ResolveMessage}";
657
658 // Walk through and verify the config options
659 // Note: The log service does not currently have any options
660
661 for (unsigned int i = 0; i < pInfo->numOptions; ++i)
662 {
663 STAFString optionError("Invalid option, ");
664 optionError += pInfo->pOptionName[i];
665 *pErrorBuffer = optionError.adoptImpl();
666 return kSTAFServiceConfigurationError;
667 }
668
669 // Setup parsers
670
671 // PARMS parser
672
673 data.fParmsParser = STAFCommandParserPtr(new STAFCommandParser,
674 STAFCommandParserPtr::INIT);
675 data.fParmsParser->addOption(
676 "DIRECTORY", 1, STAFCommandParser::kValueRequired);
677 data.fParmsParser->addOption(
678 "ENABLEREMOTELOGGING", 1, STAFCommandParser::kValueNotAllowed);
679 data.fParmsParser->addOption(
680 "REMOTELOGSERVER", 1, STAFCommandParser::kValueRequired);
681 data.fParmsParser->addOption(
682 "REMOTELOGSERVICE", 1, STAFCommandParser::kValueRequired);
683 data.fParmsParser->addOption(
684 "MAXRECORDSIZE", 1, STAFCommandParser::kValueRequired);
685 data.fParmsParser->addOption(
686 "DEFAULTMAXQUERYRECORDS", 1, STAFCommandParser::kValueRequired);
687 data.fParmsParser->addOption(
688 "RESOLVEMESSAGE", 1, STAFCommandParser::kValueNotAllowed);
689 data.fParmsParser->addOption(
690 "NORESOLVEMESSAGE", 1, STAFCommandParser::kValueNotAllowed);
691 data.fParmsParser->addOption(
692 "ENABLERESOLVEMESSAGEVAR", 1, STAFCommandParser::kValueNotAllowed);
693 data.fParmsParser->addOption(
694 "DISABLERESOLVEMESSAGEVAR", 1, STAFCommandParser::kValueNotAllowed);
695
696 data.fParmsParser->addOptionGroup(
697 "NORESOLVEMESSAGE RESOLVEMESSAGE", 0, 1);
698 data.fParmsParser->addOptionGroup(
699 "ENABLERESOLVEMESSAGEVAR " "DISABLERESOLVEMESSAGEVAR", 0, 1);
700 data.fParmsParser->addOptionGroup(
701 "ENABLEREMOTELOGGING DIRECTORY", 0, 1);
702 data.fParmsParser->addOptionGroup(
703 "ENABLEREMOTELOGGING MAXRECORDSIZE", 0, 1);
704 data.fParmsParser->addOptionGroup(
705 "ENABLEREMOTELOGGING DEFAULTMAXQUERYRECORDS", 0, 1);
706 data.fParmsParser->addOptionGroup(
707 "ENABLEREMOTELOGGING RESOLVEMESSAGE", 0, 1);
708 data.fParmsParser->addOptionGroup(
709 "ENABLEREMOTELOGGING NORESOLVEMESSAGE", 0, 1);
710 data.fParmsParser->addOptionGroup(
711 "ENABLEREMOTELOGGING ENABLERESOLVEMESSAGEVAR", 0, 1);
712 data.fParmsParser->addOptionGroup(
713 "ENABLEREMOTELOGGING DISABLERESOLVEMESSAGEVAR", 0, 1);
714
715 data.fParmsParser->addOptionNeed("REMOTELOGSERVER REMOTELOGSERVICE",
716 "ENABLEREMOTELOGGING");
717 data.fParmsParser->addOptionNeed("ENABLEREMOTELOGGING",
718 "REMOTELOGSERVER");
719
720 // LOG parser
721
722 data.fLogParser = STAFCommandParserPtr(new STAFCommandParser,
723 STAFCommandParserPtr::INIT);
724 data.fLogParser->addOption(
725 "LOG", 1, STAFCommandParser::kValueNotAllowed);
726 data.fLogParser->addOption(
727 "GLOBAL", 1, STAFCommandParser::kValueNotAllowed);
728 data.fLogParser->addOption(
729 "MACHINE", 1, STAFCommandParser::kValueNotAllowed);
730 data.fLogParser->addOption(
731 "HANDLE", 1, STAFCommandParser::kValueNotAllowed);
732 data.fLogParser->addOption(
733 "LOGTYPE", 1, STAFCommandParser::kValueRequired);
734 data.fLogParser->addOption(
735 "LOGNAME", 1, STAFCommandParser::kValueRequired);
736 data.fLogParser->addOption(
737 "LEVEL", 1, STAFCommandParser::kValueRequired);
738 data.fLogParser->addOption(
739 "MESSAGE", 1, STAFCommandParser::kValueRequired);
740 data.fLogParser->addOption(
741 "RESOLVEMESSAGE", 1, STAFCommandParser::kValueNotAllowed);
742 data.fLogParser->addOption(
743 "NORESOLVEMESSAGE", 1, STAFCommandParser::kValueNotAllowed);
744 data.fLogParser->addOption(
745 "RMTMACHINE", 1, STAFCommandParser::kValueRequired);
746 data.fLogParser->addOption(
747 "RMTNICKNAME", 1, STAFCommandParser::kValueRequired);
748 data.fLogParser->addOption(
749 "RMTNAME", 1, STAFCommandParser::kValueRequired);
750 data.fLogParser->addOption(
751 "RMTHANDLE", 1, STAFCommandParser::kValueRequired);
752 data.fLogParser->addOption(
753 "RMTUSER", 1, STAFCommandParser::kValueRequired);
754 data.fLogParser->addOption(
755 "RMTMACH", 1, STAFCommandParser::kValueRequired);
756
757 data.fLogParser->addOptionGroup("LOG", 1, 1);
758 data.fLogParser->addOptionGroup("LEVEL", 1, 1);
759 data.fLogParser->addOptionGroup("MESSAGE", 1, 1);
760 data.fLogParser->addOptionGroup("GLOBAL MACHINE HANDLE LOGTYPE", 1, 1);
761 data.fLogParser->addOptionGroup("LOGNAME", 1, 1);
762 data.fLogParser->addOptionGroup("RESOLVEMESSAGE NORESOLVEMESSAGE",
763 0, 1);
764
765 data.fLogParser->addOptionNeed("RMTMACHINE", "RMTUSER");
766 data.fLogParser->addOptionNeed(
767 "RMTNAME RMTHANDLE RMTUSER RMTMACH RMTNICKNAME", "RMTMACHINE");
768
769 // QUERY parser
770
771 data.fQueryParser = STAFCommandParserPtr(new STAFCommandParser,
772 STAFCommandParserPtr::INIT);
773 data.fQueryParser->addOption(
774 "QUERY", 1, STAFCommandParser::kValueNotAllowed);
775 data.fQueryParser->addOption(
776 "GLOBAL", 1, STAFCommandParser::kValueNotAllowed);
777 data.fQueryParser->addOption(
778 "MACHINE", 1, STAFCommandParser::kValueRequired);
779 data.fQueryParser->addOption(
780 "HANDLE", 1, STAFCommandParser::kValueRequired);
781 data.fQueryParser->addOption(
782 "LOGNAME", 1, STAFCommandParser::kValueRequired);
783 data.fQueryParser->addOption(
784 "LEVELMASK", 1, STAFCommandParser::kValueRequired);
785 data.fQueryParser->addOption(
786 "QMACHINE", 0, STAFCommandParser::kValueRequired);
787 data.fQueryParser->addOption(
788 "QHANDLE", 0, STAFCommandParser::kValueRequired);
789 data.fQueryParser->addOption(
790 "NAME", 0, STAFCommandParser::kValueRequired);
791 data.fQueryParser->addOption(
792 "USER", 0, STAFCommandParser::kValueRequired);
793 data.fQueryParser->addOption(
794 "ENDPOINT", 0, STAFCommandParser::kValueRequired);
795 data.fQueryParser->addOption(
796 "FIRST", 1, STAFCommandParser::kValueRequired);
797 data.fQueryParser->addOption(
798 "LAST", 1, STAFCommandParser::kValueRequired);
799 data.fQueryParser->addOption(
800 "ALL", 1, STAFCommandParser::kValueNotAllowed);
801 data.fQueryParser->addOption(
802 "TOTAL", 1, STAFCommandParser::kValueNotAllowed);
803 data.fQueryParser->addOption(
804 "STATS", 1, STAFCommandParser::kValueNotAllowed);
805 data.fQueryParser->addOption(
806 "LONG", 1, STAFCommandParser::kValueNotAllowed);
807 data.fQueryParser->addOption(
808 "CONTAINS", 0, STAFCommandParser::kValueRequired);
809 data.fQueryParser->addOption(
810 "CSCONTAINS", 0, STAFCommandParser::kValueRequired);
811 data.fQueryParser->addOption(
812 "STARTSWITH", 0, STAFCommandParser::kValueRequired);
813 data.fQueryParser->addOption(
814 "CSSTARTSWITH", 0, STAFCommandParser::kValueRequired);
815 data.fQueryParser->addOption(
816 "LEVELBITSTRING", 1, STAFCommandParser::kValueNotAllowed);
817 data.fQueryParser->addOption(
818 "FROM", 1, STAFCommandParser::kValueRequired);
819 data.fQueryParser->addOption(
820 "AFTER", 1, STAFCommandParser::kValueRequired);
821 data.fQueryParser->addOption(
822 "BEFORE", 1, STAFCommandParser::kValueRequired);
823 data.fQueryParser->addOption(
824 "TO", 1, STAFCommandParser::kValueRequired);
825 data.fQueryParser->addOption(
826 "FROMRECORD", 1, STAFCommandParser::kValueRequired);
827 data.fQueryParser->addOption(
828 "TORECORD", 1, STAFCommandParser::kValueRequired);
829 data.fQueryParser->addOption(
830 "RMTMACHINE", 1, STAFCommandParser::kValueRequired);
831 data.fQueryParser->addOption(
832 "RMTUSER", 1, STAFCommandParser::kValueRequired);
833
834 data.fQueryParser->addOptionGroup("QUERY", 1, 1);
835 data.fQueryParser->addOptionGroup("GLOBAL MACHINE", 1, 1);
836 data.fQueryParser->addOptionGroup("LOGNAME", 1, 1);
837 data.fQueryParser->addOptionGroup("FROM AFTER", 0, 1);
838 data.fQueryParser->addOptionGroup("BEFORE TO", 0, 1);
839 data.fQueryParser->addOptionGroup("FIRST LAST ALL", 0, 1);
840 data.fQueryParser->addOptionGroup("TOTAL STATS LONG", 0, 1);
841
842 data.fQueryParser->addOptionNeed("HANDLE", "MACHINE");
843 data.fQueryParser->addOptionNeed("RMTMACHINE", "RMTUSER");
844 data.fQueryParser->addOptionNeed("RMTUSER", "RMTMACHINE");
845
846 // PURGE parser
847
848 data.fPurgeParser = STAFCommandParserPtr(new STAFCommandParser,
849 STAFCommandParserPtr::INIT);
850 data.fPurgeParser->addOption(
851 "PURGE", 1, STAFCommandParser::kValueNotAllowed);
852 data.fPurgeParser->addOption(
853 "GLOBAL", 1, STAFCommandParser::kValueNotAllowed);
854 data.fPurgeParser->addOption(
855 "MACHINE", 1, STAFCommandParser::kValueRequired);
856 data.fPurgeParser->addOption(
857 "HANDLE", 1, STAFCommandParser::kValueRequired);
858 data.fPurgeParser->addOption(
859 "LOGNAME", 1, STAFCommandParser::kValueRequired);
860 data.fPurgeParser->addOption(
861 "LEVELMASK", 1, STAFCommandParser::kValueRequired);
862 data.fPurgeParser->addOption(
863 "QMACHINE", 0, STAFCommandParser::kValueRequired);
864 data.fPurgeParser->addOption(
865 "QHANDLE", 0, STAFCommandParser::kValueRequired);
866 data.fPurgeParser->addOption(
867 "NAME", 0, STAFCommandParser::kValueRequired);
868 data.fPurgeParser->addOption(
869 "USER", 0, STAFCommandParser::kValueRequired);
870 data.fPurgeParser->addOption(
871 "ENDPOINT", 0, STAFCommandParser::kValueRequired);
872 data.fPurgeParser->addOption(
873 "FIRST", 1, STAFCommandParser::kValueRequired);
874 data.fPurgeParser->addOption(
875 "LAST", 1, STAFCommandParser::kValueRequired);
876 data.fPurgeParser->addOption(
877 "CONTAINS", 0, STAFCommandParser::kValueRequired);
878 data.fPurgeParser->addOption(
879 "CSCONTAINS", 0, STAFCommandParser::kValueRequired);
880 data.fPurgeParser->addOption(
881 "STARTSWITH", 0, STAFCommandParser::kValueRequired);
882 data.fPurgeParser->addOption(
883 "CSSTARTSWITH", 0, STAFCommandParser::kValueRequired);
884 data.fPurgeParser->addOption(
885 "FROM", 1, STAFCommandParser::kValueRequired);
886 data.fPurgeParser->addOption(
887 "AFTER", 1, STAFCommandParser::kValueRequired);
888 data.fPurgeParser->addOption(
889 "BEFORE", 1, STAFCommandParser::kValueRequired);
890 data.fPurgeParser->addOption(
891 "TO", 1, STAFCommandParser::kValueRequired);
892 data.fPurgeParser->addOption(
893 "FROMRECORD", 1, STAFCommandParser::kValueRequired);
894 data.fPurgeParser->addOption(
895 "TORECORD", 1, STAFCommandParser::kValueRequired);
896 data.fPurgeParser->addOption(
897 "RMTMACHINE", 1, STAFCommandParser::kValueRequired);
898 data.fPurgeParser->addOption(
899 "RMTUSER", 1, STAFCommandParser::kValueRequired);
900 data.fPurgeParser->addOption(
901 "CONFIRM", 1, STAFCommandParser::kValueNotAllowed);
902 data.fPurgeParser->addOption(
903 "CONFIRMALL", 1, STAFCommandParser::kValueNotAllowed);
904
905 data.fPurgeParser->addOptionGroup("PURGE", 1, 1);
906 data.fPurgeParser->addOptionGroup("GLOBAL MACHINE", 1, 1);
907 data.fPurgeParser->addOptionGroup("LOGNAME", 1, 1);
908 data.fPurgeParser->addOptionGroup("CONFIRM CONFIRMALL", 1, 1);
909 data.fPurgeParser->addOptionGroup("FROM AFTER", 0, 1);
910 data.fPurgeParser->addOptionGroup("BEFORE TO", 0, 1);
911 data.fPurgeParser->addOptionGroup("FIRST LAST", 0, 1);
912
913 data.fPurgeParser->addOptionNeed("HANDLE", "MACHINE");
914 data.fPurgeParser->addOptionNeed("RMTMACHINE", "RMTUSER");
915 data.fPurgeParser->addOptionNeed("RMTUSER", "RMTMACHINE");
916
917 // LIST parser
918
919 data.fListParser = STAFCommandParserPtr(new STAFCommandParser,
920 STAFCommandParserPtr::INIT);
921 data.fListParser->addOption(
922 "LIST", 1, STAFCommandParser::kValueNotAllowed);
923 data.fListParser->addOption(
924 "GLOBAL", 1, STAFCommandParser::kValueNotAllowed);
925 data.fListParser->addOption(
926 "MACHINES", 1, STAFCommandParser::kValueNotAllowed);
927 data.fListParser->addOption(
928 "MACHINE", 1, STAFCommandParser::kValueRequired);
929 data.fListParser->addOption(
930 "HANDLES", 1, STAFCommandParser::kValueNotAllowed);
931 data.fListParser->addOption(
932 "HANDLE", 1, STAFCommandParser::kValueRequired);
933 data.fListParser->addOption(
934 "RMTMACHINE", 1, STAFCommandParser::kValueRequired);
935 data.fListParser->addOption(
936 "RMTUSER", 1, STAFCommandParser::kValueRequired);
937 data.fListParser->addOption(
938 "SETTINGS", 1, STAFCommandParser::kValueNotAllowed);
939
940 data.fListParser->addOptionGroup("LIST", 1, 1);
941 data.fListParser->addOptionGroup("GLOBAL MACHINES MACHINE SETTINGS",
942 1, 1);
943 data.fListParser->addOptionGroup("HANDLES HANDLE", 0, 1);
944
945 data.fListParser->addOptionNeed("HANDLES HANDLE", "MACHINE");
946 data.fListParser->addOptionNeed("RMTMACHINE", "RMTUSER");
947 data.fListParser->addOptionNeed("RMTUSER", "RMTMACHINE");
948
949
950 // DELETE parser
951
952 data.fDeleteParser = STAFCommandParserPtr(new STAFCommandParser,
953 STAFCommandParserPtr::INIT);
954 data.fDeleteParser->addOption(
955 "DELETE", 1, STAFCommandParser::kValueNotAllowed);
956 data.fDeleteParser->addOption(
957 "GLOBAL", 1, STAFCommandParser::kValueNotAllowed);
958 data.fDeleteParser->addOption(
959 "MACHINE", 1, STAFCommandParser::kValueRequired);
960 data.fDeleteParser->addOption(
961 "HANDLE", 1, STAFCommandParser::kValueRequired);
962 data.fDeleteParser->addOption(
963 "LOGNAME", 1, STAFCommandParser::kValueRequired);
964 data.fDeleteParser->addOption(
965 "CONFIRM", 1, STAFCommandParser::kValueNotAllowed);
966 data.fDeleteParser->addOption(
967 "RMTMACHINE", 1, STAFCommandParser::kValueRequired);
968 data.fDeleteParser->addOption(
969 "RMTUSER", 1, STAFCommandParser::kValueRequired);
970
971 data.fDeleteParser->addOptionGroup("DELETE", 1, 1);
972 data.fDeleteParser->addOptionGroup("GLOBAL MACHINE", 1, 1);
973 data.fDeleteParser->addOptionGroup("LOGNAME", 1, 1);
974 data.fDeleteParser->addOptionGroup("CONFIRM", 1, 1);
975
976 data.fDeleteParser->addOptionNeed("HANDLE", "MACHINE");
977 data.fDeleteParser->addOptionNeed("RMTMACHINE", "RMTUSER");
978 data.fDeleteParser->addOptionNeed("RMTUSER", "RMTMACHINE");
979
980 // SET parser
981
982 data.fSetParser = STAFCommandParserPtr(new STAFCommandParser,
983 STAFCommandParserPtr::INIT);
984 data.fSetParser->addOption(
985 "SET", 1, STAFCommandParser::kValueNotAllowed);
986 data.fSetParser->addOption(
987 "MAXRECORDSIZE", 1, STAFCommandParser::kValueRequired);
988 data.fSetParser->addOption(
989 "DEFAULTMAXQUERYRECORDS", 1, STAFCommandParser::kValueRequired);
990 data.fSetParser->addOption(
991 "NORESOLVEMESSAGE", 1, STAFCommandParser::kValueNotAllowed);
992 data.fSetParser->addOption(
993 "RESOLVEMESSAGE", 1, STAFCommandParser::kValueNotAllowed);
994 data.fSetParser->addOption(
995 "ENABLERESOLVEMESSAGEVAR", 1, STAFCommandParser::kValueNotAllowed);
996 data.fSetParser->addOption(
997 "DISABLERESOLVEMESSAGEVAR", 1, STAFCommandParser::kValueNotAllowed);
998
999 data.fSetParser->addOptionGroup("NORESOLVEMESSAGE RESOLVEMESSAGE",
1000 0, 1);
1001 data.fSetParser->addOptionGroup("ENABLERESOLVEMESSAGEVAR "
1002 "DISABLERESOLVEMESSAGEVAR",
1003 0, 1);
1004
1005 // Construct the map class for the marshalled QUERY log-record output
1006
1007 data.fLogRecordClass = STAFMapClassDefinition::create(
1008 "STAF/Service/Log/LogRecord");
1009
1010 data.fLogRecordClass->addKey("timestamp", "Date-Time");
1011 data.fLogRecordClass->addKey("level", "Level");
1012 data.fLogRecordClass->addKey("message", "Message");
1013
1014 // Construct the map class for the marshalled QUERY LONG log-record
1015 // output
1016
1017 data.fLogRecordLongClass = STAFMapClassDefinition::create(
1018 "STAF/Service/Log/LogRecordLong");
1019
1020 data.fLogRecordLongClass->addKey("recordNumber", "Record #");
1021 data.fLogRecordLongClass->setKeyProperty(
1022 "recordNumber", "display-short-name", "R#");
1023 data.fLogRecordLongClass->addKey("timestamp", "Date-Time");
1024 data.fLogRecordLongClass->addKey("machine", "Machine");
1025 data.fLogRecordLongClass->addKey("handle", "Handle");
1026 data.fLogRecordLongClass->setKeyProperty(
1027 "handle", "display-short-name", "H#");
1028 data.fLogRecordLongClass->addKey("handleName", "Handle Name");
1029 data.fLogRecordLongClass->setKeyProperty(
1030 "handleName", "display-short-name", "Name");
1031 data.fLogRecordLongClass->addKey("user", "User");
1032 data.fLogRecordLongClass->addKey("endpoint", "Endpoint");
1033 data.fLogRecordLongClass->addKey("level", "Level");
1034 data.fLogRecordLongClass->addKey("message", "Message");
1035
1036 // Construct the map class for the marshalled QUERY STATS output
1037
1038 data.fQueryStatsClass = STAFMapClassDefinition::create(
1039 "STAF/Service/Log/QueryStats");
1040
1041 data.fQueryStatsClass->addKey("fatal", sFATALPretty);
1042 data.fQueryStatsClass->addKey("error", sERRORPretty);
1043 data.fQueryStatsClass->addKey("warning", sWARNINGPretty);
1044 data.fQueryStatsClass->addKey("info", sINFOPretty);
1045 data.fQueryStatsClass->addKey("trace", sTRACEPretty);
1046 data.fQueryStatsClass->addKey("trace2", sTRACE2Pretty);
1047 data.fQueryStatsClass->addKey("trace3", sTRACE3Pretty);
1048 data.fQueryStatsClass->addKey("debug", sDEBUGPretty);
1049 data.fQueryStatsClass->addKey("debug2", sDEBUG2Pretty);
1050 data.fQueryStatsClass->addKey("debug3", sDEBUG3Pretty);
1051 data.fQueryStatsClass->addKey("start", sSTARTPretty);
1052 data.fQueryStatsClass->addKey("stop", sSTOPPretty);
1053 data.fQueryStatsClass->addKey("pass", sPASSPretty);
1054 data.fQueryStatsClass->addKey("fail", sFAILPretty);
1055 data.fQueryStatsClass->addKey("status", sSTATUSPretty);
1056 data.fQueryStatsClass->addKey("user1", sUSER1Pretty);
1057 data.fQueryStatsClass->addKey("user2", sUSER2Pretty);
1058 data.fQueryStatsClass->addKey("user3", sUSER3Pretty);
1059 data.fQueryStatsClass->addKey("user4", sUSER4Pretty);
1060 data.fQueryStatsClass->addKey("user5", sUSER5Pretty);
1061 data.fQueryStatsClass->addKey("user6", sUSER6Pretty);
1062 data.fQueryStatsClass->addKey("user7", sUSER7Pretty);
1063 data.fQueryStatsClass->addKey("user8", sUSER8Pretty);
1064
1065 // Construct the map class for the marshalled PURGE request output
1066
1067 data.fPurgeStatsClass = STAFMapClassDefinition::create(
1068 "STAF/Service/Log/PurgeStats");
1069
1070 data.fPurgeStatsClass->addKey("purgedRecords", "Purged Records");
1071 data.fPurgeStatsClass->addKey("totalRecords", "Total Records");
1072
1073 // Construct the map class for the marshalled LIST SETTINGS output
1074 // for local logging
1075
1076 data.fListLocalSettingsClass = STAFMapClassDefinition::create(
1077 "STAF/Service/Log/LocalSettings");
1078
1079 data.fListLocalSettingsClass->addKey("loggingMode", "Logging Mode");
1080 data.fListLocalSettingsClass->addKey("directory", "Directory");
1081 data.fListLocalSettingsClass->addKey("maxRecordSize",
1082 "Max Record Size");
1083 data.fListLocalSettingsClass->addKey("defaultMaxQueryRecords",
1084 "Default Max Query Records");
1085 data.fListLocalSettingsClass->addKey("resolveMessage",
1086 "Resolve Message");
1087 data.fListLocalSettingsClass->addKey("resolveMessageVar",
1088 "Resolve Message Var");
1089
1090 // Construct the map class for the marshalled LIST SETTINGS output
1091 // for remote logging
1092
1093 data.fListRemoteSettingsClass = STAFMapClassDefinition::create(
1094 "STAF/Service/Log/RemoteSettings");
1095
1096 data.fListRemoteSettingsClass->addKey("loggingMode", "Logging Mode");
1097 data.fListRemoteSettingsClass->addKey("remoteLogServer",
1098 "Remote Log Server");
1099 data.fListRemoteSettingsClass->addKey("remoteLogService",
1100 "Remote Log Service");
1101
1102 // Construct map class for marshalled LIST logs/machines/handles output
1103
1104 data.fListLogsClass = STAFMapClassDefinition::create(
1105 "STAF/Service/Log/ListLogs");
1106
1107 data.fListLogsClass->addKey("logName", "Log Name");
1108 data.fListLogsClass->addKey("timestamp", "Date-Time");
1109 data.fListLogsClass->addKey("upperSize", "U-Size");
1110 data.fListLogsClass->addKey("size", "L-Size");
1111
1112 // Set service handle
1113
1114 *pServiceHandle = new LogServiceData(data);
1115
1116 return kSTAFOk;
1117 }
1118 catch (STAFException &e)
1119 { *pErrorBuffer = getExceptionString(e,
1120 "STAFLogService.cpp: STAFServiceConstruct").adoptImpl();
1121 }
1122 catch (...)
1123 {
1124 STAFString error("STAFLogService.cpp: STAFServiceConstruct: "
1125 "Caught unknown exception");
1126 *pErrorBuffer = error.adoptImpl();
1127 }
1128
1129 return kSTAFUnknownError;
1130 }
1131
1132
STAFServiceInit(STAFServiceHandle_t serviceHandle,void * pInitInfo,unsigned int initLevel,STAFString_t * pErrorBuffer)1133 STAFRC_t STAFServiceInit(STAFServiceHandle_t serviceHandle,
1134 void *pInitInfo, unsigned int initLevel,
1135 STAFString_t *pErrorBuffer)
1136 {
1137 STAFRC_t retCode = kSTAFUnknownError;
1138
1139 try
1140 {
1141 if (initLevel != 30) return kSTAFInvalidAPILevel;
1142
1143 LogServiceData *pData =
1144 reinterpret_cast<LogServiceData *>(serviceHandle);
1145
1146 STAFServiceInitLevel30 *pInfo =
1147 reinterpret_cast<STAFServiceInitLevel30 *>(pInitInfo);
1148
1149 retCode = STAFHandle::create(pData->fName, pData->fHandle);
1150
1151 if (retCode != kSTAFOk)
1152 return retCode;
1153
1154 STAFCommandParseResultPtr parsedResult =
1155 pData->fParmsParser->parse(pInfo->parms);
1156
1157 if (parsedResult->rc != kSTAFOk)
1158 {
1159 *pErrorBuffer = parsedResult->errorBuffer.adoptImpl();
1160 return parsedResult->rc;
1161 }
1162
1163 if (parsedResult->optionTimes(sENABLEREMOTELOGGING) != 0)
1164 {
1165 pData->fRLogMode = 1;
1166
1167 STAFResultPtr serverResult = resolveOpLocal(pData, parsedResult,
1168 sREMOTELOGSERVER);
1169 if (serverResult->rc != kSTAFOk)
1170 {
1171 *pErrorBuffer = serverResult->result.adoptImpl();
1172 return serverResult->rc;
1173 }
1174
1175 pData->fRemoteLogServer = serverResult->result;
1176
1177 STAFResultPtr serviceResult = resolveOpLocal(pData, parsedResult,
1178 sREMOTELOGSERVICE);
1179 if (serviceResult->rc != kSTAFOk)
1180 {
1181 *pErrorBuffer = serviceResult->result.adoptImpl();
1182 return serviceResult->rc;
1183 }
1184
1185 if (serviceResult->result.length() != 0)
1186 pData->fRemoteLogService = serviceResult->result;
1187 }
1188
1189 STAFResultPtr dirResult = resolveOpLocal(pData, parsedResult,
1190 sDIRECTORY);
1191 if (dirResult->rc != kSTAFOk)
1192 {
1193 *pErrorBuffer = dirResult->result.adoptImpl();
1194 return dirResult->rc;
1195 }
1196
1197 STAFFSPath logPath;
1198
1199 if (dirResult->result.length() == 0)
1200 {
1201 logPath.setRoot(pInfo->writeLocation);
1202 logPath.addDir("service");
1203 logPath.addDir(pData->fShortName.toLowerCase());
1204 pData->fRoot = logPath.asString();
1205 }
1206 else
1207 {
1208 pData->fRoot = dirResult->result;
1209 logPath.setRoot(pData->fRoot);
1210 }
1211
1212 // Create the log data directory if it doesn't already exist to
1213 // verify the log data directory name.
1214
1215 if (!logPath.exists())
1216 {
1217 try
1218 {
1219 STAFFSEntryPtr logdir =
1220 logPath.createDirectory(kSTAFFSCreatePath);
1221 }
1222 catch (...)
1223 {
1224 STAFString error("STAFLogService.cpp: STAFServiceInit: "
1225 "Invalid Log Directory: " + pData->fRoot);
1226 cout << error << endl;
1227 *pErrorBuffer = error.adoptImpl();
1228 return kSTAFServiceConfigurationError;
1229 }
1230 }
1231
1232 if (parsedResult->optionTimes(sMAXRECORDSIZE) != 0)
1233 {
1234 STAFResultPtr maxResult = resolveOpLocal(pData, parsedResult,
1235 sMAXRECORDSIZE);
1236
1237 if (maxResult->rc != kSTAFOk)
1238 {
1239 *pErrorBuffer = maxResult->result.adoptImpl();
1240 return maxResult->rc;
1241 }
1242
1243 // Convert resolved option string to an unsigned integer in range
1244 // 0 to UINT_MAX
1245
1246 maxResult = convertOptionStringToUInt(
1247 maxResult->result, sMAXRECORDSIZE, pData->fMaxRecordSize);
1248
1249 if (maxResult->rc != kSTAFOk)
1250 {
1251 *pErrorBuffer = maxResult->result.adoptImpl();
1252 return maxResult->rc;
1253 }
1254 }
1255
1256 if (parsedResult->optionTimes(sDEFAULTMAXQUERYRECORDS) != 0)
1257 {
1258 STAFResultPtr maxResult = resolveOpLocal(
1259 pData, parsedResult, sDEFAULTMAXQUERYRECORDS);
1260
1261 if (maxResult->rc != kSTAFOk)
1262 {
1263 *pErrorBuffer = maxResult->result.adoptImpl();
1264 return maxResult->rc;
1265 }
1266
1267 // Convert resolved option string to an unsigned integer in range
1268 // 0 to UINT_MAX
1269
1270 maxResult = convertOptionStringToUInt(
1271 maxResult->result, sDEFAULTMAXQUERYRECORDS,
1272 pData->fDefaultMaxQueryRecords);
1273
1274 if (maxResult->rc != kSTAFOk)
1275 {
1276 *pErrorBuffer = maxResult->result.adoptImpl();
1277 return maxResult->rc;
1278 }
1279 }
1280
1281 if (parsedResult->optionTimes(sRESOLVEMESSAGE) != 0)
1282 pData->fDefaultResolveMessage = 1;
1283 else if (parsedResult->optionTimes(sNORESOLVEMESSAGE) != 0)
1284 pData->fDefaultResolveMessage = 0;
1285
1286 if (parsedResult->optionTimes(sENABLERESOLVEMESSAGEVAR) != 0)
1287 pData->fUseResolveMessageVar = 1;
1288 else if (parsedResult->optionTimes(sDISABLERESOLVEMESSAGEVAR) != 0)
1289 pData->fUseResolveMessageVar = 0;
1290
1291 // Get the default authenticator
1292
1293 STAFResultPtr resResult = pData->fHandle->submit(
1294 sLocal, sVar, sDefAuthString);
1295
1296 if (resResult->rc != kSTAFOk)
1297 {
1298 *pErrorBuffer = resResult->result.adoptImpl();
1299 return resResult->rc;
1300 }
1301
1302 pData->fDefaultAuthenticator = resResult->result;
1303
1304 // Get the machine name for the local machine
1305
1306 resResult = pData->fHandle->submit(sLocal, sVar, sResMachineString);
1307
1308 if (resResult->rc != kSTAFOk)
1309 {
1310 *pErrorBuffer = resResult->result.adoptImpl();
1311 return resResult->rc;
1312 }
1313
1314 pData->fLocalMachineName = resResult->result;
1315
1316 // Get the line separator
1317
1318 resResult = pData->fHandle->submit(sLocal, sVar, sEOLString);
1319
1320 if (resResult->rc != kSTAFOk)
1321 {
1322 *pErrorBuffer = resResult->result.adoptImpl();
1323 return resResult->rc;
1324 }
1325
1326 sLineSep = resResult->result;
1327
1328 // Assign the help text string for the service
1329
1330 sHelpMsg = STAFString("*** ") + pData->fShortName + " Service Help ***" +
1331 sLineSep + sLineSep +
1332 "LOG <GLOBAL | MACHINE | HANDLE> LOGNAME <Logname> LEVEL <Level>" +
1333 sLineSep +
1334 " MESSAGE <Message> [RESOLVEMESSAGE | NORESOLVEMESSAGE]" +
1335 sLineSep + sLineSep +
1336 "QUERY <GLOBAL | MACHINE <Machine> [HANDLE <Handle>]> LOGNAME <Logname>" +
1337 sLineSep +
1338 " [LEVELMASK <Mask>] [QMACHINE <Machine>]... " +
1339 "[QHANDLE <Handle>]..." +
1340 sLineSep +
1341 " [NAME <Name>]... [USER <User>]... [ENDPOINT <Endpoint>]..." +
1342 sLineSep +
1343 " [CONTAINS <String>]... [CSCONTAINS <String>]..." +
1344 sLineSep +
1345 " [STARTSWITH <String>]... [CSSTARTSWITH <String>]..." +
1346 sLineSep +
1347 " [FROM <Timestamp> | AFTER <Timestamp>]" +
1348 sLineSep +
1349 " [BEFORE <Timestamp> | TO <Timestamp>]" +
1350 sLineSep +
1351 " [FROMRECORD <Num>] [TORECORD <Num>]" +
1352 sLineSep +
1353 " [FIRST <Num> | LAST <Num> | ALL] [TOTAL | STATS | LONG]" +
1354 sLineSep +
1355 " [LEVELBITSTRING]" +
1356 sLineSep + sLineSep +
1357 "LIST GLOBAL | MACHINES | MACHINE <Machine> [HANDLES | HANDLE <Handle>] |" +
1358 sLineSep +
1359 " SETTINGS" +
1360 sLineSep + sLineSep +
1361 "DELETE <GLOBAL | MACHINE <Machine> [HANDLE <Handle>]>" +
1362 sLineSep +
1363 " LOGNAME <Logname> CONFIRM" +
1364 sLineSep + sLineSep +
1365 "PURGE <GLOBAL | MACHINE <Machine> [HANDLE <Handle>]> LOGNAME <Logname>" +
1366 sLineSep +
1367 " CONFIRM | CONFIRMALL" +
1368 sLineSep +
1369 " [LEVELMASK <Mask>] [QMACHINE <Machine>]... [QHANDLE <Handle>]..." +
1370 sLineSep +
1371 " [NAME <Name>]... [USER <User>]... [ENDPOINT <Endpoint>]..." +
1372 sLineSep +
1373 " [CONTAINS <String>]... [CSCONTAINS <String>]..." +
1374 sLineSep +
1375 " [STARTSWITH <String>]... [CSSTARTSWITH <String>]..." +
1376 sLineSep +
1377 " [FROM <Timestamp> | AFTER <Timestamp>]" +
1378 sLineSep +
1379 " [BEFORE <Timestamp> | TO <Timestamp>]" +
1380 sLineSep +
1381 " [FROMRECORD <Num>] [TORECORD <Num>]" +
1382 sLineSep +
1383 " [FIRST <Num> | LAST <Num>]" +
1384 sLineSep + sLineSep +
1385 "SET [MAXRECORDSIZE <Size>] [DEFAULTMAXQUERYRECORDS <Number>]" +
1386 sLineSep +
1387 " [ENABLERESOLVEMESSAGEVAR | DISABLERESOLVEMESSAGEVAR]" +
1388 sLineSep +
1389 " [RESOLVEMESSAGE | NORESOLVEMESSAGE]" +
1390 sLineSep + sLineSep +
1391 "VERSION" +
1392 sLineSep + sLineSep +
1393 "HELP";
1394
1395 // Register help for the error codes for this service
1396
1397 registerHelpData(pData, kSTAFLogInvalidLevel,
1398 STAFString("Invalid level"),
1399 STAFString("An invalid logging level was specified. "
1400 "See the STAF User's Guide for a complete list of "
1401 "logging levels."));
1402
1403 registerHelpData(pData, kSTAFLogInvalidFileFormat,
1404 STAFString("Invalid file format"),
1405 STAFString("An invalid/unknown record format was encountered "
1406 "while reading the log file"));
1407
1408 registerHelpData(pData, kSTAFLogPurgeFailure,
1409 STAFString("Unable to purge all log records"),
1410 STAFString("Your purge criteria selected every record in the log "
1411 "file. Use CONFIRMALL instead of CONFIRM if you "
1412 "really want to delete every record (or submit a "
1413 "DELETE request). Or, modify your purge criteria."));
1414
1415 registerHelpData(pData, kSTAFLogExceededDefaultMaxRecords,
1416 STAFString("Exceeded default maximum query records"),
1417 STAFString("Your query criteria selected more records than "
1418 "allowed by the DefaultMaxQueryRecords setting. "
1419 "Use the FIRST <Num> or LAST <Num> option to specify "
1420 "the number of records or the ALL option if you "
1421 "really want all of the records."));
1422 }
1423 catch (STAFException &e)
1424 {
1425 *pErrorBuffer = getExceptionString(e,
1426 "STAFLogService.cpp: STAFServiceInit").adoptImpl();
1427 }
1428 catch (...)
1429 {
1430 STAFString error("STAFLogService.cpp: STAFServiceInit: "
1431 "Caught unknown exception");
1432 *pErrorBuffer = error.adoptImpl();
1433 }
1434
1435 return retCode;
1436 }
1437
1438
STAFServiceAcceptRequest(STAFServiceHandle_t serviceHandle,void * pRequestInfo,unsigned int reqLevel,STAFString_t * pResultBuffer)1439 STAFRC_t STAFServiceAcceptRequest(STAFServiceHandle_t serviceHandle,
1440 void *pRequestInfo, unsigned int reqLevel,
1441 STAFString_t *pResultBuffer)
1442 {
1443 if (reqLevel != 30) return kSTAFInvalidAPILevel;
1444
1445 STAFRC_t retCode = kSTAFUnknownError;
1446
1447 try
1448 {
1449 STAFResultPtr result(new STAFResult(), STAFResultPtr::INIT);
1450
1451 STAFServiceRequestLevel30 *pInfo =
1452 reinterpret_cast<STAFServiceRequestLevel30 *>(pRequestInfo);
1453
1454 LogServiceData *pData =
1455 reinterpret_cast<LogServiceData *>(serviceHandle);
1456
1457 STAFString request(pInfo->request);
1458 STAFString action = request.subWord(0, 1).toUpperCase();
1459
1460 if (pData->fRLogMode != 0)
1461 {
1462 if (action == sLOG) result = handleRemoteLog(pInfo, pData);
1463 else if (action == sVERSION)
1464 {
1465 result = STAFResultPtr(new STAFResult(kSTAFOk, sVersionInfo),
1466 STAFResultPtr::INIT);
1467 }
1468 else if ((action == sLIST) &&
1469 (request.subWord(1, 2).toUpperCase() == sSETTINGS))
1470 {
1471 result = handleList(pInfo, pData);
1472 }
1473 else result = handleRemoteLogGeneral(pInfo, pData);
1474 }
1475 else if (action == sLOG) result = handleLog(pInfo, pData);
1476 else if (action == sQUERY) result = handleQuery(pInfo, pData);
1477 else if (action == sLIST) result = handleList(pInfo, pData);
1478 else if (action == sDELETE) result = handleDelete(pInfo, pData);
1479 else if (action == sPURGE) result = handlePurge(pInfo, pData);
1480 else if (action == sSET) result = handleSet(pInfo, pData);
1481 else if (action == sHELP) result = handleHelp(pInfo, pData);
1482 else if (action == sVERSION)
1483 {
1484 result = STAFResultPtr(new STAFResult(kSTAFOk, sVersionInfo),
1485 STAFResultPtr::INIT);
1486 }
1487 else
1488 {
1489 STAFString errMsg = STAFString("'") + request.subWord(0, 1) +
1490 "' is not a valid command request for the " +
1491 pData->fShortName + " service" + sLineSep + sLineSep +
1492 sHelpMsg;
1493
1494 result = STAFResultPtr(new STAFResult(
1495 kSTAFInvalidRequestString, errMsg), STAFResultPtr::INIT);
1496 }
1497
1498 *pResultBuffer = result->result.adoptImpl();
1499 retCode = result->rc;
1500 }
1501 catch (STAFException &e)
1502 {
1503 retCode = e.getErrorCode();
1504
1505 *pResultBuffer = getExceptionString(
1506 e, "STAFLogService.cpp: STAFServiceAcceptRequest").adoptImpl();
1507 }
1508 catch (...)
1509 {
1510 STAFString error("STAFLogService.cpp: STAFServiceAcceptRequest: "
1511 "Caught unknown exception");
1512 *pResultBuffer = error.adoptImpl();
1513 }
1514
1515 return retCode;
1516 }
1517
1518
STAFServiceTerm(STAFServiceHandle_t serviceHandle,void * pTermInfo,unsigned int termLevel,STAFString_t * pErrorBuffer)1519 STAFRC_t STAFServiceTerm(STAFServiceHandle_t serviceHandle, void *pTermInfo,
1520 unsigned int termLevel, STAFString_t *pErrorBuffer)
1521 {
1522 if (termLevel != 0) return kSTAFInvalidAPILevel;
1523
1524 STAFRC_t retCode = kSTAFUnknownError;
1525
1526 try
1527 {
1528 retCode = kSTAFOk;
1529
1530 LogServiceData *pData =
1531 reinterpret_cast<LogServiceData *>(serviceHandle);
1532
1533 // Un-register Help Data
1534
1535 unregisterHelpData(pData, kSTAFLogInvalidLevel);
1536 unregisterHelpData(pData, kSTAFLogInvalidFileFormat);
1537 unregisterHelpData(pData, kSTAFLogPurgeFailure);
1538 }
1539 catch (STAFException &e)
1540 {
1541 *pErrorBuffer = getExceptionString(e,
1542 "STAFLogService.cpp: STAFServiceTerm").adoptImpl();
1543 }
1544 catch (...)
1545 {
1546 STAFString error("STAFLogService.cpp: STAFServiceTerm: "
1547 "Caught unknown exception");
1548 *pErrorBuffer = error.adoptImpl();
1549 }
1550
1551 return retCode;
1552 }
1553
1554
STAFServiceDestruct(STAFServiceHandle_t * serviceHandle,void * pDestructInfo,unsigned int destructLevel,STAFString_t * pErrorBuffer)1555 STAFRC_t STAFServiceDestruct(STAFServiceHandle_t *serviceHandle,
1556 void *pDestructInfo, unsigned int destructLevel,
1557 STAFString_t *pErrorBuffer)
1558 {
1559 if (destructLevel != 0) return kSTAFInvalidAPILevel;
1560
1561 STAFRC_t retCode = kSTAFUnknownError;
1562
1563 try
1564 {
1565 LogServiceData *pData =
1566 reinterpret_cast<LogServiceData *>(*serviceHandle);
1567 delete pData;
1568 *serviceHandle = 0;
1569
1570 retCode = kSTAFOk;
1571 }
1572 catch (STAFException &e)
1573 {
1574 *pErrorBuffer = getExceptionString(e,
1575 "STAFLogService.cpp: STAFServiceDestruct").adoptImpl();
1576 }
1577 catch (...)
1578 {
1579 STAFString error("STAFLogService.cpp: STAFServiceDestruct: "
1580 "Caught unknown exception");
1581 *pErrorBuffer = error.adoptImpl();
1582 }
1583
1584 return retCode;
1585 }
1586
1587
handleLog(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)1588 STAFResultPtr handleLog(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData)
1589 {
1590 // XXX: This routine in particular has serious issues when we add the
1591 // ability to resolve remote handle variables. It relies on functions
1592 // which assume that the requestor is in the pInfo structure, which it
1593 // may not be if we are a remote log server.
1594
1595 INIT_TIMES();
1596 RECORD_TIME("Parsing");
1597
1598 STAFCommandParseResultPtr parsedResult =
1599 pData->fLogParser->parse(pInfo->request);
1600
1601 if (parsedResult->rc != kSTAFOk)
1602 {
1603 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
1604 parsedResult->errorBuffer), STAFResultPtr::INIT);
1605 }
1606
1607 RECORD_TIME("Check trust");
1608
1609 // Verify that the requesting machine/user has at least trust level 3
1610
1611 if (parsedResult->optionTimes(sRMTMACHINE) == 0)
1612 {
1613 VALIDATE_TRUST(3, pData->fShortName, "LOG", pData->fLocalMachineName);
1614 }
1615 else
1616 {
1617 // Verify that the remote log machine/user has at least trust level 3
1618
1619 STAFString trustRequest(
1620 sGetMachine + parsedResult->optionValue(sRMTMACHINE) +
1621 sGetUser + parsedResult->optionValue(sRMTUSER));
1622
1623 STAFResultPtr trustResult = pData->fHandle->submit(
1624 sLocal, sTrust, trustRequest);
1625
1626 if (trustResult->rc != kSTAFOk)
1627 {
1628 STAFString errorMsg = STAFString(
1629 "Verifying that the remote log machine/user has at least "
1630 "trust level 3 failed. STAF local TRUST ") + trustRequest +
1631 " failed with RC: " + trustResult->rc +
1632 ", Result: " + trustResult->result;
1633
1634 return STAFResultPtr(
1635 new STAFResult(trustResult->rc, errorMsg),
1636 STAFResultPtr::INIT);
1637 }
1638
1639 try
1640 {
1641 unsigned int trustLevel = trustResult->result.asUInt();
1642
1643 VALIDATE_TRUST3(3, pData->fShortName, "LOG",
1644 pData->fLocalMachineName, trustLevel,
1645 parsedResult->optionValue(sRMTMACHINE), "",
1646 parsedResult->optionValue(sRMTUSER));
1647 }
1648 catch (STAFException)
1649 {
1650 STAFString errorMsg = STAFString(
1651 "Verifying that the remote log machine/user has at least "
1652 "trust level 3 failed. STAF local TRUST ") + trustRequest +
1653 " did not return a numeric trust level, Result: " +
1654 trustResult->result;
1655
1656 return STAFResultPtr(
1657 new STAFResult(kSTAFAccessDenied, errorMsg),
1658 STAFResultPtr::INIT);
1659 }
1660 }
1661
1662 // Get log level and log mask and see if we should log
1663
1664 RECORD_TIME("Check log level");
1665
1666 STAFResultPtr levelResult = resolveOp(pInfo, pData, parsedResult, sLEVEL);
1667
1668 if (levelResult->rc != kSTAFOk) return levelResult;
1669
1670 unsigned int logLevel = 0;
1671
1672 if (!isValidLogLevel(levelResult->result, logLevel))
1673 {
1674 return STAFResultPtr(new STAFResult(kSTAFLogInvalidLevel,
1675 levelResult->result),
1676 STAFResultPtr::INIT);
1677 }
1678
1679 STAFResultPtr logmaskResult = resolveStr(pInfo, pData,
1680 pData->fResolveLogMaskString);
1681 if ((logmaskResult->rc != kSTAFOk) &&
1682 (logmaskResult->rc != kSTAFVariableDoesNotExist))
1683 {
1684 return logmaskResult;
1685 }
1686
1687 if (logmaskResult->rc == kSTAFVariableDoesNotExist)
1688 logmaskResult->result = sEverythingLogMask;
1689
1690 unsigned int logMask = 0;
1691
1692 if (!convertLogMaskToUInt(logmaskResult->result, logMask))
1693 {
1694 return STAFResultPtr(new STAFResult(kSTAFLogInvalidLevel,
1695 logmaskResult->result),
1696 STAFResultPtr::INIT);
1697 }
1698
1699 if (!(logLevel & logMask))
1700 return STAFResultPtr(new STAFResult, STAFResultPtr::INIT);
1701
1702 // Get logname and message
1703
1704 RECORD_TIME("Get logname and message");
1705
1706 STAFResultPtr lognameResult = resolveOp(pInfo, pData, parsedResult,
1707 sLOGNAME);
1708
1709 if (lognameResult->rc != kSTAFOk) return lognameResult;
1710
1711 // if the user specifies to resolve messages or
1712 // STAF/Service/Log/ResolveMessage is enabled and set or
1713 // the default is to resolve messages and the user didn't say not to
1714 // then resolve the message
1715
1716 STAFString message = parsedResult->optionValue(sMESSAGE);
1717 unsigned int resolveMessage = pData->fDefaultResolveMessage;
1718
1719 if (parsedResult->optionTimes(sRESOLVEMESSAGE) != 0)
1720 {
1721 resolveMessage = 1;
1722 }
1723 else if (parsedResult->optionTimes(sNORESOLVEMESSAGE) != 0)
1724 {
1725 resolveMessage = 0;
1726 }
1727 else if (pData->fUseResolveMessageVar != 0)
1728 {
1729 STAFResultPtr resolveResult = resolveStr(pInfo, pData,
1730 pData->fResolveMessageString);
1731 if (resolveResult->rc == kSTAFOk)
1732 {
1733 try
1734 {
1735 if (resolveResult->result.asUInt() != 0)
1736 resolveMessage = 1;
1737 else
1738 resolveMessage = 0;
1739 }
1740 catch (STAFException)
1741 {
1742 STAFString errorMsg = STAFString("The resolved value for ") +
1743 pData->fResolveMessageString + " must be 0 or 1. "
1744 "Invalid value: " + resolveResult->result;
1745
1746 return STAFResultPtr(
1747 new STAFResult(kSTAFInvalidValue, errorMsg),
1748 STAFResultPtr::INIT);
1749 }
1750 }
1751 else if (resolveResult->rc != kSTAFVariableDoesNotExist)
1752 {
1753 return resolveResult;
1754 }
1755 }
1756
1757 if (resolveMessage != 0)
1758 {
1759 STAFResultPtr messageResult = resolveOp(
1760 pInfo, pData, parsedResult, sMESSAGE);
1761
1762 if (messageResult->rc != kSTAFOk) return messageResult;
1763
1764 message = messageResult->result;
1765 }
1766
1767 if (message.length(STAFString::kChar) > pData->fMaxRecordSize)
1768 message = message.subString(0, pData->fMaxRecordSize, STAFString::kChar);
1769
1770 // Check for remote logging info
1771
1772 RECORD_TIME("Check for remote");
1773
1774 bool isRemote = false;
1775 STAFString remoteMachine;
1776 STAFString remoteHandleName;
1777 STAFString remoteHandle;
1778 STAFString remoteUser;
1779 STAFString remoteLogicalMachine;
1780 STAFString remoteNickname;
1781
1782 if (parsedResult->optionTimes(sRMTMACHINE) != 0)
1783 {
1784 isRemote = true;
1785 remoteMachine = parsedResult->optionValue(sRMTMACHINE);
1786 remoteHandleName = parsedResult->optionValue(sRMTNAME);
1787 remoteHandle = parsedResult->optionValue(sRMTHANDLE);
1788 remoteUser = parsedResult->optionValue(sRMTUSER);
1789 remoteLogicalMachine = parsedResult->optionValue(sRMTMACH);
1790 remoteNickname = parsedResult->optionValue(sRMTNICKNAME);
1791 }
1792
1793 // Setup/Create the path
1794
1795 RECORD_TIME("Create path");
1796
1797 STAFFSPath logfilePath;
1798
1799 logfilePath.setRoot(pData->fRoot);
1800
1801 if (parsedResult->optionTimes(sGLOBAL) != 0)
1802 {
1803 logfilePath.addDir(sGLOBAL);
1804 }
1805 else
1806 {
1807 logfilePath.addDir(sMACHINE);
1808
1809 if (isRemote)
1810 logfilePath.addDir(remoteNickname);
1811 else
1812 logfilePath.addDir(pInfo->machineNickname);
1813
1814 if (parsedResult->optionTimes(sMACHINE) != 0)
1815 {
1816 logfilePath.addDir(sGLOBAL);
1817 }
1818 else
1819 {
1820 logfilePath.addDir(sHANDLE);
1821
1822 if (isRemote)
1823 logfilePath.addDir(remoteHandle);
1824 else
1825 logfilePath.addDir(pInfo->handle);
1826 }
1827 }
1828
1829 if (!logfilePath.exists())
1830 {
1831 try
1832 {
1833 // XXX: Don't want exceptions here
1834 STAFFSEntryPtr logdir =
1835 logfilePath.createDirectory(kSTAFFSCreatePath);
1836 }
1837 catch (...)
1838 { /* Do Nothing */ }
1839 }
1840
1841 logfilePath.setName(lognameResult->result);
1842 logfilePath.setExtension(sLogExt);
1843
1844 // Must get lock before opening file to avoid log corruption problem
1845 // with multiple simultaneous read/writes to same log.
1846
1847 // Get a write lock on the global Read/Write Semaphore
1848
1849 RECORD_TIME("Get and lock entry");
1850
1851 STAFLogFileLocksPtr logLocks =
1852 STAFLogFileLocks::acquireLocks(logfilePath.asString());
1853 STAFRWSemRLock accessLock(*logLocks->logAccess);
1854 STAFMutexSemLock recordLock(*logLocks->recordAccess);
1855
1856 // Open the log file
1857
1858 RECORD_TIME("Open log file");
1859
1860 fstream logfile(logfilePath.asString().toCurrentCodePage()->buffer(),
1861 ios::out | ios::app | STAF_ios_binary);
1862
1863 if (!logfile)
1864 {
1865 return STAFResultPtr(new STAFResult(kSTAFFileOpenError,
1866 logfilePath.asString()),
1867 STAFResultPtr::INIT);
1868 }
1869
1870 // Write the log file data
1871
1872 RECORD_TIME("Write log record");
1873
1874 STAFTimestamp currTimestamp;
1875
1876 LogRecord logRecord(currTimestamp.asDateString().asUInt(),
1877 currTimestamp.asSecondsPastMidnight(), logLevel,
1878 pInfo->machine, pInfo->handleName, pInfo->handle,
1879 pInfo->user, pInfo->endpoint, message);
1880
1881 if (isRemote)
1882 {
1883 logRecord.machine = remoteLogicalMachine;
1884 logRecord.handle = remoteHandle.asUIntWithDefault(0);
1885 logRecord.handleName = remoteHandleName;
1886 logRecord.user = remoteUser;
1887 logRecord.endpoint = remoteMachine;
1888 }
1889
1890 writeLogRecordToFile(logfile, logRecord);
1891
1892 RECORD_TIME("Log complete (except for file close)");
1893 OUTPUT_TIMES();
1894
1895 return STAFResultPtr(new STAFResult, STAFResultPtr::INIT);
1896 }
1897
1898
handleQuery(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)1899 STAFResultPtr handleQuery(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData)
1900 {
1901 STAFCommandParseResultPtr parsedResult =
1902 pData->fQueryParser->parse(pInfo->request);
1903
1904 if (parsedResult->rc != kSTAFOk)
1905 {
1906 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
1907 parsedResult->errorBuffer), STAFResultPtr::INIT);
1908 }
1909
1910 if (parsedResult->optionTimes(sRMTMACHINE) == 0)
1911 {
1912 // Verify that the requesting machine/user has at least trust level 2
1913
1914 VALIDATE_TRUST(2, pData->fShortName, "QUERY", pData->fLocalMachineName);
1915 }
1916 else
1917 {
1918 // Verify that the remote log machine/user has at least trust level 2
1919
1920 STAFString trustRequest(
1921 sGetMachine + parsedResult->optionValue(sRMTMACHINE) +
1922 sGetUser + parsedResult->optionValue(sRMTUSER));
1923
1924 STAFResultPtr trustResult = pData->fHandle->submit(
1925 sLocal, sTrust, trustRequest);
1926
1927 if (trustResult->rc != kSTAFOk)
1928 {
1929 STAFString errorMsg = STAFString(
1930 "Verifying that the remote log machine/user has at least "
1931 "trust level 2 failed. STAF local TRUST ") + trustRequest +
1932 " failed with RC: " + trustResult->rc +
1933 ", Result: " + trustResult->result;
1934
1935 return STAFResultPtr(
1936 new STAFResult(trustResult->rc, errorMsg),
1937 STAFResultPtr::INIT);
1938 }
1939
1940 try
1941 {
1942 unsigned int trustLevel = trustResult->result.asUInt();
1943
1944 VALIDATE_TRUST3(2, pData->fShortName, "QUERY",
1945 pData->fLocalMachineName, trustLevel,
1946 parsedResult->optionValue(sRMTMACHINE), "",
1947 parsedResult->optionValue(sRMTUSER));
1948 }
1949 catch (STAFException)
1950 {
1951 STAFString errorMsg = STAFString(
1952 "Verifying that the remote log machine/user has at least "
1953 "trust level 2 failed. STAF local TRUST ") + trustRequest +
1954 " did not return a numeric trust level, Result: " +
1955 trustResult->result;
1956
1957 return STAFResultPtr(
1958 new STAFResult(kSTAFAccessDenied, errorMsg),
1959 STAFResultPtr::INIT);
1960 }
1961 }
1962
1963 // Build up the log filter criteria
1964
1965 STAFResultPtr errorResult;
1966 LogRecordFilter logFilter;
1967 LogStats logStats = { 0 };
1968
1969 if (!updateQueryPurgeLogFilter(logFilter, errorResult, pInfo, pData,
1970 parsedResult))
1971 {
1972 return errorResult;
1973 }
1974
1975 // See if they specified LEVELBITSTRING or STATS or TOTAL
1976
1977 bool levelAsBits = (parsedResult->optionTimes(sLEVELBITSTRING) > 0) ?
1978 true : false;
1979 bool onlyStats = (parsedResult->optionTimes(sSTATS) > 0) ? true : false;
1980 bool onlyTotal = (parsedResult->optionTimes(sTOTAL) > 0) ? true : false;
1981 bool longFormat = (parsedResult->optionTimes(sLONG) > 0) ? true : false;
1982
1983 unsigned int first = 0;
1984 unsigned int last = 0;
1985 bool all = false;
1986
1987 // Check if they specified FIRST or LAST or ALL
1988
1989 if (parsedResult->optionTimes(sFIRST))
1990 {
1991 STAFResultPtr result = resolveOp(
1992 pInfo, pData, parsedResult, sFIRST);
1993
1994 if (result->rc != kSTAFOk) return result;
1995
1996 // Convert resolved option string to an unsigned integer in range 0
1997 // to UINT_MAX
1998
1999 result = convertOptionStringToUInt(result->result, sFIRST, first);
2000
2001 if (result->rc != kSTAFOk) return result;
2002 }
2003 else if (parsedResult->optionTimes(sLAST))
2004 {
2005 STAFResultPtr result = resolveOp(
2006 pInfo, pData, parsedResult, sLAST);
2007
2008 if (result->rc != kSTAFOk) return result;
2009
2010 // Convert resolved option string to an unsigned integer in range 0
2011 // to UINT_MAX
2012
2013 result = convertOptionStringToUInt(result->result, sLAST, last);
2014
2015 if (result->rc != kSTAFOk) return result;
2016 }
2017 else if (parsedResult->optionTimes(sALL))
2018 {
2019 all = true;
2020 }
2021
2022 bool useFromRecord = false;
2023 unsigned int fromRecord = 0;
2024 bool useToRecord = false;
2025 unsigned int toRecord = 0;
2026
2027 if (parsedResult->optionTimes(sFROMRECORD) != 0)
2028 {
2029 STAFResultPtr result = resolveOp(
2030 pInfo, pData, parsedResult, sFROMRECORD);
2031
2032 if (result->rc != kSTAFOk) return result;
2033
2034 // Convert resolved option string to an unsigned integer in range 1
2035 // to UINT_MAX
2036
2037 result = convertOptionStringToUInt(
2038 result->result, sFROMRECORD, fromRecord, 1);
2039
2040 if (result->rc != kSTAFOk) return result;
2041
2042 useFromRecord = true;
2043 }
2044
2045 if (parsedResult->optionTimes(sTORECORD) != 0)
2046 {
2047 STAFResultPtr result = resolveOp(
2048 pInfo, pData, parsedResult, sTORECORD);
2049
2050 if (result->rc != kSTAFOk) return result;
2051
2052 // Convert resolved option string to an unsigned integer in range 1
2053 // to UINT_MAX
2054
2055 result = convertOptionStringToUInt(
2056 result->result, sTORECORD, toRecord, 1);
2057
2058 if (result->rc != kSTAFOk) return result;
2059
2060 useToRecord = true;
2061 }
2062
2063 if (useToRecord && useFromRecord && (fromRecord > toRecord))
2064 {
2065 STAFString errorMsg = STAFString("FROMRECORD value must be <= ") +
2066 "TORECORD value. FROMRECORD: " + STAFString(fromRecord) +
2067 ", TORECORD: " + STAFString(toRecord);
2068 return STAFResultPtr(new STAFResult(kSTAFInvalidValue, errorMsg),
2069 STAFResultPtr::INIT);
2070
2071 }
2072
2073 // Get the log file path
2074
2075 STAFFSPath logfilePath;
2076
2077 if (!generateQueryPurgeDeleteLogFilePath(logfilePath, errorResult,
2078 pInfo, pData, parsedResult))
2079 {
2080 return errorResult;
2081 }
2082
2083 // Open the log file
2084
2085 if (!logfilePath.exists())
2086 {
2087 return STAFResultPtr(new STAFResult(kSTAFDoesNotExist,
2088 logfilePath.name()),
2089 STAFResultPtr::INIT);
2090 }
2091
2092 fstream logfile(logfilePath.asString().toCurrentCodePage()->buffer(),
2093 ios::in | STAF_ios_binary);
2094
2095 if (!logfile)
2096 {
2097 return STAFResultPtr(new STAFResult(kSTAFFileOpenError,
2098 logfilePath.asString()),
2099 STAFResultPtr::INIT);
2100 }
2101
2102 // Determine if should return an error and limit number of records if the
2103 // number of records matching the query criteria exceeds the default
2104 // maximum query records.
2105
2106 bool limitRecords = false;
2107
2108 if ((pData->fDefaultMaxQueryRecords != 0) && (!all) &&
2109 (first == 0) && (last == 0) && (!onlyTotal) && (!onlyStats))
2110 {
2111 limitRecords = true;
2112 last = pData->fDefaultMaxQueryRecords;
2113 }
2114
2115 STAFRC_t rc = kSTAFOk;
2116
2117 // Create the marshalling context
2118 STAFObjectPtr mc = STAFObject::createMarshallingContext();
2119
2120 // Create an empty list object for the marshalled list of log records
2121 STAFObjectPtr logList = STAFObject::createList();
2122
2123 // Set the log record map class definition pointer
2124
2125 STAFMapClassDefinitionPtr mapClassPtr = pData->fLogRecordClass->
2126 reference();
2127
2128 if (longFormat)
2129 mapClassPtr = pData->fLogRecordLongClass->reference();
2130
2131 // Get a read lock on the global Read/Write Semaphore
2132
2133 STAFLogFileLocksPtr logLocks =
2134 STAFLogFileLocks::acquireLocks(logfilePath.asString());
2135 STAFRWSemRLock accessLock(*logLocks->logAccess);
2136
2137 // Read each record
2138
2139 const int RECORDS_PER_LOCK = 100;
2140 unsigned int currFirstRecords = 0;
2141 STAFString result = STAFString();
2142 unsigned int totalRecords = 0;
2143 LogRecord logRecord;
2144
2145 // If LAST option is specified, use a FIFO queue to store the last <nnn>
2146 // log records. A std::queue uses a deque as the default container and
2147 // provides better performance than a list for large LAST values
2148 std::queue<LogRecord> lastLogRecordsQueue;
2149
2150 // Record number counter (used to compare with fromRecord and toRecord)
2151 // and to know which record number is currently being processed.
2152 unsigned int recordNum = 0;
2153
2154 // Flag to use to indicate if don't need to process any more records
2155 bool done = false;
2156
2157 while (!logfile.eof() && !done)
2158 {
2159 STAFMutexSemLock recordLock(*logLocks->recordAccess);
2160
2161 for (int recordCount = 0;
2162 (recordCount < RECORDS_PER_LOCK) && !logfile.eof();
2163 ++recordCount)
2164 {
2165 recordNum++;
2166
2167 // First, get the information from the log record
2168
2169 unsigned int status = readLogRecordFromFile(
2170 logfile, logRecord, recordNum);
2171
2172 if (status == kReadLogEndOfFile)
2173 {
2174 // Finish up with whatever needs to be done
2175 continue;
2176 }
2177 else if (status == kReadLogInvalidFormat)
2178 {
2179 // Invalid log record format. Cannot continue.
2180
2181 STAFString errorMsg = STAFString(
2182 "Invalid record format in record number ") + recordNum +
2183 " with format ID " + logRecord.recordFormatID;
2184
2185 return STAFResultPtr(
2186 new STAFResult(kSTAFLogInvalidFileFormat, errorMsg),
2187 STAFResultPtr::INIT);
2188 }
2189
2190 // Now, make sure this record meets the selection criteria
2191
2192 if (useFromRecord)
2193 {
2194 if (recordNum < fromRecord)
2195 {
2196 // Ignore this log record
2197 continue;
2198 }
2199 }
2200
2201 if (useToRecord)
2202 {
2203 if (recordNum > toRecord)
2204 {
2205 // Don't need to process any more log records
2206 done = true;
2207 break;
2208 }
2209 }
2210
2211 // XXX: Might want to make a change to stop once we reach the
2212 // BEFORE / TO date
2213
2214 if (!logRecordMatchesFilter(logRecord, logFilter,
2215 pData->fDefaultAuthenticator))
2216 {
2217 continue;
2218 }
2219
2220 // Now, do whatever we are supposed to with the record
2221
2222 /* DEBUG: printLogRecord(logRecord); */
2223
2224 if (last > 0)
2225 {
2226 // Make sure we only keep 'last' number of records
2227 if (lastLogRecordsQueue.size() == last)
2228 {
2229 lastLogRecordsQueue.pop();
2230
2231 // ???-CVR: This check seems odd. The user seems to have
2232 // explicitly told us how many records they want,
2233 // but if they've also told us some maximum
2234 // number of records, then we return an error.
2235 // Seems like we need to see if they've actually
2236 // exceeded the limit before returning this error.
2237
2238 if (limitRecords) rc = kSTAFLogExceededDefaultMaxRecords;
2239 }
2240
2241 lastLogRecordsQueue.push(logRecord);
2242 }
2243 else
2244 {
2245 if (onlyTotal)
2246 {
2247 ++totalRecords;
2248 }
2249 else if (onlyStats)
2250 {
2251 updateLogStats(logStats, logRecord.logLevel);
2252 }
2253 else
2254 {
2255 addLogRecordToList(logList, mapClassPtr, logRecord,
2256 levelAsBits, longFormat);
2257 }
2258
2259 if ((first > 0) && (++currFirstRecords >= first))
2260 {
2261 // Don't need to process any more log records
2262 done = true;
2263 break;
2264 }
2265 }
2266 }
2267 }
2268
2269 // If we were doing the "last" set of things, we now need to generate
2270 // the output or update the stats
2271
2272 if (last > 0)
2273 {
2274 while (!lastLogRecordsQueue.empty())
2275 {
2276 if (onlyTotal) ++totalRecords;
2277 else if (onlyStats)
2278 {
2279 logRecord = lastLogRecordsQueue.front();
2280 updateLogStats(logStats, logRecord.logLevel);
2281 }
2282 else
2283 {
2284 logRecord = lastLogRecordsQueue.front();
2285 addLogRecordToList(logList, mapClassPtr, logRecord,
2286 levelAsBits, longFormat);
2287 }
2288
2289 lastLogRecordsQueue.pop();
2290 }
2291 }
2292
2293 if (onlyTotal)
2294 {
2295 result = STAFString(totalRecords);
2296 }
2297 else if (onlyStats)
2298 {
2299 // Create a map object for the marshalled map of log stats
2300
2301 STAFObjectPtr queryStatsMap =
2302 pData->fQueryStatsClass->createInstance();
2303
2304 addLogStatsToMap(queryStatsMap, logStats);
2305
2306 // Set the marshalling context map class definitions and root object
2307
2308 mc->setMapClassDefinition(pData->fQueryStatsClass->reference());
2309 mc->setRootObject(queryStatsMap);
2310
2311 result = mc->marshall();
2312 }
2313 else
2314 {
2315 // Set the marshalling context map class definitions and root object
2316
2317 mc->setMapClassDefinition(mapClassPtr->reference());
2318 mc->setRootObject(logList);
2319
2320 result = mc->marshall();
2321 }
2322
2323 return STAFResultPtr(new STAFResult(rc, result), STAFResultPtr::INIT);
2324 }
2325
2326
handleList(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)2327 STAFResultPtr handleList(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData)
2328 {
2329 STAFCommandParseResultPtr parsedResult =
2330 pData->fListParser->parse(pInfo->request);
2331
2332 if (parsedResult->rc != kSTAFOk)
2333 {
2334 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
2335 parsedResult->errorBuffer), STAFResultPtr::INIT);
2336 }
2337
2338 // Verify that the requesting machine/user has at least trust level 2
2339
2340 if (parsedResult->optionTimes(sRMTMACHINE) == 0)
2341 {
2342 VALIDATE_TRUST(2, pData->fShortName, "LIST", pData->fLocalMachineName);
2343 }
2344 else
2345 {
2346 // Verify that the remote log machine/user has at least trust level 2
2347
2348 STAFString trustRequest(
2349 sGetMachine + parsedResult->optionValue(sRMTMACHINE) +
2350 sGetUser + parsedResult->optionValue(sRMTUSER));
2351
2352 STAFResultPtr trustResult = pData->fHandle->submit(
2353 sLocal, sTrust, trustRequest);
2354
2355 if (trustResult->rc != kSTAFOk)
2356 {
2357 STAFString errorMsg = STAFString(
2358 "Verifying that the remote log machine/user has at least "
2359 "trust level 2 failed. STAF local TRUST ") + trustRequest +
2360 " failed with RC: " + trustResult->rc +
2361 ", Result: " + trustResult->result;
2362
2363 return STAFResultPtr(
2364 new STAFResult(trustResult->rc, errorMsg),
2365 STAFResultPtr::INIT);
2366 }
2367
2368 try
2369 {
2370 unsigned int trustLevel = trustResult->result.asUInt();
2371
2372 VALIDATE_TRUST3(2, pData->fShortName, "LIST",
2373 pData->fLocalMachineName, trustLevel,
2374 parsedResult->optionValue(sRMTMACHINE), "",
2375 parsedResult->optionValue(sRMTUSER));
2376 }
2377 catch (STAFException)
2378 {
2379 STAFString errorMsg = STAFString(
2380 "Verifying that the remote log machine/user has at least "
2381 "trust level 2 failed. STAF local TRUST ") + trustRequest +
2382 " did not return a numeric trust level, Result: " +
2383 trustResult->result;
2384
2385 return STAFResultPtr(
2386 new STAFResult(kSTAFAccessDenied, errorMsg),
2387 STAFResultPtr::INIT);
2388 }
2389 }
2390
2391 // Create the marshalling context
2392
2393 STAFObjectPtr mc = STAFObject::createMarshallingContext();
2394
2395 // Generate output based on the LIST options specified
2396
2397 if (parsedResult->optionTimes(sSETTINGS) != 0)
2398 {
2399 STAFString result;
2400
2401 if (pData->fRLogMode != 0)
2402 {
2403 // Create a map object for the remote log settings
2404
2405 STAFObjectPtr listRemoteSettingsMap =
2406 pData->fListRemoteSettingsClass->createInstance();
2407
2408 listRemoteSettingsMap->put("loggingMode", "Remote");
2409 listRemoteSettingsMap->put("remoteLogServer",
2410 pData->fRemoteLogServer);
2411 listRemoteSettingsMap->put("remoteLogService",
2412 pData->fRemoteLogService);
2413
2414 // Set marshalling context map class definitions and root object
2415
2416 mc->setMapClassDefinition(
2417 pData->fListRemoteSettingsClass->reference());
2418 mc->setRootObject(listRemoteSettingsMap);
2419
2420 result = mc->marshall();
2421 }
2422 else
2423 {
2424 // Create a map object for the local log settings
2425
2426 STAFObjectPtr listLocalSettingsMap =
2427 pData->fListLocalSettingsClass->createInstance();
2428
2429 listLocalSettingsMap->put("loggingMode", "Local");
2430 listLocalSettingsMap->put("directory", pData->fRoot);
2431 listLocalSettingsMap->put(
2432 "maxRecordSize", STAFString(pData->fMaxRecordSize));
2433 listLocalSettingsMap->put(
2434 "defaultMaxQueryRecords",
2435 STAFString(pData->fDefaultMaxQueryRecords));
2436
2437 if (pData->fDefaultResolveMessage != 0)
2438 listLocalSettingsMap->put("resolveMessage", "Enabled");
2439 else
2440 listLocalSettingsMap->put("resolveMessage", "Disabled");
2441
2442 if (pData->fUseResolveMessageVar != 0)
2443 listLocalSettingsMap->put("resolveMessageVar", "Enabled");
2444 else
2445 listLocalSettingsMap->put("resolveMessageVar", "Disabled");
2446
2447 // Set marshalling context map class definitions and root object
2448
2449 mc->setMapClassDefinition(
2450 pData->fListLocalSettingsClass->reference());
2451 mc->setRootObject(listLocalSettingsMap);
2452
2453 result = mc->marshall();
2454 }
2455
2456 return STAFResultPtr(new STAFResult(kSTAFOk, result),
2457 STAFResultPtr::INIT);
2458 }
2459
2460 STAFFSPath path;
2461 STAFFSEntryType_t entryType = kSTAFFSFile;
2462 STAFString extPattern = kUTF8_STAR;
2463 unsigned int globalTimes = parsedResult->optionTimes(sGLOBAL);
2464 unsigned int machinesTimes = parsedResult->optionTimes(sMACHINES);
2465 unsigned int machineTimes = parsedResult->optionTimes(sMACHINE);
2466 unsigned int handlesTimes = parsedResult->optionTimes(sHANDLES);
2467 unsigned int handleTimes = parsedResult->optionTimes(sHANDLE);
2468
2469 path.setRoot(pData->fRoot);
2470
2471 if (globalTimes != 0)
2472 {
2473 path.addDir(sGLOBAL);
2474 extPattern = sLogExt;
2475 }
2476 else if (machinesTimes != 0)
2477 {
2478 entryType = kSTAFFSDirectory;
2479 path.addDir(sMACHINE);
2480 }
2481 else // MACHINE was specified
2482 {
2483 STAFResultPtr machineValueResult = resolveOp(pInfo, pData, parsedResult,
2484 sMACHINE);
2485
2486 if (machineValueResult->rc != kSTAFOk) return machineValueResult;
2487
2488 path.addDir(sMACHINE);
2489 path.addDir(machineValueResult->result);
2490
2491 if (handlesTimes != 0)
2492 {
2493 entryType = kSTAFFSDirectory;
2494 path.addDir(sHANDLE);
2495 }
2496 else if (handleTimes != 0)
2497 {
2498 STAFResultPtr handleValueResult = resolveOp(pInfo, pData,
2499 parsedResult, sHANDLE);
2500
2501 if (handleValueResult->rc != kSTAFOk) return handleValueResult;
2502
2503 path.addDir(sHANDLE);
2504 path.addDir(handleValueResult->result);
2505 extPattern = sLogExt;
2506 }
2507 else // Only MACHINE was specified
2508 {
2509 path.addDir(sGLOBAL);
2510 extPattern = sLogExt;
2511 }
2512 }
2513
2514 // Set marshalling context map class definitions
2515
2516 mc->setMapClassDefinition(pData->fListLogsClass->reference());
2517
2518 // Create a empty list object for the marshalled list of logs, machines,
2519 // or handles
2520
2521 STAFObjectPtr outputList = STAFObject::createList();
2522
2523 if (path.exists())
2524 {
2525 STAFFSEntryPtr dirEntry;
2526
2527 try
2528 {
2529 dirEntry = path.getEntry();
2530 }
2531 catch (STAFException &e)
2532 {
2533 STAFString msg = "STAFLogService::handleList: Error getting "
2534 "entry for directory " + path.asString();
2535 STAFString result = getExceptionString(
2536 e, msg.toCurrentCodePage()->buffer()).adoptImpl();
2537
2538 return STAFResultPtr(new STAFResult(kSTAFFileOpenError, result),
2539 STAFResultPtr::INIT);
2540 }
2541
2542 STAFFSEnumPtr dirEnum = dirEntry->enumerate(
2543 kUTF8_STAR, extPattern, entryType);
2544
2545 for (; dirEnum->isValid(); dirEnum->next())
2546 {
2547 STAFFSEntryPtr entry = dirEnum->entry();
2548 STAFString data;
2549
2550 if (machinesTimes || handlesTimes)
2551 {
2552 // Don't strip of the extension, because it could be
2553 // part of the machine name if using long names
2554
2555 outputList->append(
2556 entry->path().setRoot().clearDirList().asString());
2557 }
2558 else
2559 {
2560 STAFObjectPtr logMap = pData->fListLogsClass->createInstance();
2561
2562 logMap->put("logName",
2563 entry->path().setRoot().setExtension()
2564 .clearDirList().asString());
2565 logMap->put("timestamp", entry->modTime().asString());
2566 logMap->put("upperSize", entry->size().first);
2567 logMap->put("size", entry->size().second);
2568
2569 outputList->append(logMap);
2570 }
2571 }
2572 }
2573
2574 // Set the root object for the marshalling context
2575
2576 mc->setRootObject(outputList);
2577
2578 // Set the result to the marshalled output for a list of log records
2579
2580 return STAFResultPtr(new STAFResult(kSTAFOk, mc->marshall()),
2581 STAFResultPtr::INIT);
2582 }
2583
2584
handleDelete(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)2585 STAFResultPtr handleDelete(STAFServiceRequestLevel30 *pInfo,
2586 LogServiceData *pData)
2587 {
2588 STAFCommandParseResultPtr parsedResult =
2589 pData->fDeleteParser->parse(pInfo->request);
2590
2591 if (parsedResult->rc != kSTAFOk)
2592 {
2593 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
2594 parsedResult->errorBuffer), STAFResultPtr::INIT);
2595 }
2596
2597 // Verify the requesting machine/user has at least trust level 4
2598
2599 if (parsedResult->optionTimes(sRMTMACHINE) == 0)
2600 {
2601 VALIDATE_TRUST(4, pData->fShortName, "DELETE",
2602 pData->fLocalMachineName);
2603 }
2604 else
2605 {
2606 // Verify the remote log machine/user has at least trust level 4
2607
2608 STAFString trustRequest(
2609 sGetMachine + parsedResult->optionValue(sRMTMACHINE) +
2610 sGetUser + parsedResult->optionValue(sRMTUSER));
2611
2612 STAFResultPtr trustResult = pData->fHandle->submit(
2613 sLocal, sTrust, trustRequest);
2614
2615 if (trustResult->rc != kSTAFOk)
2616 {
2617 STAFString errorMsg = STAFString(
2618 "Verifying that the remote log machine/user has at least "
2619 "trust level 4 failed. STAF local TRUST ") + trustRequest +
2620 " failed with RC: " + trustResult->rc +
2621 ", Result: " + trustResult->result;
2622
2623 return STAFResultPtr(
2624 new STAFResult(trustResult->rc, errorMsg),
2625 STAFResultPtr::INIT);
2626 }
2627
2628 try
2629 {
2630 unsigned int trustLevel = trustResult->result.asUInt();
2631
2632 VALIDATE_TRUST3(4, pData->fShortName, "DELETE",
2633 pData->fLocalMachineName, trustLevel,
2634 parsedResult->optionValue(sRMTMACHINE), "",
2635 parsedResult->optionValue(sRMTUSER));
2636 }
2637 catch (STAFException)
2638 {
2639 STAFString errorMsg = STAFString(
2640 "Verifying that the remote log machine/user has at least "
2641 "trust level 4 failed. STAF local TRUST ") + trustRequest +
2642 " did not return a numeric trust level, Result: " +
2643 trustResult->result;
2644
2645 return STAFResultPtr(
2646 new STAFResult(kSTAFAccessDenied, errorMsg),
2647 STAFResultPtr::INIT);
2648 }
2649 }
2650
2651 STAFFSPath logfilePath;
2652 STAFResultPtr errorResult;
2653
2654 if (!generateQueryPurgeDeleteLogFilePath(logfilePath, errorResult,
2655 pInfo, pData, parsedResult))
2656 {
2657 return errorResult;
2658 }
2659
2660 if (!logfilePath.exists())
2661 {
2662 return STAFResultPtr(new STAFResult(kSTAFDoesNotExist,
2663 logfilePath.name()),
2664 STAFResultPtr::INIT);
2665 }
2666
2667 STAFFSEntryPtr logfileEntry;
2668
2669 try
2670 {
2671 logfileEntry = logfilePath.getEntry();
2672 }
2673 catch (STAFException &e)
2674 {
2675 STAFString msg = "STAFLogService::handleDelete: Error getting "
2676 "entry for logfile " + logfilePath.asString();
2677 STAFString result = getExceptionString(
2678 e, msg.toCurrentCodePage()->buffer()).adoptImpl();
2679
2680 return STAFResultPtr(new STAFResult(kSTAFFileDeleteError, result),
2681 STAFResultPtr::INIT);
2682 }
2683
2684 // Get a write lock on the global Read/Write Semaphore
2685
2686 STAFLogFileLocksPtr logLocks =
2687 STAFLogFileLocks::acquireLocks(logfilePath.asString());
2688 STAFRWSemWLock accessLock(*logLocks->logAccess);
2689
2690 logfileEntry->remove();
2691
2692 return STAFResultPtr(new STAFResult, STAFResultPtr::INIT);
2693 }
2694
2695
handlePurge(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)2696 STAFResultPtr handlePurge(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData)
2697 {
2698 STAFCommandParseResultPtr parsedResult =
2699 pData->fPurgeParser->parse(pInfo->request);
2700
2701 if (parsedResult->rc != kSTAFOk)
2702 {
2703 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
2704 parsedResult->errorBuffer), STAFResultPtr::INIT);
2705 }
2706
2707 // Verify that the requesting machine/user has at least trust level 4
2708
2709 if (parsedResult->optionTimes(sRMTMACHINE) == 0)
2710 {
2711 VALIDATE_TRUST(4, pData->fShortName, "PURGE", pData->fLocalMachineName);
2712 }
2713 else
2714 {
2715 // Verify that the remote log machine/user has at least trust level 4
2716
2717 STAFString trustRequest(
2718 sGetMachine + parsedResult->optionValue(sRMTMACHINE) +
2719 sGetUser + parsedResult->optionValue(sRMTUSER));
2720
2721 STAFResultPtr trustResult = pData->fHandle->submit(
2722 sLocal, sTrust, trustRequest);
2723
2724 if (trustResult->rc != kSTAFOk)
2725 {
2726 STAFString errorMsg = STAFString(
2727 "Verifying that the remote log machine/user has at least "
2728 "trust level 4 failed. STAF local TRUST ") + trustRequest +
2729 " failed with RC: " + trustResult->rc +
2730 ", Result: " + trustResult->result;
2731
2732 return STAFResultPtr(
2733 new STAFResult(trustResult->rc, errorMsg),
2734 STAFResultPtr::INIT);
2735 }
2736
2737 try
2738 {
2739 unsigned int trustLevel = trustResult->result.asUInt();
2740
2741 VALIDATE_TRUST3(4, pData->fShortName, "PURGE",
2742 pData->fLocalMachineName, trustLevel,
2743 parsedResult->optionValue(sRMTMACHINE), "",
2744 parsedResult->optionValue(sRMTUSER));
2745 }
2746 catch (STAFException)
2747 {
2748 STAFString errorMsg = STAFString(
2749 "Verifying that the remote log machine/user has at least "
2750 "trust level 4 failed. STAF local TRUST ") + trustRequest +
2751 " did not return a numeric trust level, Result: " +
2752 trustResult->result;
2753
2754 return STAFResultPtr(
2755 new STAFResult(kSTAFAccessDenied, errorMsg),
2756 STAFResultPtr::INIT);
2757 }
2758 }
2759
2760 // See if they specified the CONFIRMALL option
2761
2762 bool confirmAll = false;
2763
2764 if (parsedResult->optionTimes(sCONFIRMALL) != 0)
2765 {
2766 confirmAll = true;
2767 }
2768
2769 // Build up the log filter criteria
2770
2771 STAFResultPtr errorResult;
2772 LogRecordFilter logFilter;
2773 LogStats logStats = { 0 };
2774
2775 if (!updateQueryPurgeLogFilter(logFilter, errorResult, pInfo, pData,
2776 parsedResult))
2777 {
2778 return errorResult;
2779 }
2780
2781 unsigned int first = 0;
2782 unsigned int last = 0;
2783 STAFResultPtr result;
2784
2785 if (parsedResult->optionTimes(sFIRST) != 0)
2786 {
2787 // Resolve any STAF variables in the FIRST option value
2788
2789 result = resolveOp(pInfo, pData, parsedResult, sFIRST);
2790
2791 if (result->rc != kSTAFOk) return result;
2792
2793 // Convert resolved option string to an unsigned integer in range
2794 // 0 to UINT_MAX
2795
2796 result = convertOptionStringToUInt(result->result, sFIRST, first);
2797
2798 if (result->rc != kSTAFOk) return result;
2799 }
2800 else if (parsedResult->optionTimes(sLAST) != 0)
2801 {
2802 // Resolve any STAF varaibles in the LAST option value
2803
2804 result = resolveOp(pInfo, pData, parsedResult, sLAST);
2805
2806 if (result->rc != kSTAFOk) return result;
2807
2808 // Convert resolved option string to an unsigned integer in range
2809 // 0 to UINT_MAX
2810
2811 result = convertOptionStringToUInt(result->result, sLAST, last);
2812
2813 if (result->rc != kSTAFOk) return result;
2814 }
2815
2816 bool useFromRecord = false;
2817 unsigned int fromRecord = 0;
2818 bool useToRecord = false;
2819 unsigned int toRecord = 0;
2820
2821 if (parsedResult->optionTimes(sFROMRECORD) != 0)
2822 {
2823 result = resolveOp(pInfo, pData, parsedResult, sFROMRECORD);
2824
2825 if (result->rc != kSTAFOk) return result;
2826
2827 // Convert resolved option string to an unsigned integer in range
2828 // 1 to UINT_MAX
2829
2830 result = convertOptionStringToUInt(
2831 result->result, sFROMRECORD, fromRecord, 1);
2832
2833 if (result->rc != kSTAFOk) return result;
2834
2835 useFromRecord = true;
2836 }
2837
2838 if (parsedResult->optionTimes(sTORECORD) != 0)
2839 {
2840 result = resolveOp(pInfo, pData, parsedResult, sTORECORD);
2841
2842 if (result->rc != kSTAFOk) return result;
2843
2844 // Convert resolved option string to an unsigned integer in range
2845 // 1 to UINT_MAX
2846
2847 result = convertOptionStringToUInt(
2848 result->result, sTORECORD, toRecord, 1);
2849
2850 if (result->rc != kSTAFOk) return result;
2851
2852 useToRecord = true;
2853 }
2854
2855 if (useToRecord && useFromRecord && (fromRecord > toRecord))
2856 {
2857 STAFString errorMsg = STAFString("FROMRECORD value must be <= ") +
2858 "TORECORD value. FROMRECORD: " + STAFString(fromRecord) +
2859 ", TORECORD: " + STAFString(toRecord);
2860 return STAFResultPtr(new STAFResult(kSTAFInvalidValue, errorMsg),
2861 STAFResultPtr::INIT);
2862 }
2863
2864 // Get the log file path
2865
2866 STAFFSPath logfilePath;
2867
2868 if (!generateQueryPurgeDeleteLogFilePath(logfilePath, errorResult,
2869 pInfo, pData, parsedResult))
2870 {
2871 return errorResult;
2872 }
2873
2874 // See if the log file exists
2875
2876 if (!logfilePath.exists())
2877 {
2878 return STAFResultPtr(new STAFResult(kSTAFDoesNotExist,
2879 logfilePath.name()),
2880 STAFResultPtr::INIT);
2881 }
2882
2883 STAFFSEntryPtr logfileEntry;
2884
2885 try
2886 {
2887 logfileEntry = logfilePath.getEntry();
2888 }
2889 catch (STAFException &e)
2890 {
2891 STAFString msg = "STAFLogService::handlePurge: Error getting "
2892 "entry for logfile " + logfilePath.asString();
2893 STAFString result = getExceptionString(
2894 e, msg.toCurrentCodePage()->buffer()).adoptImpl();
2895
2896 return STAFResultPtr(new STAFResult(kSTAFFileOpenError, result),
2897 STAFResultPtr::INIT);
2898 }
2899
2900 // Get a write lock on the global Read/Write Semaphore
2901
2902 STAFLogFileLocksPtr logLocks =
2903 STAFLogFileLocks::acquireLocks(logfilePath.asString());
2904 STAFRWSemWLock accessLock(*logLocks->logAccess);
2905
2906 // Now copy the log file to a temporary file
2907
2908 STAFFSPath tempfilePath = logfilePath;
2909
2910 tempfilePath.setExtension(sTmpExt);
2911
2912 try
2913 {
2914 logfileEntry->copy(tempfilePath.asString());
2915 }
2916 catch (STAFException &e)
2917 {
2918 STAFString msg = "STAFLogService::handlePurge: Error copying "
2919 "logfile " + logfilePath.asString() + " to temporary file " +
2920 tempfilePath.asString();
2921 STAFString result = getExceptionString(
2922 e, msg.toCurrentCodePage()->buffer()).adoptImpl();
2923
2924 return STAFResultPtr(new STAFResult(kSTAFFileWriteError, result),
2925 STAFResultPtr::INIT);
2926 }
2927
2928 // Open the log file and temporary log file
2929 // Note: Notice the log file is the output file and temporary file is
2930 // the input file
2931 // Note: We don't need to lock the temporary file since only one PURGE
2932 // can occur at any given time
2933
2934 fstream logfile(logfilePath.asString().toCurrentCodePage()->buffer(),
2935 ios::out | STAF_ios_binary | ios::trunc);
2936
2937 if (!logfile)
2938 {
2939 return STAFResultPtr(new STAFResult(kSTAFFileOpenError,
2940 logfilePath.asString()),
2941 STAFResultPtr::INIT);
2942 }
2943
2944
2945 fstream tempfile(tempfilePath.asString().toCurrentCodePage()->buffer(),
2946 ios::in | STAF_ios_binary);
2947
2948 if (!tempfile)
2949 {
2950 return STAFResultPtr(new STAFResult(kSTAFFileOpenError,
2951 tempfilePath.asString()),
2952 STAFResultPtr::INIT);
2953 }
2954
2955 // Read each record
2956
2957 unsigned int currFirstRecords = 0;
2958 unsigned int writtenRecords = 0;
2959 LogRecord logRecord;
2960
2961 // If LAST option is specified, use a FIFO queue to store the last <nnn>
2962 // log records. A std::queue uses a deque as the default container and
2963 // provides better performance than a list for large LAST values
2964 std::queue<LogRecord> lastLogRecordsQueue;
2965
2966 // Record number counter (used to compare with fromRecord and toRecord)
2967 unsigned int recordNum = 0;
2968
2969 while (!tempfile.eof())
2970 {
2971 // First, get the information from the log record
2972
2973 unsigned int status = readLogRecordFromFile(
2974 tempfile, logRecord, recordNum + 1);
2975
2976 if (status == kReadLogEndOfFile)
2977 {
2978 // Finish up with whatever needs to be done
2979 continue;
2980 }
2981 else if (status == kReadLogInvalidFormat)
2982 {
2983 // Invalid log record format. Cannot continue.
2984
2985 STAFString errorMsg = STAFString(
2986 "Invalid record format in record number ") + recordNum +
2987 " with format ID " + logRecord.recordFormatID;
2988
2989 return STAFResultPtr(
2990 new STAFResult(kSTAFLogInvalidFileFormat, errorMsg),
2991 STAFResultPtr::INIT);
2992 }
2993
2994 recordNum++;
2995
2996 // Now, make sure this record meets the selection criteria
2997
2998 bool match = true;
2999
3000 if (useFromRecord)
3001 {
3002 if (recordNum < fromRecord)
3003 {
3004 // Ignore this log record
3005 match = false;
3006 }
3007 }
3008
3009 if (useToRecord)
3010 {
3011 if (recordNum > toRecord)
3012 {
3013 match = false;
3014 }
3015 }
3016
3017 // See if this record meets the selection criteria
3018
3019 if (!match || (match && !logRecordMatchesFilter(
3020 logRecord, logFilter, pData->fDefaultAuthenticator)))
3021 {
3022 // If it doesn't match then, it isn't purged so we write it to
3023 // the file
3024 writeLogRecordToFile(logfile, logRecord);
3025 ++writtenRecords;
3026 }
3027 else
3028 {
3029 // If it does match, then handle first and last issues
3030 // Note: If first/last is not specified then the record is purged
3031 // and won't be written
3032
3033 if (last > 0)
3034 {
3035 // Make sure we only purge 'last' number of records
3036 if (lastLogRecordsQueue.size() == last)
3037 {
3038 writeLogRecordToFile(logfile, lastLogRecordsQueue.front());
3039 lastLogRecordsQueue.pop();
3040 ++writtenRecords;
3041 }
3042
3043 lastLogRecordsQueue.push(logRecord);
3044 }
3045 else if ((first > 0) && (++currFirstRecords > first))
3046 {
3047 writeLogRecordToFile(logfile, logRecord);
3048 ++writtenRecords;
3049 }
3050 }
3051 }
3052
3053 unsigned int totalRecords = recordNum;
3054
3055 // Make sure we didn't purge the whole file if didn't specify the
3056 // CONFIRMALL option and if there were any records in the log file to
3057 // begin with
3058
3059 if ((writtenRecords == 0) && (totalRecords > 0) && !confirmAll)
3060 {
3061 // If so, copy the temp file back and return an error
3062
3063 try
3064 {
3065 tempfilePath.getEntry()->copy(logfilePath.asString());
3066 }
3067 catch (STAFException &e)
3068 {
3069 STAFString msg = "STAFLogService::handlePurge: Error copying "
3070 "temporary file " + tempfilePath.asString() + " back to "
3071 "logfile " + logfilePath.asString();
3072 STAFString result = getExceptionString(
3073 e, msg.toCurrentCodePage()->buffer()).adoptImpl();
3074 return STAFResultPtr(new STAFResult(kSTAFLogPurgeFailure, result),
3075 STAFResultPtr::INIT);
3076 }
3077
3078 STAFString msg = "Your purge criteria selected every record in the "
3079 "log file. Use CONFIRMALL instead of CONFIRM if you really want "
3080 "to delete every record (or submit a DELETE request). Or, "
3081 "modify your purge criteria if you don't want to delete every "
3082 "record.";
3083
3084 return STAFResultPtr(new STAFResult(kSTAFLogPurgeFailure, msg),
3085 STAFResultPtr::INIT);
3086 }
3087
3088 // Remove the temporary file
3089 tempfile.close();
3090
3091 try
3092 {
3093 tempfilePath.getEntry()->remove();
3094 }
3095 catch (STAFException)
3096 {
3097 // Ignore
3098 }
3099
3100 // Create a map object for the marshalled map of log purge stats
3101
3102 STAFObjectPtr purgeStatsMap = pData->fPurgeStatsClass->createInstance();
3103
3104 purgeStatsMap->put("purgedRecords",
3105 STAFString(totalRecords - writtenRecords));
3106 purgeStatsMap->put("totalRecords", STAFString(totalRecords));
3107
3108 // Create the marshalling context and set map class definitions and
3109 // its root object
3110
3111 STAFObjectPtr mc = STAFObject::createMarshallingContext();
3112
3113 mc->setMapClassDefinition(pData->fPurgeStatsClass->reference());
3114 mc->setRootObject(purgeStatsMap);
3115
3116 // Set the result to the marshalled output for a map of purge statistics
3117
3118 return STAFResultPtr(new STAFResult(kSTAFOk, mc->marshall()),
3119 STAFResultPtr::INIT);
3120 }
3121
3122
handleSet(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)3123 STAFResultPtr handleSet(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData)
3124 {
3125 // Verify that the requesting machine/user has at least trust level 5
3126
3127 VALIDATE_TRUST(5, pData->fShortName, "SET", pData->fLocalMachineName);
3128
3129 STAFString result;
3130
3131 STAFCommandParseResultPtr parsedResult =
3132 pData->fSetParser->parse(pInfo->request);
3133
3134 if (parsedResult->rc != kSTAFOk)
3135 {
3136 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
3137 parsedResult->errorBuffer), STAFResultPtr::INIT);
3138 }
3139
3140 if (parsedResult->optionTimes(sMAXRECORDSIZE) != 0)
3141 {
3142 STAFResultPtr maxResult = resolveOp(pInfo, pData, parsedResult,
3143 sMAXRECORDSIZE);
3144
3145 if (maxResult->rc != kSTAFOk) return maxResult;
3146
3147 // Convert resolved option string to an unsigned integer in range
3148 // 0 to UINT_MAX
3149
3150 maxResult = convertOptionStringToUInt(
3151 maxResult->result, sMAXRECORDSIZE, pData->fMaxRecordSize);
3152
3153 if (maxResult->rc != kSTAFOk) return maxResult;
3154 }
3155
3156 if (parsedResult->optionTimes(sDEFAULTMAXQUERYRECORDS) != 0)
3157 {
3158 STAFResultPtr maxResult = resolveOp(
3159 pInfo, pData, parsedResult, sDEFAULTMAXQUERYRECORDS);
3160
3161 if (maxResult->rc != kSTAFOk) return maxResult;
3162
3163 // Convert resolved option string to an unsigned integer in range
3164 // 0 to UINT_MAX
3165
3166 maxResult = convertOptionStringToUInt(
3167 maxResult->result, sDEFAULTMAXQUERYRECORDS,
3168 pData->fDefaultMaxQueryRecords);
3169
3170 if (maxResult->rc != kSTAFOk) return maxResult;
3171 }
3172
3173 if (parsedResult->optionTimes(sRESOLVEMESSAGE) != 0)
3174 {
3175 pData->fDefaultResolveMessage = 1;
3176 }
3177 else if (parsedResult->optionTimes(sNORESOLVEMESSAGE) != 0)
3178 {
3179 pData->fDefaultResolveMessage = 0;
3180 }
3181
3182 if (parsedResult->optionTimes(sENABLERESOLVEMESSAGEVAR) != 0)
3183 {
3184 pData->fUseResolveMessageVar = 1;
3185 }
3186 else if (parsedResult->optionTimes(sDISABLERESOLVEMESSAGEVAR) != 0)
3187 {
3188 pData->fUseResolveMessageVar = 0;
3189 }
3190
3191 return STAFResultPtr(new STAFResult(kSTAFOk), STAFResultPtr::INIT);
3192 }
3193
3194
handleHelp(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)3195 STAFResultPtr handleHelp(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData)
3196 {
3197 // Verify that the requesting machine/user has at least trust level 1
3198
3199 VALIDATE_TRUST(1, pData->fShortName, "HELP", pData->fLocalMachineName);
3200
3201 // Return the help information for the service
3202
3203 return STAFResultPtr(new STAFResult(kSTAFOk, sHelpMsg),
3204 STAFResultPtr::INIT);
3205 }
3206
3207
handleRemoteLog(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)3208 STAFResultPtr handleRemoteLog(STAFServiceRequestLevel30 *pInfo,
3209 LogServiceData *pData)
3210 {
3211 // Verify that the requesting machine/user has at least trust level 1 in
3212 // order to perform a remote LOG request
3213
3214 VALIDATE_TRUST(1, pData->fShortName, "LOG", pData->fLocalMachineName);
3215
3216 STAFCommandParseResultPtr parsedResult =
3217 pData->fLogParser->parse(pInfo->request);
3218
3219 if (parsedResult->rc != kSTAFOk)
3220 {
3221 return STAFResultPtr(new STAFResult(kSTAFInvalidRequestString,
3222 parsedResult->errorBuffer), STAFResultPtr::INIT);
3223 }
3224
3225 // Get log level and log mask and see if we should log
3226
3227 STAFResultPtr levelResult = resolveOp(pInfo, pData, parsedResult, sLEVEL);
3228
3229 if (levelResult->rc != kSTAFOk) return levelResult;
3230
3231 unsigned int logLevel = 0;
3232
3233 if (!isValidLogLevel(levelResult->result, logLevel))
3234 {
3235 return STAFResultPtr(new STAFResult(kSTAFLogInvalidLevel,
3236 levelResult->result),
3237 STAFResultPtr::INIT);
3238 }
3239
3240 STAFResultPtr logmaskResult = resolveStr(pInfo, pData,
3241 pData->fResolveLogMaskString);
3242 if ((logmaskResult->rc != kSTAFOk) &&
3243 (logmaskResult->rc != kSTAFVariableDoesNotExist))
3244 {
3245 return logmaskResult;
3246 }
3247
3248 if (logmaskResult->rc == kSTAFVariableDoesNotExist)
3249 logmaskResult->result = sEverythingLogMask;
3250
3251 unsigned int logMask = 0;
3252
3253 if (!convertLogMaskToUInt(logmaskResult->result, logMask))
3254 {
3255 return STAFResultPtr(new STAFResult(kSTAFLogInvalidLevel,
3256 logmaskResult->result),
3257 STAFResultPtr::INIT);
3258 }
3259
3260 if (!(logLevel & logMask))
3261 return STAFResultPtr(new STAFResult, STAFResultPtr::INIT);
3262
3263 // Now pass the request on to the remote log server
3264
3265 STAFString newRequest(pInfo->request);
3266
3267 newRequest += sSpace;
3268 newRequest += sRMTMACHINE;
3269 newRequest += sSpace;
3270 newRequest += pData->fHandle->wrapData(pInfo->endpoint);
3271 newRequest += sSpace;
3272 newRequest += sRMTNAME;
3273 newRequest += sSpace;
3274 newRequest += pData->fHandle->wrapData(pInfo->handleName);
3275 newRequest += sSpace;
3276 newRequest += sRMTHANDLE;
3277 newRequest += sSpace;
3278 newRequest += STAFString(pInfo->handle);
3279 newRequest += sSpace + sRMTUSER + sSpace;
3280 newRequest += pData->fHandle->wrapData(pInfo->user);
3281 newRequest += sSpace + sRMTMACH + sSpace;
3282 newRequest += pData->fHandle->wrapData(pInfo->machine);
3283 newRequest += sSpace + sRMTNICKNAME + sSpace;
3284 newRequest += pData->fHandle->wrapData(pInfo->machineNickname);
3285
3286 return pData->fHandle->submit(pData->fRemoteLogServer,
3287 pData->fRemoteLogService, newRequest);
3288 }
3289
3290
handleRemoteLogGeneral(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData)3291 STAFResultPtr handleRemoteLogGeneral(STAFServiceRequestLevel30 *pInfo,
3292 LogServiceData *pData)
3293 {
3294 // Verify that the requesting machine/user has at least trust level 1
3295 // in order to submit a request to the remote log service
3296
3297 STAFString request = STAFString(pInfo->request).subWord(0, 1).toUpperCase();
3298
3299 VALIDATE_TRUST(1, pData->fShortName, request, pData->fLocalMachineName);
3300
3301 // Pass the request on to the remote log server
3302
3303 STAFString newRequest(pInfo->request);
3304
3305 newRequest += sSpace;
3306 newRequest += sRMTMACHINE;
3307 newRequest += sSpace;
3308 newRequest += pData->fHandle->wrapData(pInfo->machine);
3309 newRequest += sSpace + sRMTUSER + sSpace;
3310 newRequest += pData->fHandle->wrapData(pInfo->user);
3311
3312 return pData->fHandle->submit(pData->fRemoteLogServer,
3313 pData->fRemoteLogService, newRequest);
3314 }
3315
3316
resolveStr(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData,const STAFString & theString)3317 STAFResultPtr resolveStr(STAFServiceRequestLevel30 *pInfo,
3318 LogServiceData *pData, const STAFString &theString)
3319 {
3320 return pData->fHandle->submit(
3321 sLocal, sVar, sResStrResolve + STAFString(pInfo->requestNumber) +
3322 sString + pData->fHandle->wrapData(theString));
3323 }
3324
3325
resolveOp(STAFServiceRequestLevel30 * pInfo,LogServiceData * pData,STAFCommandParseResultPtr & parsedResult,const STAFString & fOption,unsigned int optionIndex)3326 STAFResultPtr resolveOp(STAFServiceRequestLevel30 *pInfo, LogServiceData *pData,
3327 STAFCommandParseResultPtr &parsedResult,
3328 const STAFString &fOption, unsigned int optionIndex)
3329 {
3330 // ???: Would const STAFString & work here?
3331 STAFString optionValue = parsedResult->optionValue(fOption, optionIndex);
3332
3333 if (optionValue.find(sLeftCurly) == STAFString::kNPos)
3334 {
3335 return STAFResultPtr(new STAFResult(kSTAFOk, optionValue),
3336 STAFResultPtr::INIT);
3337 }
3338
3339 return resolveStr(pInfo, pData, optionValue);
3340 }
3341
3342
resolveOpLocal(LogServiceData * pData,STAFCommandParseResultPtr & parsedResult,const STAFString & fOption,unsigned int optionIndex)3343 STAFResultPtr resolveOpLocal(LogServiceData *pData,
3344 STAFCommandParseResultPtr &parsedResult,
3345 const STAFString &fOption,
3346 unsigned int optionIndex)
3347 {
3348 // ???: Would const STAFString & work here?
3349 STAFString optionValue = parsedResult->optionValue(fOption, optionIndex);
3350
3351 if (optionValue.find(sLeftCurly) == STAFString::kNPos)
3352 {
3353 return STAFResultPtr(new STAFResult(kSTAFOk, optionValue),
3354 STAFResultPtr::INIT);
3355 }
3356
3357 return pData->fHandle->submit(sLocal, sVar, sResStrResolve +
3358 sString +
3359 pData->fHandle->wrapData(optionValue));
3360 }
3361
3362
convertStringToUInt(const STAFString & theString,unsigned int & number,const unsigned int minValue,const unsigned int maxValue)3363 STAFResultPtr convertStringToUInt(const STAFString &theString,
3364 unsigned int &number,
3365 const unsigned int minValue,
3366 const unsigned int maxValue)
3367 {
3368 return convertOptionStringToUInt(theString, "", number,
3369 minValue, maxValue);
3370 }
3371
3372
convertOptionStringToUInt(const STAFString & theString,const STAFString & optionName,unsigned int & number,const unsigned int minValue,const unsigned int maxValue)3373 STAFResultPtr convertOptionStringToUInt(const STAFString &theString,
3374 const STAFString &optionName,
3375 unsigned int &number,
3376 const unsigned int minValue,
3377 const unsigned int maxValue)
3378 {
3379 // Convert an option value to an unsigned integer
3380
3381 STAFString_t errorBufferT = 0;
3382
3383 STAFRC_t rc = STAFUtilConvertStringToUInt(
3384 theString.getImpl(), optionName.getImpl(), &number,
3385 &errorBufferT, minValue, maxValue);
3386
3387 if (rc == kSTAFOk)
3388 {
3389 return STAFResultPtr(new STAFResult(), STAFResultPtr::INIT);
3390 }
3391 else
3392 {
3393 return STAFResultPtr(
3394 new STAFResult(rc, STAFString(errorBufferT, STAFString::kShallow)),
3395 STAFResultPtr::INIT);
3396 }
3397 }
3398
3399
isValidLogLevel(const STAFString & levelString,unsigned int & outputLevel)3400 bool isValidLogLevel(const STAFString &levelString, unsigned int &outputLevel)
3401 {
3402 if (levelString.findFirstNotOf(sZeroOne) == STAFString::kNPos)
3403 {
3404 // If we are here, the level string is all zeros and ones
3405 // If the level string has more than 32 characters or has more than
3406 // one "1" then it is invalid
3407
3408 if (levelString.length(STAFString::kChar) > 32) return false;
3409 if (levelString.count(sOne) != 1) return false;
3410
3411 unsigned int index = levelString.find(sOne, 0, STAFString::kChar);
3412
3413 outputLevel = 1;
3414 outputLevel <<= (levelString.length(STAFString::kChar) - index - 1);
3415 }
3416 else
3417 {
3418 if (!convertLogLevelToUInt(levelString, outputLevel)) return false;
3419 }
3420
3421 if ((outputLevel > 0x00004000) && (outputLevel < 0x01000000)) return false;
3422
3423 return true;
3424 }
3425
3426
3427 // returns true if the level string is understood
3428 // returns false if the level string is bad
3429
convertLogLevelToUInt(const STAFString & levelString,unsigned int & outputLevel)3430 bool convertLogLevelToUInt(const STAFString &levelString,
3431 unsigned int &outputLevel)
3432 {
3433 STAFString upperLevel = levelString.toUpperCase();
3434
3435 if (upperLevel == sFATAL) outputLevel = 0x00000001;
3436 else if (upperLevel == sERROR) outputLevel = 0x00000002;
3437 else if (upperLevel == sWARNING) outputLevel = 0x00000004;
3438 else if (upperLevel == sINFO) outputLevel = 0x00000008;
3439 else if (upperLevel == sTRACE) outputLevel = 0x00000010;
3440 else if (upperLevel == sTRACE2) outputLevel = 0x00000020;
3441 else if (upperLevel == sTRACE3) outputLevel = 0x00000040;
3442 else if (upperLevel == sDEBUG) outputLevel = 0x00000080;
3443 else if (upperLevel == sDEBUG2) outputLevel = 0x00000100;
3444 else if (upperLevel == sDEBUG3) outputLevel = 0x00000200;
3445 else if (upperLevel == sSTART) outputLevel = 0x00000400;
3446 else if (upperLevel == sSTOP) outputLevel = 0x00000800;
3447 else if (upperLevel == sPASS) outputLevel = 0x00001000;
3448 else if (upperLevel == sFAIL) outputLevel = 0x00002000;
3449 else if (upperLevel == sSTATUS) outputLevel = 0x00004000;
3450 else if (upperLevel == sUSER1) outputLevel = 0x01000000;
3451 else if (upperLevel == sUSER2) outputLevel = 0x02000000;
3452 else if (upperLevel == sUSER3) outputLevel = 0x04000000;
3453 else if (upperLevel == sUSER4) outputLevel = 0x08000000;
3454 else if (upperLevel == sUSER5) outputLevel = 0x10000000;
3455 else if (upperLevel == sUSER6) outputLevel = 0x20000000;
3456 else if (upperLevel == sUSER7) outputLevel = 0x40000000;
3457 else if (upperLevel == sUSER8) outputLevel = 0x80000000;
3458 else return false;
3459
3460 return true;
3461 }
3462
3463
convertLogLevelToString(unsigned int logLevel,bool levelAsBits)3464 STAFString &convertLogLevelToString(unsigned int logLevel, bool levelAsBits)
3465 {
3466 if (logLevel == 0x00000001)
3467 return levelAsBits ? sFATALBits : sFATALPretty;
3468 else if (logLevel == 0x00000002)
3469 return levelAsBits ? sERRORBits : sERRORPretty;
3470 else if (logLevel == 0x00000004)
3471 return levelAsBits ? sWARNINGBits : sWARNINGPretty;
3472 else if (logLevel == 0x00000008)
3473 return levelAsBits ? sINFOBits : sINFOPretty;
3474 else if (logLevel == 0x00000010)
3475 return levelAsBits ? sTRACEBits : sTRACEPretty;
3476 else if (logLevel == 0x00000020)
3477 return levelAsBits ? sTRACE2Bits : sTRACE2Pretty;
3478 else if (logLevel == 0x00000040)
3479 return levelAsBits ? sTRACE3Bits : sTRACE3Pretty;
3480 else if (logLevel == 0x00000080)
3481 return levelAsBits ? sDEBUGBits : sDEBUGPretty;
3482 else if (logLevel == 0x00000100)
3483 return levelAsBits ? sDEBUG2Bits : sDEBUG2Pretty;
3484 else if (logLevel == 0x00000200)
3485 return levelAsBits ? sDEBUG3Bits : sDEBUG3Pretty;
3486 else if (logLevel == 0x00000400)
3487 return levelAsBits ? sSTARTBits : sSTARTPretty;
3488 else if (logLevel == 0x00000800)
3489 return levelAsBits ? sSTOPBits : sSTOPPretty;
3490 else if (logLevel == 0x00001000)
3491 return levelAsBits ? sPASSBits : sPASSPretty;
3492 else if (logLevel == 0x00002000)
3493 return levelAsBits ? sFAILBits : sFAILPretty;
3494 else if (logLevel == 0x00004000)
3495 return levelAsBits ? sSTATUSBits : sSTATUSPretty;
3496 else if (logLevel == 0x01000000)
3497 return levelAsBits ? sUSER1Bits : sUSER1Pretty;
3498 else if (logLevel == 0x02000000)
3499 return levelAsBits ? sUSER2Bits : sUSER2Pretty;
3500 else if (logLevel == 0x04000000)
3501 return levelAsBits ? sUSER3Bits : sUSER3Pretty;
3502 else if (logLevel == 0x08000000)
3503 return levelAsBits ? sUSER4Bits : sUSER4Pretty;
3504 else if (logLevel == 0x10000000)
3505 return levelAsBits ? sUSER5Bits : sUSER5Pretty;
3506 else if (logLevel == 0x20000000)
3507 return levelAsBits ? sUSER6Bits : sUSER6Pretty;
3508 else if (logLevel == 0x40000000)
3509 return levelAsBits ? sUSER7Bits : sUSER7Pretty;
3510 else if (logLevel == 0x80000000)
3511 return levelAsBits ? sUSER8Bits : sUSER8Pretty;
3512 else
3513 return levelAsBits ? sUNKNOWNBits : sUNKNOWNPretty;
3514 }
3515
3516
convertLogMaskToUInt(const STAFString & logmaskString,unsigned int & logmaskOutput)3517 bool convertLogMaskToUInt(const STAFString &logmaskString,
3518 unsigned int &logmaskOutput)
3519 {
3520 logmaskOutput = 0;
3521
3522 if (logmaskString.findFirstNotOf(sZeroOne) == STAFString::kNPos)
3523 {
3524 // If we are here, the level string is all zeros and ones
3525 // If the level string has more than 32 characters then it is invalid
3526
3527 if (logmaskString.length(STAFString::kChar) > 32) return false;
3528
3529 for (int i = 0; i < logmaskString.length(STAFString::kChar); ++i)
3530 {
3531 if (logmaskString.subString(i, 1, STAFString::kChar) == sOne)
3532 {
3533 logmaskOutput |=
3534 1 << (logmaskString.length(STAFString::kChar) - i - 1);
3535 }
3536 }
3537 }
3538 else
3539 {
3540 for (int i = 0; i < logmaskString.numWords(); ++i)
3541 {
3542 unsigned int thisLevel = 0;
3543
3544 if (convertLogLevelToUInt(logmaskString.subWord(i, 1), thisLevel))
3545 logmaskOutput |= thisLevel;
3546 else
3547 return false;
3548 }
3549 }
3550
3551 return true;
3552 }
3553
3554
writeUIntToFile(ostream & output,unsigned int data,unsigned int length)3555 void writeUIntToFile(ostream &output, unsigned int data, unsigned int length)
3556 {
3557 union
3558 {
3559 char bytes[4];
3560 unsigned int uint;
3561 };
3562
3563 uint = STAFUtilSwapUInt(STAFUtilConvertNativeUIntToLE(data));
3564
3565 output.write(&bytes[4 - length], length);
3566 }
3567
3568
readUIntFromFile(istream & input,unsigned int & data,unsigned int length)3569 void readUIntFromFile(istream &input, unsigned int &data, unsigned int length)
3570 {
3571 union
3572 {
3573 char bytes[4];
3574 unsigned int uint;
3575 };
3576
3577 uint = 0;
3578
3579 input.read(&bytes[4 - length], length);
3580
3581 data = STAFUtilConvertLEUIntToNative(STAFUtilSwapUInt(uint));
3582 }
3583
3584
readStringFromFile(istream & input,STAFString & inString)3585 void readStringFromFile(istream &input, STAFString &inString)
3586 {
3587 // First read in the UTF-8 data
3588
3589 unsigned int stringLength = 0;
3590
3591 readUIntFromFile(input, stringLength);
3592
3593 char *inputData = new char[stringLength];
3594
3595 input.read(inputData, stringLength);
3596
3597 try
3598 {
3599 inString = STAFString(inputData, stringLength, STAFString::kUTF8);
3600 }
3601 catch(...)
3602 {
3603 delete [] inputData;
3604 throw;
3605 }
3606
3607 delete [] inputData;
3608 }
3609
3610
writeStringToFile(ostream & output,const STAFString & outString)3611 void writeStringToFile(ostream &output, const STAFString &outString)
3612 {
3613 unsigned int stringLength = outString.length();
3614
3615 writeUIntToFile(output, stringLength);
3616 output.write(outString.buffer(), stringLength);
3617 }
3618
3619
3620 // returns true if the logfile path was generated successfully
3621 // returns false (and errorResult is set) if there was an error generating
3622 // the logfile path
3623
generateQueryPurgeDeleteLogFilePath(STAFFSPath & logfilePath,STAFResultPtr & errorResult,STAFServiceRequestLevel30 * pInfo,LogServiceData * pData,STAFCommandParseResultPtr & parsedResult)3624 bool generateQueryPurgeDeleteLogFilePath(STAFFSPath &logfilePath,
3625 STAFResultPtr &errorResult, STAFServiceRequestLevel30 *pInfo,
3626 LogServiceData *pData, STAFCommandParseResultPtr &parsedResult)
3627 {
3628 // Get logname
3629
3630 STAFResultPtr lognameResult = resolveOp(pInfo, pData, parsedResult,
3631 sLOGNAME);
3632
3633 if (lognameResult->rc != kSTAFOk)
3634 {
3635 errorResult = lognameResult;
3636 return false;
3637 }
3638
3639 // Setup the path
3640
3641 logfilePath.setRoot(pData->fRoot);
3642
3643 if (parsedResult->optionTimes(sGLOBAL) != 0)
3644 {
3645 // They specified a GLOBAL log file
3646
3647 logfilePath.addDir(sGLOBAL);
3648 }
3649 else
3650 {
3651 // They specified at least a MACHINE log file
3652
3653 STAFResultPtr machineResult = resolveOp(pInfo, pData, parsedResult,
3654 sMACHINE);
3655
3656 if (machineResult->rc != kSTAFOk)
3657 {
3658 errorResult = machineResult;
3659 return false;
3660 }
3661
3662 logfilePath.addDir(sMACHINE);
3663 logfilePath.addDir(machineResult->result);
3664
3665 if (parsedResult->optionTimes(sHANDLE) != 0)
3666 {
3667 // They specified a HANDLE log file
3668
3669 STAFResultPtr handleResult = resolveOp(pInfo, pData, parsedResult,
3670 sHANDLE);
3671
3672 if (handleResult->rc != kSTAFOk)
3673 {
3674 errorResult = handleResult;
3675 return false;
3676 }
3677
3678 logfilePath.addDir(sHANDLE);
3679 logfilePath.addDir(handleResult->result);
3680 }
3681 else
3682 {
3683 logfilePath.addDir(sGLOBAL);
3684 }
3685 }
3686
3687 logfilePath.setName(lognameResult->result);
3688 logfilePath.setExtension(sLogExt);
3689
3690 return true;
3691 }
3692
3693
readLogRecordFromFile(istream & logfile,LogRecord & logRecord,unsigned int recordNum)3694 unsigned int readLogRecordFromFile(istream &logfile, LogRecord &logRecord,
3695 unsigned int recordNum)
3696 {
3697 unsigned int totalLength = 0;
3698
3699 readUIntFromFile(logfile, logRecord.recordFormatID, 1);
3700
3701 if (logfile.eof()) return kReadLogEndOfFile;
3702
3703 logRecord.recordNumber = recordNum;
3704
3705 if (logRecord.recordFormatID == sCurrRecordFormatID)
3706 {
3707 // This format added endpoint to the log record
3708
3709 readUIntFromFile(logfile, logRecord.date);
3710 readUIntFromFile(logfile, logRecord.secondsPastMidnight, 3);
3711 readUIntFromFile(logfile, logRecord.logLevel);
3712 readUIntFromFile(logfile, logRecord.handle);
3713 readStringFromFile(logfile, logRecord.machine);
3714 readStringFromFile(logfile, logRecord.handleName);
3715 readStringFromFile(logfile, logRecord.user);
3716 readStringFromFile(logfile, logRecord.endpoint);
3717 readStringFromFile(logfile, logRecord.message);
3718 }
3719 else if (logRecord.recordFormatID == 3)
3720 {
3721 // This format added user to the log record for Feature #627135
3722
3723 readUIntFromFile(logfile, logRecord.date);
3724 readUIntFromFile(logfile, logRecord.secondsPastMidnight, 3);
3725 readUIntFromFile(logfile, logRecord.logLevel);
3726 readUIntFromFile(logfile, logRecord.handle);
3727 readStringFromFile(logfile, logRecord.machine);
3728 readStringFromFile(logfile, logRecord.handleName);
3729 readStringFromFile(logfile, logRecord.user);
3730 readStringFromFile(logfile, logRecord.message);
3731 logRecord.endpoint = "tcp" + sSpecSeparator + logRecord.machine;
3732 }
3733 else if (logRecord.recordFormatID == 2)
3734 {
3735 readUIntFromFile(logfile, logRecord.date);
3736 readUIntFromFile(logfile, logRecord.secondsPastMidnight, 3);
3737 readUIntFromFile(logfile, logRecord.logLevel);
3738 readUIntFromFile(logfile, logRecord.handle);
3739 readStringFromFile(logfile, logRecord.machine);
3740 readStringFromFile(logfile, logRecord.handleName);
3741 readStringFromFile(logfile, logRecord.message);
3742 logRecord.user = sUnauthenticatedUser;
3743 logRecord.endpoint = "tcp" + sSpecSeparator + logRecord.machine;
3744 }
3745 else if (logRecord.recordFormatID == 1)
3746 {
3747 // This is the format used by the last couple of implementations
3748 // of the Log service written in Rexx
3749
3750 readUIntFromFile(logfile, logRecord.date);
3751 readUIntFromFile(logfile, logRecord.secondsPastMidnight, 3);
3752 readUIntFromFile(logfile, logRecord.logLevel);
3753 readUIntFromFile(logfile, totalLength);
3754
3755 if (totalLength < 3)
3756 {
3757 // Log record is incomplete
3758 return kReadLogInvalidFormat;
3759 }
3760
3761 // Get a buffer and read the rest of the data
3762
3763 STAFRefPtr<char> data = STAFRefPtr<char>(new char[totalLength],
3764 STAFRefPtr<char>::INIT);
3765 logfile.read(data, totalLength);
3766
3767 STAFString dataString(data, totalLength, STAFString::kCurrent);
3768
3769 // Find the separation points for the other fields
3770
3771 unsigned int sepLoc1 = dataString.find(sOldSep);
3772
3773 if (sepLoc1 == STAFString::kNPos)
3774 {
3775 // Log record is incomplete
3776 return kReadLogInvalidFormat;
3777 }
3778
3779 unsigned int sepLoc2 = dataString.find(sOldSep, sepLoc1 + 1);
3780
3781 if (sepLoc2 == STAFString::kNPos)
3782 {
3783 // Log record is incomplete
3784 return kReadLogInvalidFormat;
3785 }
3786
3787 unsigned int sepLoc3 = dataString.find(sOldSep, sepLoc2 + 1);
3788
3789 if (sepLoc3 == STAFString::kNPos)
3790 {
3791 // Log record is incomplete
3792 return kReadLogInvalidFormat;
3793 }
3794
3795 logRecord.machine = dataString.subString(0, sepLoc1);
3796 logRecord.handle = dataString.subString(
3797 sepLoc1 + 1, sepLoc2 - sepLoc1 - 1).asUIntWithDefault(0);
3798 logRecord.handleName = dataString.subString(
3799 sepLoc2 + 1, sepLoc3 - sepLoc2 - 1);
3800
3801 if ((sepLoc3 + 1) >= dataString.length())
3802 {
3803 // Log record is incomplete
3804 return kReadLogInvalidFormat;
3805 }
3806
3807 logRecord.message = dataString.subString(sepLoc3 + 1);
3808
3809 logRecord.user = sUnauthenticatedUser;
3810 logRecord.endpoint = "tcp" + sSpecSeparator + logRecord.machine;
3811 }
3812 else if (logRecord.recordFormatID == 0)
3813 {
3814 // This means one of two things:
3815 // 1) The recordFormatID is really 0 which was the format used by the
3816 // first few implementations of the LOG service written in Rexx a
3817 // long time ago (circa 1999). This is unlikely.
3818 // 2) The log record is empty (e.g. incomplete and invalid) and the
3819 // format ID defaulted to 0 as it could not be read.
3820 // This is the more likely reason.
3821
3822 readUIntFromFile(logfile, totalLength);
3823
3824 if (totalLength < 7)
3825 {
3826 // Log record is incomplete
3827 return kReadLogInvalidFormat;
3828 }
3829
3830 readUIntFromFile(logfile, logRecord.date);
3831 readUIntFromFile(logfile, logRecord.secondsPastMidnight, 3);
3832
3833 // Remove date and time length from totalLength
3834
3835 totalLength -= 7;
3836
3837 // Get a buffer and read the rest of the data
3838
3839 STAFRefPtr<char> data = STAFRefPtr<char>(new char[totalLength],
3840 STAFRefPtr<char>::INIT);
3841 logfile.read(data, totalLength);
3842
3843 STAFString dataString(data, totalLength, STAFString::kCurrent);
3844
3845 // Find the separation points for the other fields
3846
3847 unsigned int sepLoc1 = dataString.find(sOldSep);
3848
3849 if (sepLoc1 == STAFString::kNPos)
3850 {
3851 // Log record is incomplete
3852 return kReadLogInvalidFormat;
3853 }
3854
3855 unsigned int sepLoc2 = dataString.find(sOldSep, sepLoc1 + 1);
3856
3857 if (sepLoc2 == STAFString::kNPos)
3858 {
3859 // Log record is incomplete
3860 return kReadLogInvalidFormat;
3861 }
3862
3863 unsigned int sepLoc3 = dataString.find(sOldSep, sepLoc2 + 1);
3864
3865 if (sepLoc3 == STAFString::kNPos)
3866 {
3867 // Log record is incomplete
3868 return kReadLogInvalidFormat;
3869 }
3870
3871 logRecord.machine = dataString.subString(0, sepLoc1);
3872 logRecord.handle = dataString.subString(
3873 sepLoc1 + 1, sepLoc2 - sepLoc1 - 1).asUIntWithDefault(0);
3874 logRecord.handleName = dataString.subString(
3875 sepLoc2 + 1, sepLoc3 - sepLoc2 - 1);
3876
3877 if ((sepLoc3 + 5) >= dataString.length())
3878 {
3879 // Log record is incomplete
3880 return kReadLogInvalidFormat;
3881 }
3882
3883 logRecord.message = dataString.subString(sepLoc3 + 5);
3884
3885 logRecord.logLevel = *(reinterpret_cast<unsigned int *>(
3886 const_cast<char *>(dataString.buffer()
3887 + sepLoc3 + 1)));
3888
3889 // Fixup log level from Rexx's big-endian to native format
3890
3891 logRecord.logLevel = STAFUtilConvertLEUIntToNative(
3892 STAFUtilSwapUInt(logRecord.logLevel));
3893
3894 logRecord.user = sUnauthenticatedUser;
3895 logRecord.endpoint = "tcp" + sSpecSeparator + logRecord.machine;
3896 }
3897 else
3898 {
3899 // This indicates that the log record has an invalid record format ID
3900 return kReadLogInvalidFormat;
3901 }
3902
3903 return kReadLogOk;
3904 }
3905
3906
writeLogRecordToFile(ostream & logfile,LogRecord & logRecord)3907 void writeLogRecordToFile(ostream &logfile, LogRecord &logRecord)
3908 {
3909 writeUIntToFile(logfile, sCurrRecordFormatID, 1);
3910 writeUIntToFile(logfile, logRecord.date);
3911 writeUIntToFile(logfile, logRecord.secondsPastMidnight, 3);
3912 writeUIntToFile(logfile, logRecord.logLevel);
3913 writeUIntToFile(logfile, logRecord.handle);
3914 writeStringToFile(logfile, logRecord.machine);
3915 writeStringToFile(logfile, logRecord.handleName);
3916 writeStringToFile(logfile, logRecord.user);
3917 writeStringToFile(logfile, logRecord.endpoint);
3918 writeStringToFile(logfile, STAFHandle::maskPrivateData(logRecord.message));
3919 }
3920
3921
3922 // Add a log record in a marshalling context as a map to the logList
3923
addLogRecordToList(STAFObjectPtr & logList,STAFMapClassDefinitionPtr & logRecordClass,const LogRecord & logRecord,bool levelAsBits,bool longFormat)3924 void addLogRecordToList(STAFObjectPtr &logList,
3925 STAFMapClassDefinitionPtr &logRecordClass,
3926 const LogRecord &logRecord, bool levelAsBits,
3927 bool longFormat)
3928 {
3929 unsigned int year = logRecord.date / 10000;
3930 unsigned int month = (logRecord.date % 10000) / 100;
3931 unsigned int day = logRecord.date % 100;
3932 unsigned int hour = logRecord.secondsPastMidnight / 3600;
3933 unsigned int minute = (logRecord.secondsPastMidnight % 3600) / 60;
3934 unsigned int second = logRecord.secondsPastMidnight % 60;
3935
3936 STAFString timestampString;
3937
3938 try
3939 {
3940 STAFTimestamp theTimestamp(year, month, day, hour, minute, second);
3941 timestampString = theTimestamp.asString();
3942 }
3943 catch (STAFException)
3944 {
3945 // Instead of returning a STAFTimestamp exception in the output of a
3946 // LOG QUERY request when encountering a log record with an invalid
3947 // timestamp (which isn't very helpful), output "00000000-00:00:00" for
3948 // the timestamp so that valid log records can be displayed.
3949 // Note: If the system crashed while writing to a log file, the last
3950 // record in the log may be corrupt (e.g. have an invalid timestamp).
3951 timestampString = "00000000-00:00:00";
3952 }
3953
3954 STAFObjectPtr logRecordMap = logRecordClass->createInstance();
3955
3956 logRecordMap->put("timestamp", timestampString);
3957 logRecordMap->put("level", convertLogLevelToString(
3958 logRecord.logLevel, levelAsBits));
3959 logRecordMap->put("message", logRecord.message);
3960
3961 if (longFormat)
3962 {
3963 logRecordMap->put("recordNumber", STAFString(logRecord.recordNumber));
3964 logRecordMap->put("machine", logRecord.machine);
3965 logRecordMap->put("handle", STAFString(logRecord.handle));
3966 logRecordMap->put("handleName", logRecord.handleName);
3967 logRecordMap->put("user", logRecord.user);
3968 logRecordMap->put("endpoint", logRecord.endpoint);
3969 }
3970
3971 logList->append(logRecordMap);
3972 }
3973
3974
printLogRecord(const LogRecord & logRecord)3975 void printLogRecord(const LogRecord &logRecord)
3976 {
3977 cout << "Record #: " << logRecord.recordNumber
3978 << ", Record ID: " << logRecord.recordFormatID
3979 << ", Date: " << logRecord.date
3980 << ", Seconds: " << logRecord.secondsPastMidnight
3981 << ", Level: 0x" << hex << logRecord.logLevel << dec << endl
3982 << "Machine: " << logRecord.machine
3983 << ", HandleName: " << logRecord.handleName
3984 << " ,Handle: " << logRecord.handle
3985 << ", User: " << logRecord.user
3986 << ", Endpoint: " << logRecord.endpoint
3987 << endl << "Message: " << logRecord.message << endl << endl;
3988 }
3989
3990
logRecordMatchesFilter(const LogRecord & logRecord,const LogRecordFilter & logFilter,const STAFString & defaultAuthenticator)3991 bool logRecordMatchesFilter(const LogRecord &logRecord,
3992 const LogRecordFilter &logFilter,
3993 const STAFString &defaultAuthenticator)
3994 {
3995 // Check if the record matches the specified date(s)
3996
3997 if (logFilter.useFrom &&
3998 ((logRecord.date < logFilter.fromTimestamp.date) ||
3999 ((logRecord.date == logFilter.fromTimestamp.date) &&
4000 (logRecord.secondsPastMidnight < logFilter.fromTimestamp.seconds))))
4001 {
4002 return false;
4003 }
4004
4005 if (logFilter.useAfter &&
4006 ((logRecord.date < logFilter.afterTimestamp.date) ||
4007 ((logRecord.date == logFilter.afterTimestamp.date) &&
4008 (logRecord.secondsPastMidnight <= logFilter.afterTimestamp.seconds))))
4009 {
4010 return false;
4011 }
4012
4013 if (logFilter.useBefore &&
4014 ((logRecord.date > logFilter.beforeTimestamp.date) ||
4015 ((logRecord.date == logFilter.beforeTimestamp.date) &&
4016 (logRecord.secondsPastMidnight >= logFilter.beforeTimestamp.seconds))))
4017 {
4018 return false;
4019 }
4020
4021 if (logFilter.useTo &&
4022 ((logRecord.date > logFilter.toTimestamp.date) ||
4023 ((logRecord.date == logFilter.toTimestamp.date) &&
4024 (logRecord.secondsPastMidnight > logFilter.toTimestamp.seconds))))
4025 {
4026 return false;
4027 }
4028
4029 if (logFilter.useLevelMask && !(logFilter.levelMask & logRecord.logLevel))
4030 return false;
4031
4032 // Check if the record matches at least one of the specified QMACHINE(s)
4033
4034 StringList::const_iterator stringIter;
4035 bool foundMatch = false;
4036
4037 for (stringIter = logFilter.qMachines.begin();
4038 !foundMatch && (stringIter != logFilter.qMachines.end()); ++stringIter)
4039 {
4040 if (logRecord.machine.isEqualTo(*stringIter,
4041 kSTAFStringCaseInsensitive))
4042 {
4043 foundMatch = true;
4044 }
4045 }
4046
4047 if ((logFilter.qMachines.size() != 0) && !foundMatch)
4048 return false;
4049
4050 // Check if the record matches at least one of ths specified handle NAME(s)
4051
4052 foundMatch = false;
4053
4054 for (stringIter = logFilter.names.begin();
4055 !foundMatch && (stringIter != logFilter.names.end()); ++stringIter)
4056 {
4057 if (logRecord.handleName.isEqualTo(*stringIter,
4058 kSTAFStringCaseInsensitive))
4059 {
4060 foundMatch = true;
4061 }
4062 }
4063
4064 if ((logFilter.names.size() != 0) && !foundMatch)
4065 return false;
4066
4067 // Check if the record matches at least one of the specified ENDPOINT(s)
4068
4069 foundMatch = false;
4070
4071 for (stringIter = logFilter.endpoints.begin();
4072 !foundMatch && (stringIter != logFilter.endpoints.end());
4073 ++stringIter)
4074 {
4075 if (logRecord.endpoint.isEqualTo(*stringIter,
4076 kSTAFStringCaseInsensitive))
4077 {
4078 foundMatch = true;
4079 }
4080 }
4081
4082 if ((logFilter.endpoints.size() != 0) && !foundMatch)
4083 return false;
4084
4085 /* XXX: This used to do a case-insensitive match on authenticator
4086 and a case-sensitive match on user identifer and match
4087 using wildcards. We decided to remove this until we came
4088 up with a more generic matching scheme to use for all
4089 STAF requests that also allows some sort of escaping in
4090 case someone really wanted to match on a * or ? characater
4091
4092 // Change authenticator in logRecord's user to lower-case
4093
4094 STAFString lowerLogRecordUser = logRecord.user;
4095
4096 unsigned int sepIndex = lowerLogRecordUser.find(sSpecSeparator);
4097
4098 if (sepIndex != STAFString::kNPos)
4099 {
4100 lowerLogRecordUser =
4101 logRecord.user.subString(0, sepIndex).toLowerCase() +
4102 logRecord.user.subString(sepIndex);
4103 }
4104
4105 // Check if the record matches at least one USER option
4106
4107 foundMatch = false;
4108
4109 for (stringIter = logFilter.users.begin();
4110 !foundMatch && (stringIter != logFilter.users.end()); ++stringIter)
4111 {
4112 STAFString lowerUser = *stringIter;
4113
4114 // Check if authenticator was specified in the user value
4115
4116 sepIndex = lowerUser.find(sSpecSeparator);
4117
4118 if (sepIndex == STAFString::kNPos)
4119 {
4120 // No authenticator specified - get default authenticator
4121 // and change authenticator to lower-case
4122 lowerUser = defaultAuthenticator.toLowerCase() + sSpecSeparator +
4123 lowerUser;
4124 }
4125 else
4126 {
4127 // User specified in form of Authenticator://UserIdentifier
4128 // Change authenticator to lower-case.
4129 lowerUser = lowerUser.subString(0, sepIndex).toLowerCase() +
4130 lowerUser.subString(sepIndex);
4131 }
4132
4133 if (lowerLogRecordUser.matchesWildcards(lowerUser))
4134 foundMatch = true;
4135 }
4136 */
4137
4138 // Check if the record matches at least one of the specified USER(s)
4139
4140 foundMatch = false;
4141
4142 for (stringIter = logFilter.users.begin();
4143 !foundMatch && (stringIter != logFilter.users.end());
4144 ++stringIter)
4145 {
4146 if (logRecord.user.isEqualTo(*stringIter,
4147 kSTAFStringCaseInsensitive))
4148 {
4149 foundMatch = true;
4150 }
4151 }
4152
4153 if ((logFilter.users.size() != 0) && !foundMatch)
4154 return false;
4155
4156 // Check if matches at least one CONTAINS option
4157
4158 STAFString lowerMessage = logRecord.message.toLowerCase();
4159 foundMatch = false;
4160
4161 for (stringIter = logFilter.contains.begin();
4162 !foundMatch && (stringIter != logFilter.contains.end()); ++stringIter)
4163 {
4164 if (lowerMessage.find(*stringIter) != STAFString::kNPos)
4165 foundMatch = true;
4166 }
4167
4168 if ((logFilter.contains.size() != 0) && !foundMatch)
4169 return false;
4170
4171 // Check if matches at least one CSCONTAINS option
4172
4173 STAFString message = logRecord.message;
4174 foundMatch = false;
4175
4176 for (stringIter = logFilter.cscontains.begin();
4177 !foundMatch && (stringIter != logFilter.cscontains.end()); ++stringIter)
4178 {
4179 if (message.find(*stringIter) != STAFString::kNPos)
4180 foundMatch = true;
4181 }
4182
4183 if ((logFilter.cscontains.size() != 0) && !foundMatch)
4184 return false;
4185
4186 // Check if matches at least one STARTSWITH or CSSTARTSWITH option
4187
4188 foundMatch = false;
4189
4190 for (stringIter = logFilter.startswith.begin();
4191 !foundMatch && (stringIter != logFilter.startswith.end());
4192 ++stringIter)
4193 {
4194 if (lowerMessage.find(*stringIter) == 0)
4195 foundMatch = true;
4196 }
4197
4198 for (stringIter = logFilter.csstartswith.begin();
4199 !foundMatch && (stringIter != logFilter.csstartswith.end());
4200 ++stringIter)
4201 {
4202 if (message.find(*stringIter) == 0)
4203 foundMatch = true;
4204 }
4205
4206 if ((logFilter.startswith.size() != 0 || logFilter.csstartswith.size() != 0)
4207 && !foundMatch)
4208 return false;
4209
4210 // Check if matches at least one QHANDLE option
4211
4212 foundMatch = false;
4213
4214 for (HandleList::const_iterator hIter = logFilter.qHandles.begin();
4215 !foundMatch && (hIter != logFilter.qHandles.end()); ++hIter)
4216 {
4217 if (*hIter == logRecord.handle)
4218 foundMatch = true;
4219 }
4220
4221 if ((logFilter.qHandles.size() != 0) && !foundMatch)
4222 return false;
4223
4224 return true;
4225 }
4226
4227
4228 // returns true if the log filter was updated successfully
4229 // returns false (and result is set) if there was an error updating
4230 // the log filter
4231
updateQueryPurgeLogFilter(LogRecordFilter & logFilter,STAFResultPtr & result,STAFServiceRequestLevel30 * pInfo,LogServiceData * pData,STAFCommandParseResultPtr & parsedResult)4232 bool updateQueryPurgeLogFilter(LogRecordFilter &logFilter,
4233 STAFResultPtr &result, STAFServiceRequestLevel30 *pInfo,
4234 LogServiceData *pData, STAFCommandParseResultPtr &parsedResult)
4235 {
4236 int i = 0;
4237
4238 for (i = 1; i <= parsedResult->optionTimes(sCONTAINS); ++i)
4239 {
4240 result = resolveOp(pInfo, pData, parsedResult, sCONTAINS, i);
4241
4242 if (result->rc != kSTAFOk) return false;
4243
4244 logFilter.contains.push_back(result->result.toLowerCase());
4245 }
4246
4247 for (i = 1; i <= parsedResult->optionTimes(sCSCONTAINS); ++i)
4248 {
4249 result = resolveOp(pInfo, pData, parsedResult, sCSCONTAINS, i);
4250
4251 if (result->rc != kSTAFOk) return false;
4252
4253 logFilter.cscontains.push_back(result->result);
4254 }
4255
4256 for (i = 1; i <= parsedResult->optionTimes(sSTARTSWITH); ++i)
4257 {
4258 result = resolveOp(pInfo, pData, parsedResult, sSTARTSWITH, i);
4259
4260 if (result->rc != kSTAFOk) return false;
4261
4262 logFilter.startswith.push_back(result->result.toLowerCase());
4263 }
4264
4265 for (i = 1; i <= parsedResult->optionTimes(sCSSTARTSWITH); ++i)
4266 {
4267 result = resolveOp(pInfo, pData, parsedResult, sCSSTARTSWITH, i);
4268
4269 if (result->rc != kSTAFOk) return false;
4270
4271 logFilter.csstartswith.push_back(result->result);
4272 }
4273
4274 for (i = 1; i <= parsedResult->optionTimes(sQMACHINE); ++i)
4275 {
4276 result = resolveOp(pInfo, pData, parsedResult, sQMACHINE, i);
4277
4278 if (result->rc != kSTAFOk) return false;
4279
4280 logFilter.qMachines.push_back(result->result);
4281 }
4282
4283 for (i = 1; i <= parsedResult->optionTimes(sNAME); ++i)
4284 {
4285 result = resolveOp(pInfo, pData, parsedResult, sNAME, i);
4286
4287 if (result->rc != kSTAFOk) return false;
4288
4289 logFilter.names.push_back(result->result);
4290 }
4291
4292 for (i = 1; i <= parsedResult->optionTimes(sUSER); ++i)
4293 {
4294 result = resolveOp(pInfo, pData, parsedResult, sUSER, i);
4295
4296 if (result->rc != kSTAFOk) return false;
4297
4298 logFilter.users.push_back(result->result);
4299 }
4300
4301 for (i = 1; i <= parsedResult->optionTimes(sENDPOINT); ++i)
4302 {
4303 result = resolveOp(pInfo, pData, parsedResult, sENDPOINT, i);
4304
4305 if (result->rc != kSTAFOk) return false;
4306
4307 logFilter.endpoints.push_back(result->result);
4308 }
4309
4310 for (i = 1; i <= parsedResult->optionTimes(sQHANDLE); ++i)
4311 {
4312 result = resolveOp(pInfo, pData, parsedResult, sQHANDLE, i);
4313
4314 if (result->rc != kSTAFOk) return false;
4315
4316 // Convert resolved option string to an unsigned integer in range
4317 // 1 to UINT_MAX
4318
4319 unsigned int qHandle;
4320
4321 result = convertOptionStringToUInt(
4322 result->result, sQHANDLE, qHandle, 1);
4323
4324 if (result->rc != kSTAFOk) return false;
4325
4326 logFilter.qHandles.push_back(qHandle);
4327 }
4328
4329 if (parsedResult->optionTimes(sLEVELMASK) != 0)
4330 {
4331 result = resolveOp(pInfo, pData, parsedResult, sLEVELMASK);
4332
4333 if (result->rc != kSTAFOk) return false;
4334
4335 if (!convertLogMaskToUInt(result->result, logFilter.levelMask))
4336 {
4337 result->rc = kSTAFLogInvalidLevel;
4338 return false;
4339 }
4340
4341 logFilter.useLevelMask = true;
4342 }
4343
4344 if (parsedResult->optionTimes(sFROM) != 0)
4345 {
4346 result = resolveOp(pInfo, pData, parsedResult, sFROM);
4347
4348 if (result->rc != kSTAFOk) return false;
4349
4350 // Replace case-insensitive occurrence of TODAY with current date
4351 STAFString timestampString = result->result.toUpperCase().replace(
4352 sTODAY, (STAFTimestamp::now().asString()).subString(0, 8));
4353
4354 if (!STAFTimestamp::isValidTimestampString(timestampString,
4355 sTimestampSeps))
4356 {
4357 result->rc = kSTAFInvalidValue;
4358 return false;
4359 }
4360
4361 STAFTimestamp from(timestampString, sTimestampSeps);
4362
4363 logFilter.useFrom = true;
4364 logFilter.fromTimestamp.date = from.asDateString().asUInt();
4365 logFilter.fromTimestamp.seconds = from.asSecondsPastMidnight();
4366 }
4367
4368 if (parsedResult->optionTimes(sAFTER) != 0)
4369 {
4370 result = resolveOp(pInfo, pData, parsedResult, sAFTER);
4371
4372 if (result->rc != kSTAFOk) return false;
4373
4374 // Replace case-insensitive occurrence of TODAY with current date
4375 STAFString timestampString = result->result.toUpperCase().replace(
4376 sTODAY, (STAFTimestamp::now().asString()).subString(0, 8));
4377
4378 if (!STAFTimestamp::isValidTimestampString(timestampString,
4379 sTimestampSeps))
4380 {
4381 result->rc = kSTAFInvalidValue;
4382 return false;
4383 }
4384
4385 STAFTimestamp after(timestampString, sTimestampSeps);
4386
4387 logFilter.useAfter = true;
4388 logFilter.afterTimestamp.date = after.asDateString().asUInt();
4389 logFilter.afterTimestamp.seconds = after.asSecondsPastMidnight();
4390 }
4391
4392 if (parsedResult->optionTimes(sBEFORE) != 0)
4393 {
4394 result = resolveOp(pInfo, pData, parsedResult, sBEFORE);
4395
4396 if (result->rc != kSTAFOk) return false;
4397
4398 // Replace case-insensitive occurrence of TODAY with current date
4399 STAFString timestampString = result->result.toUpperCase().replace(
4400 sTODAY, (STAFTimestamp::now().asString()).subString(0, 8));
4401
4402 if (!STAFTimestamp::isValidTimestampString(timestampString,
4403 sTimestampSeps))
4404 {
4405 result->rc = kSTAFInvalidValue;
4406 return false;
4407 }
4408
4409 STAFTimestamp before(timestampString, sTimestampSeps);
4410
4411 logFilter.useBefore = true;
4412 logFilter.beforeTimestamp.date = before.asDateString().asUInt();
4413 logFilter.beforeTimestamp.seconds = before.asSecondsPastMidnight();
4414 }
4415
4416 if (parsedResult->optionTimes(sTO) != 0)
4417 {
4418 result = resolveOp(pInfo, pData, parsedResult, sTO);
4419
4420 if (result->rc != kSTAFOk) return false;
4421
4422 // Replace case-insensitive occurrence of TODAY with current date
4423 STAFString timestampString = result->result.toUpperCase().replace(
4424 sTODAY, (STAFTimestamp::now().asString()).subString(0, 8));
4425
4426 if (!STAFTimestamp::isValidTimestampString(timestampString,
4427 sTimestampSeps))
4428 {
4429 result->rc = kSTAFInvalidValue;
4430 return false;
4431 }
4432
4433 STAFTimestamp to(timestampString, sTimestampSeps);
4434
4435 logFilter.useTo = true;
4436 logFilter.toTimestamp.date = to.asDateString().asUInt();
4437 logFilter.toTimestamp.seconds = to.asSecondsPastMidnight();
4438 }
4439
4440 return true;
4441 }
4442
4443
updateLogStats(LogStats & logStats,unsigned int logLevel)4444 void updateLogStats(LogStats &logStats, unsigned int logLevel)
4445 {
4446 if (logLevel == 0x00000001) ++logStats.fatal;
4447 else if (logLevel == 0x00000002) ++logStats.error;
4448 else if (logLevel == 0x00000004) ++logStats.warning;
4449 else if (logLevel == 0x00000008) ++logStats.info;
4450 else if (logLevel == 0x00000010) ++logStats.trace;
4451 else if (logLevel == 0x00000020) ++logStats.trace2;
4452 else if (logLevel == 0x00000040) ++logStats.trace3;
4453 else if (logLevel == 0x00000080) ++logStats.debug;
4454 else if (logLevel == 0x00000100) ++logStats.debug2;
4455 else if (logLevel == 0x00000200) ++logStats.debug3;
4456 else if (logLevel == 0x00000400) ++logStats.start;
4457 else if (logLevel == 0x00000800) ++logStats.stop;
4458 else if (logLevel == 0x00001000) ++logStats.pass;
4459 else if (logLevel == 0x00002000) ++logStats.fail;
4460 else if (logLevel == 0x00004000) ++logStats.status;
4461 else if (logLevel == 0x01000000) ++logStats.user1;
4462 else if (logLevel == 0x02000000) ++logStats.user2;
4463 else if (logLevel == 0x04000000) ++logStats.user3;
4464 else if (logLevel == 0x08000000) ++logStats.user4;
4465 else if (logLevel == 0x10000000) ++logStats.user5;
4466 else if (logLevel == 0x20000000) ++logStats.user6;
4467 else if (logLevel == 0x40000000) ++logStats.user7;
4468 else if (logLevel == 0x80000000) ++logStats.user8;
4469 }
4470
4471
4472 // Add log stats in a marshalling context as a map to the logList
4473
addLogStatsToMap(STAFObjectPtr & queryStatsMap,const LogStats & logStats)4474 void addLogStatsToMap(STAFObjectPtr &queryStatsMap, const LogStats &logStats)
4475 {
4476 queryStatsMap->put("fatal", STAFString(logStats.fatal));
4477 queryStatsMap->put("error", STAFString(logStats.error));
4478 queryStatsMap->put("warning", STAFString(logStats.warning));
4479 queryStatsMap->put("info", STAFString(logStats.info));
4480 queryStatsMap->put("trace", STAFString(logStats.trace));
4481 queryStatsMap->put("trace2", STAFString(logStats.trace2));
4482 queryStatsMap->put("trace3", STAFString(logStats.trace3));
4483 queryStatsMap->put("debug", STAFString(logStats.debug));
4484 queryStatsMap->put("debug2", STAFString(logStats.debug2));
4485 queryStatsMap->put("debug3", STAFString(logStats.debug3));
4486 queryStatsMap->put("start", STAFString(logStats.start));
4487 queryStatsMap->put("stop", STAFString(logStats.stop));
4488 queryStatsMap->put("pass", STAFString(logStats.pass));
4489 queryStatsMap->put("fail", STAFString(logStats.fail));
4490 queryStatsMap->put("status", STAFString(logStats.status));
4491 queryStatsMap->put("user1", STAFString(logStats.user1));
4492 queryStatsMap->put("user2", STAFString(logStats.user2));
4493 queryStatsMap->put("user3", STAFString(logStats.user3));
4494 queryStatsMap->put("user4", STAFString(logStats.user4));
4495 queryStatsMap->put("user5", STAFString(logStats.user5));
4496 queryStatsMap->put("user6", STAFString(logStats.user6));
4497 queryStatsMap->put("user7", STAFString(logStats.user7));
4498 queryStatsMap->put("user8", STAFString(logStats.user8));
4499 }
4500
4501
registerHelpData(LogServiceData * pData,unsigned int errorNumber,const STAFString & shortInfo,const STAFString & longInfo)4502 void registerHelpData(LogServiceData *pData, unsigned int errorNumber,
4503 const STAFString &shortInfo, const STAFString &longInfo)
4504 {
4505 static STAFString regString("REGISTER SERVICE %C ERROR %d INFO %C "
4506 "DESCRIPTION %C");
4507
4508 pData->fHandle->submit(sLocal, sHELP, STAFHandle::formatString(
4509 regString.getImpl(), pData->fShortName.getImpl(), errorNumber,
4510 shortInfo.getImpl(), longInfo.getImpl()));
4511 }
4512
4513
unregisterHelpData(LogServiceData * pData,unsigned int errorNumber)4514 void unregisterHelpData(LogServiceData *pData, unsigned int errorNumber)
4515 {
4516 static STAFString regString("UNREGISTER SERVICE %C ERROR %d");
4517
4518 pData->fHandle->submit(sLocal, sHELP, STAFHandle::formatString(
4519 regString.getImpl(), pData->fShortName.getImpl(), errorNumber));
4520 }
4521
4522