00001 #include "otsdaq-utilities/Logbook/LogbookSupervisor.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <dirent.h>
00015 #include <sys/stat.h>
00016
00017
00018 using namespace ots;
00019
00020
00021 const std::string LOGBOOK_PATH = getenv("LOGBOOK_DATA_PATH") + std::string("/");
00022 #define LOGBOOK_EXPERIMENT_LIST_PATH LOGBOOK_PATH + "experiment_list.xml"
00023 #define LOGBOOK_EXPERIMENT_DIR_PREFACE "log_"
00024 #define LOGBOOK_UPLOADS_PATH "uploads/" //within experiment directory
00025 #define LOGBOOK_LOGBOOKS_PATH "logbooks/"
00026 #define LOGBOOK_PREVIEWS_PATH "previews/"
00027 #define LOGBOOK_FILE_PREFACE "entries_"
00028 #define LOGBOOK_FILE_EXTENSION ".xml"
00029
00030 #define ACTIVE_EXPERIMENT_PATH LOGBOOK_PATH + "active_experiment.txt"
00031 #define REMOVE_EXPERIMENT_LOG_PATH LOGBOOK_PATH + "removed_experiments.log"
00032
00033 #define XML_ADMIN_STATUS "logbook_admin_status"
00034 #define XML_STATUS "logbook_status"
00035 #define XML_MOST_RECENT_DAY "most_recent_day"
00036 #define XML_EXPERIMENTS_ROOT "experiments"
00037 #define XML_EXPERIMENT "experiment"
00038 #define XML_ACTIVE_EXPERIMENT "active_experiment"
00039 #define XML_EXPERIMENT_CREATE "create_time"
00040 #define XML_EXPERIMENT_CREATOR "creator"
00041
00042 #define XML_LOGBOOK_ENTRY "logbook_entry"
00043 #define XML_LOGBOOK_ENTRY_SUBJECT "logbook_entry_subject"
00044 #define XML_LOGBOOK_ENTRY_TEXT "logbook_entry_text"
00045 #define XML_LOGBOOK_ENTRY_FILE "logbook_entry_file"
00046 #define XML_LOGBOOK_ENTRY_TIME "logbook_entry_time"
00047 #define XML_LOGBOOK_ENTRY_CREATOR "logbook_entry_creator"
00048 #define XML_LOGBOOK_ENTRY_HIDDEN "logbook_entry_hidden"
00049 #define XML_LOGBOOK_ENTRY_HIDER "logbook_entry_hider"
00050 #define XML_LOGBOOK_ENTRY_HIDDEN_TIME "logbook_entry_hidden_time"
00051
00052 #define XML_PREVIEW_INDEX "preview_index"
00053 #define LOGBOOK_PREVIEW_FILE "preview.xml"
00054 #define LOGBOOK_PREVIEW_UPLOAD_PREFACE "upload_"
00055
00056 XDAQ_INSTANTIATOR_IMPL(LogbookSupervisor)
00057
00058 #undef __MF_SUBJECT__
00059 #define __MF_SUBJECT__ "Logbook"
00060
00061
00062
00063
00064 int sendmail(const char *to, const char *from, const char *subject, const char *message)
00065 {
00066 int retval = -1;
00067 FILE *mailpipe = popen("/usr/lib/sendmail -t", "w");
00068 if (mailpipe != NULL) {
00069 fprintf(mailpipe, "To: %s\n", to);
00070 fprintf(mailpipe, "From: %s\n", from);
00071 fprintf(mailpipe, "Subject: %s\n\n", subject);
00072 fwrite(message, 1, strlen(message), mailpipe);
00073 fwrite(".\n", 1, 2, mailpipe);
00074 pclose(mailpipe);
00075 retval = 0;
00076 }
00077 else {
00078 perror("Failed to invoke sendmail");
00079 }
00080 return retval;
00081 }
00082
00083
00084
00085
00086 LogbookSupervisor::LogbookSupervisor(xdaq::ApplicationStub* stub)
00087 : CoreSupervisorBase(stub)
00088 , allowedFileUploadTypes_({"image/png","image/jpeg","image/gif","image/bmp","application/pdf","application/zip","text/plain"})
00089 , matchingFileUploadTypes_({"png","jpeg","gif","bmp","pdf","zip","txt"})
00090 {
00091 INIT_MF("LogbookSupervisor");
00092
00093
00094
00095
00096
00097
00098 xoap::bind(this, &LogbookSupervisor::MakeSystemLogbookEntry, "MakeSystemLogbookEntry" , XDAQ_NS_URI);
00099
00100 init();
00101
00102
00103
00104 }
00105
00106
00107 LogbookSupervisor::~LogbookSupervisor(void)
00108 {
00109 destroy();
00110 }
00111
00112 void LogbookSupervisor::init(void)
00113 {
00114
00115
00116
00117
00118 if(1)
00119 {
00120 std::string path = LOGBOOK_PATH;
00121 DIR *dir = opendir(path.c_str());
00122 if(dir)
00123 closedir(dir);
00124 else if(-1 == mkdir(path.c_str(),0755))
00125 {
00126
00127 std::stringstream ss;
00128 ss << __COUT_HDR_FL__ << "Service directory creation failed: " <<
00129 path << std::endl;
00130 __SS_THROW__;
00131 }
00132
00133 path = LOGBOOK_PATH + LOGBOOK_UPLOADS_PATH;
00134 dir = opendir(path.c_str());
00135 if(dir)
00136 closedir(dir);
00137 else if(-1 == mkdir((path).c_str(),0755))
00138 {
00139
00140 __SS__ << "Service directory creation failed: " <<
00141 path << std::endl;
00142 __SS_THROW__;
00143 }
00144
00145 path = LOGBOOK_PATH + LOGBOOK_LOGBOOKS_PATH;
00146 dir = opendir(path.c_str());
00147 if(dir)
00148 closedir(dir);
00149 else if(-1 == mkdir(path.c_str(),0755))
00150 {
00151
00152 __SS__ << "Service directory creation failed: " <<
00153 path << std::endl;
00154 __SS_THROW__;
00155 }
00156 }
00157
00158 getActiveExperiment();
00159 __COUT__ << "Active Experiment is " << activeExperiment_ << std::endl;
00160 mostRecentDayIndex_ = 0;
00161
00162 }
00163
00164
00165 void LogbookSupervisor::destroy(void)
00166 {
00167
00168 }
00169
00170
00171 void LogbookSupervisor::defaultPage(xgi::Input * in, xgi::Output * out )
00172 {
00173 __COUT__ << " active experiment " << activeExperiment_ << std::endl;
00174 *out << "<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame src='/WebPath/html/Logbook.html?urn=" <<
00175 this->getApplicationDescriptor()->getLocalId() << "&active_experiment=" << activeExperiment_ << "'></frameset></html>";
00176 }
00177
00178
00179
00180
00181
00182 void LogbookSupervisor::setSupervisorPropertyDefaults()
00183 {
00184 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold, std::string() +
00185 "*=1 | CreateExperiment=-1 | RemoveExperiment=-1 | GetExperimentListAdmin=-1 | SetActiveExperiment=-1" +
00186 " | AdminRemoveRestoreEntry=-1");
00187 }
00188
00189
00190
00191
00192 void LogbookSupervisor::forceSupervisorPropertyValues()
00193 {
00194 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
00195 "RefreshLogbook");
00196 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NonXMLRequestTypes,
00197 "LogImage | LogReport");
00198
00199
00200 }
00201
00202
00203
00204
00205
00206 void LogbookSupervisor::request(const std::string& requestType, cgicc::Cgicc& cgiIn,
00207 HttpXmlDocument& xmlOut, const WebUsers::RequestUserInfo& userInfo)
00208 {
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 if(requestType == "CreateExperiment")
00268 {
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 std::string creator = userInfo.username_;
00286
00287 createExperiment(CgiDataUtilities::postData(cgiIn,"Experiment"), creator, &xmlOut);
00288
00289 __COUT__ << "Created" << std::endl;
00290 }
00291 else if(requestType == "RemoveExperiment")
00292 {
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 std::string remover = userInfo.username_;
00303 removeExperiment(CgiDataUtilities::postData(cgiIn,"Experiment"), remover, &xmlOut);
00304 }
00305 else if(requestType == "GetExperimentList")
00306 {
00307
00308 if(userInfo.permissionLevel_ >=
00309 CoreSupervisorBase::getSupervisorPropertyUserPermissionsThreshold("GetExperimentListAdmin"))
00310 {
00311 xmlOut.addTextElementToData("is_admin","0");
00312 return;
00313 }
00314
00315
00316 xmlOut.addTextElementToData("is_admin","1");
00317 getExperiments(&xmlOut);
00318 }
00319 else if(requestType == "SetActiveExperiment")
00320 {
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 webUserSetActiveExperiment(CgiDataUtilities::postData(cgiIn,"Experiment"), &xmlOut);
00331 }
00332 else if(requestType == "RefreshLogbook")
00333 {
00334
00335
00336 std::string Date = CgiDataUtilities::postData(cgiIn,"Date");
00337 std::string Duration = CgiDataUtilities::postData(cgiIn,"Duration");
00338
00339 time_t date;
00340 unsigned char duration;
00341 sscanf(Date.c_str(),"%li",&date);
00342 sscanf(Duration.c_str(),"%hhu",&duration);
00343
00344 __COUT__ << "date " << date << " duration " << (int)duration << std::endl;
00345 std::stringstream str;
00346 refreshLogbook(date, duration, &xmlOut, (std::ostringstream *)&str);
00347 __COUT__ << str.str() << std::endl;
00348 }
00349 else if(requestType == "PreviewEntry")
00350 {
00351
00352
00353
00354
00355
00356
00357 cleanUpPreviews();
00358 std::string EntryText = cgiIn("EntryText");
00359 __COUT__ << "EntryText " << EntryText << std::endl << std::endl;
00360 std::string EntrySubject = cgiIn("EntrySubject");
00361 __COUT__ << "EntrySubject " << EntrySubject << std::endl << std::endl;
00362
00363
00364 std::string creator = userInfo.username_;
00365
00366 savePostPreview(EntrySubject,EntryText,cgiIn.getFiles(),creator,&xmlOut);
00367
00368 }
00369 else if(requestType == "ApproveEntry")
00370 {
00371
00372
00373
00374 std::string PreviewNumber = CgiDataUtilities::postData(cgiIn,"PreviewNumber");
00375 std::string Approve = CgiDataUtilities::postData(cgiIn,"Approve");
00376
00377 movePreviewEntry(PreviewNumber,Approve=="1",&xmlOut);
00378 }
00379 else if(requestType == "AdminRemoveRestoreEntry")
00380 {
00381
00382
00383
00384
00385
00386
00387 std::string EntryId = CgiDataUtilities::postData(cgiIn,"EntryId");
00388 bool Hide = CgiDataUtilities::postData(cgiIn,"Hide")=="1"?true:false;
00389
00390
00391 std::string hider = userInfo.username_;
00392
00393 hideLogbookEntry(EntryId,Hide,hider);
00394
00395 xmlOut.addTextElementToData(XML_ADMIN_STATUS,"1");
00396 }
00397 else
00398 __COUT__ << "requestType request not recognized." << std::endl;
00399 }
00400
00401
00402
00403
00404
00405 void LogbookSupervisor::nonXmlRequest(const std::string& requestType, cgicc::Cgicc& cgiIn,
00406 std::ostream& out, const WebUsers::RequestUserInfo& userInfo)
00407 {
00408
00409
00410
00411
00412 if(requestType == "LogImage")
00413 {
00414 std::string src = CgiDataUtilities::getData(cgiIn,"src");
00415 __COUT__ << " Get Log Image " << src << std::endl;
00416
00417 out << "<!DOCTYPE HTML><html lang='en'><frameset col='100%' row='100%'><frame src='/WebPath/html/LogbookImage.html?urn=" <<
00418 this->getApplicationDescriptor()->getLocalId() << "&src=" << src << "'></frameset></html>";
00419 }
00420 else if(requestType == "LogReport")
00421 {
00422 std::string activeExperiment = CgiDataUtilities::getData(cgiIn,"activeExperiment");
00423 __COUT__ << " Start Log Report for " << activeExperiment << std::endl;
00424
00425 out << "<!DOCTYPE HTML><html lang='en'><header><title>ots Logbook Reports</title></header><frameset col='100%' row='100%'><frame src='/WebPath/html/LogbookReport.html?urn=" <<
00426 this->getApplicationDescriptor()->getLocalId() << "&activeExperiment=" << activeExperiment << "'></frameset></html>";
00427 }
00428 else
00429 __COUT__ << "requestType request not recognized." << std::endl;
00430 }
00431
00432
00433
00434
00435
00436 xoap::MessageReference LogbookSupervisor::MakeSystemLogbookEntry (xoap::MessageReference msg)
00437 {
00438 SOAPParameters parameters("EntryText");
00439
00440
00441 SOAPUtilities::receive(msg, parameters);
00442 std::string EntryText = parameters.getValue("EntryText");
00443
00444 __COUT__ << "Received External Supervisor System Entry " << EntryText << std::endl;
00445 __COUT__ << "Active Experiment is " << activeExperiment_ << std::endl;
00446
00447 std::string retStr = "Success";
00448
00449
00450 std::string logPath, logDirPath = (std::string)LOGBOOK_PATH + (std::string)LOGBOOK_LOGBOOKS_PATH +
00451 (std::string)LOGBOOK_EXPERIMENT_DIR_PREFACE + activeExperiment_;
00452
00453
00454 char dayIndexStr[20];
00455 HttpXmlDocument logXml;
00456 char fileIndex[40];
00457 xercesc::DOMElement* entryEl;
00458 DIR *dir;
00459
00460 if(activeExperiment_ == "")
00461 {
00462 retStr = "Warning - Currently, no Active Experiment.";
00463 __COUT__ << retStr << std::endl;
00464 goto XOAP_CLEANUP;
00465 }
00466
00467
00468 dir = opendir(logDirPath.c_str());
00469 if(!dir)
00470 {
00471 retStr = "Error - Active Experiment directory missing.";
00472 __COUT__ << retStr << std::endl;
00473 goto XOAP_CLEANUP;
00474 }
00475 closedir(dir);
00476
00477 sprintf(dayIndexStr,"%6.6lu",time(0)/(60*60*24));
00478
00479 logPath = logDirPath + "/" + LOGBOOK_FILE_PREFACE + activeExperiment_ + "_" + (std::string)dayIndexStr + LOGBOOK_FILE_EXTENSION;
00480 __COUT__ << "logPath " << logPath << std::endl;
00481
00482 logXml.loadXmlDocument(logPath);
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 entryEl = logXml.addTextElementToData(XML_LOGBOOK_ENTRY);
00494
00495 sprintf(fileIndex,"%lu_%lu",time(0),clock());
00496 logXml.addTextElementToParent(XML_LOGBOOK_ENTRY_TIME, fileIndex, entryEl);
00497 logXml.addTextElementToParent(XML_LOGBOOK_ENTRY_CREATOR, "SYSTEM LOG", entryEl);
00498 logXml.addTextElementToParent(XML_LOGBOOK_ENTRY_TEXT, EntryText, entryEl);
00499 logXml.addTextElementToParent(XML_LOGBOOK_ENTRY_SUBJECT, "System Log", entryEl);
00500
00501 logXml.saveXmlDocument(logPath);
00502
00503 XOAP_CLEANUP:
00504
00505
00506 SOAPParameters retParameters("Status",retStr);
00507
00508
00509
00510
00511 return SOAPUtilities::makeSOAPMessageReference("LogbookEntryStatusResponse",retParameters);
00512 }
00513
00514
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 std::string LogbookSupervisor::getActiveExperiment()
00549 {
00550 FILE *fp = fopen(std::string((std::string)ACTIVE_EXPERIMENT_PATH).c_str(),"r");
00551 if(!fp) activeExperiment_ = "";
00552 else
00553 {
00554 char line[100];
00555 if(!fgets(line,100,fp)) line[0] = '\0';
00556 fclose(fp);
00557
00558
00559 if(line[strlen(line)-2] == '\r')
00560 line[strlen(line)-2] = '\0';
00561 else if(line[strlen(line)-1] == '\n')
00562 line[strlen(line)-1] = '\0';
00563
00564 activeExperiment_ = line;
00565 }
00566
00567 return activeExperiment_;
00568 }
00569
00570
00571
00572
00573 void LogbookSupervisor::setActiveExperiment(std::string experiment)
00574 {
00575 FILE *fp = fopen(std::string((std::string)ACTIVE_EXPERIMENT_PATH).c_str(),"w");
00576 if(!fp)
00577 {
00578 __COUT__ << "FATAL ERROR!!! - file write" << std::endl;
00579 return;
00580 }
00581
00582 fprintf(fp,"%s",experiment.c_str());
00583 fclose(fp);
00584
00585 if(activeExperiment_ != "" && activeExperiment_ != experiment)
00586 theRemoteWebUsers_.makeSystemLogbookEntry(
00587 allSupervisorInfo_.getGatewayDescriptor(),
00588 "Experiment was made inactive.");
00589
00590 bool entryNeeded = false;
00591 if(experiment != "" && activeExperiment_ != experiment)
00592 entryNeeded = true;
00593
00594 activeExperiment_ = experiment;
00595 __COUT__ << "Active Experiment set to " << activeExperiment_ << std::endl;
00596
00597 if(entryNeeded)
00598 theRemoteWebUsers_.makeSystemLogbookEntry(
00599 allSupervisorInfo_.getGatewayDescriptor(),
00600 "Experiment was made active.");
00601
00602 }
00603
00604
00605
00606
00607 bool LogbookSupervisor::validateExperimentName(std::string &exp)
00608 {
00609 if(exp.length() < EXPERIMENT_NAME_MIN_LENTH || exp.length() > EXPERIMENT_NAME_MAX_LENTH) return false;
00610 for(int i=0;i<(int)exp.length();++i)
00611 if(!(
00612 (exp[i] >= 'a' && exp[i] <= 'z') ||
00613 (exp[i] >= 'A' && exp[i] <= 'Z') ||
00614 (exp[i] >= '0' && exp[i] <= '9') ||
00615 (exp[i] == '-' || exp[i] == '_') ) )
00616 { exp = exp.substr(0,i) + exp.substr(i+1); --i; }
00617
00618 return true;
00619 }
00620
00621
00622
00623
00624
00625 void LogbookSupervisor::getExperiments(HttpXmlDocument *xmlOut, std::ostringstream *out)
00626 {
00627
00628 HttpXmlDocument expXml;
00629 if(!expXml.loadXmlDocument((std::string)LOGBOOK_EXPERIMENT_LIST_PATH))
00630 {
00631 __COUT__ << "Fatal Error - Experiment database." << std::endl;
00632 __COUT__ << "Creating empty experiment database." << std::endl;
00633
00634 expXml.addTextElementToData((std::string)XML_EXPERIMENTS_ROOT);
00635 expXml.saveXmlDocument((std::string)LOGBOOK_EXPERIMENT_LIST_PATH);
00636 return;
00637 }
00638
00639 std::vector<std::string> exps;
00640 expXml.getAllMatchingValues(XML_EXPERIMENT,exps);
00641
00642 if(xmlOut) xmlOut->addTextElementToData(XML_ACTIVE_EXPERIMENT, activeExperiment_);
00643
00644 for(unsigned int i=0;i<exps.size();++i)
00645 {
00646 if(xmlOut) xmlOut->addTextElementToData(XML_EXPERIMENT, exps[i]);
00647 if(out) *out << exps[i] << std::endl;
00648 }
00649 }
00650
00651
00652
00653 void LogbookSupervisor::createExperiment(std::string experiment, std::string creator, HttpXmlDocument *xmlOut)
00654 {
00655 if(!validateExperimentName(experiment))
00656 {
00657 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Error - Experiment name must be 3-25 characters.");
00658 return;
00659 }
00660
00661 __COUT__ << "experiment " << experiment << std::endl;
00662
00663
00664 std::string dirPath = (std::string)LOGBOOK_PATH + (std::string)LOGBOOK_LOGBOOKS_PATH +
00665 (std::string)LOGBOOK_EXPERIMENT_DIR_PREFACE + experiment;
00666
00667 __COUT__ << "dirPath " << dirPath << std::endl;
00668
00669 bool directoryExists = false;
00670 DIR *dir = opendir(dirPath.c_str());
00671 if(dir)
00672 {
00673 closedir(dir);
00674 directoryExists = true;
00675 }
00676
00677
00678 HttpXmlDocument expXml;
00679 if(!expXml.loadXmlDocument((std::string)LOGBOOK_EXPERIMENT_LIST_PATH))
00680 {
00681 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Fatal Error - Experiment database.");
00682 return;
00683 }
00684
00685 std::vector<std::string> exps;
00686 expXml.getAllMatchingValues(XML_EXPERIMENT,exps);
00687
00688 for(unsigned int i=0;i<exps.size();++i)
00689 if(experiment == exps[i])
00690 {
00691 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Failed - Experiment, " + experiment + ", already exists.");
00692 return;
00693 }
00694 __COUT__ << "experiments count: " << exps.size() << std::endl;
00695
00696
00697
00698
00699
00700
00701
00702
00703 xercesc::DOMElement* expEl = expXml.addTextElementToParent(XML_EXPERIMENT, experiment, XML_EXPERIMENTS_ROOT);
00704 char createTime[20];
00705 sprintf(createTime,"%lu",time(0));
00706 expXml.addTextElementToParent(XML_EXPERIMENT_CREATE, createTime, expEl);
00707 expXml.addTextElementToParent(XML_EXPERIMENT_CREATOR, creator, expEl);
00708 expXml.saveXmlDocument((std::string)LOGBOOK_EXPERIMENT_LIST_PATH);
00709
00710
00711 if(directoryExists)
00712 {
00713
00714
00715 dirPath += "/" + (std::string)LOGBOOK_UPLOADS_PATH;
00716 __COUT__ << "Checking uploads directory" << std::endl;
00717
00718 directoryExists = false;
00719 dir = opendir(dirPath.c_str());
00720 if(!dir)
00721 {
00722 __COUT__ << "Creating uploads directory" << std::endl;
00723 if(-1 == mkdir(dirPath.c_str(),0755))
00724 {
00725 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Failed - uploads directory for " + experiment + " was not created.");
00726 __COUT__ << "Uploads directory failure." << std::endl;
00727 return;
00728 }
00729 }
00730 else
00731 closedir(dir);
00732
00733 xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Directory already exists for " + experiment +
00734 ", re-added to list of experiments.");
00735 return;
00736 }
00737 __COUT__ << "Creating experiment and uploads directory at: " <<
00738 dirPath << std::endl;
00739 if(-1 == mkdir(dirPath.c_str(),0755) ||
00740 -1 == mkdir((dirPath + "/" +
00741 (std::string)LOGBOOK_UPLOADS_PATH).c_str(),0755))
00742 {
00743 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Failed - directory, " + experiment + ", could not be created.");
00744 return;
00745 }
00746
00747 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Experiment, " + experiment + ", successfully created.");
00748 }
00749
00750
00751
00752
00753
00754 void LogbookSupervisor::webUserSetActiveExperiment(std::string experiment, HttpXmlDocument *xmlOut)
00755 {
00756 if(experiment == "")
00757 {
00758 setActiveExperiment(experiment);
00759 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Active experiment cleared successfully.");
00760 }
00761
00762
00763 HttpXmlDocument expXml;
00764 if(!expXml.loadXmlDocument((std::string)LOGBOOK_EXPERIMENT_LIST_PATH))
00765 {
00766 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Fatal Error - Experiment database.");
00767 return;
00768 }
00769 std::vector<std::string> exps;
00770 expXml.getAllMatchingValues(XML_EXPERIMENT,exps);
00771
00772 unsigned int i;
00773 for(i=0;i<exps.size();++i)
00774 if(experiment == exps[i]) break;
00775
00776 if(i == exps.size())
00777 {
00778 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Failed - Experiment, " + experiment + ", not found.");
00779 return;
00780 }
00781
00782
00783 setActiveExperiment(experiment);
00784 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Active experiment set to " + experiment + " successfully.");
00785 }
00786
00787
00788
00789
00790
00791 void LogbookSupervisor::removeExperiment(std::string experiment, std::string remover, HttpXmlDocument *xmlOut)
00792 {
00793 __COUT__ << "experiment " << experiment << std::endl;
00794
00795
00796 HttpXmlDocument expXml;
00797 if(!expXml.loadXmlDocument((std::string)LOGBOOK_EXPERIMENT_LIST_PATH))
00798 {
00799 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Fatal Error - Experiment database.");
00800 return;
00801 }
00802 std::vector<std::string> exps;
00803 expXml.getAllMatchingValues(XML_EXPERIMENT,exps);
00804
00805 unsigned int i;
00806 for(i=0;i<exps.size();++i)
00807 if(experiment == exps[i]) break;
00808
00809 if(i == exps.size())
00810 {
00811 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Failed - Experiment, " + experiment + ", not found.");
00812 return;
00813 }
00814
00815
00816
00817
00818 xercesc::DOMElement* parent = expXml.getMatchingElement(XML_EXPERIMENTS_ROOT);
00819 xercesc::DOMElement* child = expXml.getMatchingElement(XML_EXPERIMENT,i);
00820 __COUT__ << "experiments original count: " << expXml.getChildrenCount(parent) << std::endl;
00821 expXml.recursiveRemoveChild(child, parent);
00822 __COUT__ << "experiments new count: " << expXml.getChildrenCount(parent) << std::endl;
00823
00824
00825 FILE *fp = fopen(((std::string)REMOVE_EXPERIMENT_LOG_PATH).c_str(),"a");
00826 if(!fp)
00827 {
00828 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Fatal Error - Remove log.");
00829 return;
00830 }
00831 fprintf(fp,"%s -- %s Experiment removed by %s.\n",asctime(localtime(&((time_t const&)(time(0))))),
00832 experiment.c_str(), remover.c_str());
00833 fclose(fp);
00834
00835 expXml.saveXmlDocument((std::string)LOGBOOK_EXPERIMENT_LIST_PATH);
00836
00837
00838 if(activeExperiment_ == experiment)
00839 setActiveExperiment();
00840
00841 if(xmlOut) xmlOut->addTextElementToData(XML_ADMIN_STATUS,"Experiment, " + experiment + ", successfully removed.");
00842 }
00843
00844
00845
00846
00847
00848
00849
00850 void LogbookSupervisor::refreshLogbook(time_t date, unsigned char duration,
00851 HttpXmlDocument *xmlOut, std::ostringstream *out, std::string experiment)
00852 {
00853 if(experiment == "") experiment = activeExperiment_;
00854 if(xmlOut) xmlOut->addTextElementToData(XML_ACTIVE_EXPERIMENT,experiment);
00855
00856
00857 std::string dirPath = (std::string)LOGBOOK_PATH + (std::string)LOGBOOK_LOGBOOKS_PATH +
00858 (std::string)LOGBOOK_EXPERIMENT_DIR_PREFACE + experiment;
00859
00860 if(out) *out << __COUT_HDR_FL__ << "dirPath " << dirPath << std::endl;
00861
00862 DIR *dir = opendir(dirPath.c_str());
00863 if(!dir)
00864 {
00865 if(xmlOut) xmlOut->addTextElementToData(XML_STATUS,"Error - Directory for experiment, " + experiment + ", missing.");
00866 if(out) *out << __COUT_HDR_FL__ << "Error - Directory missing" << std::endl;
00867 return;
00868 }
00869
00870 unsigned int baseDay;
00871
00872 if(!date)
00873 {
00874 struct dirent *drnt;
00875 unsigned int extractedDay;
00876 int start, finish;
00877
00878 mostRecentDayIndex_ = 0;
00879 while ((drnt=readdir(dir))){
00880
00881
00882 if(strcmp(&(drnt->d_name[strlen(drnt->d_name)-4]),".xml")) continue;
00883
00884 for(finish=strlen(drnt->d_name)-1;finish>0;--finish)
00885 if(drnt->d_name[finish] == '.') break;
00886 if(finish == 0)
00887 {
00888 if(out) *out << __COUT_HDR_FL__ << "failed to find day index finish " << std::endl;
00889 return;
00890 }
00891 for(start=finish-1;start>0;--start)
00892 if(drnt->d_name[start-1] == '_') break;
00893 if(start == 0)
00894 {
00895 if(out) *out << __COUT_HDR_FL__ << "failed to find day index start " << std::endl;
00896 return;
00897 }
00898 drnt->d_name[finish] = '\0';
00899 extractedDay = atoi((char *)(&(drnt->d_name[start])));
00900
00901 if(!mostRecentDayIndex_ || mostRecentDayIndex_ < extractedDay) mostRecentDayIndex_ = extractedDay;
00902 }
00903 if(out) *out << __COUT_HDR_FL__ << "dirContents done, found most recent day: " << mostRecentDayIndex_ << std::endl;
00904
00905 baseDay = mostRecentDayIndex_;
00906 }
00907 else
00908 baseDay = (date/(60*60*24));
00909 closedir(dir);
00910
00911 std::string entryPath;
00912 char dayIndexStr[20];
00913 FILE *fp;
00914
00915
00916
00917
00918 for(unsigned char i=duration;i!=0;--i)
00919 {
00920 sprintf(dayIndexStr,"%6.6u",baseDay-i+1);
00921 entryPath = dirPath + "/" + LOGBOOK_FILE_PREFACE + experiment + "_" + (std::string)dayIndexStr + LOGBOOK_FILE_EXTENSION;
00922
00923 if(out) *out << __COUT_HDR_FL__ << "Directory Entry " << entryPath << std::endl;
00924
00925 fp = fopen(entryPath.c_str(),"r");
00926 if(!fp)
00927 {
00928 if(out) *out << __COUT_HDR_FL__ << "File not found" << std::endl;
00929 continue;
00930 }
00931 fclose(fp);
00932
00933
00934
00935 HttpXmlDocument logXml;
00936 if(!logXml.loadXmlDocument(entryPath))
00937 {
00938 if(xmlOut) xmlOut->addTextElementToData(XML_STATUS,"Critical Failure - log did not load. Notify admins.");
00939 if(out) *out << __COUT_HDR_FL__ << "Failure - log XML did not load" << std::endl;
00940 return;
00941 }
00942
00943 if(xmlOut) xmlOut->copyDataChildren(logXml);
00944 }
00945
00946 if(xmlOut) xmlOut->addTextElementToData(XML_STATUS,"1");
00947 if(out) *out << __COUT_HDR_FL__ << "Today: " << time(0)/(60*60*24) << std::endl;
00948
00949 sprintf(dayIndexStr,"%lu",time(0)/(60*60*24) - mostRecentDayIndex_);
00950 if(xmlOut) xmlOut->addTextElementToData(XML_MOST_RECENT_DAY,dayIndexStr);
00951 }
00952
00953
00954
00955
00956
00957 void LogbookSupervisor::cleanUpPreviews()
00958 {
00959 std::string previewPath = (std::string)LOGBOOK_PATH + (std::string)LOGBOOK_PREVIEWS_PATH;
00960
00961 DIR *dir = opendir(previewPath.c_str());
00962 if(!dir)
00963 {
00964 __COUT__ << "Error - Previews directory missing: " << previewPath << std::endl;
00965 return;
00966 }
00967
00968 struct dirent *entry;
00969 time_t dirCreateTime;
00970 unsigned int i;
00971
00972 while((entry = readdir(dir)))
00973 {
00974 if( strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0
00975 && strcmp(entry->d_name, ".svn") != 0 )
00976 {
00977
00978 for(i=0;i<strlen(entry->d_name);++i)
00979 if(entry->d_name[i] == '_')
00980 { entry->d_name[i] = ' '; break; }
00981 sscanf(entry->d_name,"%li",&dirCreateTime);
00982
00983 if((time(0) - dirCreateTime) > LOGBOOK_PREVIEW_EXPIRATION_TIME)
00984 {
00985 __COUT__ << "Expired" << std::endl;
00986
00987 entry->d_name[i] = '_';
00988
00989 __COUT__ << "rm -rf " << previewPath + (std::string)entry->d_name << std::endl << std::endl;
00990 system(((std::string)("rm -rf " + previewPath + (std::string)entry->d_name)).c_str());
00991 }
00992 }
00993 }
00994
00995 closedir(dir);
00996 }
00997
00998
00999
01000
01001
01002 void LogbookSupervisor::savePostPreview(std::string &subject, std::string &text, const std::vector<cgicc::FormFile> &files, std::string creator,
01003 HttpXmlDocument *xmlOut)
01004 {
01005 if(activeExperiment_ == "")
01006 {
01007 if(xmlOut) xmlOut->addTextElementToData(XML_STATUS,"Failed - no active experiment currently!");
01008 return;
01009 }
01010
01011 char fileIndex[40];
01012 sprintf(fileIndex,"%lu_%lu",time(0),clock());
01013 std::string previewPath = (std::string)LOGBOOK_PATH + (std::string)LOGBOOK_PREVIEWS_PATH + (std::string)fileIndex;
01014
01015 __COUT__ << "previewPath " << previewPath << std::endl;
01016 if(-1 == mkdir(previewPath.c_str(),0755))
01017 {
01018 if(xmlOut) xmlOut->addTextElementToData(XML_STATUS,"Failed - preview could not be generated.");
01019 return;
01020 }
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 escapeLogbookEntry(text);
01034 escapeLogbookEntry(subject);
01035 __COUT__ << "~~subject " << subject << std::endl << "~~text " << text << std::endl << std::endl;
01036
01037 HttpXmlDocument previewXml;
01038
01039 previewXml.addTextElementToData(XML_LOGBOOK_ENTRY);
01040 previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_TIME, fileIndex, XML_LOGBOOK_ENTRY);
01041 if(xmlOut) xmlOut->addTextElementToData(XML_LOGBOOK_ENTRY_TIME,fileIndex);
01042 previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_CREATOR, creator, XML_LOGBOOK_ENTRY);
01043 if(xmlOut) xmlOut->addTextElementToData(XML_LOGBOOK_ENTRY_CREATOR,creator);
01044 previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_TEXT, text, XML_LOGBOOK_ENTRY);
01045 if(xmlOut) xmlOut->addTextElementToData(XML_LOGBOOK_ENTRY_TEXT,text);
01046 previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_SUBJECT, subject, XML_LOGBOOK_ENTRY);
01047 if(xmlOut) xmlOut->addTextElementToData(XML_LOGBOOK_ENTRY_SUBJECT,subject);
01048
01049 __COUT__ << "file size " << files.size() << std::endl;
01050
01051 std::string filename;
01052 std::ofstream myfile;
01053 for (unsigned int i=0; i<files.size(); ++i)
01054 {
01055
01056 previewXml.addTextElementToParent(XML_LOGBOOK_ENTRY_FILE, files[i].getDataType(), XML_LOGBOOK_ENTRY);
01057 if(xmlOut) xmlOut->addTextElementToData(XML_LOGBOOK_ENTRY_FILE,files[i].getDataType());
01058
01059 if((filename = validateUploadFileType(files[i].getDataType())) == "")
01060 {
01061 if(xmlOut) xmlOut->addTextElementToData(XML_STATUS,"Failed - invalid file type, " +
01062 files[i].getDataType() + ".");
01063 return;
01064 }
01065
01066
01067 sprintf(fileIndex,"%d",i);
01068 filename = previewPath + "/" + (std::string)LOGBOOK_PREVIEW_UPLOAD_PREFACE +
01069 (std::string)fileIndex + "." + filename;
01070
01071 __COUT__ << "file " << i << " - " << filename << std::endl;
01072 myfile.open(filename.c_str());
01073 if (myfile.is_open())
01074 {
01075 files[i].writeToStream(myfile);
01076 myfile.close();
01077 }
01078 }
01079
01080
01081 previewXml.saveXmlDocument(previewPath + "/" + (std::string)LOGBOOK_PREVIEW_FILE);
01082
01083 if(xmlOut) xmlOut->addTextElementToData(XML_STATUS,"1");
01084 if(xmlOut) xmlOut->addTextElementToData(XML_PREVIEW_INDEX,"1");
01085 }
01086
01087
01088
01089
01090
01091
01092
01093 void LogbookSupervisor::movePreviewEntry(std::string previewNumber, bool approve,
01094 HttpXmlDocument *xmlOut)
01095 {
01096
01097 __COUT__ << "previewNumber " << previewNumber << (approve?" Accepted":" Cancelled") << std::endl;
01098
01099 std::string sysCmd, previewPath = (std::string)LOGBOOK_PATH + (std::string)LOGBOOK_PREVIEWS_PATH + previewNumber;
01100
01101 if (approve) {
01102
01103
01104 HttpXmlDocument previewXml;
01105 previewXml.loadXmlDocument(previewPath + "/" + (std::string)LOGBOOK_PREVIEW_FILE);
01106
01107 std::string logPath, logDirPath = (std::string)LOGBOOK_PATH + (std::string)LOGBOOK_LOGBOOKS_PATH +
01108 (std::string)LOGBOOK_EXPERIMENT_DIR_PREFACE + activeExperiment_;
01109
01110
01111 DIR *dir = opendir(logDirPath.c_str());
01112 if(!dir)
01113 {
01114 __COUT__ << "Error - Active Experiment directory missing: " << logPath << std::endl;
01115 return;
01116 }
01117 closedir(dir);
01118
01119 char dayIndexStr[20];
01120 sprintf(dayIndexStr,"%6.6lu",time(0)/(60*60*24));
01121
01122 logPath = logDirPath + "/" + LOGBOOK_FILE_PREFACE + activeExperiment_ + "_" + (std::string)dayIndexStr + LOGBOOK_FILE_EXTENSION;
01123 __COUT__ << "logPath " << logPath << std::endl;
01124
01125 HttpXmlDocument logXml;
01126 logXml.loadXmlDocument(logPath);
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 logXml.copyDataChildren(previewXml);
01138 logXml.saveXmlDocument(logPath);
01139
01140
01141 std::vector<std::string> fileTypes;
01142 previewXml.getAllMatchingValues(XML_LOGBOOK_ENTRY_FILE,fileTypes);
01143 std::string entryTimeLabel = previewXml.getMatchingValue(XML_LOGBOOK_ENTRY_TIME);
01144 std::string fileExtension, previewFilename, logFilename;
01145 char fileIndex[10];
01146 for(unsigned int i=0;i<fileTypes.size();++i)
01147 {
01148 if((fileExtension = validateUploadFileType(fileTypes[i])) == "")
01149 {
01150 __COUT__ << "Failed - invalid file type: " << fileTypes[i] << std::endl;
01151 continue;
01152 }
01153
01154
01155 sprintf(fileIndex,"%d",i);
01156 previewFilename = (std::string)LOGBOOK_PREVIEW_UPLOAD_PREFACE + (std::string)fileIndex + "." + fileExtension;
01157 logFilename = (std::string)LOGBOOK_PREVIEW_UPLOAD_PREFACE + entryTimeLabel + "_" +
01158 (std::string)fileIndex + "." + fileExtension;
01159
01160 sysCmd = "mv " + (previewPath + "/" + previewFilename) + " " +
01161 (logDirPath + "/" + (std::string)LOGBOOK_UPLOADS_PATH + logFilename);
01162 __COUT__ << sysCmd << std::endl;
01163 system(sysCmd.c_str());
01164 }
01165 }
01166
01167
01168 sysCmd = "rm -rf " + previewPath;
01169 __COUT__ << sysCmd << std::endl << std::endl;
01170 system(sysCmd.c_str());
01171 }
01172
01173
01174
01175
01176 std::string LogbookSupervisor::validateUploadFileType(const std::string fileType)
01177 {
01178 for (unsigned int i=0; i<allowedFileUploadTypes_.size(); ++i)
01179 if (allowedFileUploadTypes_[i] == fileType)
01180 return matchingFileUploadTypes_[i];
01181
01182 return "";
01183 }
01184
01185
01186
01187
01188
01189 void LogbookSupervisor::escapeLogbookEntry(std::string &entry)
01190 {
01191
01192
01193 }
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 void LogbookSupervisor::hideLogbookEntry(const std::string &entryId, bool hide,const std::string &hider)
01205 {
01206 __COUT__ << "Hide=" << hide << " for entryid " << entryId << std::endl;
01207
01208
01209 char dayIndexStr[20];
01210 unsigned int i;
01211 for(i=0;i<entryId.length();++i)
01212 if(entryId[i] == '_') { dayIndexStr[i] = '\0'; break;}
01213 else
01214 dayIndexStr[i] = entryId[i];
01215 time_t days;
01216 sscanf(dayIndexStr,"%li",&days);
01217 days /= 60*60*24;
01218 sprintf(dayIndexStr,"%6.6lu",days);
01219
01220 std::string logDirPath = (std::string)LOGBOOK_PATH + (std::string)LOGBOOK_LOGBOOKS_PATH +
01221 (std::string)LOGBOOK_EXPERIMENT_DIR_PREFACE + activeExperiment_;
01222 std::string logPath = logDirPath + "/" + LOGBOOK_FILE_PREFACE + activeExperiment_ + "_" + (std::string)dayIndexStr + LOGBOOK_FILE_EXTENSION;
01223
01224 __COUT__ << "logPath=" << logPath << std::endl;
01225
01226
01227 HttpXmlDocument logXml;
01228 if(!logXml.loadXmlDocument(logPath))
01229 {
01230 __COUT__ << "Failure - log XML did not load" << std::endl;
01231 return;
01232 }
01233
01234 std::vector<std::string> allEntryIds;
01235 logXml.getAllMatchingValues(XML_LOGBOOK_ENTRY_TIME,allEntryIds);
01236 for(i=0;i<allEntryIds.size();++i)
01237 if(allEntryIds[i] == entryId) break;
01238 if(i == allEntryIds.size())
01239 {
01240 __COUT__ << "Failure - entry not found" << std::endl;
01241 return;
01242 }
01243
01244 __COUT__ << "found " << logXml.getMatchingValue(XML_LOGBOOK_ENTRY_TEXT,i) << std::endl;
01245
01246 xercesc::DOMElement* hiddenParentEl, *entryParentEl = logXml.getMatchingElement(XML_LOGBOOK_ENTRY,i);
01247
01248
01249 hiddenParentEl = logXml.getMatchingElementInSubtree(entryParentEl,XML_LOGBOOK_ENTRY_HIDDEN);
01250
01251 if(hide)
01252 {
01253 if(hiddenParentEl)
01254 {
01255 __COUT__ << "Hidden tag already applied to entry." << std::endl;
01256 return;
01257 }
01258 hiddenParentEl = logXml.addTextElementToParent(XML_LOGBOOK_ENTRY_HIDDEN,"1",entryParentEl);
01259 logXml.addTextElementToParent(XML_LOGBOOK_ENTRY_HIDER,hider,hiddenParentEl);
01260 sprintf(dayIndexStr,"%lu",time(0));
01261 logXml.addTextElementToParent(XML_LOGBOOK_ENTRY_HIDDEN_TIME,dayIndexStr,hiddenParentEl);
01262 }
01263 else
01264 {
01265 if(!hiddenParentEl)
01266 {
01267 __COUT__ << "Entry already was not hidden." << std::endl;
01268 return;
01269 }
01270
01271 logXml.recursiveRemoveChild(hiddenParentEl,entryParentEl);
01272 }
01273 logXml.saveXmlDocument(logPath);
01274 __COUT__ << "Success." << std::endl;
01275 }
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286