19#include <condition_variable>
39#define DEFAULT_REFRESH 60
42static MUTEX_T* request_mutex = NULL;
60 sprintf(buf,
"%d",
i);
74 for (
int i=0;
i<3;
i++) {
81 for (
int i=0;
i<3;
i++) {
99extern const char *
mname[];
131 {
".ASC",
"text/plain" },
132 {
".CSS",
"text/css" },
133 {
".CSV",
"text/csv" },
134 {
".HTM",
"text/html" },
135 {
".HTML",
"text/html" },
136 {
".TXT",
"text/plain" },
138 {
".BMP",
"image/bmp" },
139 {
".GIF",
"image/gif" },
140 {
".ICO",
"image/x-icon" },
141 {
".JPEG",
"image/jpeg" },
142 {
".JPG",
"image/jpeg" },
143 {
".PNG",
"image/png" },
144 {
".SVG",
"image/svg+xml" },
145 {
".TIF",
"image/tiff" },
146 {
".TIFF",
"image/tiff" },
148 {
".MID",
"audio/midi" },
149 {
".MP3",
"audio/mpeg" },
150 {
".OGA",
"audio/ogg" },
151 {
".OGG",
"audio/ogg" },
152 {
".WAV",
"audio/wav" },
154 {
".BIN",
"application/octet-stream" },
155 {
".BZ",
"application/x-bzip" },
156 {
".BZ2",
"application/x-bzip2" },
157 {
".DOC",
"application/msword" },
158 {
".EPS",
"application/postscript" },
159 {
".GZ",
"application/gzip" },
160 {
".JS",
"application/javascript" },
161 {
".JSON",
"application/json" },
162 {
".MJS",
"application/javascript" },
163 {
".PDF",
"application/pdf" },
164 {
".PHP",
"application/x-httpd-php" },
165 {
".RTF",
"application/rtf" },
166 {
".PS",
"application/postscript" },
167 {
".ROOT",
"application/octet-stream" },
168 {
".XLS",
"application/x-msexcel" },
169 {
".XML",
"application/xml" },
170 {
".ZIP",
"application/zip" },
172 {
".ODP",
"application/vnd.oasis.opendocument.presentation" },
173 {
".ODS",
"application/vnd.oasis.opendocument.spreadsheet" },
174 {
".ODT",
"application/vnd.oasis.opendocument.text" },
184 std::string mimetype;
186 if (mimetype.length() > 0) {
213#define HTTP_ENCODING "UTF-8"
218 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
219 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
220 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
221 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x91, 0x68,
222 0x36, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4D,
223 0x45, 0x07, 0xD4, 0x0B, 0x1A, 0x08, 0x37, 0x07,
224 0x0D, 0x7F, 0x16, 0x5C, 0x00, 0x00, 0x00, 0x09,
225 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x2E, 0x23,
226 0x00, 0x00, 0x2E, 0x23, 0x01, 0x78, 0xA5, 0x3F,
227 0x76, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D,
228 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61,
229 0x05, 0x00, 0x00, 0x01, 0x7D, 0x49, 0x44, 0x41,
230 0x54, 0x78, 0xDA, 0x63, 0xFC, 0xFF, 0xFF, 0x3F,
231 0x03, 0x29, 0x80, 0x09, 0xAB, 0xE8, 0xD2, 0x65,
232 0x77, 0x36, 0x6F, 0x7E, 0x8A, 0x5D, 0xC7, 0x7F,
233 0x0C, 0x30, 0x67, 0xEE, 0x0D, 0x56, 0xCE, 0xCD,
234 0x5C, 0xBC, 0x3B, 0xB6, 0x6D, 0x7F, 0x81, 0x29,
235 0xCB, 0x88, 0xE6, 0x24, 0x20, 0x57, 0x50, 0x7C,
236 0xDD, 0xCF, 0x1F, 0x6C, 0x40, 0xCB, 0xB5, 0xB5,
237 0x05, 0xCF, 0x1C, 0xB7, 0x42, 0xB3, 0x80, 0x05,
238 0x8D, 0xCF, 0xC8, 0xC8, 0x58, 0x5A, 0x2A, 0xFB,
239 0xF6, 0x4D, 0x37, 0x1B, 0xAB, 0xA0, 0xB4, 0x4C,
240 0x0A, 0x51, 0x4E, 0x02, 0x82, 0x85, 0xCB, 0x12,
241 0x0E, 0x1D, 0xAB, 0xC7, 0x2A, 0xC5, 0x82, 0x69,
242 0xC4, 0xAF, 0x5F, 0x7F, 0x1E, 0x3F, 0xF8, 0xCD,
243 0xCB, 0xF1, 0xF5, 0xEF, 0xDF, 0x7F, 0xCC, 0xCC,
244 0x4C, 0x84, 0x6D, 0x98, 0x59, 0xD5, 0xEB, 0xCF,
245 0xA5, 0x16, 0xC4, 0xAB, 0x71, 0x72, 0xCB, 0x21,
246 0x4C, 0x59, 0x74, 0x03, 0x5E, 0x3F, 0x7F, 0xB3,
247 0x6B, 0xD6, 0x22, 0x46, 0xA6, 0x7F, 0x0C, 0x0C,
248 0x7F, 0xD7, 0x75, 0x4D, 0xFB, 0xF1, 0xFD, 0x27,
249 0x81, 0x78, 0xB8, 0x7D, 0xE9, 0x0A, 0xCB, 0xFF,
250 0xDF, 0x4C, 0x8C, 0x8C, 0x40, 0xF6, 0xAD, 0x4B,
251 0x67, 0x1F, 0xDE, 0xBD, 0x8B, 0x45, 0x03, 0x3C,
252 0x60, 0x8F, 0x9D, 0xD8, 0xB3, 0xEB, 0x74, 0xB5,
253 0x90, 0x26, 0x07, 0x03, 0x48, 0xE4, 0x3F, 0x8F,
254 0xF6, 0xFF, 0x1B, 0x0F, 0x9A, 0x1E, 0x3E, 0x3A,
255 0xFB, 0xF3, 0xDB, 0x8F, 0xB7, 0x0F, 0x9E, 0x43,
256 0x83, 0xF1, 0xCF, 0xDF, 0x3F, 0x8A, 0x29, 0xCE,
257 0x3F, 0x7F, 0xFD, 0xFC, 0xCF, 0xF0, 0xDF, 0x98,
258 0xE9, 0xB5, 0x8F, 0xBD, 0x8A, 0x3C, 0x6F, 0xEC,
259 0xB9, 0x2D, 0x47, 0xFE, 0xFC, 0xFF, 0x6F, 0x16,
260 0x6C, 0xF3, 0xEC, 0xD3, 0x1C, 0x2E, 0x96, 0xEF,
261 0xBF, 0xAB, 0x7E, 0x32, 0x7D, 0xE2, 0x10, 0xCE,
262 0x88, 0xF4, 0x69, 0x2B, 0x60, 0xFC, 0xF4, 0xF5,
263 0x97, 0x78, 0x8A, 0x36, 0xD8, 0x44, 0x86, 0x18,
264 0x0D, 0xD7, 0x29, 0x95, 0x13, 0xD8, 0xD9, 0x58,
265 0xE1, 0x0E, 0xF8, 0xF1, 0xF3, 0xDB, 0xC6, 0xD6,
266 0xEC, 0x5F, 0x53, 0x8E, 0xBF, 0xFE, 0xC3, 0x70,
267 0x93, 0x8D, 0x6D, 0xDA, 0xCB, 0x0B, 0x4C, 0x3F,
268 0xFF, 0xFC, 0xFA, 0xCF, 0x0C, 0xB4, 0x09, 0x84,
269 0x54, 0xD5, 0x74, 0x91, 0x55, 0x03, 0x01, 0x07,
270 0x3B, 0x97, 0x96, 0x6E, 0xC8, 0x17, 0xFE, 0x7F,
271 0x4F, 0xF8, 0xFE, 0xBC, 0x95, 0x16, 0x60, 0x62,
272 0x62, 0x64, 0xE1, 0xE6, 0x60, 0x73, 0xD1, 0xB2,
273 0x7A, 0xFA, 0xE2, 0xF1, 0xDF, 0x3F, 0xFF, 0xC4,
274 0x78, 0x44, 0x31, 0xA3, 0x45, 0x2B, 0xD0, 0xE3,
275 0xF6, 0xD9, 0xE3, 0x2F, 0x2E, 0x9D, 0x29, 0xA9,
276 0xAC, 0x07, 0xA6, 0x03, 0xF4, 0xB4, 0x44, 0x10,
277 0x00, 0x00, 0x75, 0x65, 0x12, 0xB0, 0x49, 0xFF,
278 0x3F, 0x68, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
279 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
283 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10,
284 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x28, 0x01,
285 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x28, 0x00,
286 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00,
287 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x0F,
291 0x0A, 0x00, 0x5C, 0x86, 0x4C, 0x00, 0x2F, 0x5E,
292 0x1A, 0x00, 0xBF, 0xD3, 0xD7, 0x00, 0x29, 0x17,
293 0x8D, 0x00, 0x50, 0xA7, 0xA4, 0x00, 0x59, 0x57,
294 0x7F, 0x00, 0xC6, 0xA3, 0xAC, 0x00, 0xFC, 0xFE,
295 0xFC, 0x00, 0x28, 0x12, 0x53, 0x00, 0x58, 0x7D,
296 0x72, 0x00, 0xC4, 0x3A, 0x34, 0x00, 0x3C, 0x3D,
297 0x69, 0x00, 0xC5, 0xB6, 0xB9, 0x00, 0x94, 0x92,
298 0x87, 0x00, 0x7E, 0x7A, 0xAA, 0x00, 0x88, 0x88,
299 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x81, 0x22,
300 0xD8, 0x88, 0x88, 0x88, 0xF6, 0xD8, 0x82, 0x22,
301 0xE8, 0x88, 0x88, 0x8D, 0x44, 0x98, 0x82, 0x22,
302 0xA8, 0x88, 0x88, 0x8F, 0x44, 0x48, 0x82, 0x22,
303 0x25, 0x76, 0x67, 0x55, 0x44, 0xF8, 0x88, 0x88,
304 0x3A, 0xC9, 0x9C, 0x53, 0x83, 0x88, 0x88, 0x88,
305 0x8D, 0x99, 0x99, 0x38, 0x88, 0x88, 0x88, 0x88,
306 0x88, 0x99, 0x9C, 0x88, 0x88, 0x88, 0x88, 0x88,
307 0x88, 0xF9, 0x9D, 0x88, 0x88, 0x88, 0x88, 0x88,
308 0x88, 0x8A, 0x58, 0x88, 0x88, 0x88, 0x88, 0x88,
309 0x88, 0x85, 0xD8, 0x88, 0x88, 0x88, 0x88, 0x88,
310 0x88, 0xEA, 0xAE, 0x88, 0x88, 0x88, 0x88, 0x88,
311 0x88, 0x00, 0x0B, 0x88, 0x88, 0x88, 0x88, 0x88,
312 0x88, 0x70, 0x0D, 0x88, 0x88, 0x88, 0x88, 0x88,
313 0x88, 0x87, 0xD8, 0x88, 0x88, 0x88, 0x88, 0x88,
314 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
331 int minor,
int major,
int text,
int label,
int grid,
double ymin,
double ymax,
334 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax);
336void show_header(
Return* r,
const char *title,
const char *method,
const char *path,
int refresh);
343 char c1, c2, *ps, *pp;
345 if (
str == NULL || pattern == NULL)
350 pp = (
char *) pattern;
353 if (toupper(c1) == toupper(c2)) {
358 if (toupper(c1) != toupper(c2))
380 return tv.tv_sec*1.0 +
tv.tv_usec/1000000.0;
426 printf(
"M %s ",
fMethod.c_str());
427 printf(
"URL %s ",
fUri.c_str());
428 if (
fRPC.length() > 0) {
429 printf(
"RPC %s ",
fRPC.c_str());
441 std::vector<RequestTrace*>
fBuf;
477 for (
unsigned i=0;
i<
fBuf.size();
i++) {
486 for (
unsigned i=0;
i<
fBuf.size();
i++) {
488 if (
fBuf[
k] != NULL) {
490 if (
fBuf[
k] == NULL) {
497 if (
fBuf[
k] == NULL) {
511#define WEB_BUFFER_SIZE (6*1024*1024)
560 for (
int i=0;
i<1000;
i++) {
572 assert(!
"Cannot happen!");
588void rread(
const char* filename,
int fh,
int len)
593 cm_msg(
MERROR,
"rread",
"Cannot read file \'%s\', read of %d returned %d, errno %d (%s)", filename, len, rd, errno, strerror(errno));
604 size_t len = strlen(
str);
623 size_t len = strlen(
str);
632 for (
size_t i = 0;
i < len;
i++) {
633 if (strncmp(
str +
i,
"http://", 7) == 0) {
636 char* p = (
char *) (
str +
i + 7);
639 for (
k = 0; *p && *p !=
' ' && *p !=
'\n';
k++,
i++)
643 sprintf(
return_buffer +
j,
"<a href=\"http://%s\">http://%s</a>", link, link);
698#define PARAM_LENGTH 256
699#define TEXT_SIZE 50000
732 printf(
"Error: parameter value too big\n");
746 int size = strlen(
value)+1;
747 _value[
i] = (
char*)malloc(size);
752 printf(
"Error: parameter array too small\n");
856 if (isxdigit(p[0]) && isxdigit(p[1])) {
862 sscanf(
str,
"%02X", &
i);
868 }
else if (*p ==
'+') {
898 if (isxdigit(p[0]) && isxdigit(p[1])) {
902 sscanf(
str,
"%02X", &
i);
908 }
else if (*p ==
'+') {
928 int len = strlen(ps);
929 char *
str = (
char*)malloc(len*3 + 10);
937 sprintf(pd,
"%%%02X", (*p)&0xFF);
945 printf(
"urlEncode [");
946 for (p=ps; *p!=0; p++)
947 printf(
"0x%02x ", (*p)&0xFF);
950 printf(
"urlEncode [%s] -> [%s]\n", ps,
str);
953 mstrlcpy(ps,
str, ps_size);
965 const char* p = text;
971 sprintf(buf,
"%%%02X", (*p)&0xFF);
978 printf(
"urlEncode [");
979 for (p=text; *p!=0; p++)
980 printf(
"0x%02x ", (*p)&0xFF);
983 printf(
"urlEncode [%s] -> [%s]\n", text, encoded.c_str());
998 std::vector<std::string> paths;
1004 paths.push_back(buf);
1012 paths.push_back(buf);
1016 paths.push_back(cwd +
"/");
1017 paths.push_back(cwd +
"/resources/");
1021 char *m = getenv(
"MIDASSYS");
1023 paths.push_back(std::string(m) +
"/resources/");
1037 if (strlen(filename) < 1) {
1038 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' is too short",
1044 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' starting with \'%c\' which is not allowed",
1049 if (strstr(filename,
"..") != NULL) {
1050 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' containing \'..\' which is not allowed",
1057 std::vector<std::string> paths_not_found;
1059 for (
unsigned i=0;
i<paths.size();
i++) {
1060 std::string path = paths[
i];
1061 if (path.length() < 1)
1079 FILE*
fp = fopen(xpath.c_str(),
"r");
1081 struct stat statbuf;
1082 int status = fstat(fileno(
fp), &statbuf);
1084 cm_msg(
MERROR,
"open_resource_file",
"Cannot fstat() file \'%s\', error %d (%s)", xpath.c_str(), errno, strerror(errno));
1089 if (statbuf.st_mode & S_IFREG) {
1095 }
else if (statbuf.st_mode & S_IFDIR) {
1096 cm_msg(
MERROR,
"open_resource_file",
"File \'%s\' for resource \'%s\' is a directory", xpath.c_str(), filename);
1100 cm_msg(
MERROR,
"open_resource_file",
"File \'%s\' for resource \'%s\' is not a regular file, st_mode is 0x%08x", xpath.c_str(), filename, statbuf.st_mode);
1119 paths_not_found.push_back(xpath);
1123 for (
unsigned i=0;
i<paths_not_found.size();
i++) {
1126 s += paths_not_found[
i];
1129 cm_msg(
MERROR,
"open_resource_file",
"Cannot find resource file \'%s\', tried %s", filename, s.c_str());
1137 std::string ext_upper;
1138 const char* p = filename;
1139 const char* last_dot = NULL;
1150 ext_upper += toupper(*p);
1156 if (
type.length() > 0)
1159 cm_msg(
MERROR,
"get_content_type",
"Unknown HTTP Content-Type for resource file \'%s\', file extension \'%s\'", filename, ext_upper.c_str());
1161 return "text/plain";
1172 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1174 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
1178 time_t now = time(NULL);
1179 now += (int) (3600 * 24);
1181 gmtime_r(&now, &gmt_tms);
1182 const char* format =
"%A, %d-%b-%y %H:%M:%S GMT";
1185 strftime(
str,
sizeof(
str), format, &gmt_tms);
1194 struct stat stat_buf;
1195 fstat(fileno(
fp), &stat_buf);
1196 int length = stat_buf.st_size;
1197 r->
rsprintf(
"Content-Length: %d\r\n", length);
1205 r->
rread(path.c_str(), fileno(
fp), length);
1214 FILE *
fp = fopen(path.c_str(),
"rb");
1219 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1223 r->
rsprintf(
"Error: Cannot read \"%s\", fopen() errno %d (%s)\n", path.c_str(), errno, strerror(errno));
1241 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1245 r->
rsprintf(
"Error: resource file \"%s\" not found, see messages\n",
name.c_str());
1255INT sendmail(
const char* from_host,
const char *smtp_host,
const char *from,
const char *to,
const char *subject,
const char *text)
1257 struct sockaddr_in bind_addr;
1258 struct hostent *phe;
1260 char *
str, buf[256];
1263 printf(
"\n\nEmail from %s to %s, SMTP host %s:\n", from, to, smtp_host);
1266 s =
socket(AF_INET, SOCK_STREAM, 0);
1271 memset(&bind_addr, 0,
sizeof(bind_addr));
1272 bind_addr.sin_family = AF_INET;
1273 bind_addr.sin_port = htons((
short) 25);
1275 phe = gethostbyname(smtp_host);
1278 memcpy((
char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
1280 if (connect(s, (
const sockaddr*)&bind_addr,
sizeof(bind_addr)) < 0) {
1286 str = (
char*)malloc(strsize);
1288 assert(
str != NULL);
1302 sprintf(
str,
"HELO %s\r\n", from_host);
1303 send(s,
str, strlen(
str), 0);
1310 if (strchr(from,
'<')) {
1311 mstrlcpy(buf, strchr(from,
'<') + 1,
sizeof(buf));
1312 if (strchr(buf,
'>'))
1313 *strchr(buf,
'>') = 0;
1315 mstrlcpy(buf, from,
sizeof(buf));
1317 sprintf(
str,
"MAIL FROM: %s\n", buf);
1318 send(s,
str, strlen(
str), 0);
1325 sprintf(
str,
"RCPT TO: <%s>\r\n", to);
1326 send(s,
str, strlen(
str), 0);
1333 sprintf(
str,
"DATA\r\n");
1334 send(s,
str, strlen(
str), 0);
1341 sprintf(
str,
"To: %s\r\nFrom: %s\r\nSubject: %s\r\n", to, from, subject);
1342 send(s,
str, strlen(
str), 0);
1347 send(s,
str, strlen(
str), 0);
1355 localtime_r(&now, &tms);
1356 strftime(buf,
sizeof(buf),
"%a, %d %b %Y %H:%M:%S", &tms);
1357 offset = (-(int) timezone);
1360 sprintf(
str,
"Date: %s %+03d%02d\r\n", buf, (
int) (
offset / 3600),
1361 (
int) ((abs((
int)
offset) / 60) % 60));
1362 send(s,
str, strlen(
str), 0);
1366 sprintf(
str,
"Content-Type: TEXT/PLAIN; charset=US-ASCII\r\n\r\n");
1367 send(s,
str, strlen(
str), 0);
1372 const char* p = text;
1374 while (strstr(p,
"\r\n.\r\n")) {
1376 mstrlcat(
str, p,
i);
1378 mstrlcat(
str,
"\r\n..\r\n", strsize);
1380 mstrlcat(
str, p, strsize);
1381 mstrlcat(
str,
"\r\n", strsize);
1382 send(s,
str, strlen(
str), 0);
1387 sprintf(
str,
".\r\n");
1388 send(s,
str, strlen(
str), 0);
1395 sprintf(
str,
"QUIT\n");
1396 send(s,
str, strlen(
str), 0);
1417 mstrlcpy(
str, path,
sizeof(
str));
1422 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
1426 if (strncmp(path,
"http:", 5) == 0)
1427 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1428 else if (strncmp(path,
"https:", 6) == 0)
1429 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1431 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1440 r->
rsprintf(
"HTTP/1.1 307 Temporary Redirect\r\n");
1443 r->
rsprintf(
"Location: %s\r\n", path);
1445 r->
rsprintf(
"<html>redirect to %s</html>\r\n", path);
1478 for (
i = 0; search_name[
i] ;
i++)
1479 str2[
i] = toupper(search_name[
i]);
1482 if (strstr(xstr1, str2) != NULL) {
1485 std::string path_encoded =
urlEncode(path.c_str());
1489 r->
rsprintf(
"<tr><td class=\"ODBkey\"><a href=\"?cmd=odb&odb_path=/%s\">/%s</a></tr>\n", path_encoded.c_str(), path.c_str());
1492 char* p =
const_cast<char *
>(path.data() + path.length() - 1);
1493 while (*p && *p !=
'/')
1500 size =
sizeof(
data);
1502 std::string data_str;
1504 data_str =
"<no read access>";
1508 r->
rsprintf(
"<tr><td class=\"ODBkey\">");
1509 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=/%s\">/%s/%s</a></td>", path_encoded.c_str(), path.c_str(),
key->
name);
1510 r->
rsprintf(
"<td class=\"ODBvalue\">%s</td></tr>\n", data_str.c_str());
1516 r->
rsprintf(
"<tr><td rowspan=%d class=\"ODBkey\">",
i);
1517 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=/%s\">/%s/%s\n", path_encoded.c_str(), path.c_str(),
key->
name);
1520 size =
sizeof(
data);
1528 r->
rsprintf(
"<td class=\"ODBvalue\">[%d] %s</td></tr>\n",
i, data_str.c_str());
1551 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
1552 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
1555 r->
rsprintf(
"<table class=\"mtable\" style=\"width: 95%%\">\n");
1557 r->
rsprintf(
" <td class=\"mtableheader\">MIDAS Help Page</td>\n");
1564 r->
rsprintf(
" <td style=\"text-align:right;\">Documentation:</td>\n");
1565 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://midas.triumf.ca\">https://midas.triumf.ca</a></td>\n");
1568 r->
rsprintf(
" <td style=\"text-align:right;\">Discussion Forum:</td>\n");
1569 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://midas.triumf.ca/forum/\">https://midas.triumf.ca/forum/</a></td>\n");
1572 r->
rsprintf(
" <td style=\"text-align:right;\">Code:</td>\n");
1573 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://bitbucket.org/tmidas/midas/\">https://bitbucket.org/tmidas/midas/</a></td>\n");
1576 r->
rsprintf(
" <td style=\"text-align:right;\">Report a bug:</td>\n");
1577 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://bitbucket.org/tmidas/midas/issues/\">https://bitbucket.org/tmidas/midas/issues/</a></td>\n");
1581 r->
rsprintf(
" <td style=\"text-align:right;\">Version:</td>\n");
1585 r->
rsprintf(
" <td style=\"text-align:right;\">Revision:</td>\n");
1587 std::string url =
"https://bitbucket.org/tmidas/midas/commits/";
1593 std::string::size_type pos = rev.find(
"-g");
1594 if (pos != std::string::npos) {
1595 std::string hash = rev.substr(pos+2);
1596 pos = hash.find(
"-dirty");
1597 if (pos != std::string::npos) {
1598 hash = hash.substr(0, pos);
1600 pos = hash.find(
" ");
1601 if (pos != std::string::npos) {
1602 hash = hash.substr(0, pos);
1605 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"%s\">%s</a></td>\n", url.c_str(), rev.c_str());
1607 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", rev.c_str());
1612 r->
rsprintf(
" <td style=\"text-align:right;\">MIDASSYS:</td>\n");
1613 s = getenv(
"MIDASSYS");
1614 if (!s) s =
"(unset)";
1615 mstrlcpy(
str, s,
sizeof(
str));
1616 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n",
str);
1620 r->
rsprintf(
" <td style=\"text-align:right;\">mhttpd current directory:</td>\n");
1622 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", cwd.c_str());
1626 r->
rsprintf(
" <td style=\"text-align:right;\">Exptab file:</td>\n");
1631 r->
rsprintf(
" <td style=\"text-align:right;\">Experiment:</td>\n");
1636 r->
rsprintf(
" <td style=\"text-align:right;\">Experiment directory:</td>\n");
1644 if (
list.size() == 1) {
1646 r->
rsprintf(
" <td style=\"text-align:right;\">System logfile:</td>\n");
1649 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", s.c_str());
1653 r->
rsprintf(
" <td style=\"text-align:right;\">Logfiles:</td>\n");
1654 r->
rsprintf(
" <td style=\"text-align:left;\">\n");
1655 for (
unsigned i=0 ;
i<
list.size() ;
i++) {
1668 r->
rsprintf(
" <td style=\"text-align:right;\">Image history:</td>\n");
1673 r->
rsprintf(
" <td style=\"text-align:right;\">Resource paths:</td>\n");
1674 r->
rsprintf(
" <td style=\"text-align:left;\">");
1676 for (
unsigned i=0;
i<resource_paths.size();
i++) {
1679 r->
rsputs(resource_paths[
i].c_str());
1682 if (exp != resource_paths[
i]) {
1694 r->
rsprintf(
" <td style=\"text-align:right;\">midas.css:</td>\n");
1696 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1698 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1702 r->
rsprintf(
" <td style=\"text-align:right;\">midas.js:</td>\n");
1704 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1706 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1710 r->
rsprintf(
" <td style=\"text-align:right;\">controls.js:</td>\n");
1712 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1714 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1718 r->
rsprintf(
" <td style=\"text-align:right;\">mhttpd.js:</td>\n");
1720 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1722 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1726 r->
rsprintf(
" <td style=\"text-align:right;\">obsolete.js:</td>\n");
1728 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1730 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1734 r->
rsprintf(
" <td style=\"text-align:right;\">Obsolete mhttpd.css:</td>\n");
1736 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1738 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1742 r->
rsprintf(
" <td style=\"text-align:right;\">JSON-RPC schema:</td>\n");
1743 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?mjsonrpc_schema\">json format</a> or <a href=\"?mjsonrpc_schema_text\">text table format</a></td>\n");
1747 r->
rsprintf(
" <td style=\"text-align:right;\">JavaScript examples:</td>\n");
1748 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=example\">example.html</a></td>\n");
1752 r->
rsprintf(
" <td style=\"text-align:right;\">Custom page example:</td>\n");
1753 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=custom_example\">custom_example.html</a></td>\n");
1761 r->
rsprintf(
"<table class=\"mtable\" style=\"width: 95%%\">\n");
1763 r->
rsprintf(
" <td class=\"mtableheader\">Contributions</td>\n");
1767 r->
rsprintf(
"Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Thomas Lindner - Shuoyi Ma - Rudi Meier - Bill Mills - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Chris Pearson - Renee Poutissou - Stefan Ritt - Zaher Salman - Ryu Sawada - Tamsen Schurman - Ben Smith - Andreas Suter - Jan M. Wouters - Piotr Adam Zolnierczuk\n");
1787 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1789 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
1790 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
1793 r->
rsprintf(
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n");
1797 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
1798 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
1799 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
1803 r->
rsprintf(
"<meta http-equiv=\"Refresh\" content=\"%02d\">\n", refresh);
1805 r->
rsprintf(
"<title>%s</title></head>\n", title);
1807 mstrlcpy(
str, path,
sizeof(
str));
1812 (
"<body><form name=\"form1\" method=\"POST\" action=\"%s\" enctype=\"multipart/form-data\">\n\n",
1815 r->
rsprintf(
"<body><form name=\"form1\" method=\"GET\" action=\"%s\">\n\n",
str);
1819 std::string exptname;
1828 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1830 r->
rsprintf(
"Access-Control-Allow-Origin: *\r\n");
1831 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
1832 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
1841 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1846 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
1847 r->
rsprintf(
"<title>MIDAS error</title></head>\n");
1848 r->
rsprintf(
"<body><H1>%s</H1></body></html>\n", error);
1856 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1858 r->
rsprintf(
"Content-Type: text/plain\r\n");
1861 r->
rsprintf(
"MIDAS error: %s\n", error);
1869 r->
rsprintf(
"window.addEventListener(\"load\", function(e) { mhttpd_init('%s', 1000); });\n", cur_page);
1872 r->
rsprintf(
"<!-- header and side navigation will be filled in mhttpd_init -->\n");
1873 r->
rsprintf(
"<div id=\"mheader\"></div>\n");
1874 r->
rsprintf(
"<div id=\"msidenav\"></div>\n");
1875 r->
rsprintf(
"<div id=\"mmain\">\n");
1885 cm_msg(
MERROR,
"check_obsolete_odb",
"ODB \"%s\" is obsolete, please delete it.", odb_path);
1894 int size =
sizeof(true_value);
1940 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/Base URL\" is obsolete, please delete it.");
1945 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/CSS File\" is obsolete, please delete it.");
1950 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/JS File\" is obsolete, please delete it.");
1955 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/Start-Stop Buttons\" is obsolete, please delete it.");
1958 bool xdefault =
true;
1959 odb->RB(
"Experiment/Pause-Resume Buttons", &xdefault,
true);
1961#ifdef HAVE_MONGOOSE616
1970 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Logger/Message file\" is obsolete, please delete it and use \"/Logger/Message dir\" and \"/Logger/message file date format\" instead.");
1986 std::string external_elog_url;
1988 size =
sizeof(external_elog);
1994 size =
sizeof(
BOOL);
2000 const char def_button[][
NAME_LENGTH] = {
"8h",
"24h",
"7d" };
2021 size_t len = strlen(text);
2022 for (
size_t i = 0;
i < len;
i++) {
2050 size_t len = strlen(text);
2051 for (
size_t i = 0;
i < len;
i++) {
2080 size_t len = strlen(text);
2081 for (
size_t i = 0;
i < len;
i++) {
2105 size_t len = strlen(text);
2106 for (
size_t i = 0;
i < len;
i++) {
2152 bout +=
"<table border=3 cellpadding=1 class=\"dialogTable\">\n";
2154 ctime_r(&now, ctimebuf);
2155 bout +=
msprintf(
"<tr><th colspan=2>%s</tr>\n", ctimebuf);
2156 bout +=
msprintf(
"<tr><th colspan=2>%s</tr>\n", path);
2177 size =
sizeof(
data);
2183 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2184 data_str =
"(empty)";
2188 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
2192 bout +=
"</td><td>";
2196 bout +=
")</td></tr>\n";
2200 bout +=
"</td></tr>\n";
2207 size =
sizeof(
data);
2212 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2213 data_str =
"(empty)";
2221 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
2229 bout +=
")<br></td></tr>\n";
2236 bout +=
"<br></td></tr>\n";
2243 bout +=
"</table>\n";
2250 char path[256], path1[256];
2251 char mail_to[256], mail_from[256], mail_list[256],
2252 smtp_host[256], tag[80], mail_param[1000];
2255 char att_file[3][256];
2256 int fh, size, n_mail;
2257 char mhttpd_full_url[256];
2260 mstrlcpy(att_file[0], pp->
getparam(
"attachment0"),
sizeof(att_file[0]));
2261 mstrlcpy(att_file[1], pp->
getparam(
"attachment1"),
sizeof(att_file[1]));
2262 mstrlcpy(att_file[2], pp->
getparam(
"attachment2"),
sizeof(att_file[2]));
2265 for (
int i = 0;
i < 3;
i++) {
2267 sprintf(
str,
"attachment%d",
i);
2272 mstrlcpy(path1, path,
sizeof(path1));
2273 while (strchr(path,
'\\'))
2274 *strchr(path,
'\\') =
'/';
2280 int bufsize = bout.length()+1;
2281 char* buf = (
char*)
M_MALLOC(bufsize);
2282 memcpy(buf, bout.c_str(), bufsize);
2283 mstrlcpy(att_file[
i], path,
sizeof(att_file[0]));
2284 mstrlcat(att_file[
i],
".html",
sizeof(att_file[0]));
2289 else if ((fh = open(path1, O_RDONLY |
O_BINARY)) >= 0) {
2290 size = lseek(fh, 0, SEEK_END);
2292 lseek(fh, 0, SEEK_SET);
2293 int rd =
read(fh, buf, size);
2297 mstrlcpy(att_file[
i], path,
sizeof(att_file[0]));
2300 }
else if (strncmp(path,
"/HS/", 4) == 0) {
2301 char* buf = (
char*)
M_MALLOC(100000);
2303 mstrlcpy(
str, path + 4,
sizeof(
str));
2304 if (strchr(
str,
'?')) {
2305 p = strchr(
str,
'?') + 1;
2317 p = strtok(NULL,
"&");
2320 *strchr(
str,
'?') = 0;
2323 mstrlcpy(att_file[
i],
str,
sizeof(att_file[0]));
2331 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
2336 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
2337 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
2338 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
2339 r->
rsprintf(
"<title>ELog Error</title></head>\n");
2340 r->
rsprintf(
"<i>Error: Attachment file <i>%s</i> not valid.</i><p>\n", pp->
getparam(
str));
2341 r->
rsprintf(
"Please go back and enter a proper filename (use the <b>Browse</b> button).\n");
2342 r->
rsprintf(
"<body></body></html>\n");
2348 int edit = atoi(pp->
getparam(
"edit"));
2353 mstrlcpy(tag, pp->
getparam(
"orig"),
sizeof(tag));
2363 *pp->
getparam(
"html") ?
"HTML" :
"plain",
2376 std::string elog_host_name;
2383 sprintf(mhttpd_full_url,
"http://%s/", elog_host_name.c_str());
2391 str +=
"/Elog/Email ";
2398 size =
sizeof(mail_list);
2402 show_error(r,
"No SMTP host defined under /Elog/SMTP host");
2405 size =
sizeof(smtp_host);
2408 p = strtok(mail_list,
",");
2410 mstrlcpy(mail_to, p,
sizeof(mail_to));
2412 std::string exptname;
2415 sprintf(mail_from,
"MIDAS %s <MIDAS@%s>", exptname.c_str(), elog_host_name.c_str());
2417 std::string mail_text;
2418 mail_text +=
"A new entry has been submitted by ";
2419 mail_text += pp->
getparam(
"author");
2423 mail_text +=
"Experiment : ";
2424 mail_text += exptname.c_str();
2427 mail_text +=
"Type : ";
2431 mail_text +=
"System : ";
2432 mail_text += pp->
getparam(
"system");
2435 mail_text +=
"Subject : ";
2436 mail_text += pp->
getparam(
"subject");
2439 mail_text +=
"Link : ";
2440 mail_text += mhttpd_full_url;
2441 mail_text +=
"/EL/";
2450 sendmail(elog_host_name.c_str(), smtp_host, mail_from, mail_to, pp->
getparam(
"type"), mail_text.c_str());
2452 if (mail_param[0] == 0)
2453 mstrlcpy(mail_param,
"?",
sizeof(mail_param));
2455 mstrlcat(mail_param,
"&",
sizeof(mail_param));
2456 sprintf(mail_param + strlen(mail_param),
"mail%d=%s", n_mail++, mail_to);
2458 p = strtok(NULL,
",");
2467 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
2476 r->
rsprintf(
"Location: ?cmd=Show+elog&tag=%s&%s\n\n<html>redir</html>\r\n", tag, mail_param + 1);
2478 r->
rsprintf(
"Location: ?cmd=Show+elog&tag=%s\n\n<html>redir</html>\r\n", tag);
2508 lseek(fh, 0, SEEK_END);
2509 int length =
TELL(fh);
2510 lseek(fh, 0, SEEK_SET);
2512 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
2514 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
2519 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
2539 sprintf(
str,
"/Equipment/%s/Settings/Editable", eq_name);
2561 int i,
j,
k, colspan, size, n_var, i_edit, i_set, line;
2562 char eq_name[32], group[32];
2572 i_edit = atoi(pp->
getparam(
"index"));
2577 i_set = atoi(pp->
getparam(
"index"));
2581 mstrlcpy(eq_name, pp->
getparam(
"eq"),
sizeof(eq_name));
2582 mstrlcpy(group,
"All",
sizeof(group));
2584 mstrlcpy(group, pp->
getparam(
"group"),
sizeof(group));
2589 sprintf(
str,
"/Equipment/%s/Settings", eq_name);
2592 HNDLE hkeynames = 0;
2603 if (strncmp(
key.
name,
"Names", 5) == 0)
2609 if (!hkeyset || !hkeynames) {
2611 sprintf(
str,
"?cmd=odb&odb_path=/Equipment/%s/Variables", eq_name);
2618 show_header(r,
"MIDAS slow control",
"", group, i_edit == -1 ? refresh : 0);
2619 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
2620 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
2621 r->
rsprintf(
"<script type=\"text/javascript\" src=\"obsolete.js\"></script>\n");
2626 r->
rsprintf(
"<tr><td colspan=15>\n");
2629 r->
rsprintf(
"<input type=submit name=cmd value=Set>\n");
2634 r->
rsprintf(
"<table class=\"ODBtable\" style=\"max-width:700px;\">");
2638 r->
rsprintf(
"<tr><td class=\"subStatusTitle\" colspan=15><i>Equipment:</i> \n");
2666 if (strncmp(
key.
name,
"Names", 5) == 0) {
2687 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names", eq_name);
2694 r->
rsprintf(
"<tr><td colspan=15><i>Groups:</i> ");
2698 r->
rsprintf(
"<b>All</b> ");
2700 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s\">All</a> ",
urlEncode(eq_name).c_str());
2704 memset(group_name, 0,
sizeof(group_name));
2708 for (
int level = 0; ; level++) {
2709 bool next_level =
false;
2712 size =
sizeof(name_str);
2715 char *s = strchr(name_str,
'%');
2716 for (
int k=0; s &&
k<level;
k++)
2717 s = strchr(s+1,
'%');
2721 if (strchr(s+1,
'%'))
2731 mstrlcpy(group_name[
j], name_str,
sizeof(group_name[0]));
2741 r->
rsprintf(
"<b>%s</b> ", group_name[
i]);
2743 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s&group=%s\">%s</a> ",
urlEncode(eq_name).c_str(),
urlEncode(group_name[
i]).c_str(), group_name[
i]);
2747 r->
rsprintf(
"<i>ODB:</i> ");
2748 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Common\">Common</a> ",
urlEncode(eq_name).c_str());
2749 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Settings\">Settings</a> ",
urlEncode(eq_name).c_str());
2750 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Variables\">Variables</a> ",
urlEncode(eq_name).c_str());
2754 std::string vars_path =
msprintf(
"/Equipment/%s/Variables", eq_name);
2768 if (
i == 0 ||
i > 15) {
2775 r->
rsprintf(
"<tr class=\"subStatusTitle\"><th colspan=%d>Names", colspan);
2778 for (
int i = 0;;
i++) {
2793 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names", eq_name);
2802 for (
int i = 0;
i < num_values;
i++) {
2803 char names_str[256];
2804 size =
sizeof(names_str);
2808 mstrlcpy(
name, names_str,
sizeof(
name));
2814 char *s = strstr(
name, group);
2817 if (
name[strlen(group)] !=
'%')
2821 if (strlen(
name) < 1)
2822 sprintf(
name,
"[%d]",
i);
2825 r->
rsprintf(
"<tr class=\"ODBtableEven\"><td colspan=%d><nobr>%s</nobr>", colspan,
name);
2827 r->
rsprintf(
"<tr class=\"ODBtableOdd\"><td colspan=%d><nobr>%s</nobr>", colspan,
name);
2829 for (
int j = 0;;
j++) {
2842 size =
sizeof(
data);
2847 if (n_var == i_set) {
2859 if (n_var == i_edit) {
2861 r->
rsprintf(
"<input type=text size=10 maxlenth=80 name=value value=\"%s\">\n", data_str.c_str());
2862 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set>\n");
2863 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", i_edit);
2866 sprintf(odb_path,
"Equipment/%s/Variables/%s[%d]", eq_name, varkey.
name,
i);
2868 r->
rsprintf(
"<a href=\"#\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\', 0);return false;\" >%s</a>", odb_path, data_str.c_str());
2872 r->
rsprintf(
"<td align=center>%s", data_str.c_str());
2879 r->
rsprintf(
"<tr><td colspan=15><i>Groups:</i> ");
2883 r->
rsprintf(
"<b>All</b> ");
2885 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s\">All</a> ", eq_name);
2889 std::string vars_path =
msprintf(
"/Equipment/%s/Variables", eq_name);
2894 for (
int i = 0;;
i++) {
2912 r->
rsprintf(
"<i>ODB:</i> ");
2913 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Common\">Common</a> ",
urlEncode(eq_name).c_str());
2914 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Settings\">Settings</a> ",
urlEncode(eq_name).c_str());
2915 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Variables\">Variables</a> ",
urlEncode(eq_name).c_str());
2925 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
2927 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
2939 r->
rsprintf(
"<tr class=\"subStatusTitle\"><th colspan=9>Names<th>%s</tr>\n", varkey.
name);
2942 HNDLE hkeyroot = hkey;
2955 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<br></tr>\n", style,
key.
name);
2959 size =
sizeof(
data);
2965 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2966 data_str =
"(empty)";
2970 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
2972 (
"<tr class=\"%s\" ><td colspan=9>%s<td align=center>%s (%s)<br></tr>\n",
2973 style,
key.
name, data_str.c_str(), hex_str.c_str());
2975 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<td align=center>%s<br></tr>\n",
2976 style,
key.
name, data_str.c_str());
2984 size =
sizeof(
data);
2989 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2990 data_str =
"(empty)";
2997 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
2998 r->
rsprintf(
"<td>[%d] %s (%s)<br></tr>\n",
k, data_str.c_str(), hex_str.c_str());
3000 r->
rsprintf(
"<td>[%d] %s<br></tr>\n",
k, data_str.c_str());
3008 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names %s", eq_name, varkey.
name);
3016 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<td align=center><i>... %d values ...</i>",
3022 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
3024 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
3028 size =
sizeof(
name);
3031 sprintf(
name,
"%s[%d]", varkey.
name,
j);
3034 if (strlen(
name) < 1) {
3035 sprintf(
name,
"%s[%d]", varkey.
name,
j);
3038 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s", style,
name);
3040 size =
sizeof(
data);
3045 if (n_var == i_set) {
3054 sprintf(
str,
"%s", group);
3058 if (n_var == i_edit) {
3059 r->
rsprintf(
"<td align=center><input type=text size=10 maxlenth=80 name=value value=\"%s\">\n", data_str.c_str());
3060 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set></tr>\n");
3061 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", i_edit);
3062 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
3065 sprintf(odb_path,
"Equipment/%s/Variables/%s[%d]", eq_name, varkey.
name,
j);
3068 r->
rsprintf(
"<a href=\"#\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\', 0);return false;\" >%s</a>", odb_path, data_str.c_str());
3073 r->
rsprintf(
"<td align=center>%s\n", data_str.c_str());
3095 char str[256], *ps, *pt;
3103 strcpy(
type,
"text");
3105 while (*p && *p !=
'<')
3113 while (*p && ((*p ==
' ') || iscntrl(*p)))
3131 while (*p && ((*p ==
' ') || iscntrl(*p)))
3141 while (*p && *p !=
'\"')
3147 while (*p && *p !=
' ' && *p !=
'>')
3160 while (*p && *p !=
'\"')
3166 while (*p && *p !=
' ' && *p !=
'>')
3187 while (*p && *p !=
' ' && *p !=
'>')
3199 while (*p && *p !=
'\"')
3205 while (*p && *p !=
' ' && *p !=
'>')
3216 while (*p && *p !=
'\"')
3222 while (*p && *p !=
' ' && *p !=
'>')
3227 if (strchr(p,
'=')) {
3228 mstrlcpy(
str, p,
sizeof(
str));
3229 pt = strchr(
str,
'=')+1;
3232 while (*pt && *pt !=
'\"')
3238 while (*pt && *pt !=
' ' && *pt !=
'>')
3243 mstrlcat(tail,
" ", 256);
3244 mstrlcat(tail,
str, 256);
3246 mstrlcat(tail,
str, 256);
3256 while (*p && ((*p ==
' ') || iscntrl(*p)))
3260 cm_msg(
MERROR,
"find_odb_tag",
"Invalid odb tag '%s'", ps);
3263 }
while (*p !=
'>');
3268 while (*p && *p !=
'>')
3279 int size,
index, i_edit, i_set;
3287 i_edit = atoi(pp->
getparam(
"index"));
3292 i_set = atoi(pp->
getparam(
"index"));
3295 mstrlcpy(full_keypath, keypath1,
sizeof(full_keypath));
3296 mstrlcpy(keypath, keypath1,
sizeof(keypath));
3299 if (strchr(keypath,
'[') && strchr(keypath,
']')) {
3300 for (p = strchr(keypath,
'[') + 1; *p && *p !=
']'; p++)
3304 if (*p && *p ==
']') {
3305 index = atoi(strchr(keypath,
'[') + 1);
3306 *strchr(keypath,
'[') = 0;
3313 r->
rsprintf(
"<b>Key \"%s\" not found in ODB</b>\n", keypath);
3316 size =
sizeof(
data);
3319 std::string data_str;
3320 if (format && strlen(format)>0)
3329 if (n_var == i_set) {
3332 if (data_str[0] ==
'y')
3337 if (atoi(data_str.c_str()) > 0)
3347 std::string options;
3348 if (data_str[0] ==
'y' || atoi(data_str.c_str()) > 0)
3349 options +=
"checked ";
3351 options +=
"disabled ";
3354 options +=
"onClick=\"o=document.createElement('input');o.type='hidden';o.name='cbi';o.value='";
3356 options +=
"';document.form1.appendChild(o);";
3357 options +=
"document.form1.submit();\" ";
3364 r->
rsprintf(
"<input type=\"checkbox\" %s>\n", options.c_str());
3369 if (n_var == i_set) {
3377 size =
sizeof(
data);
3382 if (n_var == i_edit) {
3383 r->
rsprintf(
"<input type=text size=10 maxlength=80 name=value value=\"%s\">\n", data_str.c_str());
3384 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set>\n");
3385 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", n_var);
3386 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
3390 r->
rsprintf(
"<a href=\"#\" %s>", tail);
3394 r->
rsprintf(
"<a onClick=\"promptpwd('%s?cmd=Edit&index=%d&pnam=%s')\" href=\"#\">", path, n_var,
pwd);
3396 r->
rsprintf(
"<a href=\"%s?cmd=Edit&index=%d\" %s>", path, n_var, tail);
3400 r->
rsputs(data_str.c_str());
3403 }
else if (edit == 2) {
3404 r->
rsprintf(
"<a href=\"#\" onclick=\"ODBEdit('%s')\">\n", full_keypath);
3405 r->
rsputs(data_str.c_str());
3409 r->
rsputs(data_str.c_str());
3431 "Src = STRING : [256] ",
3432 "Format = STRING : [32] %1.1f",
3433 "Font = STRING : [32] Medium",
3437 "FGColor = STRING : [8] 000000",
3438 "BGColor = STRING : [8] FFFFFF",
3471 "Src = STRING : [256] ",
3475 "Height = INT : 100",
3476 "Direction = INT : 0",
3478 "Logscale = BOOL : n",
3480 "Max = DOUBLE : 10",
3481 "FGColor = STRING : [8] 000000",
3482 "BGColor = STRING : [8] FFFFFF",
3483 "BDColor = STRING : [8] 808080",
3489 int x, y, width, height, direction,
axis;
3503 int i,
n, size, ivalue;
3509 for (
i=0 ;
i<(int)strlen(src) ;
i++)
3510 if (src[
i] ==
'>' || src[
i] ==
'&')
3512 strncpy(
str, src,
i);
3516 while (strlen(
str) > 0 &&
str[strlen(
str)-1] ==
' ')
3521 cm_msg(
MERROR,
"evaluate_src",
"Invalid Src key \"%s\" for Fill \"%s\"",
3527 size =
sizeof(
data);
3534 *fvalue = (
value[0] ==
'y');
3536 *fvalue = atof(
value.c_str());
3540 if (src[
i] ==
'>' && src[
i+1] ==
'>') {
3543 while (src[
i] ==
' ' || isdigit(src[
i]))
3545 ivalue = (int)*fvalue;
3550 if (src[
i] ==
'&') {
3552 while (src[
i] ==
' ')
3554 if (src[
i] ==
'0' && src[
i+1] ==
'x')
3555 sscanf(src+2+
i,
"%x", &
n);
3558 while (src[
i] ==
' ' || isxdigit(src[
i]) || src[
i] ==
'x')
3560 ivalue = (int)*fvalue;
3576 if (filename[0] ==
'/')
3584 std::string custom_path =
"";
3591 if (custom_path.length() < 1)
3595 cm_msg(
MERROR,
"add_custom_path",
"ODB /Custom/Path has a forbidden value \"%s\", please change it", custom_path.c_str());
3601 std::string full_filename = custom_path;
3602 if (full_filename[full_filename.length()-1] !=
DIR_SEPARATOR)
3604 full_filename += filename;
3606 return full_filename;
3614 std::string filename;
3620 sprintf(
str,
"/Custom/%s",
name);
3624 sprintf(
str,
"/Custom/%s&",
name);
3627 sprintf(
str,
"/Custom/%s!",
name);
3633 sprintf(
str,
"show_custom_file: Invalid custom page: \"/Custom/%s\" not found in ODB",
name);
3645 sprintf(errtext,
"show_custom_file: Error: db_get_key() for \"%s\" status %d",
str,
status);
3651 char* ctext = (
char*)malloc(size);
3657 sprintf(errtext,
"show_custom_file: Error: db_get_data() for \"%s\" status %d",
str,
status);
3676 char str[256],
data[256], src[256];
3677 int i,
index, length,
status, size, width, height, bgcol, fgcol, bdcol, r, g, b, x, y;
3678 HNDLE hDB, hkeygif, hkeyroot, hkey, hkeyval;
3679 double fvalue, ratio;
3691 sprintf(
str,
"/Custom/Images/%s",
name);
3702 std::string filename;
3707 f = fopen(full_filename.c_str(),
"rb");
3709 sprintf(
str,
"show_custom_gif: Cannot open file \"%s\"", full_filename.c_str());
3718 sprintf(
str,
"show_custom_gif: File \"%s\" is not a GIF image", filename.c_str());
3735 size =
sizeof(label);
3738 cm_msg(
MERROR,
"show_custom_gif",
"Cannot open data record for label \"%s\"",
3743 if (label.
src[0] == 0) {
3750 cm_msg(
MERROR,
"show_custom_gif",
"Invalid Src key \"%s\" for label \"%s\"",
3756 size =
sizeof(
data);
3769 if (strstr(label.
format,
"%c"))
3778 sscanf(label.
fgcolor,
"%02x%02x%02x", &r, &g, &b);
3783 sscanf(label.
bgcolor,
"%02x%02x%02x", &r, &g, &b);
3798 width =
value.length() * pfont->
w + 5 + 5;
3799 height = pfont->
h + 2 + 2;
3801 if (label.
align == 0) {
3804 label.
y + height, bgcol);
3808 }
else if (label.
align == 1) {
3811 label.
y + height, bgcol);
3813 label.
y + height, fgcol);
3818 label.
y + height, bgcol);
3839 cm_msg(
MERROR,
"show_custom_gif",
"Cannot open data record for bar \"%s\"",
3844 if (bar.
src[0] == 0) {
3851 cm_msg(
MERROR,
"show_custom_gif",
"Invalid Src key \"%s\" for bar \"%s\"",
3857 size =
sizeof(
data);
3863 fvalue = atof(
value.c_str());
3865 sscanf(bar.
fgcolor,
"%02x%02x%02x", &r, &g, &b);
3870 sscanf(bar.
bgcolor,
"%02x%02x%02x", &r, &g, &b);
3875 sscanf(bar.
bdcolor,
"%02x%02x%02x", &r, &g, &b);
3886 ratio = (log(fvalue) - log(bar.
min)) / (log(bar.
max) - log(bar.
min));
3888 ratio = (fvalue - bar.
min) / (bar.
max - bar.
min);
3897 r = (int) (ratio + 0.5);
3904 bar.
y + bar.
height - 1, fgcol);
3909 else if (bar.
axis == 2)
3915 ratio = ratio * (bar.
height - 2);
3916 r = (int) (ratio + 0.5);
3919 bar.
y + bar.
width, bgcol);
3923 bar.
y + bar.
width - 1, fgcol);
3926 haxis(im,
gdFontSmall, bdcol, 0, bar.
x, bar.
y, bar.
height, -3, -5, -7, -18,
3928 else if (bar.
axis == 2)
3930 5, 7, 8, 0, bar.
min, bar.
max);
3962 size =
sizeof(
data);
3965 cm_msg(
MERROR,
"show_custom_gif",
"No \"Limits\" entry for Fill \"%s\"",
3969 for (
i = 0;
i < size / (int)
sizeof(
double);
i++)
3970 if (*((
double *)
data +
i) > fvalue)
3977 cm_msg(
MERROR,
"show_custom_gif",
"No \"Fillcolors\" entry for Fill \"%s\"",
3982 size =
sizeof(
data);
3983 strcpy(
data,
"FFFFFF");
3986 sscanf(
data,
"%02x%02x%02x", &r, &g, &b);
4001 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
4004 rr->
rsprintf(
"Content-Type: image/gif\r\n");
4005 rr->
rsprintf(
"Content-Length: %d\r\n", length);
4006 rr->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
4007 rr->
rsprintf(
"Expires: Fri, 01-Jan-1983 00:00:00 GMT\r\n\r\n");
4019 { 9999,
"mhttpd_jrpc_rev0", {
4034 int count = 0, substring = 0, rpc;
4036 const char *xname = p->
getparam(
"name");
4037 const char *srpc = p->
getparam(
"rpc");
4039 if (!srpc || !xname) {
4041 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4046 mstrlcpy(sname, xname,
sizeof(sname));
4048 if (sname[strlen(sname)-1]==
'*') {
4049 sname[strlen(sname)-1] = 0;
4065 r->
rsprintf(
"calling rpc %d | ", rpc);
4070 HNDLE hDB, hrootkey, hsubkey, hkey;
4082 sprintf(
str,
"RPC/%d", rpc);
4089 size =
sizeof(client_name);
4094 if (strlen(sname) > 0) {
4096 if (strstr(client_name, sname) != client_name)
4099 if (strcmp(sname, client_name) != 0)
4106 r->
rsprintf(
"client %s", client_name);
4144 { 9998,
"mhttpd_jrpc_rev1", {
4161 int status, substring = 0, rpc;
4163 const char *xname = p->
getparam(
"name");
4164 const char *srpc = p->
getparam(
"rpc");
4166 if (!srpc || !xname) {
4168 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4173 mstrlcpy(sname, xname,
sizeof(sname));
4175 if (sname[strlen(sname)-1]==
'*') {
4176 sname[strlen(sname)-1] = 0;
4195 std::string reply_header;
4196 std::string reply_body;
4204 HNDLE hDB, hrootkey, hsubkey, hkey;
4208 int buf_length = 1024;
4210 int max_reply_length = atoi(p->
getparam(
"max_reply_length"));
4211 if (max_reply_length > buf_length)
4212 buf_length = max_reply_length;
4214 char* buf = (
char*)malloc(buf_length);
4216 assert(buf != NULL);
4221 for (
int i=0; ;
i++) {
4227 sprintf(
str,
"RPC/%d", rpc);
4234 size =
sizeof(client_name);
4239 if (strlen(sname) > 0) {
4241 if (strstr(client_name, sname) != client_name)
4244 if (strcmp(sname, client_name) != 0)
4252 int connect_status = -1;
4253 int call_status = -1;
4254 int call_length = 0;
4255 int disconnect_status = -1;
4286 call_length = strlen(buf);
4296 if (reply_header.length() > 0)
4297 reply_header +=
" | ";
4300 sprintf(tmp,
"%s %d %d %d %d", client_name, connect_status, call_status, disconnect_status, call_length);
4301 reply_header += tmp;
4312 if (reply_header.length() > 0) {
4313 r->
rsputs(reply_header.c_str());
4315 r->
rsputs(reply_body.c_str());
4327 const char *cmd = p->
getparam(
"rcmd");
4328 const char *args = p->
getparam(
"rarg");
4330 if (!
name || !cmd || !args) {
4332 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4338 int buf_length = 1024;
4340 int max_reply_length = atoi(p->
getparam(
"max_reply_length"));
4341 if (max_reply_length > buf_length)
4342 buf_length = max_reply_length;
4344 char* buf = (
char*)malloc(buf_length);
4345 assert(buf != NULL);
4354 r->
rsprintf(
"<RPC_CONNECT_ERROR>%d</RPC_CONNECT_ERROR>",
status);
4395 size =
sizeof(
data);
4405 std::string data_str;
4406 if (format && format[0])
4410 r->
rsputs(data_str.c_str());
4418 r->
rsputs(
"<DB_OUT_OF_RANGE>");
4420 std::string data_str;
4425 r->
rsputs(data_str.c_str());
4437 if (s1.length() < strlen(s2))
4439 return (strncasecmp(s1.c_str(), s2, strlen(s2)) == 0);
4456 char str[
TEXT_SIZE], format[256], facility[256], user[256];
4465 const int ENCODING_NONE = 0;
4466 const int ENCODING_ODB = 1;
4467 const int ENCODING_XML = 2;
4468 const int ENCODING_JSON = 3;
4470 std::string cmd_parameter;
4471 std::string encoding_parameter;
4472 int encoding = ENCODING_NONE;
4474 std::string jsonp_callback;
4475 bool single =
false;
4476 bool multiple =
false;
4477 std::vector<std::string> odb;
4482 cmd_parameter = p->
getparam(
"cmd");
4486 encoding_parameter = p->
getparam(
"encoding");
4489 if (encoding_parameter.length() > 0) {
4491 encoding = ENCODING_ODB;
4493 encoding = ENCODING_XML;
4495 encoding = ENCODING_JSON;
4498 if (encoding == ENCODING_JSON) {
4501 jsonp_callback = p->
getparam(
"callback");
4512 for (
int i=0 ; ;
i++) {
4514 sprintf(ppath,
"odb%d",
i);
4522 printf(
"command [%s], encoding %d [%s], jsonp %d, single %d, multiple %d, odb array size %d\n", cmd_parameter.c_str(), encoding, encoding_parameter.c_str(), jsonp, single, multiple, (
int)odb.size());
4530 ppath +=
"/Custom/Pwd/";
4541 if (strchr(
str,
'[')) {
4542 if (*(strchr(
str,
'[')+1) ==
'*')
4546 *strchr(
str,
'[') = 0;
4555 const char* ptr = p->
getparam(
"value");
4556 for (
i=0 ; ptr != NULL ;
i++) {
4557 size =
sizeof(
data);
4559 if (strchr(
data,
','))
4560 *strchr(
data,
',') = 0;
4562 ptr = strchr(ptr,
',');
4567 size =
sizeof(
data);
4596 size =
sizeof(
data);
4617 if (strchr(
str,
'[')) {
4618 if (*(strchr(
str,
'[')+1) ==
'*')
4622 *strchr(
str,
'[') = 0;
4633 r->
rsputs(
"<DB_NO_KEY>");
4640 sprintf(ppath,
"odb%d",
i);
4641 sprintf(format,
"format%d",
i);
4644 if (strchr(
str,
'[')) {
4645 if (*(strchr(
str,
'[')+1) ==
'*')
4649 *strchr(
str,
'[') = 0;
4657 r->
rsputs(
"<DB_NO_KEY>");
4670 bool fmt_odb =
false;
4671 bool fmt_xml =
false;
4672 bool fmt_json =
true;
4673 bool fmt_jsonp =
false;
4674 int follow_links = 1;
4677 const char* fmt = NULL;
4678 const char* jsonp_callback =
"callback";
4682 }
else if (p->
isparam(
"format")) {
4689 fmt_json = (strstr(fmt,
"json") != NULL);
4692 fmt_xml = fmt_json =
false;
4694 fmt_odb = fmt_json =
false;
4696 fmt_odb = fmt_xml =
false;
4699 fmt_jsonp = (strstr(fmt,
"-p") != NULL);
4700 if (fmt_jsonp && p->
isparam(
"callback"))
4701 jsonp_callback = p->
getparam(
"callback");
4702 if (fmt_json && strstr(fmt,
"-nofollowlinks"))
4704 if (fmt_json && strstr(fmt,
"-nokeys"))
4706 if (fmt_json && strstr(fmt,
"-nolastwritten"))
4708 if (fmt_json && strstr(fmt,
"-norecurse"))
4724 r->
rsputs(jsonp_callback);
4730 char* buf = (
char *)malloc(bufsize);
4737 db_copy(
hDB, hkey, buf, &bufsize, (
char *)
"");
4746 r->
rsputs(
"<DB_NO_KEY>");
4752 r->
rsputs(jsonp_callback);
4759 }
else if (fmt_json)
4763 for (
int i=0 ; ;
i++) {
4765 sprintf(ppath,
"odb%d",
i);
4772 r->
rsputs(
"</data>\n<data>\n");
4785 r->
rsputs(
"<DB_NO_KEY/>\n");
4786 else if (fmt_json) {
4788 sprintf(tmp,
"{ \"/error\" : %d }\n",
status);
4791 r->
rsputs(
"<DB_NO_KEY>\n");
4797 char* buf = (
char *)malloc(bufsize);
4801 const char* s = strstr(buf,
"-->");
4807 }
else if (fmt_json) {
4811 db_copy(
hDB, hkey, buf, &bufsize, (
char *)
"");
4819 r->
rsputs(
"</data>\n</jcopy>\n");
4841 r->
rsputs(jsonp_callback.c_str());
4855 for (
unsigned i=0;
i<odb.size();
i++) {
4861 if (multiple &&
i>0)
4870 r->
rsputs(
"<DB_NO_KEY>\n");
4874 if (multiple &&
i>0)
4924 r->
rsputs(jsonp_callback.c_str());
4937 for (
unsigned i=0;
i<odb.size();
i++) {
4940 int arraylength = 0;
4945 arraylength = atoi(p->
getparam(
"arraylen"));
4946 strlength = atoi(p->
getparam(
"strlen"));
4948 else if (multiple) {
4950 sprintf(buf,
"type%d",
i);
4952 sprintf(buf,
"arraylen%d",
i);
4953 arraylength = atoi(p->
getparam(buf));
4954 sprintf(buf,
"strlen%d",
i);
4955 strlength = atoi(p->
getparam(buf));
4965 char* s = (
char*)calloc(strlength, 1);
4977 if (multiple &&
i>0)
5013 r->
rsputs(jsonp_callback.c_str());
5026 for (
unsigned i=0;
i<odb.size();
i++) {
5029 int arraylength = 0;
5033 arraylength = atoi(p->
getparam(
"arraylen"));
5034 strlength = atoi(p->
getparam(
"strlen"));
5036 else if (multiple) {
5038 sprintf(buf,
"arraylen%d",
i);
5039 arraylength = atoi(p->
getparam(buf));
5040 sprintf(buf,
"strlen%d",
i);
5041 strlength = atoi(p->
getparam(buf));
5052 char* olddata = (
char*)malloc(oldsize);
5058 char* s = (
char*)calloc(newsize, 1);
5077 if (multiple &&
i>0)
5110 r->
rsputs(jsonp_callback.c_str());
5123 for (
unsigned i=0;
i<odb.size();
i++) {
5124 const char*
name = NULL;
5127 else if (multiple) {
5129 sprintf(buf,
"name%d",
i);
5139 if (multiple &&
i>0)
5172 r->
rsputs(jsonp_callback.c_str());
5185 for (
unsigned i=0;
i<odb.size();
i++) {
5186 const char* dest = NULL;
5189 else if (multiple) {
5191 sprintf(buf,
"dest%d",
i);
5200 if (multiple &&
i>0)
5233 r->
rsputs(jsonp_callback.c_str());
5246 for (
unsigned i=0;
i<odb.size();
i++) {
5250 else if (multiple) {
5252 sprintf(buf,
"index%d",
i);
5264 if (multiple &&
i>0)
5297 r->
rsputs(jsonp_callback.c_str());
5310 for (
unsigned i=0;
i<odb.size();
i++) {
5315 if (multiple &&
i>0)
5342 mstrlcpy(facility, p->
getparam(
"f"),
sizeof(facility));
5344 mstrlcpy(facility,
"midas",
sizeof(facility));
5355 char* messages = NULL;
5356 int num_messages = 0;
5369 mstrlcpy(facility, p->
getparam(
"facility"),
sizeof(facility));
5371 mstrlcpy(facility,
"midas",
sizeof(facility));
5374 mstrlcpy(user, p->
getparam(
"user"),
sizeof(user));
5376 mstrlcpy(user,
"javascript_commands",
sizeof(user));
5388 r->
rsputs(
"Message successfully created\n");
5398 r->
rsputs(alarms.c_str());
5425 int size, n_var,
index, edit;
5426 char keypath[256],
type[32], *p, *ps;
5427 char pwd[256], tail[256];
5432 std::string path = pp->
getparam(
"page");
5435 show_error_404(r,
"show_custom_page: Invalid custom page: \"page\" parameter is empty");
5439 if (strstr(path.c_str(),
"..")) {
5441 str +=
"Invalid custom page name \'";
5443 str +=
"\' contains \'..\'";
5448 if (strstr(path.c_str(),
".gif")) {
5453 if (strchr(path.c_str(),
'.')) {
5460 std::string xpath = std::string(
"/Custom/") + path;
5463 xpath = std::string(
"/Custom/") + path +
"&";
5466 xpath = std::string(
"/Custom/") + path +
"!";
5478 ctext = (
char*)malloc(size);
5481 std::string errtext =
msprintf(
"show_custom_page: Error: db_get_data() for \"%s\" status %d", xpath.c_str(),
status);
5487 std::string content_type =
"text/html";
5490 if (std::string(ctext).substr(0, 5) ==
"?cmd=") {
5497 if (strchr(ctext,
'\n') == 0) {
5499 int fh = open(full_filename.c_str(), O_RDONLY |
O_BINARY);
5501 std::string
str =
msprintf(
"show_custom_page: Cannot open file \"%s\", open() errno %d (%s)", full_filename.c_str(), errno, strerror(errno));
5508 off_t off = lseek(fh, 0, SEEK_END);
5510 std::string
str =
msprintf(
"show_custom_page: Cannot open file \"%s\", lseek(SEEK_END) errno %d (%s)", full_filename.c_str(), errno, strerror(errno));
5517 lseek(fh, 0, SEEK_SET);
5518 ctext = (
char*)malloc(size+1);
5519 ssize_t rd =
read(fh, ctext, size);
5542 ps = strchr(p,
'>') + 1;
5544 if (
pwd[0] && n_var == atoi(pp->
getparam(
"index"))) {
5547 mstrlcpy(
str, path.c_str(),
sizeof(
str));
5548 if (strlen(
str)>0 &&
str[strlen(
str)-1] ==
'&')
5551 ppath +=
"/Custom/Pwd/";
5568 }
while (p != NULL);
5576 ppath +=
"/Custom/Pwd/";
5586 std::string podb = pp->
getparam(
"odb");
5587 std::string::size_type pos = podb.find(
'[');
5588 if (pos != std::string::npos) {
5589 index = atoi(podb.substr(pos+1).c_str());
5599 size =
sizeof(
data);
5602 if (atoi(data_str.c_str()) == 0)
5617 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
5633 ps = strchr(p + 1,
'>') + 1;
5638 }
while (p != NULL);
5649 std::string
str =
msprintf(
"Invalid custom page: Page \"%s\" not found in ODB", path.c_str());
5660 int c,
n, a, f,
d,
q, x, r, ia, id, w;
5662 HNDLE hDB, hrootkey, hsubkey, hkey;
5665 static HNDLE hconn = 0;
5682 size =
sizeof(client_name);
5689 if (client_name[0]) {
5697 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
5702 rr->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
5703 rr->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
5704 rr->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
5705 rr->
rsprintf(
"<title>MIDAS CAMAC interface</title></head>\n");
5706 rr->
rsprintf(
"<body><form method=\"GET\" action=\"CNAF\">\n\n");
5714 rr->
rsprintf(
"<table border=3 cellpadding=1>\n");
5715 rr->
rsprintf(
"<tr><th colspan=3>MIDAS experiment \"%s\"",
str);
5717 if (client_name[0] == 0)
5718 rr->
rsprintf(
"<th colspan=3 class=\"redLight\">No CAMAC server running</tr>\n");
5719 else if (hconn == 0)
5720 rr->
rsprintf(
"<th colspan=3 class=\"redLight\">Cannot connect to %s</tr>\n", client_name);
5722 rr->
rsprintf(
"<th colspan=3>CAMAC server: %s</tr>\n", client_name);
5726 a = f =
d =
q = x = 0;
5732 rr->
rsprintf(
"<tr><td colspan=3>\n");
5733 rr->
rsprintf(
"<input type=submit name=cmd value=Execute>\n");
5736 rr->
rsprintf(
"<input type=submit name=cmd value=ODB>\n");
5737 rr->
rsprintf(
"<input type=submit name=cmd value=Status>\n");
5738 rr->
rsprintf(
"<input type=submit name=cmd value=Help>\n");
5745 rr->
rsprintf(
"<th colspan=3>Data");
5750 const char* cmd = p->
getparam(
"cmd");
5752 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_CRATE_CLEAR, 0, 0, 0, 0, 0, &
d, &size, &x,
5755 rr->
rsprintf(
"<tr><td colspan=6 class=\"greenLight\">C cycle executed sucessfully</tr>\n");
5757 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_CRATE_ZINIT, 0, 0, 0, 0, 0, &
d, &size, &x,
5760 rr->
rsprintf(
"<tr><td colspan=6 class=\"greenLight\">Z cycle executed sucessfully</tr>\n");
5762 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_INHIBIT_CLEAR, 0, 0, 0, 0, 0, &
d, &size, &x,
5766 (
"<tr><td colspan=6 class=\"greenLight\">Clear inhibit executed sucessfully</tr>\n");
5768 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_INHIBIT_SET, 0, 0, 0, 0, 0, &
d, &size, &x,
5772 (
"<tr><td colspan=6 class=\"greenLight\">Set inhibit executed sucessfully</tr>\n");
5784 if (strncmp(pd,
"0x", 2) == 0)
5785 sscanf(pd + 2,
"%x", &
d);
5797 for (
i = 0;
i < r;
i++) {
5803 rpc_client_call(hconn,
RPC_CNAF24,
CNAF, 0,
c,
n, a, f, &
d, &size, &x,
5816 status =
rpc_client_call(hconn,
RPC_CNAF24,
CNAF, 0,
c,
n, a, f, &
d, &size, &x, &
q);
5823 (
"<tr><td colspan=6 class=\"redLight\">Error executing function, code = %d</tr>",
5826 rr->
rsprintf(
"<tr align=center><td>%d",
n);
5829 rr->
rsprintf(
"<td colspan=3>%d / 0x%04X Q%d X%d",
d,
d,
q, x);
5842 (
"<tr align=center><td><input type=text size=3 name=N value=%d>\n",
5844 rr->
rsprintf(
"<td><input type=text size=3 name=A value=%d>\n", a);
5845 rr->
rsprintf(
"<td><input type=text size=3 name=F value=%d>\n", f);
5847 (
"<td colspan=3><input type=text size=8 name=D value=%d></tr>\n",
5851 rr->
rsprintf(
"<tr><td colspan=2>Repeat");
5852 rr->
rsprintf(
"<td><input type=text size=3 name=R value=%d>\n", r);
5855 (
"<td align=center colspan=3><input type=submit name=cmd value=\"C cycle\">\n");
5856 rr->
rsprintf(
"<input type=submit name=cmd value=\"Z cycle\">\n");
5858 rr->
rsprintf(
"<tr><td colspan=2>Repeat delay [ms]");
5859 rr->
rsprintf(
"<td><input type=text size=3 name=W value=%d>\n", w);
5862 (
"<td align=center colspan=3><input type=submit name=cmd value=\"Set inhibit\">\n");
5863 rr->
rsprintf(
"<input type=submit name=cmd value=\"Clear inhibit\">\n");
5865 rr->
rsprintf(
"<tr><td colspan=2>Data increment");
5866 rr->
rsprintf(
"<td><input type=text size=3 name=ID value=%d>\n",
id);
5869 (
"<td colspan=3 align=center>Branch <input type=text size=3 name=B value=0>\n");
5871 rr->
rsprintf(
"<tr><td colspan=2>A increment");
5872 rr->
rsprintf(
"<td><input type=text size=3 name=IA value=%d>\n", ia);
5875 (
"<td colspan=3 align=center>Crate <input type=text size=3 name=C value=%d>\n",
5878 rr->
rsprintf(
"</table></body>\r\n");
5890static const NAME_TABLE prefix_table[] = {
5891 {PRFX_PICO,
"pico",},
5892 {PRFX_NANO,
"nano",},
5893 {PRFX_MICRO,
"micro",},
5894 {PRFX_MILLI,
"milli",},
5896 {PRFX_KILO,
"kilo",},
5897 {PRFX_MEGA,
"mega",},
5898 {PRFX_GIGA,
"giga",},
5899 {PRFX_TERA,
"tera",},
5903static const NAME_TABLE unit_table[] = {
5905 {UNIT_METER,
"meter",},
5906 {UNIT_GRAM,
"gram",},
5907 {UNIT_SECOND,
"second",},
5908 {UNIT_MINUTE,
"minute",},
5909 {UNIT_HOUR,
"hour",},
5910 {UNIT_AMPERE,
"ampere",},
5911 {UNIT_KELVIN,
"kelvin",},
5912 {UNIT_CELSIUS,
"deg. celsius",},
5913 {UNIT_FARENHEIT,
"deg. farenheit",},
5915 {UNIT_HERTZ,
"hertz",},
5916 {UNIT_PASCAL,
"pascal",},
5918 {UNIT_WATT,
"watt",},
5919 {UNIT_VOLT,
"volt",},
5921 {UNIT_TESLA,
"tesls",},
5922 {UNIT_LITERPERSEC,
"liter/sec",},
5924 {UNIT_FARAD,
"farad",},
5926 {UNIT_BOOLEAN,
"boolean",},
5927 {UNIT_BYTE,
"byte",},
5928 {UNIT_WORD,
"word",},
5929 {UNIT_DWORD,
"dword",},
5930 {UNIT_ASCII,
"ascii",},
5931 {UNIT_STRING,
"string",},
5932 {UNIT_BAUD,
"baud",},
5934 {UNIT_PERCENT,
"percent",},
5936 {UNIT_COUNT,
"counts",},
5937 {UNIT_FACTOR,
"factor",},
5943void print_mscb_var(
char *
value,
char *evalue,
char *unit, MSCB_INFO_VAR *info_chn,
void *pdata)
5947 unsigned short usdata;
5949 unsigned int uidata;
5956 if (info_chn->unit == UNIT_STRING) {
5957 memset(
str, 0,
sizeof(
str));
5958 strncpy(
str, (
char *)pdata, info_chn->width);
5959 for (
i = 0;
i < (int) strlen(
str);
i++)
5962 strcat(
value,
"\\001");
5965 strcat(
value,
"\\002");
5968 strcat(
value,
"\\t");
5971 strcat(
value,
"\\n");
5974 strcat(
value,
"\\r");
5981 mstrlcpy(evalue,
value, 256);
5983 switch (info_chn->width) {
5986 strcpy(evalue,
"0");
5990 if (info_chn->flags & MSCBF_SIGNED) {
5991 sprintf(
value,
"%d (0x%02X/", *((
signed char *)pdata), *((
signed char *)pdata));
5992 sprintf(evalue,
"%d", *((
signed char *)pdata));
5994 sprintf(
value,
"%u (0x%02X/", *((
unsigned char *)pdata), *((
unsigned char *)pdata));
5995 sprintf(evalue,
"%u", *((
unsigned char *)pdata));
5998 for (
i = 0;
i < 8;
i++)
5999 if (*((
unsigned char *)pdata) & (0x80 >>
i))
6007 if (info_chn->flags & MSCBF_SIGNED) {
6008 sdata = *((
signed short *)pdata);
6010 sprintf(
value,
"%d (0x%04X)", sdata, sdata);
6011 sprintf(evalue,
"%d", sdata);
6013 usdata = *((
unsigned short *)pdata);
6015 sprintf(
value,
"%u (0x%04X)", usdata, usdata);
6016 sprintf(evalue,
"%u", usdata);
6021 if (info_chn->flags & MSCBF_FLOAT) {
6022 fdata = *((
float *)pdata);
6024 sprintf(
value,
"%1.6lg", fdata);
6025 sprintf(evalue,
"%1.6lg", fdata);
6027 if (info_chn->flags & MSCBF_SIGNED) {
6028 idata = *((
signed int *)pdata);
6030 sprintf(
value,
"%d (0x%08X)", idata, idata);
6031 sprintf(evalue,
"%d", idata);
6033 uidata = *((
unsigned int *)pdata);
6035 sprintf(
value,
"%u (0x%08X)", uidata, uidata);
6036 sprintf(evalue,
"%u", uidata);
6045 if (info_chn->prefix) {
6046 for (
i = 0; prefix_table[
i].id != 99;
i++)
6047 if ((
unsigned char)prefix_table[
i].
id == info_chn->prefix)
6049 if (prefix_table[
i].
id)
6050 strcpy(unit, prefix_table[
i].
name);
6054 if (info_chn->unit && info_chn->unit != UNIT_STRING) {
6055 for (
i = 0; unit_table[
i].id;
i++)
6056 if ((
unsigned char)unit_table[
i].
id == info_chn->unit)
6058 if (unit_table[
i].
id)
6059 strcat(unit, unit_table[
i].
name);
6063static int cmp_int(
const void *a,
const void *b)
6065 return *((
int *)a) > *((
int *)b);
6070void create_mscb_tree()
6074 int i,
j,
k, l, size, address[1000], dev_badr[1000], dev_adr[1000], dev_chn[1000],
6075 n_address, n_dev_adr;
6076 char mscb_dev[256], mscb_pwd[32], eq_name[32];
6102 size =
sizeof(mscb_dev);
6105 size =
sizeof(mscb_pwd);
6109 size =
sizeof(dev_adr);
6111 n_dev_adr = size /
sizeof(int);
6114 size =
sizeof(mscb_dev);
6117 size =
sizeof(mscb_pwd);
6122 size =
sizeof(dev_badr);
6124 size =
sizeof(dev_chn);
6126 for (
k=0 ;
k<size/(int)
sizeof(
int) && n_dev_adr < (int)(
sizeof(dev_adr)/
sizeof(int)) ;
k++) {
6127 for (l=0 ; l<dev_chn[
k] ; l++)
6128 dev_adr[n_dev_adr++] = dev_badr[
k]+l;
6143 size =
sizeof(address);
6145 n_address = size /
sizeof(
int);
6150 for (
k=0 ;
k<n_dev_adr ;
k++) {
6151 for (l=0 ; l<n_address ; l++)
6152 if (address[l] == dev_adr[
k])
6156 address[n_address++] = dev_adr[
k];
6160 qsort(address, n_address,
sizeof(
int), cmp_int);
6174void show_mscb_page(
Param* p,
Return* r,
int refresh)
6176 int i,
j,
n, ind, fi, fd,
status, size, n_addr, cur_node, adr, show_hidden;
6177 unsigned int uptime;
6178 BOOL comment_created;
6181 char dbuf[256], evalue[256], unit[256], cur_subm_name[256];
6182 HNDLE hDB, hKeySubm, hKeyCurSubm,
hKey, hKeyAddr, hKeyComm;
6185 MSCB_INFO_VAR info_var;
6186 int ping_addr[0x10000];
6194 mstrlcpy(cur_subm_name, p->
getparam(
"subm"),
sizeof(cur_subm_name));
6195 if (cur_subm_name[0] == 0) {
6199 sprintf(errorstr,
"No submaster defined under /MSCB/Submaster");
6204 strcpy(cur_subm_name,
key.
name);
6209 cur_node = atoi(p->
getparam(
"node"));
6224 std::vector<int>
addr;
6225 std::vector<char> node_comment;
6230 addr.resize(n_addr);
6231 size =
sizeof(int)*n_addr;
6241 comment_created =
FALSE;
6253 node_comment.resize(32);
6254 comment_created =
TRUE;
6257 fd = mscb_init(cur_subm_name, 0,
"",
FALSE);
6260 for (
i=0 ;
i<0x10000 ;
i++)
6262 for (
i=0 ;
i<1000 ;
i++)
6264 for (
i=0 ;
i<0x10000 ;
i+=100)
6266 for (
i=0 ;
i<0x10000 ;
i+= 0x100)
6268 for (
i=0xFF00 ;
i<0x10000 ;
i++)
6271 for (ind =
n = 0; ind < 0x10000; ind++) {
6272 if (!ping_addr[ind])
6275 status = mscb_ping(fd, (
unsigned short) ind, 1, 0);
6276 if (
status == MSCB_SUCCESS) {
6279 for (
j=ind;
j<ind+100 &&
j<0x10000 ;
j++)
6283 status = mscb_info(fd, (
unsigned short) ind, &
info);
6285 if (
status == MSCB_SUCCESS) {
6287 for (
j=0 ;
j<n_addr ;
j++)
6291 addr.resize(n_addr+1);
6293 node_comment.resize(32*(n_addr+1));
6295 strncpy(node_comment.data()+n_addr*32,
info.node_name, 32);
6297 }
else if (comment_created) {
6298 node_comment.resize(32*n_addr);
6300 strncpy(node_comment.data()+
j*32,
info.node_name, 32);
6310 sprintf(redirstr,
"?cmd=mscb&subm=%s", cur_subm_name);
6316 sprintf(errorstr,
"Cannot talk to submaster \"%s\"", cur_subm_name);
6329 fd = mscb_init(cur_subm_name, 0,
"",
FALSE);
6331 status = mscb_info_variable(fd,
6332 (
unsigned short) cur_node, (
unsigned char)
i, &info_var);
6333 if (
status == MSCB_SUCCESS) {
6334 if (info_var.unit == UNIT_STRING) {
6336 mstrlcpy(valstr,
value,
sizeof(valstr));
6337 if (strlen(valstr) > 0 && valstr[strlen(valstr) - 1] ==
'\n')
6338 valstr[strlen(valstr) - 1] = 0;
6340 status = mscb_write(fd, (
unsigned short) cur_node,
6341 (
unsigned char)
i, valstr, strlen(valstr) + 1);
6343 if (info_var.flags & MSCBF_FLOAT) {
6344 fvalue = (float) atof(
value);
6345 memcpy(&dbuf, &fvalue,
sizeof(
float));
6347 if (
value[1] ==
'x')
6348 sscanf(
value + 2,
"%x", (
int *)&dbuf);
6350 *((
int *)dbuf) = atoi(
value);
6353 status = mscb_write(fd, (
unsigned short) cur_node,
6354 (
unsigned char)
i, dbuf, info_var.width);
6359 sprintf(redirstr,
"?cmd=mscb&subm=%s&node=%d", cur_subm_name, cur_node);
6365 show_hidden = atoi(p->
getparam(
"hidden"));
6367 show_hidden =
FALSE;
6370 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
6371 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
6375 r->
rsprintf(
"<style type=\"text/css\">\r\n");
6376 r->
rsprintf(
"select { width:150px; background-color:#FFFFE0; font-size:12px; }\r\n");
6378 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6380 r->
rsprintf(
" vertical-align:top;\r\n");
6381 r->
rsprintf(
" font-size:16px;\r\n");
6382 r->
rsprintf(
" border-right:1px solid #808080;\r\n");
6385 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6387 r->
rsprintf(
" vertical-align:top;\r\n");
6388 r->
rsprintf(
" font-size:16px;\r\n");
6389 r->
rsprintf(
" border-right:1px solid #808080;\r\n");
6392 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6394 r->
rsprintf(
" vertical-align:top;\r\n");
6395 r->
rsprintf(
" font-size:10px;\r\n");
6399 r->
rsprintf(
" font-weight:bold;\r\n");
6400 r->
rsprintf(
" font-size:12px;\r\n");
6403 r->
rsprintf(
" background-color:#F0F0F0;\r\n");
6405 r->
rsprintf(
" font-size:12px;\r\n");
6406 r->
rsprintf(
" border:1px solid #808080;\r\n");
6407 r->
rsprintf(
" border-right:1px solid #FFFFFF;\r\n");
6408 r->
rsprintf(
" border-bottom:1px solid #FFFFFF;\r\n");
6412 r->
rsprintf(
" font-size:12px;\r\n");
6417 r->
rsprintf(
"<script type=\"text/javascript\">\r\n");
6418 r->
rsprintf(
"function mscb_edit(index, value)\r\n");
6420 r->
rsprintf(
" var new_value = prompt('Please enter new value', value);\r\n");
6421 r->
rsprintf(
" if (new_value != undefined) {\r\n");
6422 r->
rsprintf(
" window.location.search = '?cmd=mscb&subm=%s&node=%d&idx='+index+'&value='+new_value;\n", cur_subm_name, cur_node);
6429 r->
rsprintf(
"<table class=\"mtable\">");
6430 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>MSCB</th><tr>");
6434 r->
rsprintf(
"<tr><td colspan=2>\n");
6435 r->
rsprintf(
"<table width=100%%><tr>\n");
6436 r->
rsprintf(
"<td><input type=button value=Reload onclick=\"window.location.search='?cmd=mscb&subm=%s&node=%d&rnd=%d'\"></td>\n", cur_subm_name, cur_node, rand());
6438 r->
rsprintf(
"<tr><td colspan=\"2\" cellpadding=\"0\" cellspacing=\"0\">\r\n");
6442 r->
rsprintf(
"<h1>No MSCB Submasters defined in ODB</h1>\r\n");
6453 r->
rsprintf(
"<table width=\"100%%\" cellpadding=\"0\" cellspacing=\"0\">");
6456 r->
rsprintf(
"<tr><td class=\"subm\">\r\n");
6468 r->
rsprintf(
"<select name=\"subm\" id=\"subm\" size=%d ",
i);
6469 r->
rsprintf(
"onChange=\"window.location.search='?cmd=mscb&subm='+document.getElementById('subm').value;\">\r\n");
6479 size =
sizeof(comment);
6481 mstrlcat(
str,
": ",
sizeof(
str));
6482 mstrlcat(
str, comment,
sizeof(
str));
6486 (cur_subm_name[0] == 0 &&
i == 0)) {
6495 r->
rsprintf(
"<td class=\"node\">\r\n");
6498 r->
rsprintf(
"<script type=\"text/javascript\">\n");
6500 r->
rsprintf(
"function rescan()\n");
6502 r->
rsprintf(
" flag = confirm('Rescan can take up to one minute.');\n");
6503 r->
rsprintf(
" if (flag == true)\n");
6504 r->
rsprintf(
" window.location.href = '?cmd=mscb&mcmd=Rescan&subm=%s';\n", cur_subm_name);
6509 r->
rsprintf(
"<input type=button name=cmd value=\"Rescan\" onClick=\"rescan();\">");
6513 r->
rsprintf(
"No submaster found in ODB\r\n");
6534 if (hKeyComm == 0) {
6548 r->
rsprintf(
"<select name=\"node\" id=\"node\" size=%d ",
i);
6549 r->
rsprintf(
"onChange=\"window.location.search='?cmd=mscb&subm=%s&node='+document.getElementById('node').value;\">\r\n", cur_subm_name);
6559 if (adr == cur_node)
6571 size =
sizeof(comment);
6573 sprintf(
str,
"%d: %s", adr, comment);
6575 sprintf(
str,
"%d", adr);
6577 if (cur_node == 0 &&
i == 0)
6579 if (adr == cur_node)
6580 r->
rsprintf(
"<option selected>%s</option>\r\n",
str);
6588 r->
rsprintf(
"<td class=\"vars\">\r\n");
6592 r->
rsprintf(
"<tr><td colspan=3 align=center><b>%s:%d</b>",
key.
name, cur_node);
6604 if (fd == EMSCB_WRONG_PASSWORD)
6605 r->
rsprintf(
"<tr><td colspan=3><b>Invalid password</b></td>");
6607 r->
rsprintf(
"<tr><td colspan=3><b>Submaster does not respond</b></td>");
6610 mscb_set_eth_max_retry(fd, 3);
6611 mscb_set_max_retry(1);
6613 status = mscb_ping(fd, cur_node, 0, 1);
6614 if (
status != MSCB_SUCCESS) {
6615 r->
rsprintf(
"<tr><td colspan=3><b>No response from node</b></td>");
6618 status = mscb_info(fd, (
unsigned short) cur_node, &
info);
6619 if (
status != MSCB_SUCCESS) {
6620 r->
rsprintf(
"<tr><td colspan=3><b>No response from node</b></td>");
6624 mstrlcpy(tr16,
info.node_name,
sizeof(tr16));
6625 r->
rsprintf(
"<tr><td class=\"v1\">Node name<td colspan=2 class=\"v2\">%s</tr>\n", tr16);
6626 r->
rsprintf(
"<tr><td class=\"v1\">GIT revision<td colspan=2 class=\"v2\">%d</tr>\n",
info.revision);
6628 if (
info.rtc[0] &&
info.rtc[0] != 0xFF) {
6629 for (
i=0 ;
i<6 ;
i++)
6631 r->
rsprintf(
"<tr><td class=\"v1\">Real Time Clock<td colspan=2 class=\"v2\">%02d-%02d-%02d %02d:%02d:%02d</td>\n",
6636 status = mscb_uptime(fd, (
unsigned short) cur_node, &uptime);
6637 if (
status == MSCB_SUCCESS)
6638 r->
rsprintf(
"<tr><td class=\"v1\">Uptime<td colspan=2 class=\"v2\">%dd %02dh %02dm %02ds</tr>\n",
6639 uptime / (3600 * 24),
6640 (uptime % (3600 * 24)) / 3600, (uptime % 3600) / 60,
6643 r->
rsprintf(
"<tr><td colspan=3><hr></td></tr>\r\n");
6646 for (
i=0 ;
i <
info.n_variables ;
i++) {
6647 mscb_info_variable(fd, cur_node,
i, &info_var);
6648 if (info_var.flags & MSCBF_HIDDEN)
6651 if (
i <
info.n_variables) {
6653 strcpy(
str, show_hidden ?
" checked" :
"");
6654 r->
rsprintf(
"<tr><td colspan=3><input type=checkbox%s name=\"hidden\" value=\"1\"",
str);
6655 r->
rsprintf(
"onChange=\"window.location.search=?cmd=mscb&subm=%s&node=%d&hidden=1\">Display hidden variables<hr></td></tr>\r\n", cur_subm_name, cur_node);
6659 for (fi=0 ; fi <
info.n_variables ; ) {
6660 for (
i=fi,size=0 ;
i <
info.n_variables && size < 100;
i++) {
6661 mscb_info_variable(fd, cur_node,
i, &info_var);
6662 size += info_var.width;
6665 size =
sizeof(dbuf);
6666 status = mscb_read_range(fd, cur_node, fi,
i-1, dbuf, &size);
6667 if (
status != MSCB_SUCCESS) {
6668 r->
rsprintf(
"<tr><td colspan=3><b>Error reading data from node</b></td>");
6673 for (
j=fi ;
j<
i ;
j++) {
6674 status = mscb_info_variable(fd, cur_node,
j, &info_var);
6675 if ((info_var.flags & MSCBF_HIDDEN) == 0 || show_hidden) {
6677 mstrlcpy(tr8, info_var.name,
sizeof(tr8));
6678 r->
rsprintf(
"<tr><td class=\"v1\">%s</td>\r\n", tr8);
6679 r->
rsprintf(
"<td class=\"v2\">\r\n");
6681 print_mscb_var(
value, evalue, unit, &info_var, pd);
6682 r->
rsprintf(
"<a href=\"#\" onClick=\"mscb_edit(%d,'%s')\">%s</a>",
6684 r->
rsprintf(
"</td><td class=\"v3\">%s</td>", unit);
6687 pd += info_var.width;
6695 r->
rsprintf(
"</td></tr></table>\r\n");
6696 r->
rsprintf(
"</td></tr></table>\r\n");
6697 r->
rsprintf(
"</td></tr></table>\r\n");
6698 r->
rsprintf(
"</div></body></html>\r\n");
6707 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
6712 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
6713 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
6714 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
6715 r->
rsprintf(
"<title>Enter password</title></head><body>\n\n");
6717 r->
rsprintf(
"<form method=\"GET\" action=\".\">\n\n");
6720 r->
rsprintf(
"<table class=\"headerTable\"><tr><td></td><tr></table>\n");
6722 r->
rsprintf(
"<table class=\"dialogTable\">\n");
6724 r->
rsprintf(
"<tr><th class=\"redLight\">Wrong password!</tr>\n");
6726 r->
rsprintf(
"<tr><th>Please enter password</tr>\n");
6727 r->
rsprintf(
"<tr><td align=center><input type=password name=pwd></tr>\n");
6728 r->
rsprintf(
"<tr><td align=center><input type=submit value=Submit></tr>");
6750 if (strcmp(password,
str) == 0)
6754 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
6759 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
6760 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
6761 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
6762 r->
rsprintf(
"<title>Enter password</title></head><body>\n\n");
6764 r->
rsprintf(
"<form method=\"GET\" action=\".\">\n\n");
6768 r->
rsprintf(
"<input type=hidden name=redir value=\"%s\">\n", redir);
6771 r->
rsprintf(
"<table class=\"headerTable\"><tr><td></td><tr></table>\n");
6773 r->
rsprintf(
"<table class=\"dialogTable\">\n");
6776 r->
rsprintf(
"<tr><th class=\"redLight\">Wrong password!</tr>\n");
6779 (
"<tr><th>Please enter password to obtain write access</tr>\n");
6780 r->
rsprintf(
"<tr><td align=center><input type=password name=wpwd></tr>\n");
6781 r->
rsprintf(
"<tr><td align=center><input type=submit value=Submit></tr>");
6798 int keyPresent, size,
status, line, link_index;
6809 if (strcmp(dec_path,
"root") == 0) {
6814 mstrlcpy(xdecpath, dec_path,
sizeof(xdecpath));
6815 if (strrchr(xdecpath,
'/'))
6816 mstrlcpy(xdecpath, strrchr(xdecpath,
'/')+1,
sizeof(xdecpath));
6817 if (xdecpath[0] == 0)
6818 mstrlcpy(xdecpath,
"root",
sizeof(xdecpath));
6819 show_header(r,
"MIDAS online database",
"", xdecpath, 0);
6822 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
6823 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
6824 r->
rsprintf(
"<script type=\"text/javascript\" src=\"obsolete.js\"></script>\n");
6825 r->
rsprintf(
"<script type=\"text/javascript\" src=\"controls.js\"></script>\n");
6830 r->
rsprintf(
"Error: cannot find key %s<P>\n", dec_path);
6840 mstrlcpy(xdec_path, dec_path,
sizeof(xdec_path));
6843 char* p = xdec_path + strlen(xdec_path) - 1;
6844 while (*p && *p !=
'/')
6851 r->
rsprintf(
"Error: cannot find key %s<P>\n", xdec_path);
6856 dec_path = xdec_path;
6869 r->
rsprintf(
"<table class=\"mtableheader\">\n");
6870 r->
rsprintf(
"<tr><td colspan=%d>\n", colspan);
6871 r->
rsprintf(
"<input type=button value=ELog onclick=\"self.location=\'?cmd=Alarms\';\">\n");
6872 r->
rsprintf(
"</td></tr></table>\n\n");
6878 r->
rsprintf(
"<table class=\"mtable\" style=\"border-spacing:0px;\">\n");
6879 r->
rsprintf(
"<tr><th colspan=%d class=\"mtableheader\">Online Database Browser</tr>\n", colspan);
6882 r->
rsprintf(
"<tr><td colspan=%d>\n", colspan);
6883 r->
rsprintf(
"<input type=button value=Find onclick=\"self.location=\'?cmd=Find\';\">\n");
6884 r->
rsprintf(
"<input type=button value=Create onclick=\"dlgShow('dlgCreate')\">\n");
6885 r->
rsprintf(
"<input type=button value=Link onclick=\"dlgShow('dlgLink')\">\n");
6886 r->
rsprintf(
"<input type=button value=Delete onclick=\"dlgShow('dlgDelete')\">\n");
6887 r->
rsprintf(
"<input type=button value=\"Create Elog from this page\" onclick=\"self.location=\'?cmd=Create Elog from this page&odb_path=%s\';\">\n",
urlEncode(odbpath.c_str()).c_str());
6888 r->
rsprintf(
"<input type=button value=\"Show open records\" onclick=\"self.location=\'?cmd=odb_sor&odb_path=%s\';\">\n",
urlEncode(odbpath.c_str()).c_str());
6889 r->
rsprintf(
"<input type=button value=\"Show ODB clients\" onclick=\"self.location=\'?cmd=odb_scl\';\">\n");
6895 std::string dd =
"";
6897 dd +=
"<!-- Demo dialog -->\n";
6898 dd +=
"<div id=\"dlgDelete\" class=\"dlgFrame\">\n";
6899 dd +=
"<div class=\"dlgTitlebar\">Delete ODB entry</div>\n";
6900 dd +=
"<div class=\"dlgPanel\">\n";
6901 dd +=
"<div id=odbpath>";
6903 dd += MJsonNode::Encode(odbpath.c_str());
6906 dd +=
"<div><br></div>\n";
6908 dd +=
"<table class=\"dialogTable\">\n";
6909 dd +=
"<th colspan=2>Delete ODB entries:</th>\n";
6911 std::vector<std::string> delete_list;
6913 int count_delete = 0;
6918 r->
rsprintf(
"<tr><td colspan=%d class='ODBpath'><b>", colspan);
6919 r->
rsprintf(
"<a href=\"?cmd=oldodb\">/</a> \n");
6921 std::string enc_root_path;
6925 const char* p = dec_path;
6928 while (*p && *p !=
'/')
6933 if (pd.length() > 0)
6934 r->
rsprintf(
"<a href=\"?cmd=oldodb&odb_path=%s\">%s</a>\n / ", enc_root_path.c_str(), pd.c_str());
6936 enc_root_path +=
"/";
6946 for(
int scan=0; scan<2; scan++){
6947 if(scan==1 && keyPresent==1) {
6948 r->
rsprintf(
"<tr class=\"titleRow\">\n");
6949 r->
rsprintf(
"<th class=\"ODBkey\">Key</th>\n");
6950 r->
rsprintf(
"<th class=\"ODBvalue\">Value ");
6951 r->
rsprintf(
"<script type=\"text/javascript\">\n");
6952 r->
rsprintf(
"function expand()\n");
6954 r->
rsprintf(
" var n = document.getElementsByName('ext');\n");
6955 r->
rsprintf(
" for (i=0 ; i<n.length ; i++) {\n");
6956 r->
rsprintf(
" if (n[i].style.display == 'none')\n");
6957 r->
rsprintf(
" n[i].style.display = 'table-cell';\n");
6959 r->
rsprintf(
" n[i].style.display = 'none';\n");
6961 r->
rsprintf(
" if (document.getElementById('expp').expflag === true) {\n");
6962 r->
rsprintf(
" document.getElementById('expp').expflag = false;\n");
6963 r->
rsprintf(
" document.getElementById('expp').innerHTML = '⇥';\n");
6965 r->
rsprintf(
" document.getElementById('expp').expflag = true;\n");
6966 r->
rsprintf(
" document.getElementById('expp').innerHTML = '⇤';\n");
6970 r->
rsprintf(
"<div style=\"display:inline;float:right\"><a id=\"expp\"href=\"#\" onClick=\"expand();return false;\">⇥</div>");
6972 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Type</th>\n");
6973 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">#Val</th>\n");
6974 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Size</th>\n");
6975 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Written</th>\n");
6976 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Mode</th>\n");
6980 for (
int i = 0;;
i++) {
6987 delete_list.push_back(
key.
name);
6991 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
6993 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
6995 std::string keyname =
key.
name;
6998 std::string enc_full_path = enc_root_path + enc_keyname;
7000 std::string odb_path = dec_path;
7001 if (odb_path.length() > 0 && odb_path[odb_path.length() - 1] !=
'/')
7006 std::string enc_link_ref;
7011 size =
sizeof(link_name);
7020 enc_link_ref =
"?cmd=Set&odb_path=";
7021 enc_link_ref += enc_full_path;
7025 sprintf(link_name,
"%s",
"(empty)");
7029 std::string enc_ref;
7032 if (enc_root_path.back() ==
'/' && link_name[0] ==
'/') {
7035 enc_ref +=
"?cmd=Set&odb_path=";
7036 enc_ref += enc_root_path;
7041 enc_ref +=
"?cmd=Set&odb_path=";
7042 enc_ref += enc_root_path;
7048 enc_ref +=
"?cmd=Set&odb_path=";
7049 enc_ref += enc_full_path;
7054 r->
rsprintf(
"<tr><td class=\"yellowLight\">");
7055 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td><b><div style=\"color:red\"><cannot resolve link></div></b></tr>\n", keyname.c_str(), enc_link_ref.c_str(), link_name[0]?link_name:
"(empty)");
7061 r->
rsprintf(
"<tr><td colspan=%d class=\"ODBdirectory\"><a href=\"?cmd=oldodb&odb_path=%s\">▶ %s</a>\n", colspan, enc_full_path.c_str(), keyname.c_str());
7063 r->
rsprintf(
"<i>→ <a href=\"%s\">%s</a></i>", enc_link_ref.c_str(), link_name);
7067 if (strchr(link_name,
'['))
7068 link_index = atoi(strchr(link_name,
'[')+1);
7075 size =
sizeof(
data);
7078 std::string data_str;
7080 if (link_index != -1)
7086 if (size ==
sizeof(
data)) {
7087 data_str +=
"...(truncated)";
7091 std::string hex_str;
7094 if (link_index != -1)
7100 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
7101 data_str =
"(empty)";
7106 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
7108 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7109 r->
rsprintf(
"%s <i>→ ", keyname.c_str());
7110 r->
rsprintf(
"<a href=\"%s\">%s</a></i>\n", enc_link_ref.c_str(), link_name);
7111 r->
rsprintf(
"<td class=\"%s\">\n", style);
7113 r->
rsprintf(
"%s (%s)", data_str.c_str(), hex_str.c_str());
7115 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7116 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">%s (%s)</a>\n", odb_path.c_str(), data_str.c_str(), hex_str.c_str());
7119 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7120 r->
rsprintf(
"%s<td class=\"%s\">", keyname.c_str(), style);
7122 r->
rsprintf(
"%s (%s)", data_str.c_str(), hex_str.c_str());
7124 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7125 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">%s (%s)</a>\n", odb_path.c_str(), data_str.c_str(), hex_str.c_str());
7129 if (strchr(data_str.c_str(),
'\n')) {
7131 r->
rsprintf(
"<td class=\"ODBkey\">");
7132 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td class=\"ODBvalue\">", keyname.c_str(), enc_link_ref.c_str(), link_name);
7134 r->
rsprintf(
"<td class=\"ODBkey\">%s<td class=\"%s\">", keyname.c_str(), style);
7138 if (strlen(
data) > data_str.length())
7139 r->
rsprintf(
"<i>... (%d bytes total)<p>\n", (
int)strlen(
data));
7141 r->
rsprintf(
"<a href=\"%s\">Edit</a>\n", enc_ref.c_str());
7144 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7145 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td class=\"%s\">", keyname.c_str(), enc_link_ref.c_str(), link_name, style);
7149 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7150 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", odb_path.c_str());
7155 r->
rsprintf(
"<td class=\"ODBkey\">%s<td class=\"%s\">", keyname.c_str(), style);
7156 if (!write_access) {
7159 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7160 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", odb_path.c_str());
7169 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7173 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7177 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7181 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7185 else if (delta < 3600)
7186 r->
rsprintf(
"%1.0lfm", delta / 60.0);
7187 else if (delta < 86400)
7188 r->
rsprintf(
"%1.0lfh", delta / 3600.0);
7189 else if (delta < 86400 * 99)
7190 r->
rsprintf(
"%1.0lfd", delta / 86400.0);
7195 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7211 r->
rsprintf(
"<tr><td class=\"ODBkey\">%s<td class=\"%s\"><span style=\"font-style: italic\"><a href=\"?cmd=oldodb&odb_path=%s&all=1\">... %d values ...</a></span>\n", keyname.c_str(), style, enc_full_path.c_str(),
key.
num_values);
7215 r->
rsprintf(
"<tr><td class=\"ODBkey\" rowspan=%d>%s<br><i>→ <a href=\"%s\">%s</a></i>\n",
key.
num_values, keyname.c_str(), enc_link_ref.c_str(), link_name);
7221 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
7223 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
7226 size =
sizeof(
data);
7230 std::string hex_str;
7238 if (size ==
sizeof(
data)) {
7239 data_str +=
"...(truncated)";
7243 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
7244 data_str =
"(empty)";
7250 enc_ref +=
"?cmd=Set&odb_path=";
7251 enc_ref += enc_full_path;
7252 enc_ref +=
"&index=";
7265 r->
rsprintf(
"<td class=\"%s\">[%d] ", style,
j);
7267 r->
rsprintf(
"<a href=\"%s\">", enc_ref.c_str());
7269 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), tmpstr.c_str());
7270 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", tmpstr.c_str());
7272 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
7273 r->
rsprintf(
"%s (%s)</a>\n", data_str.c_str(), hex_str.c_str());
7275 r->
rsprintf(
"%s</a>\n", data_str.c_str());
7279 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7283 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7287 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7291 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7295 else if (delta < 3600)
7296 r->
rsprintf(
"%1.0lfm", delta / 60.0);
7297 else if (delta < 86400)
7298 r->
rsprintf(
"%1.0lfh", delta / 3600.0);
7299 else if (delta < 86400 * 99)
7300 r->
rsprintf(
"%1.0lfh", delta / 86400.0);
7305 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7333 std::sort(delete_list.begin(), delete_list.end());
7335 for (
unsigned i=0;
i<delete_list.size();
i++) {
7336 std::string
name = delete_list[
i];
7338 dd +=
"<tr><td style=\"text-align:left;\" align=left><input align=left type=checkbox id=delete";
7342 dd += MJsonNode::Encode(
name.c_str());
7346 dd +=
"</input></td></tr>\n";
7350 dd +=
"<input type=button value=Delete onClick='mhttpd_delete_page_handle_delete(event);'>\n";
7351 dd +=
"<input type=button value=Cancel onClick='mhttpd_delete_page_handle_cancel(event);'>\n";
7359 std::string cd =
"";
7361 cd +=
"<!-- Demo dialog -->\n";
7362 cd +=
"<div id=\"dlgCreate\" class=\"dlgFrame\">\n";
7363 cd +=
"<div class=\"dlgTitlebar\">Create ODB entry</div>\n";
7364 cd +=
"<div class=\"dlgPanel\">\n";
7366 cd +=
"<div id=odbpath>";
7368 cd += MJsonNode::Encode(odbpath.c_str());
7371 cd +=
"<div><br></div>\n";
7373 cd +=
"<table class=\"dialogTable\">\n";
7374 cd +=
"<th colspan=2>Create ODB entry:</th>\n";
7378 cd +=
"<select type=text size=1 id=create_tid name=type>";
7379 cd +=
"<option value=7>Integer (32-bit)";
7380 cd +=
"<option value=9>Float (4 Bytes)";
7381 cd +=
"<option value=12>String";
7382 cd +=
"<option selected value=15>Subdirectory";
7383 cd +=
"<option value=1>Byte";
7384 cd +=
"<option value=2>Signed byte";
7385 cd +=
"<option value=3>Character (8-bit)";
7386 cd +=
"<option value=4>Word (16-bit)";
7387 cd +=
"<option value=5>Short integer (16-bit)";
7388 cd +=
"<option value=6>Double Word (32-bit)";
7389 cd +=
"<option value=8>Boolean";
7390 cd +=
"<option value=10>Double float (8 Bytes)";
7394 cd +=
"<tr><td>Name<td><input type=text size=31 maxlength=31 id=create_name name=value></tr>\n";
7395 cd +=
"<tr><td>Array size<td><input type=text size=31 maxlength=31 id=create_array_length name=index value=1></tr>\n";
7396 cd +=
"<tr><td>String length<td><input type=text size=31 maxlength=31 id=create_strlen name=strlen value=32></tr>\n";
7398 cd +=
"<input type=button value=Create onClick='mhttpd_create_page_handle_create(event);'>\n";
7399 cd +=
"<input type=button value=Cancel onClick='mhttpd_create_page_handle_cancel(event);'>\n";
7407 std::string ld =
"";
7409 ld +=
"<!-- Demo dialog -->\n";
7410 ld +=
"<div id=\"dlgLink\" class=\"dlgFrame\">\n";
7411 ld +=
"<div class=\"dlgTitlebar\">Create a link to an ODB entry</div>\n";
7412 ld +=
"<div class=\"dlgPanel\">\n";
7414 ld +=
"<div id=link_odbpath>";
7416 ld += MJsonNode::Encode(odbpath.c_str());
7419 ld +=
"<div><br></div>\n";
7421 ld +=
"<table class=\"dialogTable\">\n";
7422 ld +=
"<th colspan=2>Create a link to an ODB entry:</th>\n";
7423 ld +=
"<tr><td>Name<td><input type=text size=31 maxlength=31 id=link_name name=value></tr>\n";
7424 ld +=
"<tr><td>Link target<td><input type=text size=31 maxlength=256 id=link_target name=target></tr>\n";
7426 ld +=
"<input type=button value=Link onClick='mhttpd_link_page_handle_link(event);'>\n";
7427 ld +=
"<input type=button value=Cancel onClick='mhttpd_link_page_handle_cancel(event);'>\n";
7445 std::string odb_path = pp->
getparam(
"odb_path");
7455 r->
rsprintf(
"Error: cannot find key %s<P>\n", odb_path.c_str());
7465 r->
rsprintf(
"<table class=\"dialogTable\">");
7468 r->
rsprintf(
"<input type=hidden name=index value=\"%d\">\n",
index);
7473 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", group);
7475 r->
rsprintf(
"<input type=hidden name=odb_path value=\"%s\">\n", odb_path.c_str());
7483 str1 = odb_path.c_str();
7485 r->
rsprintf(
"<tr><th colspan=2>Set new value - type = %s</tr>\n", data_str1.c_str());
7486 r->
rsprintf(
"<tr><td>%s<td>\n", str1.c_str());
7489 size =
sizeof(
data);
7496 if (strchr(data_str.c_str(),
'\n') != NULL) {
7497 r->
rsprintf(
"<textarea rows=20 cols=80 name=\"text\">\n");
7502 if ((
int) data_str.length() > size)
7503 size = data_str.length() + 3;
7507 r->
rsprintf(
"<input type=\"text\" size=%d maxlength=256 name=\"value\" value=\"", size);
7514 r->
rsprintf(
"<tr><td align=center colspan=2>");
7515 r->
rsprintf(
"<input type=submit name=cmd value=Set>");
7516 r->
rsprintf(
"<input type=submit name=cmd value=Cancel>");
7520 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
7531 r->
rsprintf(
"Error: cannot find key %s<P>\n", odb_path.c_str());
7560 r->
rsprintf(
"<h2>Write access not allowed</h2>\n");
7576 if (
value[0] == 0) {
7584 r->
rsprintf(
"<table class=\"dialogTable\">");
7586 r->
rsprintf(
"<tr><th colspan=2>Find string in Online Database</tr>\n");
7587 r->
rsprintf(
"<tr><td>Enter substring (case insensitive)\n");
7589 r->
rsprintf(
"<td><input type=\"text\" size=\"20\" maxlength=\"80\" name=\"value\">\n");
7592 r->
rsprintf(
"<tr><td align=center colspan=2>");
7593 r->
rsprintf(
"<input type=submit name=cmd value=Find>");
7594 r->
rsprintf(
"<input type=submit name=cmd value=Cancel>");
7598 r->
rsprintf(
"<input type=hidden name=cmd value=Find>");
7606 r->
rsprintf(
"<table class=\"mtable\">\n");
7607 r->
rsprintf(
"<tr><th colspan=2 class=\"mtableheader\">");
7608 r->
rsprintf(
"Results of search for substring \"%s\"</tr>\n",
value);
7609 r->
rsprintf(
"<tr><th class=\"titlerow\">Key<th>Value</tr>\n");
7631#define LN10 2.302585094
7632#define LOG2 0.301029996
7633#define LOG5 0.698970005
7636 int x1,
int y1,
int width,
7637 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax)
7639 double dx, int_dx, frac_dx, x_act, label_dx, major_dx, x_screen, maxwidth;
7640 int tick_base, major_base, label_base, n_sig1, n_sig2, xs;
7642 double base[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
7644 if (xmax <= xmin || width <= 0)
7648 dx = (xmax - xmin) / (
double) (width / 5);
7650 frac_dx = modf(log(dx) /
LN10, &int_dx);
7656 tick_base = frac_dx <
LOG2 ? 1 : frac_dx <
LOG5 ? 2 : 3;
7657 major_base = label_base = tick_base + 1;
7660 dx = pow(10, int_dx) *
base[tick_base];
7661 major_dx = pow(10, int_dx) *
base[major_base];
7662 label_dx = major_dx;
7668 n_sig1 = (int) floor(log(fabs(xmin)) /
LN10) - (
int) floor(log(fabs(label_dx)) /
LN10) + 1;
7674 (int) floor(log(fabs(xmax)) /
LN10) - (
int) floor(log(fabs(label_dx)) /
LN10) + 1;
7676 n_sig1 =
MAX(n_sig1, n_sig2);
7677 n_sig1 =
MAX(n_sig1, 4);
7680 sprintf(
str,
"%1.*lG", n_sig1, floor(xmin / dx) * dx);
7681 maxwidth = font->
h / 2 * strlen(
str);
7682 sprintf(
str,
"%1.*lG", n_sig1, floor(xmax / dx) * dx);
7683 maxwidth =
MAX(maxwidth, font->
h / 2 * strlen(
str));
7684 sprintf(
str,
"%1.*lG", n_sig1, floor(xmax / dx) * dx + label_dx);
7685 maxwidth =
MAX(maxwidth, font->
h / 2 * strlen(
str));
7688 while (maxwidth > 0.7 * label_dx / (xmax - xmin) * width) {
7690 label_dx = pow(10, int_dx) *
base[label_base];
7691 if (label_base % 3 == 2 && major_base % 3 == 1) {
7693 major_dx = pow(10, int_dx) *
base[major_base];
7697 x_act = floor(xmin / dx) * dx;
7702 x_screen = (x_act - xmin) / (xmax - xmin) * width + x1;
7703 xs = (int) (x_screen + 0.5);
7705 if (x_screen > x1 + width + 0.001)
7708 if (x_screen >= x1) {
7709 if (fabs(floor(x_act / major_dx + 0.5) - x_act / major_dx) <
7710 dx / major_dx / 10.0) {
7712 if (fabs(floor(x_act / label_dx + 0.5) - x_act / label_dx) <
7713 dx / label_dx / 10.0) {
7718 if (grid != 0 && xs > x1 && xs < x1 + width)
7723 sprintf(
str,
"%1.*lG", n_sig1, x_act);
7725 y1 + label,
str, col);
7732 if (grid != 0 && xs > x1 && xs < x1 + width)
7745 if (fabs(x_act) < dx / 100)
7758 t_sec = (time_t) sec;
7761 localtime_r(&t_sec, &tms);
7762 strcpy(mon,
mname[tms.tm_mon]);
7767 sprintf(result,
"%02d %s %02d %02d:%02d:%02d",
7768 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min,
7770 else if (
base < 3600 * 24)
7771 sprintf(result,
"%02d %s %02d %02d:%02d",
7772 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min);
7774 sprintf(result,
"%02d %s %02d", tms.tm_mday, mon, tms.tm_year % 100);
7777 sprintf(result,
"%02d:%02d:%02d", tms.tm_hour, tms.tm_min, tms.tm_sec);
7778 else if (
base < 3600 * 3)
7779 sprintf(result,
"%02d:%02d", tms.tm_hour, tms.tm_min);
7780 else if (
base < 3600 * 24)
7781 sprintf(result,
"%02d %s %02d %02d:%02d",
7782 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min);
7784 sprintf(result,
"%02d %s %02d", tms.tm_mday, mon, tms.tm_year % 100);
7789 int x1,
int y1,
int width,
int xr,
7790 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax)
7792 int dx, x_act, label_dx, major_dx, x_screen, maxwidth;
7793 int tick_base, major_base, label_base, xs, xl;
7795 const int base[] = { 1, 5, 10, 60, 300, 600, 1800, 3600, 3600 * 6, 3600 * 12, 3600 * 24, 0 };
7797 int force_date, d1, d2;
7800 if (xmax <= xmin || width <= 0)
7805 localtime_r(<ime, &tms);
7807 ltime = (time_t) xmax;
7808 localtime_r(<ime, &tms);
7810 force_date = (d1 != d2);
7813 dx = (int) ((xmax - xmin) / (double) (width / 5) + 0.5);
7815 for (tick_base = 0;
base[tick_base]; tick_base++) {
7816 if (
base[tick_base] > dx)
7819 if (!
base[tick_base])
7821 dx =
base[tick_base];
7823 if (
base[tick_base + 1])
7824 major_base = tick_base + 1;
7826 major_base = tick_base;
7827 major_dx =
base[major_base];
7829 if (
base[major_base + 1])
7830 label_base = major_base + 1;
7832 label_base = major_base;
7833 label_dx =
base[label_base];
7837 maxwidth = font->
h / 2 * strlen(
str);
7840 if (maxwidth > 0.7 * label_dx / (xmax - xmin) * width) {
7841 if (
base[label_base + 1])
7842 label_dx =
base[++label_base];
7844 label_dx += 3600 * 24;
7855 x_screen = (int) ((x_act - xmin) / (xmax - xmin) * width + x1 + 0.5);
7856 xs = (int) (x_screen + 0.5);
7858 if (x_screen > x1 + width + 0.001)
7861 if (x_screen >= x1) {
7868 if (grid != 0 && xs > x1 && xs < x1 + width)
7876 xl = (int) xs - font->
w * strlen(
str) / 2;
7879 if (xl + font->
w * (
int) strlen(
str) > xr)
7880 xl = xr - font->
w * strlen(
str);
7888 if (grid != 0 && xs > x1 && xs < x1 + width)
7901 if (fabs((
double)x_act) < dx / 100)
7910 int x1,
int y1,
int width,
7911 int minor,
int major,
int text,
int label,
int grid,
double ymin,
double ymax,
7914 double dy, int_dy, frac_dy, y_act, label_dy, major_dy, y_screen, y_next;
7915 int tick_base, major_base, label_base, n_sig1, n_sig2, ys, max_width;
7918 const double base[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
7920 if (ymax <= ymin || width <= 0)
7924 if (fabs(ymax - ymin) <= 1
e-10)
7928 dy = pow(10, floor(log(ymin) /
LN10));
7933 dy = (ymax - ymin) / (
double) (width / 5);
7935 frac_dy = modf(log(dy) /
LN10, &int_dy);
7941 tick_base = frac_dy <
LOG2 ? 1 : frac_dy <
LOG5 ? 2 : 3;
7942 major_base = label_base = tick_base + 1;
7945 dy = pow(10, int_dy) *
base[tick_base];
7946 major_dy = pow(10, int_dy) *
base[major_base];
7947 label_dy = major_dy;
7954 (int) floor(log(fabs(ymin)) /
LN10) -
7955 (
int) floor(log(fabs(label_dy)) /
LN10) + 1;
7961 (int) floor(log(fabs(ymax)) /
LN10) -
7962 (
int) floor(log(fabs(label_dy)) /
LN10) + 1;
7964 n_sig1 =
MAX(n_sig1, n_sig2);
7965 n_sig1 =
MAX(n_sig1, 4);
7968 while (label_dy / (ymax - ymin) * width < 1.5 * font->h) {
7970 label_dy = pow(10, int_dy) *
base[label_base];
7971 if (label_base % 3 == 2 && major_base % 3 == 1) {
7973 major_dy = pow(10, int_dy) *
base[major_base];
7979 y_act = floor(ymin / dy) * dy;
7981 if (x1 != 0 || y1 != 0)
7984 last_label_y = y1 + 2 * font->
h;
7988 y_screen = y1 - (log(y_act) - log(ymin)) / (log(ymax) - log(ymin)) * width;
7990 y_screen = y1 - (y_act - ymin) / (ymax - ymin) * width;
7991 ys = (int) (y_screen + 0.5);
7993 if (y_screen < y1 - width - 0.001)
7996 if (y_screen <= y1 + 0.001) {
7997 if (fabs(floor(y_act / major_dy + 0.5) - y_act / major_dy) <
7998 dy / major_dy / 10.0) {
7999 if (fabs(floor(y_act / label_dy + 0.5) - y_act / label_dy) <
8000 dy / label_dy / 10.0) {
8001 if (x1 != 0 || y1 != 0) {
8006 if (grid != 0 && y_screen < y1 && y_screen > y1 - width) {
8015 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8018 ys - font->
h / 2,
str, col);
8022 last_label_y = ys - font->
h / 2;
8025 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8026 max_width =
MAX(max_width, (
int) (font->
w * strlen(
str)));
8029 if (x1 != 0 || y1 != 0) {
8034 if (grid != 0 && y_screen < y1 && y_screen > y1 - width)
8045 if (x1 != 0 || y1 != 0) {
8053 if (x1 != 0 || y1 != 0) {
8055 y_next = pow(10, floor(log(y_act) /
LN10) + 1);
8058 (log(y_next) - log(ymin)) / (log(ymax) -
8059 log(ymin)) * width + 0.5);
8061 if (ys + font->
h / 2 < last_label_y
8062 && ys - font->
h / 2 > y_screen + font->
h / 2) {
8063 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8066 ys - font->
h / 2,
str, col);
8072 last_label_y = ys - font->
h / 2;
8074 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8075 max_width =
MAX(max_width, (
int) (font->
w * strlen(
str)));
8085 if (fabs(y_act) < dy / 100)
8090 return max_width + abs(label);
8100 switch (
str[strlen(
str) - 1]) {
8123 for (; *
str != 0;
str++) {
8139 sprintf(buf,
"%.0f", (
double)t);
8152 cm_msg(
MINFO,
"history_watch_callback",
"History configuration may have changed, will reconnect");
8219 cm_msg(
MERROR,
"get_history",
"Cannot configure history, hs_get_history() status %d",
status);
8237#define ALLOC(t,n) (t*)calloc(sizeof(t),(n))
8238#define DELETE(x) if (x) { free(x); (x)=NULL; }
8239#define DELETEA(x, n) if (x) { for (int i=0; i<(n); i++) { free((x)[i]); (x)[i]=NULL; }; DELETE(x); }
8240#define STRDUP(x) strdup(x)
8296 printf(
"this %p, nvars %d. tstart %d, tend %d, scale %d\n",
this,
nvars, (
int)
tstart, (
int)
tend, (
int)
scale);
8323#define READ_HISTORY_DATA 0x1
8324#define READ_HISTORY_RUNMARKER 0x2
8325#define READ_HISTORY_LAST_WRITTEN 0x4
8385 cm_msg(
MERROR,
"read_history",
"Cannot find \'/History/Display\' in ODB, status %d",
status);
8392 cm_msg(
MERROR,
"read_history",
"Cannot find \'%s\' in ODB, status %d", path,
status);
8398 cm_msg(
MERROR,
"read_history",
"Cannot find \'%s/Variables\' in ODB, status %d", path,
status);
8408 data->tstart = tstart;
8410 data->scale = scale;
8412 for (
size_t i=0;
i<hp.
vars.size();
i++) {
8442 char *
q = strchr(
data->var_names[
data->nvars],
'[');
8444 data->var_index[
data->nvars] = atoi(
q+1);
8460 data->var_index[
data->nvars+0] = 0;
8461 data->var_index[
data->nvars+1] = 0;
8463 data->odb_index[
data->nvars+0] = -1;
8464 data->odb_index[
data->nvars+1] = -2;
8469 bool get_last_written =
false;
8483 printf(
"read_history: nvars %d, hs_read() status %d\n",
data->nvars,
status);
8484 for (
int i=0;
i<
data->nvars;
i++) {
8485 printf(
"read_history: %d: event [%s], var [%s], index %d, odb index %d, status %d, num_entries %d\n",
i,
data->event_names[
i],
data->var_names[
i],
data->var_index[
i],
data->odb_index[
i],
data->status[
i],
data->num_entries[
i]);
8490 cm_msg(
MERROR,
"read_history",
"Complete history failure, hs_read() status %d, see messages",
status);
8494 for (
int i=0;
i<
data->nvars;
i++) {
8496 get_last_written =
true;
8503 get_last_written =
true;
8505 if (get_last_written) {
8506 data->have_last_written =
true;
8514 data->last_written);
8517 data->have_last_written =
false;
8559 time_t tmin = endtime;
8562 for (
int k=0;
k<hsdata->
nvars;
k++) {
8593 *plastwritten = tmin;
8595 *plastwritten = tmax;
8602 printf(
"get_hist_last_written: elapsed time %f ms\n", tend-tstart);
8608 int width,
int height,
8612 int labels,
const char *bgcolor,
const char *fgcolor,
const char *gridcolor)
8620 int size,
status, r, g, b;
8623 int white, grey, red;
8625 int fgcol, bgcol, gridcol;
8645 time_t starttime, endtime;
8656 std::vector<int> var_index; var_index.resize(hp.
vars.size());
8658 for (
size_t i=0;
i<hp.
vars.size();
i++) {
8660 const char *vp = strchr(hp.
vars[
i].tag_name.c_str(),
'[');
8662 var_index[
i] = atoi(vp + 1);
8670 if ((minvalue == 0) && (maxvalue == 0)) {
8671 minvalue = -HUGE_VAL;
8672 maxvalue = +HUGE_VAL;
8687 sscanf(bgcolor,
"%02x%02x%02x", &r, &g, &b);
8689 sscanf(fgcolor,
"%02x%02x%02x", &r, &g, &b);
8691 sscanf(gridcolor,
"%02x%02x%02x", &r, &g, &b);
8728 sprintf(
str,
"History is not configured, see messages");
8752 if (hp.
vars.empty()) {
8753 sprintf(
str,
"No variables in panel %s/%s", hgroup, hpanel);
8759 sprintf(
str,
"Too many variables in panel %s/%s", hgroup, hpanel);
8767 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
8828 if (hp.
vars[
i].colour[0] ==
'#') {
8829 const char*
str = hp.
vars[
i].colour.c_str();
8836 r = strtoul(sss, NULL, 16);
8840 g = strtoul(sss, NULL, 16);
8844 b = strtoul(sss, NULL, 16);
8920 std::string odbpath;
8936 sprintf(
str,
"Variables/%s", hp.
vars[
i].tag_name.c_str());
8942 odbpath +=
"/Equipment/";
8943 odbpath += hp.
vars[
i].event_name;
8944 odbpath +=
"/Variables/";
8945 odbpath += hp.
vars[
i].tag_name;
8954 mstrlcpy(
str, hp.
vars[
i].tag_name.c_str(),
sizeof(
str));
8955 p =
str + strlen(
str) - 1;
8956 while (p >
str && *p !=
' ')
8958 std::string key_name = p + 1;
8961 std::string varname =
str;
8971 odbpath +=
"/Equipment/";
8972 odbpath += hp.
vars[
i].event_name;
8973 odbpath +=
"/Variables/";
8974 odbpath += key_name;
8996 std::string key_name =
key.
name;
9000 path +=
"Settings/Names ";
9013 odbpath +=
"/Equipment/";
9014 odbpath += hp.
vars[
i].event_name;
9015 odbpath +=
"/Variables/";
9016 odbpath += key_name;
9064 upper_limit[
i] = lower_limit[
i] = -12345;
9066 if (odbpath.length() > 0 && hkeyroot) {
9077 if (strstr(
str, odbpath.c_str())) {
9078 if (strchr(
str,
'<')) {
9079 p = strchr(
str,
'<') + 1;
9083 lower_limit[
i] = (hp.
vars[
i].factor * (atof(p) - hp.
vars[
i].voffset) + hp.
vars[
i].offset);
9085 lower_limit[
i] = atof(p);
9088 if (strchr(
str,
'>')) {
9089 p = strchr(
str,
'>') + 1;
9093 upper_limit[
i] = (hp.
vars[
i].factor * (atof(p) - hp.
vars[
i].voffset) + hp.
vars[
i].offset);
9095 upper_limit[
i] = atof(p);
9106 starttime = xendtime - scale;
9118 sprintf(
str,
"Complete history failure, read_history() status %d, see messages",
status);
9126 for (
int k=0;
k<hsdata->
nvars;
k++) {
9137 var_status[
i][0] = 0;
9139 sprintf(var_status[
i],
"not found in history");
9142 sprintf(var_status[
i],
"hs_read() error %d, see messages", hsdata->
status[
k]);
9148 int xx = (int)(hsdata->
t[
k][
j]);
9149 double yy = hsdata->
v[
k][
j];
9165 yy = hp.
vars[
i].factor * (yy - hp.
vars[
i].voffset) + hp.
vars[
i].offset;
9169 if ((
i == 0 ||
index != -1) && n_vp == 0)
9189 assert(x[
i].size() == y[
i].size());
9198 double yb1, yb2, yf1, yf2;
9207 if (ymin < minvalue)
9210 if (ymax > maxvalue)
9223 if (logaxis && ymin > 0 && ymax > 0) {
9224 yb1 = pow(10, floor(log(ymin) /
LN10));
9225 yf1 = floor(ymin / yb1);
9226 yb2 = pow(10, floor(log(ymax) /
LN10));
9227 yf2 = floor(ymax / yb2);
9229 if (yb1 == yb2 && yf1 == yf2)
9233 ybase = pow(10, floor(log(ymin) /
LN10));
9234 ymin = (floor(ymin / ybase) * ybase);
9235 ybase = pow(10, floor(log(ymax) /
LN10));
9236 ymax = ((floor(ymax / ybase) + 1) * ybase);
9249 if (ymin == 0 && ymax == 0) {
9254 ymax += (ymax - ymin) / 20.f;
9257 ymin -= (ymax - ymin) / 20.f;
9279 aoffset =
vaxis(im,
gdFontSmall, fgcol, gridcol, 0, 0, height, -3, -5, -7, -8, 0, ymin, ymax, logaxis);
9290 taxis(im,
gdFontSmall, fgcol, gridcol, x1, y1, x2 - x1, width, 3, 5, 9, 10, 0, (
double)starttime, (
double)endtime);
9292 vaxis(im,
gdFontSmall, fgcol, gridcol, x1, y1, y1 - y2, -3, -5, -7, -8, x2 - x1, ymin, ymax, logaxis);
9296 xs = ys = xold = yold = 0;
9303 const char* event_names[] = {
9308 const char* tag_names[] = {
9313 const int tag_indexes[] = {
9327 2, event_names, tag_names, tag_indexes,
9328 num_entries, tbuf, dbuf, st);
9332 int n_marker = num_entries[0];
9337 for (
j = 0;
j < (int) n_marker;
j++) {
9351 xs = (int) ((tbuf[1][
j] - starttime) / (scale/1.0) * (x2 - x1) + x1 + 0.5);
9364 if (dbuf[0][
j] == 1)
9366 else if (dbuf[0][
j] == 2)
9368 else if (dbuf[0][
j] == 3)
9391 if (num_entries[0]) {
9398 if (num_entries[1]) {
9409 int index_state = -1;
9410 int index_run_number = -1;
9412 for (
int k=0;
k<hsdata->
nvars;
k++) {
9417 index_run_number =
k;
9423 ok = (index_state >= 0) && (index_run_number >= 0);
9432 printf(
"read run info: indexes: %d, %d, status: %d, %d, entries: %d, %d\n", index_state, index_run_number, hsdata->
status[index_state], hsdata->
status[index_run_number], hsdata->
num_entries[index_state], hsdata->
num_entries[index_run_number]);
9439 if (ok && n_marker > 0 && n_marker < 100) {
9442 for (
j = 0;
j < (int) n_marker;
j++) {
9456 xs = (int) ((hsdata->
t[index_state][
j] - starttime) / (scale/1.0) * (x2 - x1) + x1 + 0.5);
9469 int state = (int)hsdata->
v[index_state][
j];
9473 else if (
state == 2)
9475 else if (
state == 3)
9499 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
9504 if (lower_limit[
i] != -12345) {
9506 if (lower_limit[
i] <= 0)
9509 ys = (int) (y1 - (log(lower_limit[
i]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9511 ys = (int) (y1 - (lower_limit[
i] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9523 if (ys > y2 && ys < y1) {
9536 if (upper_limit[
i] != -12345) {
9538 if (upper_limit[
i] <= 0)
9541 ys = (int) (y1 - (log(upper_limit[
i]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9543 ys = (int) (y1 - (upper_limit[
i] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9555 if (ys > y2 && ys < y1) {
9569 for (
j = 0;
j < (int) n_point[
i];
j++) {
9575 xs = (int) (((x[
i][
j] - starttime)/1.0) / (1.0*scale) * (x2 - x1) + x1 + 0.5);
9581 ys = (int) (y1 - (log(y[
i][
j]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9583 ys = (int) (y1 - (y[
i][
j] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9601 if (n_point[
i] > 0) {
9604 poly[1].
x = xs + 12;
9606 poly[2].
x = xs + 12;
9614 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
9625 std::string
str = hp.
vars[
i].label.c_str();
9631 if (hp.
vars[
i].voffset > 0)
9633 else if (hp.
vars[
i].voffset < 0)
9636 if (hp.
vars[
i].factor != 1) {
9637 if (hp.
vars[
i].voffset == 0)
9644 if (hp.
vars[
i].offset > 0)
9646 else if (hp.
vars[
i].offset < 0)
9655 for (
int j=0;
j<hsdata->
nvars;
j++)
9662 printf(
"graph %d: odb index %d, n_point %d, num_entries %d, have_last_written %d %d, status %d, var_status [%s]\n",
i,
k, n_point[
i], hsdata->
num_entries[
k], hsdata->
have_last_written, (
int)hsdata->
last_written[
k], hsdata->
status[
k], var_status[
i]);
9667 if (n_point[
i] > 0) {
9668 sprintf(xstr,
" = %g", y[
i][n_point[
i]-1]);
9670 sprintf(xstr,
" = all data is NaN or INF");
9675 sprintf(xstr,
" = last data %s", ctimebuf);
9677 char*s = strchr(xstr,
'\n');
9681 var_status[
i][0] = 0;
9683 sprintf(xstr,
" = no data ever");
9686 sprintf(xstr,
" = no data");
9691 if (strlen(var_status[
i]) > 1) {
9695 row =
index == -1 ?
i : 0;
9725 if (buffer == NULL) {
9726 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
9729 rr->
rsprintf(
"Content-Type: image/gif\r\n");
9730 rr->
rsprintf(
"Content-Length: %d\r\n", length);
9731 rr->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
9732 rr->
rsprintf(
"Expires: Fri, 01-Jan-1983 00:00:00 GMT\r\n\r\n");
9736 if (length > *buffer_size) {
9737 printf(
"return buffer too small\n");
9741 memcpy(buffer, gb.
data, length);
9742 *buffer_size = length;
9767 struct tm tms = *ptms;
9770 localtime_r(&t1, &tms2);
9771 tms2.tm_year = ptms->tm_year;
9772 tms2.tm_mon = ptms->tm_mon;
9773 tms2.tm_mday = ptms->tm_mday;
9774 tms2.tm_hour = ptms->tm_hour;
9775 tms2.tm_min = ptms->tm_min;
9801 memset(&tms, 0,
sizeof(
struct tm));
9803 tms.tm_year = atoi(p->
getparam(
"y1")) % 100;
9805 std::string m1 = p->
getparam(
"m1");
9806 for (
i = 0;
i < 12;
i++)
9813 tms.tm_mday = atoi(p->
getparam(
"d1"));
9814 tms.tm_hour = atoi(p->
getparam(
"h1"));
9816 if (tms.tm_year < 90)
9821 memset(&tms, 0,
sizeof(
struct tm));
9822 tms.tm_year = atoi(p->
getparam(
"y2")) % 100;
9824 std::string m2 = p->
getparam(
"m2");
9825 for (
i = 0;
i < 12;
i++)
9832 tms.tm_mday = atoi(p->
getparam(
"d2"));
9833 tms.tm_hour = atoi(p->
getparam(
"h2"));
9835 if (tms.tm_year < 90)
9840 if (ltime_end == ltime_start)
9841 ltime_end += 3600 * 24;
9844 redir +=
"?cmd=oldhistory&";
9865 time_t now = time(NULL);
9867 time_t starttime = now - 3600 * 24;
9868 time_t endtime = now;
9869 bool full_day =
true;
9875 starttime = endtime - atoi(p->
getparam(
"hscale"));
9878 starttime = endtime - 3600 * 24;
9884 r->
rsprintf(
"<tr><td colspan=2>\n");
9885 r->
rsprintf(
"<input type=hidden name=cmd value=OldHistory>\n");
9886 r->
rsprintf(
"<input type=submit name=hcmd value=Query>\n");
9887 r->
rsprintf(
"<input type=submit name=hcmd value=Cancel>\n");
9889 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", p->
getparam(
"group"));
9891 r->
rsprintf(
"<input type=hidden name=panel value=\"%s\">\n", p->
getparam(
"panel"));
9893 r->
rsprintf(
"<input type=hidden name=htime value=\"%s\">\n", p->
getparam(
"htime"));
9895 r->
rsprintf(
"<input type=hidden name=hscale value=\"%s\">\n", p->
getparam(
"hscale"));
9897 r->
rsprintf(
"<input type=hidden name=hindex value=\"%s\">\n", p->
getparam(
"hindex"));
9901 r->
rsprintf(
"<table class=\"dialogTable\">");
9904 localtime_r(&starttime, &tms);
9905 tms.tm_year += 1900;
9907 r->
rsprintf(
"<tr><td nowrap>Start date:</td>");
9909 r->
rsprintf(
"<td>Month: <select name=\"m1\">\n");
9910 r->
rsprintf(
"<option value=\"\">\n");
9911 for (
i = 0;
i < 12;
i++)
9912 if (
i == tms.tm_mon)
9918 r->
rsprintf(
" Day: <select name=\"d1\">");
9919 r->
rsprintf(
"<option selected value=\"\">\n");
9920 for (
i = 0;
i < 31;
i++)
9921 if (
i + 1 == tms.tm_mday)
9922 r->
rsprintf(
"<option selected value=%d>%d\n",
i + 1,
i + 1);
9924 r->
rsprintf(
"<option value=%d>%d\n",
i + 1,
i + 1);
9927 int start_hour = tms.tm_hour;
9931 r->
rsprintf(
" Hour: <input type=\"text\" size=5 maxlength=5 name=\"h1\" value=\"%d\">", start_hour);
9933 r->
rsprintf(
" Year: <input type=\"text\" size=5 maxlength=5 name=\"y1\" value=\"%d\">", tms.tm_year);
9936 r->
rsprintf(
"<tr><td nowrap>End date:</td>");
9938 localtime_r(&endtime, &tms);
9939 tms.tm_year += 1900;
9941 r->
rsprintf(
"<td>Month: <select name=\"m2\">\n");
9942 r->
rsprintf(
"<option value=\"\">\n");
9943 for (
i = 0;
i < 12;
i++)
9944 if (
i == tms.tm_mon)
9950 r->
rsprintf(
" Day: <select name=\"d2\">");
9951 r->
rsprintf(
"<option selected value=\"\">\n");
9952 for (
i = 0;
i < 31;
i++)
9953 if (
i + 1 == tms.tm_mday)
9954 r->
rsprintf(
"<option selected value=%d>%d\n",
i + 1,
i + 1);
9956 r->
rsprintf(
"<option value=%d>%d\n",
i + 1,
i + 1);
9959 int end_hour = tms.tm_hour;
9963 r->
rsprintf(
" Hour: <input type=\"text\" size=5 maxlength=5 name=\"h2\" value=\"%d\">", end_hour);
9965 r->
rsprintf(
" Year: <input type=\"text\" size=5 maxlength=5 name=\"y2\" value=\"%d\">", tms.tm_year);
9981 const char*sa = (
const char*)a;
9982 const char*sb = (
const char*)b;
9991 printf(
"compare [%s] and [%s]\n", sa, sb);
9994 if (sa[
i]==0 && sb[
i]==0)
9999 if (isdigit(sa[
i]) && isdigit(sb[
i])) {
10000 int va = atoi(sa+
i);
10001 int vb = atoi(sb+
i);
10004 printf(
"index %d, values %d %d\n",
i, va, vb);
10015 if (sa[
i]==sb[
i]) {
10020 printf(
"index %d, char [%c] [%c]\n",
i, sa[
i], sb[
i]);
10024 else if (sb[
i] == 0)
10038 return cmp_names(a.c_str(), b.c_str()) < 0;
10052static int cmp_tags(
const void *a,
const void *b)
10054 const TAG*sa = (
const TAG*)a;
10055 const TAG*sb = (
const TAG*)b;
10059static void sort_tags(
int ntags,
TAG* tags)
10091 str =
"bad_xdb_find_key";
10111 printf(
"hist plot: %d variables\n", (
int)hp.
vars.size());
10112 printf(
"timescale: %s, minimum: %f, maximum: %f, zero_ylow: %d, log_axis: %d, show_run_markers: %d, show_values: %d, show_fill: %d, show_factor %d, enable_factor: %d\n", hp.
timescale.c_str(), hp.
minimum, hp.
maximum, hp.
zero_ylow, hp.
log_axis, hp.
show_run_markers, hp.
show_values, hp.
show_fill, hp.
show_factor, hp.
enable_factor);
10114 for (
size_t i=0;
i<hp.
vars.size();
i++) {
10115 printf(
"var[%d] event [%s][%s] formula [%s], colour [%s] label [%s] show_raw_value %d factor %f offset %f voffset %f order %d\n", (
int)
i, hp.
vars[
i].event_name.c_str(), hp.
vars[
i].tag_name.c_str(), hp.
vars[
i].formula.c_str(), hp.
vars[
i].colour.c_str(), hp.
vars[
i].label.c_str(), hp.
vars[
i].show_raw_value, hp.
vars[
i].factor, hp.
vars[
i].offset , hp.
vars[
i].voffset, hp.
vars[
i].order);
10121 const char*
const colour[] =
10123 "#00AAFF",
"#FF9000",
"#FF00A0",
"#00C030",
10124 "#A0C0D0",
"#D0A060",
"#C04010",
"#807060",
10125 "#F0C000",
"#2090A0",
"#D040D0",
"#90B000",
10126 "#B0B040",
"#B0B0FF",
"#FFA0A0",
"#A0FFA0",
10129 for (
int i=0; colour[
i];
i++) {
10130 bool in_use =
false;
10132 for (
size_t j=0;
j<hp.
vars.size();
j++)
10133 if (hp.
vars[
j].colour == colour[
i]) {
10148 for (
size_t i=0;
i<hp.
vars.size();
i++)
10149 if (hp.
vars[
i].order > order)
10150 order = hp.
vars[
i].order;
10158 std::vector<size_t> colons;
10162 colons.push_back(
i);
10166 if (colons.size() == 0) {
10171 size_t slash_pos =
var_name.find(
"/");
10172 bool uses_per_variable_naming = (slash_pos != std::string::npos);
10174 if (uses_per_variable_naming && colons.size() % 2 == 1) {
10175 size_t middle_colon_pos = colons[colons.size() / 2];
10176 std::string slash_to_mid =
var_name.substr(slash_pos + 1, middle_colon_pos - slash_pos - 1);
10177 std::string mid_to_end =
var_name.substr(middle_colon_pos + 1);
10179 if (slash_to_mid == mid_to_end) {
10183 split_pos = middle_colon_pos;
10186 split_pos = colons[0];
10190 split_pos = colons[0];
10193 event_name =
var_name.substr(0, split_pos);
10194 tag_name =
var_name.substr(split_pos + 1);
10200 std::string path =
"History/Display/";
10205 MVOdb* o = odb->Chdir(path.c_str());
10211 o->RD(
"Minimum", &hp->
minimum);
10212 o->RD(
"Maximum", &hp->
maximum);
10222 std::vector<std::string> hist_vars;
10223 std::vector<std::string> hist_formula;
10224 std::vector<std::string> hist_colour;
10225 std::vector<std::string> hist_label;
10226 std::vector<bool> hist_show_raw_value;
10227 std::vector<double> hist_factor;
10228 std::vector<double> hist_offset;
10229 std::vector<double> hist_voffset;
10231 o->RSA(
"Variables", &hist_vars);
10232 o->RSA(
"Formula", &hist_formula);
10233 o->RSA(
"Colour", &hist_colour);
10234 o->RSA(
"Label", &hist_label);
10235 o->RBA(
"Show raw value", &hist_show_raw_value);
10236 o->RDA(
"Factor", &hist_factor);
10237 o->RDA(
"Offset", &hist_offset);
10238 o->RDA(
"VOffset", &hist_voffset);
10244 bool all_zero =
true;
10245 for (
size_t i=0;
i<hist_factor.size();
i++) {
10246 if (hist_factor[
i] != 0)
10250 for (
size_t i=0;
i<hist_factor.size();
i++) {
10251 hist_factor[
i] = 1.0;
10256 size_t num = std::max(hist_vars.size(), hist_formula.size());
10257 num = std::max(num, hist_colour.size());
10258 num = std::max(num, hist_label.size());
10259 num = std::max(num, hist_show_raw_value.size());
10260 num = std::max(num, hist_factor.size());
10261 num = std::max(num, hist_offset.size());
10262 num = std::max(num, hist_voffset.size());
10264 hist_vars.resize(num);
10265 hist_formula.resize(num);
10266 hist_colour.resize(num);
10267 hist_label.resize(num);
10268 hist_show_raw_value.resize(num);
10269 hist_factor.resize(num, 1.0);
10270 hist_offset.resize(num, 0.0);
10271 hist_voffset.resize(num, 0.0);
10273 for (
size_t i=0;
i<num;
i++) {
10280 v.
label = hist_label[
i];
10294 hp->
vars.push_back(v);
10367 hp->
vars.push_back(v);
10382 int seln = atoi(p->
getparam(
"seln"));
10383 for (
int i=0;
i<seln;
i++) {
10385 sprintf(
str,
"sel%d",
i);
10388 if (par.length() < 1)
10391 std::string event_name, tag_name;
10394 if (tag_name ==
"")
10404 hp.
vars.push_back(v);
10410 if (strlen(group) < 1) {
10411 cm_msg(
MERROR,
"SaveHistPlotToOdb",
"Error: Cannot write history plot to ODB, group \"%s\", panel \"%s\", invalid group name", group, panel);
10415 if (strlen(panel) < 1) {
10416 cm_msg(
MERROR,
"SaveHistPlotToOdb",
"Error: Cannot write history plot to ODB, group \"%s\", panel \"%s\", invalid panel name", group, panel);
10420 std::string path =
"History/Display/";
10428 MVOdb* o = odb->Chdir(path.c_str(),
true);
10430 o->WS(
"Timescale", hp.
timescale.c_str());
10431 o->WD(
"Minimum", hp.
minimum);
10432 o->WD(
"Maximum", hp.
maximum);
10441 std::vector<std::string> hist_vars;
10442 std::vector<std::string> hist_formula;
10443 std::vector<std::string> hist_colour;
10444 std::vector<std::string> hist_label;
10445 std::vector<bool> hist_show_raw_value;
10446 std::vector<double> hist_factor;
10447 std::vector<double> hist_offset;
10448 std::vector<double> hist_voffset;
10450 for (
size_t i=0;
i<hp.
vars.size();
i++) {
10451 hist_vars.push_back(hp.
vars[
i].event_name +
":" + hp.
vars[
i].tag_name);
10452 hist_formula.push_back(hp.
vars[
i].formula);
10453 hist_colour.push_back(hp.
vars[
i].colour);
10454 hist_label.push_back(hp.
vars[
i].label);
10455 hist_show_raw_value.push_back(hp.
vars[
i].show_raw_value);
10456 hist_factor.push_back(hp.
vars[
i].factor);
10457 hist_offset.push_back(hp.
vars[
i].offset);
10458 hist_voffset.push_back(hp.
vars[
i].voffset);
10461 if (hp.
vars.size() > 0) {
10462 o->WSA(
"Variables", hist_vars, 64);
10463 o->WSA(
"Formula", hist_formula, 64);
10466 o->WBA(
"Show raw value", hist_show_raw_value);
10467 o->WDA(
"Factor", hist_factor);
10468 o->WDA(
"Offset", hist_offset);
10469 o->WDA(
"VOffset", hist_voffset);
10471 o->Delete(
"Variables");
10472 o->Delete(
"Formula");
10473 o->Delete(
"Colour");
10474 o->Delete(
"Label");
10475 o->Delete(
"Show raw value");
10476 o->Delete(
"Factor");
10477 o->Delete(
"Offset");
10478 o->Delete(
"VOffset");
10489 bool something_deleted =
false;
10490 for (
unsigned i=0;
i<hp.
vars.size();
i++) {
10491 if (hp.
vars[
i].order <= 0) {
10493 something_deleted =
true;
10496 if (!something_deleted)
10505 bool need_sort =
false;
10506 for (
size_t i=1;
i<hp.
vars.size();
i++) {
10507 if (hp.
vars[
i-1].order >= hp.
vars[
i].order) {
10525 int max_display_events = 20;
10526 int max_display_tags = 200;
10527 char str[256], hcmd[256];
10529 odb->RI(
"History/MaxDisplayEvents", &max_display_events,
true);
10530 odb->RI(
"History/MaxDisplayTags", &max_display_tags,
true);
10532 mstrlcpy(hcmd, p->
getparam(
"hcmd"),
sizeof(hcmd));
10536 strcpy(hcmd,
"Refresh");
10556 if (strlen(p->
getparam(
"seln")) > 0)
10567 sprintf(
str,
"?cmd=oldhistory&group=%s&panel=%s", hgroup, hpanel);
10576 r->
rsprintf(
"<table class=\"mtable\">");
10578 r->
rsprintf(
"<tr><th colspan=11 class=\"subStatusTitle\">History Panel \"%s\" / \"%s\"</th></tr>\n", hgroup, hpanel);
10581 r->
rsprintf(
"<tr><td colspan=11>\n");
10583 r->
rsprintf(
"<input type=button value=Refresh ");
10584 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">\n");
10586 r->
rsprintf(
"<input type=button value=Save ");
10587 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Save';document.form1.submit()\">\n");
10590 r->
rsprintf(
"<input type=button value=Cancel ");
10591 std::string url =
"?cmd=oldhistory&group=";
10595 url +=
"&hcmd=Cancel";
10600 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10603 r->
rsprintf(
"<input type=button value=\"Edit in ODB\"");
10604 std::string url =
"?cmd=odb&odb_path=";
10605 url +=
"/History/Display/";
10609 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10612 r->
rsprintf(
"<input type=button value=\"Edit in new editor\"");
10613 std::string url =
"?cmd=hs_edit";
10622 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10624 r->
rsprintf(
"<input type=button value=\"Clear history cache\"");
10625 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Clear history cache';document.form1.submit()\">\n");
10626 r->
rsprintf(
"<input type=button value=\"Delete panel\"");
10627 r->
rsprintf(
"onclick=\"window.location.search='?cmd=oldhistory&group=%s&panel=%s&hcmd=Delete%%20panel'\">\n", hgroup, hpanel);
10630 r->
rsprintf(
"<tr><td colspan=11>\n");
10633 int sort_vars = *p->
getparam(
"sort_vars");
10634 r->
rsprintf(
"<input type=checkbox %s name=sort_vars value=1 onclick=\"this.form.submit();\">Sort variable names", sort_vars?
"checked":
"");
10637 int old_vars = *p->
getparam(
"old_vars");
10638 r->
rsprintf(
" <input type=checkbox %s name=old_vars value=1 onclick=\"this.form.submit();\">Show deleted and renamed variables", old_vars?
"checked":
"");
10641 r->
rsprintf(
" <input type=checkbox checked name=show_factor value=1 onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">");
10643 r->
rsprintf(
" <input type=checkbox name=show_factor value=1 onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">");
10644 r->
rsprintf(
"Show factor and offset\n");
10647 r->
rsprintf(
"<input type=hidden name=cmd value=Oldhistory>\n");
10648 r->
rsprintf(
"<input type=hidden name=hcmd value=Refresh>\n");
10649 r->
rsprintf(
"<input type=hidden name=panel value=\"%s\">\n", hpanel);
10650 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", hgroup);
10653 r->
rsprintf(
"<input type=hidden name=redir value=\"%s\">\n", p->
getparam(
"redir"));
10657 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Time scale (in units 'm', 'h', 'd'):</td>\n");
10658 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=timescale value=%s></td><td colspan=4></td></tr>\n", hp.
timescale.c_str());
10660 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Minimum (set to '-inf' for autoscale):</td>\n");
10661 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=minimum value=%f></td><td colspan=4></td></tr>\n", hp.
minimum);
10663 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Maximum (set to 'inf' for autoscale):</td>\n");
10664 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=maximum value=%f></td><td colspan=4></td></tr>\n", hp.
maximum);
10666 r->
rsprintf(
"<tr><td colspan=11>");
10669 r->
rsprintf(
"<input type=checkbox checked name=zero_ylow value=1>");
10671 r->
rsprintf(
"<input type=checkbox name=zero_ylow value=1>");
10672 r->
rsprintf(
"Zero Y; axis\n");
10675 r->
rsprintf(
"<input type=checkbox checked name=log_axis value=1>");
10677 r->
rsprintf(
"<input type=checkbox name=log_axis value=1>");
10678 r->
rsprintf(
"Logarithmic Y axis\n");
10681 r->
rsprintf(
" <input type=checkbox checked name=run_markers value=1>");
10683 r->
rsprintf(
" <input type=checkbox name=run_markers value=1>");
10684 r->
rsprintf(
"Show run markers\n");
10687 r->
rsprintf(
" <input type=checkbox checked name=show_values value=1>");
10689 r->
rsprintf(
" <input type=checkbox name=show_values value=1>");
10690 r->
rsprintf(
"Show values of variables\n");
10693 r->
rsprintf(
" <input type=checkbox checked name=show_fill value=1>");
10695 r->
rsprintf(
" <input type=checkbox name=show_fill value=1>");
10696 r->
rsprintf(
"Show graph fill\n");
10710 time_t t = time(NULL);
10715 std::vector<std::string> events;
10720 if (events.size() == 0)
10724 for (
unsigned i=0;
i<events.size();
i++)
10725 printf(
"event %d: \"%s\"\n",
i, events[
i].c_str());
10730 std::sort(events.begin(), events.end(),
cmp_events1);
10732 if (strlen(p->
getparam(
"cmdx")) > 0) {
10733 r->
rsprintf(
"<tr><th colspan=8 class=\"subStatusTitle\">List of available history variables</th></tr>\n");
10734 r->
rsprintf(
"<tr><th colspan=1>Sel<th colspan=1>Equipment<th colspan=1>Event<th colspan=1>Variable</tr>\n");
10736 std::string cmdx = p->
xgetparam(
"cmdx");
10737 std::string xeqname;
10740 for (
unsigned e=0;
e<events.size();
e++) {
10741 std::string eqname;
10742 eqname = events[
e].substr(0, events[
e].find(
"/"));
10744 if (eqname.length() < 1)
10745 eqname = events[
e];
10748 if (eqname != xeqname)
10751 std::string qcmd =
"Expand " + eqname;
10755 bool collapsed =
true;
10760 if (strlen(p->
getparam(qcmd.c_str())) > 0)
10764 if (eqname == xeqname)
10769 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10770 r->
rsprintf(
"<td><input type=submit name=cmdx value=\"%s\"></td>\n", qcmd.c_str());
10778 r->
rsprintf(
"<tr><input type=hidden name=\"%s\" value=%d></tr>\n", qcmd.c_str(), 1);
10780 std::string rcmd =
"Expand " + events[
e];
10789 if (strlen(p->
getparam(rcmd.c_str())) > 0)
10795 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10796 r->
rsprintf(
"<td>%s</td>\n", events[
e].c_str());
10797 r->
rsprintf(
"<td><input type=submit name=cmdx value=\"%s\"></td>\n", rcmd.c_str());
10802 r->
rsprintf(
"<tr><input type=hidden name=\"%s\" value=%d></tr>\n", rcmd.c_str(), 1);
10806 std::vector<TAG> tags;
10813 std::sort(tags.begin(), tags.end(),
cmp_tags);
10815 for (
unsigned v=0; v<tags.size(); v++) {
10817 for (
unsigned j=0;
j<tags[v].n_data;
j++) {
10820 if (tags[v].n_data == 1)
10821 sprintf(tagname,
"%s", tags[v].
name);
10823 sprintf(tagname,
"%s[%d]", tags[v].
name,
j);
10825 bool checked =
false;
10836 r->
rsprintf(
"<td><input type=checkbox %s name=\"sel%d\" value=\"%s:%s\"></td>\n", checked?
"checked":
"",
i++, events[
e].c_str(), tagname);
10837 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10838 r->
rsprintf(
"<td>%s</td>\n", events[
e].c_str());
10839 r->
rsprintf(
"<td>%s</td>\n", tagname);
10849 r->
rsprintf(
"<input type=hidden name=seln value=%d>\n",
i);
10850 r->
rsprintf(
"<input type=submit value=\"Add Selected\">\n");
10855 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>New history: displayed_value = formula(history_value)</td></tr>\n");
10856 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>Old history: displayed_value = offset + factor*(history_value - voffset)</td></tr>\n");
10857 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>Formula format: \"3*x+4\", \"10*Math.sin(x)\", etc. all javascript math functions can be used</td></tr>\n");
10858 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>To display the raw history value instead of computed formula or offset value, check the \"raw\" checkbox</td></tr>\n");
10859 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>To reorder entries: enter new ordering in the \"order\" column and press \"refresh\"</td></tr>\n");
10860 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>To delete entries: enter \"-1\" or leave blank the \"order\" column and press \"refresh\"</td></tr>\n");
10863 r->
rsprintf(
"<th>Col<th>Event<th>Variable<th>Formula<th>Colour<th>Label<th>Raw<th>Order");
10865 r->
rsprintf(
"<th>Factor<th>Offset<th>VOffset");
10871 size_t nvars = hp.
vars.size();
10876 if (
index < nvars) {
10879 r->
rsprintf(
"<td style=\"background-color:%s\"> <td>\n", hp.
vars[
index].colour.c_str());
10886 r->
rsprintf(
"<select name=\"event%d\" size=1 onChange=\"document.form1.submit()\">\n", (
int)
index);
10891 r->
rsprintf(
"<option value=\"/empty\"><empty>\n");
10893 if (
index==nvars) {
10894 for (
unsigned e=0;
e<events.size();
e++) {
10895 const char *p = events[
e].c_str();
10896 r->
rsprintf(
"<option value=\"%s\">%s\n", p, p);
10898 }
else if ((
int)events.size() > max_display_events) {
10900 r->
rsprintf(
"<option>(%d events omitted)\n", (
int)events.size());
10902 bool found =
false;
10903 for (
unsigned e=0;
e<events.size();
e++) {
10904 const char *s =
"";
10905 const char *p = events[
e].c_str();
10910 r->
rsprintf(
"<option %s value=\"%s\">%s\n", s, p, p);
10913 const char *p = hp.
vars[
index].event_name.c_str();
10914 r->
rsprintf(
"<option selected value=\"%s\">%s\n", p, p);
10923 if (
index < nvars) {
10924 bool found_tag =
false;
10925 std::string selected_tag = hp.
vars[
index].tag_name;
10929 std::vector<TAG> tags;
10936 printf(
"Compare %d\n",
cmp_names(
"AAA",
"BBB"));
10937 printf(
"Compare %d\n",
cmp_names(
"BBB",
"AAA"));
10938 printf(
"Compare %d\n",
cmp_names(
"AAA",
"AAA"));
10939 printf(
"Compare %d\n",
cmp_names(
"A",
"AAA"));
10940 printf(
"Compare %d\n",
cmp_names(
"A111",
"A1"));
10941 printf(
"Compare %d\n",
cmp_names(
"A111",
"A2"));
10942 printf(
"Compare %d\n",
cmp_names(
"A111",
"A222"));
10943 printf(
"Compare %d\n",
cmp_names(
"A111a",
"A111b"));
10947 std::sort(tags.begin(), tags.end(),
cmp_tags);
10950 printf(
"Event [%s] %d tags\n", hp.
vars[
index].event_name.c_str(), (
int)tags.size());
10952 for (
unsigned v=0; v<tags.size(); v++) {
10953 printf(
"tag[%d] [%s]\n", v, tags[v].
name);
10957 unsigned count_tags = 0;
10958 for (
unsigned v=0; v<tags.size(); v++)
10959 count_tags += tags[v].n_data;
10963 if ((
int)count_tags < max_display_tags) {
10964 for (
unsigned v=0; v<tags.size(); v++) {
10966 for (
unsigned j=0;
j<tags[v].n_data;
j++) {
10967 std::string tagname;
10969 if (tags[v].n_data == 1)
10970 tagname = tags[v].name;
10973 sprintf(buf,
"[%d]",
j);
10974 tagname = std::string(tags[v].
name) + buf;
10977 if (
equal_ustring(selected_tag.c_str(), tagname.c_str())) {
10978 r->
rsprintf(
"<option selected value=\"%s\">%s\n", tagname.c_str(), tagname.c_str());
10982 r->
rsprintf(
"<option value=\"%s\">%s\n", tagname.c_str(), tagname.c_str());
10991 if (hp.
vars[
index].tag_name.length() > 0)
10995 r->
rsprintf(
"<td><input type=text size=15 maxlength=256 name=\"form%d\" value=%s></td>\n", (
int)
index, hp.
vars[
index].formula.c_str());
10996 r->
rsprintf(
"<td><input type=text size=8 maxlength=10 name=\"col%d\" value=%s></td>\n", (
int)
index, hp.
vars[
index].colour.c_str());
10999 r->
rsprintf(
"<td><input type=checkbox checked name=\"raw%d\" value=1></td>", (
int)
index);
11001 r->
rsprintf(
"<td><input type=checkbox name=\"raw%d\" value=1></td>", (
int)
index);
11002 r->
rsprintf(
"<td><input type=text size=3 maxlength=32 name=\"ord%d\" value=\"%d\"></td>\n", (
int)
index, hp.
vars[
index].order);
11004 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"factor%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].factor);
11005 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"offset%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].offset);
11006 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"voffset%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].voffset);
11010 r->
rsprintf(
"<input type=hidden name=\"voffset%d\" value=\"%f\">\n", (
int)
index, hp.
vars[
index].voffset);
11013 r->
rsprintf(
"<td colspan=2><input type=submit name=cmdx value=\"List all variables\"></td>\n");
11023 r->
rsprintf(
"</body></html>\r\n");
11043 sprintf(
str,
"/History/Display/%s/%s", group, panel);
11046 sprintf(
str,
"Cannot find /History/Display/%s/%s in ODB\n", group, panel);
11052 BOOL runmarker = 1;
11053 size =
sizeof(runmarker);
11058 std::string
ts =
"1h";
11083 time_t starttime = endtime - scale;
11090 sprintf(
str,
"History error, status %d\n",
status);
11098 int *i_var = (
int *)malloc(
sizeof(
int)*hsdata->
nvars);
11100 assert(i_var != NULL);
11102 for (
int i = 0;
i < hsdata->
nvars;
i++)
11108 for (
int i = 0;
i < hsdata->
nvars;
i++)
11111 if ((t == 0) || (hsdata->
t[
i][0] > t))
11112 t = hsdata->
t[
i][0];
11114 if (t == 0 && hsdata->
nvars > 1) {
11115 show_error(r,
"No history available for choosen period");
11120 int run_index = -1;
11121 int state_index = -1;
11122 int n_run_number = 0;
11123 time_t* t_run_number = NULL;
11125 for (
int i = 0;
i < hsdata->
nvars;
i++) {
11128 t_run_number = hsdata->
t[
i];
11138 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
11140 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
11141 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
11142 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
11143 r->
rsprintf(
"Content-Type: text/plain\r\n");
11144 r->
rsprintf(
"Content-disposition: attachment; filename=\"export.csv\"\r\n");
11149 r->
rsprintf(
"Time, Timestamp, Run, Run State, ");
11153 for (
int i = 0, first = 1;
i < hsdata->
nvars;
i++) {
11170 printf(
"hsdata %p, t %d, irun %d\n", hsdata, (
int)t, i_run);
11174 while (i_run < n_run_number-1 && t_run_number[i_run+1] <= t)
11180 for (
int i = 0;
i < hsdata->
nvars;
i++)
11186 for (
int i = 0 ;
i < hsdata->
nvars ;
i++)
11193 printf(
"step to time %d: ", (
int)t);
11194 for (
int i = 0;
i < hsdata->
nvars;
i++) {
11197 printf(
" done: %d\n",
done);
11204 localtime_r(&t, &tms);
11208 strcpy(fmt,
"%Y.%m.%d %H:%M:%S");
11210 strftime(
str,
sizeof(
str), fmt, &tms);
11212 if (t_run_number && run_index>=0 && state_index>=0) {
11213 if (t_run_number[i_run] <= t)
11214 r->
rsprintf(
"%s, %d, %.0f, %.0f, ",
str, (
int)t, hsdata->
v[run_index][i_run], hsdata->
v[state_index][i_run]);
11221 for (
int i= 0 ;
i < hsdata->
nvars ;
i++)
11222 printf(
" %d (%g)", i_var[
i], hsdata->
v[
i][i_var[
i]]);
11226 for (
int i=0, first=1 ;
i<hsdata->
nvars ;
i++) {
11241 for (
int i = 0 ;
i < hsdata->
nvars ;
i++)
11243 int xdt = hsdata->
t[
i][i_var[
i]+1] - t;
11245 printf(
"var %d, i_var %d->%d, t %d->%d, dt %d\n",
i, i_var[
i], i_var[
i]+1, (
int)hsdata->
t[
i][i_var[
i]], (
int)hsdata->
t[
i][i_var[
i]+1], xdt);
11246 if (dt <= 0 || xdt < dt)
11251 printf(
"dt %d\n", dt);
11267 HNDLE hDB, hkey, hikeyp, hkeyp, hkeybutton;
11270 char hgroup[256], hpanel[256], hcmd[256];
11271 const char def_button[][
NAME_LENGTH] = {
"10m",
"1h",
"3h",
"12h",
"24h",
"3d",
"7d" };
11275 hcmd[0] = hgroup[0] = hpanel[0] = 0;
11278 mstrlcpy(hgroup, p->
getparam(
"group"),
sizeof(hgroup));
11280 mstrlcpy(hpanel, p->
getparam(
"panel"),
sizeof(hpanel));
11282 mstrlcpy(hcmd, p->
getparam(
"hcmd"),
sizeof(hcmd));
11287 redir +=
"?cmd=oldhistory&group=";
11289 redir +=
"&panel=";
11306 redir +=
"?cmd=oldhistory&group=";
11308 redir +=
"&panel=";
11327 r->
rsprintf(
"<table class=\"dialogTable\">");
11328 r->
rsprintf(
"<tr><th class=\"subStatusTitle\" colspan=2>New History Item</th><tr>");
11329 r->
rsprintf(
"<tr><td align=center colspan=2>\n");
11330 r->
rsprintf(
"Select group: ");
11331 r->
rsprintf(
"<select id=\"group\" name=\"group\">\n");
11337 for (
i = 0;;
i++) {
11350 if (!hkey ||
i == 0)
11351 r->
rsprintf(
"<option>Default</option>\n");
11354 r->
rsprintf(
"Or enter new group name: ");
11355 r->
rsprintf(
"<input type=text size=15 maxlength=31 id=new_group name=new_group>\n");
11357 r->
rsprintf(
"<tr><td align=center colspan=2>\n");
11358 r->
rsprintf(
"<br>Panel name: ");
11359 r->
rsprintf(
"<input type=text size=15 maxlength=31 id=panel name=panel><br><br>\n");
11362 r->
rsprintf(
"<tr><td align=center colspan=2>");
11363 std::string
str =
"?cmd=oldhistory&hcmd=createnew";
11364 str +=
"&new_group='+document.getElementById('new_group').value+'";
11365 str +=
"&group='+document.getElementById('group').value+'";
11366 str +=
"&panel='+document.getElementById('panel').value+'";
11367 r->
rsprintf(
"<input type=button value=Submit onclick=\"window.location.search='%s'\">\n",
str.c_str());
11373 r->
rsprintf(
"</body></html>\r\n");
11380 path +=
"/History/Display/";
11392 while (hpanel[0] ==
' ') {
11394 mstrlcpy(
str, hpanel+1,
sizeof(
str));
11395 mstrlcpy(hpanel,
str,
sizeof(hpanel));
11397 while (strlen(hpanel)> 1 && hpanel[strlen(hpanel)-1] ==
' ')
11398 hpanel[strlen(hpanel)-1] = 0;
11402 mstrlcpy(hgroup, p->
getparam(
"new_group"),
sizeof(hgroup));
11409 const char* pscale = p->
getparam(
"scale");
11410 if (pscale == NULL || *pscale == 0)
11412 const char* pwidth = p->
getparam(
"width");
11413 if (pwidth == NULL || *pwidth == 0)
11415 const char* pheight = p->
getparam(
"height");
11416 if (pheight == NULL || *pheight == 0)
11418 const char* pindex = p->
getparam(
"index");
11419 if (pindex == NULL || *pindex == 0)
11426 std::string bgcolor =
"FFFFFF";
11430 std::string fgcolor =
"000000";
11434 std::string gridcolor =
"A0A0A0";
11440 time_t endtime = 0;
11443 else if (p->
isparam(
"htime"))
11446 if (pscale && *pscale)
11452 if (pindex && *pindex)
11453 index = atoi(pindex);
11465 char* fbuffer = (
char*)
M_MALLOC(fsize);
11466 assert(fbuffer != NULL);
11477 }
else if (atoi(pmag) > 0) {
11478 width = atoi(pmag);
11483 generate_hist_graph(odb, r, hgroup, hpanel, fbuffer, &fsize, width, height, endtime, scale,
index, labels, bgcolor.c_str(), fgcolor.c_str(), gridcolor.c_str());
11488 if (dir.length() > 0 && dir[dir.length()-1] !=
DIR_SEPARATOR)
11491 time_t now = time(NULL);
11492 localtime_r(&now, &tms);
11495 tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday,
11496 tms.tm_hour, tms.tm_min, tms.tm_sec, hpanel);
11500 fh = open(fname.c_str(), O_CREAT | O_RDWR |
O_BINARY, 0644);
11502 cm_msg(
MERROR,
"show_hist_page",
"Cannot write attachment file \"%s\", open() errno %d (%s)", fname.c_str(), errno, strerror(errno));
11504 int wr =
write(fh, fbuffer, fsize);
11506 cm_msg(
MERROR,
"show_hist_page",
"Cannot write attachment file \"%s\", write(%d) returned %d, errno %d (%s)", fname.c_str(), fsize, wr, errno, strerror(errno));
11512 if (strlen(url) > 1 && url[strlen(url)-1] !=
'/')
11513 mstrlcat(url,
"/",
sizeof(url));
11514 mstrlcat(url,
"?cmd=New&fa=",
sizeof(url));
11523 std::string
str =
msprintf(
"\\HS\\%s.gif", hpanel);
11527 if (strchr(
str.c_str(),
'?'))
11541 if (strchr(
str.c_str(),
'?'))
11548 if (strchr(
str.c_str(),
'?'))
11555 show_elog_new(r, hpanel, NULL,
FALSE,
str.c_str(),
"../../EL/");
11566 if (strstr(dec_path,
".gif")) {
11575 }
else if (atoi(pwidth) > 0) {
11576 width = atoi(pwidth);
11577 if (atoi(pheight) > 0)
11578 height = atoi(pheight);
11580 height = (int)(0.625 * width);
11585 generate_hist_graph(odb, r, hgroup, hpanel, buffer, buffer_size, width, height, endtime, scale,
index, labels, bgcolor.c_str(), fgcolor.c_str(), gridcolor.c_str());
11593 time_t now = time(NULL);
11599 time_t last_written = 0;
11602 endtime = last_written + scale/2;
11608 time_t last_written = 0;
11611 if (last_written != endtime)
11612 endtime = last_written + scale/2;
11618 endtime -= scale/2;
11625 endtime += scale/2;
11637 endtime -= scale / 4;
11644 endtime += scale / 2;
11650 int xrefresh = refresh;
11655 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
11656 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
11659 r->
rsprintf(
"<table class=\"mtable\">");
11660 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>History</th></tr>");
11666 path +=
"/History/Display/";
11672 r->
rsprintf(
"<h1>Error: History panel \"%s\" in group \"%s\" does not exist</h1>\n", hpanel, hgroup);
11676 r->
rsprintf(
"</body></html>\r\n");
11682 if (pscale && *pscale)
11683 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%d>\n", scale);
11686 if (hpanel[0] && !
equal_ustring(hpanel,
"All") && hgroup[0]) {
11688 path +=
"/History/Display/";
11692 path +=
"/Timescale";
11694 std::string scalestr =
"1h";
11703 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%s>\n", scalestr.c_str());
11710 if (pwidth && *pwidth)
11711 r->
rsprintf(
"<input type=hidden name=hwidth id=hwidth value=%s>\n", pwidth);
11712 if (pheight && *pheight)
11713 r->
rsprintf(
"<input type=hidden name=hheight id=hheight value=%s>\n", pheight);
11714 if (pindex && *pindex)
11715 r->
rsprintf(
"<input type=hidden name=hindex id=hindex value=%s>\n", pindex);
11719 if (hgroup[0] == 0) {
11721 r->
rsprintf(
"<tr><td colspan=2><input type=\"button\" name=\"New\" value=\"New\" ");
11722 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New'\"></td></tr>\n");
11725 r->
rsprintf(
"<tr><td colspan=2 style=\"text-align:left;\">\n");
11727 r->
rsprintf(
"<b>Please select panel:</b><br>\n");
11730 r->
rsprintf(
"<table class=\"historyTable\">");
11733 r->
rsprintf(
"<tr><td colspan=2 class=\"titleCell\">\n");
11737 r->
rsprintf(
"<a href=\"?cmd=oldhistory&group=All\">ALL</a>\n");
11745 strcpy(
str,
"System:Trigger per sec.");
11765 for (
i = 0;;
i++) {
11774 char enc_name[256];
11775 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11781 r->
rsprintf(
"<tr><td class=\"titleCell\"><a href=\"?cmd=oldhistory&group=%s\">%s</a></td>\n<td>", enc_name,
key.
name);
11783 for (
j = 0;;
j++) {
11794 char enc_iname[256];
11795 mstrlcpy(enc_iname, ikey.
name,
sizeof(enc_iname));
11796 urlEncode(enc_iname,
sizeof(enc_iname));
11799 r->
rsprintf(
"<small><b>%s</b></small> ", ikey.
name);
11801 r->
rsprintf(
"<small><a href=\"?cmd=oldhistory&group=%s&panel=%s\">%s</a></small> \n", enc_name, enc_iname, ikey.
name);
11812 r->
rsprintf(
"<tr><td colspan=2>\n");
11816 r->
rsprintf(
"<select title=\"Select group\" id=\"fgroup\" onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value;\">\n");
11821 for (
i = 0;;
i++) {
11841 r->
rsprintf(
"<option selected value=\"%s\">%s\n",
"ALL",
"ALL");
11843 r->
rsprintf(
"<option value=\"%s\">%s\n",
"ALL",
"ALL");
11847 r->
rsprintf(
" Panel:\n");
11848 r->
rsprintf(
"<select title=\"Select panel\" id=\"fpanel\" ");
11849 r->
rsprintf(
"onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value+");
11850 r->
rsprintf(
"'&panel='+document.getElementById('fpanel').value;\">\n");
11854 for (
i = 0;;
i++) {
11873 r->
rsprintf(
"<option value=\"\">- all -\n");
11875 r->
rsprintf(
"<option selected value=\"\">- all -\n");
11881 r->
rsprintf(
"<input type=submit value=\"Go\">\n");
11884 r->
rsprintf(
" <input type=\"button\" name=\"New\" value=\"New\" ");
11885 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New&group=%s'\">\n", hgroup);
11887 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Reset\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Reset&group=%s&panel=%s'\">\n", hgroup, hpanel);
11889 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Query\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Query&group=%s&panel=%s'\">\n", hgroup, hpanel);
11891 double xendtime = endtime;
11894 double xstarttime = xendtime - scale;
11896 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"New history\" onClick=\"window.location.href='?cmd=history&group=%s&panel=%s&A=%.0f&B=%.0f'\">\n", hgroup, hpanel, xstarttime, xendtime);
11904 if (hgroup[0] && !
equal_ustring(hgroup,
"ALL") && hpanel[0] == 0) {
11905 std::string strwidth =
"Small";
11909 path +=
"/History/Display/";
11913 for (
i = 0 ;;
i++) {
11921 char enc_name[256];
11922 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11926 ref +=
"graph.gif?width=";
11928 ref +=
"&cmd=oldhistory&group=";
11934 ref2 +=
"?cmd=oldhistory&group=";
11939 if (endtime != 0) {
11941 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
11949 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
11951 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
11955 r->
rsprintf(
"Group \"%s\" not found", hgroup);
11965 path +=
"/History/Display/";
11969 path +=
"/Buttons";
11971 if (hkeybutton == 0) {
11976 cm_msg(
MERROR,
"show_hist_page",
"Cannot create history panel with invalid ODB path \"%s\"", path.c_str());
11983 r->
rsprintf(
"function histDisp(p) {\n");
11984 r->
rsprintf(
" var params = '?cmd=oldhistory&group=%s&panel=%s';\n", hgroup, hpanel);
11985 r->
rsprintf(
" params += '&'+p;\n");
11986 r->
rsprintf(
" if (document.getElementById(\'hscale\') !== null)\n");
11987 r->
rsprintf(
" params += '&hscale='+document.getElementById(\'hscale\').value;\n");
11988 r->
rsprintf(
" if (document.getElementById(\'htime\') !== null)\n");
11989 r->
rsprintf(
" params += '&htime='+document.getElementById(\'htime\').value;\n");
11990 r->
rsprintf(
" if (document.getElementById(\'hwdith\') !== null)\n");
11991 r->
rsprintf(
" params += '&hwidth='+document.getElementById(\'hwidth\').value;\n");
11992 r->
rsprintf(
" if (document.getElementById(\'hindex\') !== null)\n");
11993 r->
rsprintf(
" params += '&hindex='+document.getElementById(\'hindex\').value;\n");
11994 r->
rsprintf(
" window.location.search = params;\n");
12002 size =
sizeof(
str);
12004 r->
rsprintf(
"<input type=\"button\" title=\"display last %s\" value=%s onclick=\"histDisp('scale=%s')\">\n",
str,
str,
str);
12007 r->
rsprintf(
"<input type=\"button\" value=\"<<<\" title=\"go back in time to last available data for all variables on the plot\" onclick=\"histDisp('shift=leftmaxall')\">");
12008 r->
rsprintf(
"<input type=\"button\" value=\"<<\" title=\"go back in time to last available data\" onclick=\"histDisp('shift=leftmax')\">");
12009 r->
rsprintf(
"<input type=\"button\" value=\"<\" title=\"go back in time\" onclick=\"histDisp('shift=left')\">");
12011 r->
rsprintf(
"<input type=\"button\" value=\" + \" title=\"zoom in\" onclick=\"histDisp('shift=zoomin')\">");
12012 r->
rsprintf(
"<input type=\"button\" value=\" - \" title=\"zoom out\" onclick=\"histDisp('shift=zoomout')\">");
12014 if (endtime != 0) {
12015 r->
rsprintf(
"<input type=\"button\" value=\">\" title=\"go forward in time\" onclick=\"histDisp('shift=right')\">");
12016 r->
rsprintf(
"<input type=\"button\" value=\">>\" title=\"go to currently updated fresh data\" onclick=\"histDisp('shift=rightmax')\">");
12020 r->
rsprintf(
"<input type=\"button\" value=\"Large\" title=\"large display\" onclick=\"histDisp('width=Large')\">\n");
12021 r->
rsprintf(
"<input type=\"button\" value=\"Small\" title=\"large display\" onclick=\"histDisp('width=Small')\">\n");
12022 r->
rsprintf(
"<input type=\"button\" value=\"Create Elog\" title=\"large display\" onclick=\"histDisp('hcmd=Create Elog')\">\n");
12023 r->
rsprintf(
"<input type=\"button\" value=\"Config\" title=\"large display\" onclick=\"histDisp('hcmd=Config')\">\n");
12024 r->
rsprintf(
"<input type=\"button\" value=\"Export\" title=\"large display\" onclick=\"histDisp('hcmd=Export')\">\n");
12027 char paramstr[256];
12030 sprintf(paramstr + strlen(paramstr),
"&scale=%d", scale);
12032 sprintf(paramstr + strlen(paramstr),
"&time=%s",
time_to_string(endtime).c_str());
12033 if (pwidth && *pwidth)
12034 sprintf(paramstr + strlen(paramstr),
"&width=%s", pwidth);
12036 std::string wi =
"640";
12038 sprintf(paramstr + strlen(paramstr),
"&width=%s", wi.c_str());
12040 if (pheight && *pheight)
12041 sprintf(paramstr + strlen(paramstr),
"&height=%s", pheight);
12044 r->
rsprintf(
"<map name=\"%s\">\r\n", hpanel);
12046 if (!(pindex && *pindex)) {
12048 path +=
"/History/Display/";
12052 path +=
"/Variables";
12065 ref +=
"?cmd=oldhistory&group=";
12076 r->
rsprintf(
" <area shape=rect coords=\"%d,%d,%d,%d\" href=\"%s\">\r\n", 30, 31 + 23 *
i, 150, 30 + 23 *
i + 17, ref.c_str());
12080 std::string ref =
"?cmd=oldhistory&group=";
12094 else if (atoi(pwidth) > 0)
12095 width = atoi(pwidth);
12099 r->
rsprintf(
" <area shape=rect coords=\"%d,%d,%d,%d\" href=\"%s\">\r\n", 0, 0, width, 20, ref.c_str());
12105 if (pindex && *pindex)
12106 sprintf(paramstr + strlen(paramstr),
"&index=%s", pindex);
12110 ref +=
"graph.gif?cmd=oldhistory&group=";
12117 r->
rsprintf(
"<tr><td colspan=2><img src=\"%s\" usemap=\"#%s\"></tr>\n", ref.c_str(), hpanel);
12124 for (
i = 0,
k = 0;;
i++) {
12132 char enc_group_name[256];
12133 mstrlcpy(enc_group_name,
key.
name,
sizeof(enc_group_name));
12134 urlEncode(enc_group_name,
sizeof(enc_group_name));
12136 for (
j = 0;;
j++,
k++) {
12145 char enc_panel_name[256];
12146 mstrlcpy(enc_panel_name, ikey.
name,
sizeof(enc_panel_name));
12147 urlEncode(enc_panel_name,
sizeof(enc_panel_name));
12150 ref +=
"graph.gif?width=Small";
12151 ref +=
"&cmd=oldhistory&group=";
12152 ref += enc_group_name;
12154 ref += enc_panel_name;
12157 ref2 +=
"?cmd=oldhistory&group=";
12158 ref2 += enc_group_name;
12160 ref2 += enc_panel_name;
12162 if (endtime != 0) {
12164 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
12172 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
12174 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
12181 r->
rsprintf(
"</body></html>\r\n");
12190 const unsigned char *picon;
12191 char str[256], format[256];
12194 if (strstr(icon,
"favicon.ico") != 0) {
12197 }
else if (strstr(icon,
"favicon.png") != 0) {
12203 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
12205 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
12209 now += (int) (3600 * 24);
12211 gmtime_r(&now, &gmt_tms);
12212 strcpy(format,
"%A, %d-%b-%y %H:%M:%S GMT");
12213 strftime(
str,
sizeof(
str), format, &gmt_tms);
12217 r->
rsprintf(
"Content-Type: image/x-icon\r\n");
12219 r->
rsprintf(
"Content-Type: image/png\r\n");
12221 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
12267 if (strstr(dec_path,
"favicon.ico") != 0 ||
12268 strstr(dec_path,
"favicon.png")) {
12273 const char* password = p->
getparam(
"pwd");
12274 const char* wpassword = p->
getparam(
"wpwd");
12275 const char* command = p->
getparam(
"cmd");
12298 if (!password[0] && hkey) {
12300 int size =
sizeof(
str);
12304 db_find_key(
hDB, 0,
"/Experiment/Security/Allowed programs/mhttpd", &hkey);
12305 if (hkey == 0 && strcmp(
c->cookie_pwd.c_str(),
str) != 0) {
12316 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12325 gmtime_r(&now, &gmt_tms);
12328 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12330 r->
rsprintf(
"Set-Cookie: midas_pwd=%s; path=/; expires=%s\r\n",
12333 r->
rsprintf(
"Location: ./\n\n<html>redir</html>\r\n");
12337 if (wpassword[0]) {
12342 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12351 gmtime_r(&now, &gmt_tms);
12354 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:%M:%S GMT", &gmt_tms);
12356 r->
rsprintf(
"Set-Cookie: midas_wpwd=%s; path=/; expires=%s\r\n",
ss_crypt(wpassword,
"mi"),
str);
12359 r->
rsprintf(
"Location: %s\n\n<html>redir</html>\r\n",
str);
12365 if (strlen(dec_path) > 3 &&
12366 dec_path[strlen(dec_path)-3] ==
'm' &&
12367 dec_path[strlen(dec_path)-2] ==
'p' &&
12368 dec_path[strlen(dec_path)-1] ==
'3') {
12369 if (strrchr(dec_path,
'/'))
12378 if (strstr(dec_path,
"midas.js")) {
12383 if (strstr(dec_path,
"midas.css")) {
12390 if (strstr(dec_path,
"mhttpd.js")) {
12397 if (strstr(dec_path,
"obsolete.js")) {
12404 if (strstr(dec_path,
"mhttpd.css")) {
12411 if (strstr(dec_path,
"controls.js")) {
12444 path +=
"/Script/";
12470 path +=
"/CustomScript/";
12471 path += p->
getparam(
"customscript");
12498 std::string filename = custom[
"Status"];
12542 !(dec_path[0] ==
'H' && dec_path[1] ==
'S' && dec_path[2] ==
'/')) {
12658 show_mscb_page(p, r,
c->refresh);
12660 show_error(r,
"MSCB support not compiled into this version of mhttpd");
12678 if (strncmp(command,
"Trigger", 7) == 0) {
12691 mstrlcpy(eq_name, command + 8,
sizeof(eq_name));
12692 if (strchr(eq_name,
' '))
12693 *strchr(eq_name,
' ') = 0;
12697 path +=
"/Equipment/";
12699 path +=
"/Common/Frontend name";
12706 path +=
"/Equipment/";
12708 path +=
"/Common/Event ID";
12715 str +=
"Frontend \"";
12717 str +=
"\" not running!";
12724 str +=
"Cannot connect to frontend \"";
12746 if (strncmp(command,
"Next Subrun", 11) == 0) {
12767 mstrlcpy(
str,
"?cmd=set",
sizeof(
str));
12771 const char* group = p->
getparam(
"group");
12793 if (
equal_ustring(command,
"CNAF") || strncmp(dec_path,
"CNAF", 4) == 0) {
12809 std::string external_elog_url;
12810 int size =
sizeof(external_elog);
12813 if (external_elog && (external_elog_url.length() > 0)) {
12814 redirect(r, external_elog_url.c_str());
12824 mstrlcpy(cmdx, command,
sizeof(cmdx));
12833 if (
equal_ustring(command,
"Create ELog from this page")) {
12835 redir +=
"?cmd=New+elog";
12836 redir +=
"&odb_path=";
12859 int refresh = atoi(p->
getparam(
"refr"));
12862 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12869 now += 3600 * 24 * 365;
12872 gmtime_r(&now, &gmt_tms);
12875 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12877 r->
rsprintf(
"Set-Cookie: midas_refr=%d; path=/; expires=%s\r\n", refresh,
str);
12878 r->
rsprintf(
"Location: ./\r\n\r\n<html>redir</html>\r\n");
12925 int write_access =
TRUE;
12926 db_find_key(
hDB, 0,
"/Experiment/Security/Web Password", &hkey);
12929 int size =
sizeof(
str);
12931 if (strcmp(
c->cookie_wpwd.c_str(),
str) == 0)
12932 write_access =
TRUE;
12934 write_access =
FALSE;
12937 std::string odb_path;
12939 odb_path = p->
getparam(
"odb_path");
12970 if ((command[0]==0) && dec_path[0]) {
12972 std::string new_url =
"./?cmd=odb";
12979 if ((command[0]==0) && dec_path[0]) {
12985 for (
const char* s = dec_path; *s; s++) {
12989 std::string new_url;
12994 for (
int i=0;
i<level;
i++) {
13000 new_url +=
"?cmd=odb";
13001 new_url +=
"&odb_path=";
13028 std::string odb_path;
13033 odb_path +=
"/Custom/Images/";
13034 odb_path += dec_path;
13035 odb_path +=
"/Background";
13042 if (strstr(dec_path,
"..")) {
13044 str +=
"Invalid custom gif name \'";
13046 str +=
"\' contains \'..\'";
13057 bool found_custom =
false;
13060 odb_path +=
"/Custom/";
13061 odb_path += dec_path;
13068 found_custom =
true;
13071 odb_path +=
"/Custom/";
13072 odb_path += dec_path;
13080 found_custom =
true;
13083 odb_path +=
"/Custom/";
13084 odb_path += dec_path;
13092 found_custom =
true;
13097 if (found_custom) {
13099 if (strstr(dec_path,
"..")) {
13101 str +=
"Invalid custom page name \'";
13103 str +=
"\' contains \'..\'";
13118 std::string custom_path;
13121 if (strstr(dec_path,
"..")) {
13123 str +=
"Invalid custom file name \'";
13125 str +=
"\' contains \'..\'";
13149 if (strlen(p->
getparam(
"path")) > 0) {
13163 r->
rsprintf(
"HTTP/1.1 400 Bad Request\r\n");
13167 r->
rsprintf(
"Error: Invalid URL \"%s\" or query \"%s\" or command \"%s\"\n", p->
getparam(
"path"), p->
getparam(
"query"), command);
13174 int len = strlen(query_string);
13175 char *buf = (
char *)malloc(len+1);
13176 assert(buf != NULL);
13177 memcpy(buf, query_string, len+1);
13179 p = strtok(p,
"&");
13180 while (p != NULL) {
13182 p = strchr(p,
'=');
13191 p = strtok(NULL,
"&");
13205 param->initparam();
13208 mstrlcpy(path, url + 1,
sizeof(path));
13210 mstrlcpy(path,
string + 1,
sizeof(path));
13212 if (strchr(path,
'?'))
13213 *strchr(path,
'?') = 0;
13216 param->setparam(
"path", path);
13218 assert(query_string != NULL);
13222 param->setparam(
"query", query_string);
13224 char dec_path[256];
13225 mstrlcpy(dec_path, path,
sizeof(dec_path));
13229 param->freeparam();
13237 bool debug_decode_post =
false;
13246 mstrlcpy(path, url + 1,
sizeof(path));
13248 mstrlcpy(path, header + 1,
sizeof(path));
13249 if (strchr(path,
'?'))
13250 *strchr(path,
'?') = 0;
13251 if (strchr(path,
' '))
13252 *strchr(path,
' ') = 0;
13254 param->setparam(
"path", path);
13258 const char* pinit = string;
13264 if (strstr(
string, boundary))
13265 string = strstr(
string, boundary) + strlen(boundary);
13267 if (debug_decode_post)
13268 printf(
"decode_post: -->[%s]<--\n",
string);
13272 if (strstr(
string,
"name=")) {
13273 const char* pitem = strstr(
string,
"name=") + 5;
13274 if (*pitem ==
'\"')
13279 if (strncmp(pitem,
"attfile", 7) == 0) {
13280 int n = pitem[7] -
'1';
13286 if (strstr(pitem,
"filename=")) {
13287 const char* p = strstr(pitem,
"filename=") + 9;
13290 if (strstr(p,
"\r\n\r\n"))
13291 string = strstr(p,
"\r\n\r\n") + 4;
13292 else if (strstr(p,
"\r\r\n\r\r\n"))
13293 string = strstr(p,
"\r\r\n\r\r\n") + 6;
13298 if (strchr(pp,
'\"'))
13299 *strchr(pp,
'\"') = 0;
13303 sprintf(
str,
"attachment%d",
n);
13304 if (debug_decode_post)
13310 const char* ptmp = string;
13311 const char* p = NULL;
13313 while (*ptmp !=
'-')
13316 p = strstr(ptmp, boundary);
13327 ptmp += strlen(ptmp);
13334 char* buf = (
char*)malloc(size+1);
13338 memcpy(buf,
string, size);
13342 if (debug_decode_post)
13346 string = strstr(p, boundary) + strlen(boundary);
13348 const char* p = pitem;
13349 if (strstr(p,
"\r\n\r\n"))
13350 p = strstr(p,
"\r\n\r\n") + 4;
13351 else if (strstr(p,
"\r\r\n\r\r\n"))
13352 p = strstr(p,
"\r\r\n\r\r\n") + 6;
13354 char* ppitem = (
char*)strchr(pitem,
'\"');
13358 char* pb = (
char*)(strstr(p, boundary));
13360 string = pb + strlen(boundary);
13362 char* ptmp = (
char*)(p + (strlen(p) - 1));
13363 while (*ptmp ==
'-' || *ptmp ==
'\n' || *ptmp ==
'\r')
13369 if (debug_decode_post)
13370 printf(
"decode_post: [%s] = [%s]\n", pitem, p);
13371 param->setparam(pitem, p);
13374 while (*
string ==
'-' || *
string ==
'\n' || *
string ==
'\r')
13380 char dec_path[256];
13381 mstrlcpy(dec_path, path,
sizeof(dec_path));
13406 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo corrected successfully");
13408 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13412 cm_msg(
MERROR,
"check_odb_records",
"ODB subtree /Runinfo does not exist");
13415 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo created successfully");
13417 cm_msg(
MERROR,
"check_odb_records",
"Cannot create ODB subtree /Runinfo, db_create_record() status %d",
status);
13421 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13427 for (
i = 0 ;;
i++) {
13437 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Equipment/%s/Common corrected successfully",
key.
name);
13439 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13442 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13462#ifdef HAVE_MONGOOSE6
13463static std::vector<std::string> gUserAllowedHosts;
13466#ifdef HAVE_MONGOOSE6
13467static const std::string gOdbAllowedHosts =
"/Experiment/Security/mhttpd hosts/Allowed hosts";
13470#ifdef HAVE_MONGOOSE6
13474 cm_msg(
MINFO,
"load_allowed_hosts",
"Reloading mhttpd hosts access control list via hotlink callback");
13479 for (
unsigned int i=0;
i<gUserAllowedHosts.size();
i++)
13484 for (
int i=0; ;
i++) {
13493 if (s.length() < 1)
13506 if (
total - last < 5) {
13507 int new_size = last + 10;
13511 cm_msg(
MERROR,
"load_allowed_hosts",
"Cannot resize the allowed hosts access control list, db_resize_string(%d) status %d", new_size,
status);
13516static int init_allowed_hosts()
13530 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot create the mhttpd hosts access control list, db_get_value_string() status %d",
status);
13537 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot find the mhttpd hosts access control list, db_find_key() status %d",
status);
13541 load_allowed_hosts(
hDB, 0, 0, NULL);
13546 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot watch the mhttpd hosts access control list, db_watch() status %d",
status);
13553 int check_midas_acl(
const struct sockaddr *sa,
int len) {
13558 char hname[NI_MAXHOST];
13562 const char* status_string =
"success";
13564 status = getnameinfo(sa, len, hname,
sizeof(hname), NULL, 0, 0);
13567 status_string = gai_strerror(
status);
13572 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
status, status_string);
13577 if (strcmp(hname,
"localhost.localdomain") == 0)
13579 if (strcmp(hname,
"localhost") == 0)
13587 printf(
"Rejecting connection from \'%s\'\n", hname);
13591int open_listening_socket(
int port)
13594 struct sockaddr_in bind_addr;
13597 int lsock =
socket(AF_INET, SOCK_STREAM, 0);
13600 printf(
"Cannot create socket, socket() errno %d (%s)\n", errno, strerror(errno));
13605 memset(&bind_addr, 0,
sizeof(bind_addr));
13606 bind_addr.sin_family = AF_INET;
13607 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
13608 bind_addr.sin_port = htons((
short) port);
13612 status = setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (
char *) &flag,
sizeof(
INT));
13615 printf(
"Cannot setsockopt(SOL_SOCKET, SO_REUSEADDR), errno %d (%s)\n", errno, strerror(errno));
13619 status = bind(lsock, (
struct sockaddr *) &bind_addr,
sizeof(bind_addr));
13622 printf(
"Cannot bind() to port %d, bind() errno %d (%s)\n", port, errno, strerror(errno));
13629 printf(
"Cannot listen() on port %d, errno %d (%s), bye!\n", port, errno, strerror(errno));
13633 printf(
"mhttpd is listening on port %d\n", port);
13641int try_file_mg(
const char* try_dir,
const char* filename, std::string& path, FILE** fpp,
bool trace)
13647 if (strlen(try_dir) < 1)
13655 FILE*
fp = fopen(path.c_str(),
"r");
13659 printf(
"file \"%s\": OK!\n", path.c_str());
13661 printf(
"file \"%s\": not found.\n", path.c_str());
13674int find_file_mg(
const char* filename, std::string& path, FILE** fpp,
bool trace)
13691 try_file_mg(exptdir.c_str(), filename, path, NULL,
false);
13695#ifdef HAVE_MONGOOSE6
13699#ifdef HAVE_MONGOOSE616
13703extern void cs_md5(
char buf[33], ...);
13711#ifdef HAVE_MONGOOSE616
13712static bool multithread_mg =
true;
13715#ifdef HAVE_MONGOOSE6
13716static struct mg_mgr mgr_mg;
13740 if (!exptname.empty())
13758 size_t uri_len,
const char *ha1,
size_t ha1_len,
13759 const char *nonce,
size_t nonce_len,
const char *nc,
13760 size_t nc_len,
const char *cnonce,
size_t cnonce_len,
13761 const char *qop,
size_t qop_len,
char *resp) {
13762 static const char colon[] =
":";
13763 static const size_t one = 1;
13766 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
13767 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
13768 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
13769 colon, one, ha2,
sizeof(ha2) - 1, NULL);
13779 unsigned long now = (
unsigned long) time(NULL);
13780 unsigned long val = (
unsigned long) strtoul(nonce, NULL, 16);
13781 return now < val || now - val < 3600;
13790 const char *domain) {
13792 "HTTP/1.1 401 Unauthorized\r\n"
13793 "WWW-Authenticate: Digest qop=\"auth\", "
13794 "realm=\"%s\", nonce=\"%lu\"\r\n"
13795 "Content-Length: 0\r\n\r\n",
13796 domain, (
unsigned long) time(NULL));
13809 cm_msg(
MERROR,
"mongoose",
"mongoose web server cannot find password file \"%s\"", path.c_str());
13810 cm_msg(
MERROR,
"mongoose",
"please create password file: touch %s", path.c_str());
13814 bool have_realm =
false;
13822 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
13824 char f_domain[256];
13827 if (sscanf(buf,
"%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3) {
13830 e.username = f_user;
13831 e.password = f_ha1;
13833 if (
e.realm == auth->
realm) {
13845#ifdef HAVE_MONGOOSE6
13846std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13848 assert(!
"this code is untested!");
13854 if (buf_size == 0) {
13856 buf = (
char*)malloc(buf_size);
13857 assert(buf != NULL);
13867 if (size < buf_size) {
13868 std::string s = buf;
13873 buf_size = buf_size*2 + 16;
13874 buf = (
char*)realloc(buf, buf_size);
13875 assert(buf != NULL);
13880#ifdef HAVE_MONGOOSE616
13881std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13888 assert(buf != NULL);
13889 std::string s = buf;
13897 char expected_response[33];
13909 std::string user = find_var_mg(hdr,
"username");
13910 std::string cnonce = find_var_mg(hdr,
"cnonce");
13911 std::string
response = find_var_mg(hdr,
"response");
13912 std::string uri = find_var_mg(hdr,
"uri");
13913 std::string qop = find_var_mg(hdr,
"qop");
13914 std::string nc = find_var_mg(hdr,
"nc");
13915 std::string nonce = find_var_mg(hdr,
"nonce");
13917 if (user.length()<1)
return "";
13918 if (cnonce.length()<1)
return "";
13919 if (
response.length()<1)
return "";
13920 if (uri.length()<1)
return "";
13921 if (qop.length()<1)
return "";
13922 if (nc.length()<1)
return "";
13923 if (nonce.length()<1)
return "";
13930 const char* uri_end = strchr(hm->
uri.
p,
' ');
13931 if (!uri_end)
return "";
13933 size_t uri_length = uri_end - hm->
uri.
p;
13935 if (uri_length != uri.length())
13938 int cmp = strncmp(hm->
uri.
p, uri.c_str(), uri_length);
13947 if (
e->username != user)
13949 if (
e->realm != auth->
realm)
13951 const char* f_ha1 =
e->password.c_str();
13952 int uri_len = hm->
uri.
len;
13953 if (hm->
uri.
p[uri_len] ==
'?')
13956 hm->
uri.
p, uri_len,
13957 f_ha1, strlen(f_ha1),
13958 nonce.c_str(), nonce.length(),
13959 nc.c_str(), nc.length(),
13960 cnonce.c_str(), cnonce.length(),
13961 qop.c_str(), qop.length(),
13962 expected_response);
13963 int cmp = strcasecmp(
response.c_str(), expected_response);
13966 return e->username;
13973#ifdef HAVE_MONGOOSE616
13975struct HostlistCacheEntry
13977 time_t time_created = 0;
13978 time_t time_last_used = 0;
13979 int count_used = 0;
13982 uint32_t ipv4addr = 0;
13983 struct in6_addr ipv6addr;
13984 std::string hostname;
13985 int gai_status = 0;
13986 std::string gai_strerror;
13990static std::vector<HostlistCacheEntry*> gHostlistCache;
13992static void print_hostlist_cache()
13994 time_t now = time(NULL);
13996 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
13997 HostlistCacheEntry*
e = gHostlistCache[
i];
14003 printf(
"%3d: %s \"%s\", ok %d, count_used %d, age created: %d, last_used %d",
14005 e->ipv4?
"IPv4":(
e->ipv6?
"IPv6":
"????"),
14006 e->hostname.c_str(),
14009 (int)(now -
e->time_created),
14010 (int)(now -
e->time_last_used));
14012 if (
e->gai_status) {
14013 printf(
", getnameinfo() status %d (%s)",
e->gai_status,
e->gai_strerror.c_str());
14020static bool mongoose_check_hostlist(
const union socket_address *sa)
14022 time_t now = time(NULL);
14025 uint32_t ipv4addr = 0;
14026 struct in6_addr ipv6addr;
14028 if (sa->
sa.sa_family == AF_INET) {
14030 ipv4addr = sa->
sin.sin_addr.s_addr;
14031 }
else if (sa->
sa.sa_family == AF_INET6) {
14033 memcpy(&ipv6addr, &sa->
sin6.sin6_addr,
sizeof(ipv6addr));
14035 printf(
"Rejecting connection from unknown address family %d (AF_xxx)\n", sa->
sa.sa_family);
14039 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14040 HostlistCacheEntry*
e = gHostlistCache[
i];
14046 if ((ipv4 ==
e->ipv4) && (ipv4addr ==
e->ipv4addr)) {
14048 e->time_last_used = now;
14053 if ((ipv6 ==
e->ipv6) && (memcmp(&ipv6addr, &
e->ipv6addr,
sizeof(ipv6addr)) == 0)) {
14055 e->time_last_used = now;
14062 if (
e->time_last_used < now - 24*60*60) {
14063 printf(
"hostlist: expire \"%s\", ok %d, age %d, count_used: %d\n",
e->hostname.c_str(),
e->ok, (
int)(now -
e->time_last_used),
e->count_used);
14064 gHostlistCache[
i] = NULL;
14071 assert(ipv4 || ipv6);
14073 HostlistCacheEntry*
e =
new HostlistCacheEntry;
14075 bool found =
false;
14076 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14077 if (gHostlistCache[
i] == NULL) {
14078 gHostlistCache[
i] =
e;
14083 gHostlistCache.push_back(
e);
14086 e->time_created = now;
14087 e->time_last_used = now;
14092 e->ipv4addr = ipv4addr;
14094 memcpy(&
e->ipv6addr, &ipv6addr,
sizeof(ipv6addr));
14097 char hname[NI_MAXHOST];
14100 e->gai_status = getnameinfo(&sa->
sa,
sizeof(*sa), hname,
sizeof(hname), NULL, 0, 0);
14102 if (
e->gai_status) {
14103 e->gai_strerror = gai_strerror(
e->gai_status);
14105 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
e->gai_status,
e->gai_strerror.c_str());
14111 printf(
"connection from \"%s\"\n", hname);
14113 e->hostname = hname;
14116 if (
e->hostname ==
"localhost.localdomain")
14118 else if (
e->hostname ==
"localhost")
14129 printf(
"Rejecting connection from \'%s\'\n", hname);
14132 print_hostlist_cache();
14141 return std::string(s->
p, s->
len);
14146 size_t nlen = strlen(
name);
14160 if (cookies.length() < 1)
14162 const char* p = strstr(cookies.c_str(), cookie_name);
14165 const char* v = p+strlen(cookie_name);
14183 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> accept\n", nc, ev, ev_data);
14187 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> recv %d, buffered %d bytes\n", nc, ev, ev_data, *(
int*)ev_data, (
int)io->
len);
14196 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> send %d bytes\n", nc, ev, ev_data, *(
int*)ev_data);
14200 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> close\n", nc, ev, ev_data);
14204 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
14213 char cookie_pwd[256];
14214 char cookie_wpwd[256];
14215 char cookie_cpwd[256];
14218 cookie_wpwd[0] = 0;
14219 cookie_cpwd[0] = 0;
14222 if (s.length() > 0) {
14223 mstrlcpy(cookie_pwd, s.c_str(),
sizeof(cookie_pwd));
14224 cookie_pwd[strcspn(cookie_pwd,
" ;\r\n")] = 0;
14229 mstrlcpy(cookie_wpwd, s.c_str(),
sizeof(cookie_pwd));
14230 cookie_wpwd[strcspn(cookie_wpwd,
" ;\r\n")] = 0;
14235 mstrlcpy(cookie_cpwd, s.c_str(),
sizeof(cookie_pwd));
14236 cookie_cpwd[strcspn(cookie_cpwd,
" ;\r\n")] = 0;
14242 if (s.length() > 0)
14243 c->refresh = atoi(s.c_str());
14251 c->cookie_pwd = cookie_pwd;
14252 c->cookie_wpwd = cookie_wpwd;
14253 c->cookie_cpwd = cookie_cpwd;
14256#define RESPONSE_SENT 1
14257#define RESPONSE_QUEUED 2
14258#define RESPONSE_501 3
14268#ifdef HAVE_MONGOOSE6
14283 decode_get(rr, NULL, &cookies, uri, query_string, t);
14292#ifdef HAVE_MONGOOSE6
14304#ifdef HAVE_MONGOOSE6
14324#ifdef HAVE_MONGOOSE616
14326static uint32_t s_ncseqno = 1;
14328struct MongooseNcUserData
14330 uint32_t ncseqno = 0;
14332 MongooseNcUserData()
14334 ncseqno = s_ncseqno++;
14338 ~MongooseNcUserData()
14350 const MongooseNcUserData* ncud = (
const MongooseNcUserData*)nc->
user_data;
14351 return ncud->ncseqno;
14354static uint32_t s_wseqno = 1;
14356struct MongooseWorkObject
14358 uint32_t wseqno = 0;
14360 uint32_t wncseqno = 0;
14361 bool http_get =
false;
14362 bool http_post =
false;
14363 bool mjsonrpc =
false;
14365 std::string origin;
14367 std::string query_string;
14368 std::string post_body;
14369 std::string post_boundary;
14371 bool send_done =
false;
14375 wseqno = s_wseqno++;
14377 wncseqno = GetNcSeqno(nc);
14382 ~MongooseWorkObject()
14392struct MongooseThreadObject
14394 std::atomic_bool fIsRunning{
false};
14395 std::thread* fThread = NULL;
14398 std::deque<MongooseWorkObject*> fQueue;
14399 std::condition_variable fNotify;
14412static std::vector<MongooseThreadObject*> gMongooseThreads;
14414static void mongoose_thread(MongooseThreadObject*);
14416MongooseThreadObject* FindThread(
void* nc)
14420 MongooseThreadObject* last_not_connected = NULL;
14422 for (
auto it : gMongooseThreads) {
14423 MongooseThreadObject* to = it;
14424 if (to->fNc == nc) {
14428 if (to->fNc == NULL) {
14429 last_not_connected = to;
14433 if (last_not_connected) {
14434 MongooseThreadObject* to = last_not_connected;
14440 MongooseThreadObject* to =
new MongooseThreadObject();
14446 gMongooseThreads.push_back(to);
14448 printf(
"Mongoose web server is using %d threads \r", (
int)gMongooseThreads.size());
14451 to->fThread =
new std::thread(mongoose_thread, to);
14456void FreeThread(
void* nc)
14460 for (
auto it : gMongooseThreads) {
14461 MongooseThreadObject* to = it;
14462 if (to->fNc == nc) {
14472static void mongoose_queue(
mg_connection* nc, MongooseWorkObject* w)
14475 MongooseThreadObject* to = FindThread(nc);
14476 assert(to->fNc == nc);
14478 to->fQueue.push_back(w);
14479 to->fMutex.unlock();
14480 to->fNotify.notify_one();
14483static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag =
false);
14487 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14488 w->http_get =
true;
14491 w->query_string = query_string;
14494 mongoose_queue(nc, w);
14501 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14502 w->http_post =
true;
14505 w->query_string = query_string;
14507 w->post_boundary = boundary;
14510 mongoose_queue(nc, w);
14515static int queue_mjsonrpc(
struct mg_connection *nc,
const std::string& origin,
const std::string& post_body,
RequestTrace* t)
14517 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14518 w->mjsonrpc =
true;
14519 w->origin = origin;
14520 w->post_body = post_body;
14523 mongoose_queue(nc, w);
14528static int thread_http_get(
mg_connection *nc, MongooseWorkObject *w)
14545 decode_get(rr, NULL, &w->cookies, w->uri.c_str(), w->query_string.c_str(), w->t);
14566 bool close_flag =
false;
14584static int thread_http_post(
mg_connection *nc, MongooseWorkObject *w)
14586 const char* post_data = w->post_body.c_str();
14587 int post_data_len = w->post_body.length();
14602 decode_post(rr, NULL, (
char*)post_data, w->post_boundary.c_str(), post_data_len, &w->cookies, w->uri.c_str(), w->t);
14605 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14618 bool close_flag =
false;
14634static int thread_mjsonrpc(
mg_connection *nc, MongooseWorkObject *w)
14636 w->t->fRPC = w->post_body;
14651 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14654 reply->GetArrayBuffer(&ptr, &size);
14656 std::string headers;
14657 headers +=
"HTTP/1.1 200 OK\n";
14658 if (w->origin.length() > 0)
14659 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14661 headers +=
"Access-Control-Allow-Origin: *\n";
14662 headers +=
"Access-Control-Allow-Credentials: true\n";
14663 headers +=
"Content-Length: " +
toString(size) +
"\n";
14664 headers +=
"Content-Type: application/octet-stream\n";
14670 std::string send = headers +
"\n";
14674 mongoose_send(nc, w, send.c_str(), send.length(), ptr, size);
14683 std::string reply_string = reply->Stringify();
14684 int reply_length = reply_string.length();
14686 std::string headers;
14687 headers +=
"HTTP/1.1 200 OK\n";
14688 if (w->origin.length() > 0)
14689 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14691 headers +=
"Access-Control-Allow-Origin: *\n";
14692 headers +=
"Access-Control-Allow-Credentials: true\n";
14693 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14694 headers +=
"Content-Type: application/json\n";
14698 printf(
"-----------------------\nSending headers: %s", headers.c_str());
14699 std::string r = reply_string.substr(0, 128);
14700 printf(
"-----------------------\nSending reply (%d bytes): %s\n\n\n", (
int)reply_string.size(), r.c_str());
14703 std::string send = headers +
"\n" + reply_string;
14707 mongoose_send(nc, w, send.c_str(), send.length(), NULL, 0);
14716static int thread_work_function(
mg_connection *nc, MongooseWorkObject *w)
14719 return thread_http_get(nc, w);
14720 else if (w->http_post)
14721 return thread_http_post(nc, w);
14722 else if (w->mjsonrpc)
14723 return thread_mjsonrpc(nc, w);
14733 char boundary[256];
14736 if (ct.length() > 0) {
14737 const char* s = strstr(ct.c_str(),
"boundary=");
14739 mstrlcpy(boundary, s+9,
sizeof(boundary));
14742#ifdef HAVE_MONGOOSE616
14743 if (multithread_mg)
14744 return queue_decode_post(nc, msg, boundary, uri, query_string, t);
14751 const char* post_data = msg->
body.
p;
14752 int post_data_len = msg->
body.
len;
14756#ifdef HAVE_MONGOOSE6
14769 decode_post(rr, NULL, (
char*)post_data, boundary, post_data_len, &cookies, uri, t);
14772 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14775#ifdef HAVE_MONGOOSE6
14785#ifdef HAVE_MONGOOSE6
14808 printf(
"handle_http_get: uri [%s], query [%s]\n", uri, query_string.c_str());
14810 if (query_string ==
"mjsonrpc_schema") {
14812 std::string reply = s->Stringify();
14815 int reply_length = reply.length();
14817 const std::string origin_header =
find_header_mg(msg,
"Origin");
14819 std::string headers;
14820 headers +=
"HTTP/1.1 200 OK\n";
14821 if (origin_header.length() > 0)
14822 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14824 headers +=
"Access-Control-Allow-Origin: *\n";
14825 headers +=
"Access-Control-Allow-Credentials: true\n";
14826 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14827 headers +=
"Content-Type: application/json\n";
14833 std::string send = headers +
"\n" + reply;
14837 mg_send(nc, send.c_str(), send.length());
14844 if (query_string ==
"mjsonrpc_schema_text") {
14849 int reply_length = reply.length();
14851 const std::string origin_header =
find_header_mg(msg,
"Origin");
14853 std::string headers;
14854 headers +=
"HTTP/1.1 200 OK\n";
14855 if (origin_header.length() > 0)
14856 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14858 headers +=
"Access-Control-Allow-Origin: *\n";
14859 headers +=
"Access-Control-Allow-Credentials: true\n";
14860 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14861 headers +=
"Content-Type: text/plain\n";
14867 std::string send = headers +
"\n" + reply;
14871 mg_send(nc, send.c_str(), send.length());
14878#ifdef HAVE_MONGOOSE616
14879 if (multithread_mg)
14880 return queue_decode_get(nc, msg, uri, query_string.c_str(), t);
14889 std::string post_data =
mgstr(&msg->
body);
14892 printf(
"handle_http_post: uri [%s], query [%s], post data %d bytes\n", uri, query_string.c_str(), (
int)post_data.length());
14894 printf(
"handle_http_post: post data = \n%s\n", post_data.c_str());
14896 if (query_string.substr(0, 8) ==
"mjsonrpc") {
14897 const std::string origin_header =
find_header_mg(msg,
"Origin");
14898 const std::string ctype_header =
find_header_mg(msg,
"Content-Type");
14900 if (strstr(ctype_header.c_str(),
"application/json") == NULL) {
14901 std::string headers;
14902 headers +=
"HTTP/1.1 415 Unsupported Media Type\n";
14909 printf(
"handle_http_post: unsupported media type \"%s\"\n", ctype_header.c_str());
14911 std::string send = headers +
"\n";
14915 mg_send(nc, send.c_str(), send.length());
14922#ifdef HAVE_MONGOOSE616
14923 if (multithread_mg)
14924 return queue_mjsonrpc(nc, origin_header, post_data, t);
14929 t->
fRPC = post_data;
14931#ifdef HAVE_MONGOOSE6
14942#ifdef HAVE_MONGOOSE6
14946 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14949 reply->GetArrayBuffer(&ptr, &size);
14951 std::string headers;
14952 headers +=
"HTTP/1.1 200 OK\n";
14953 if (origin_header.length() > 0)
14954 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14956 headers +=
"Access-Control-Allow-Origin: *\n";
14957 headers +=
"Access-Control-Allow-Credentials: true\n";
14958 headers +=
"Content-Length: " +
toString(size) +
"\n";
14959 headers +=
"Content-Type: application/octet-stream\n";
14965 std::string send = headers +
"\n";
14969 mg_send(nc, send.c_str(), send.length());
14979 std::string reply_string = reply->Stringify();
14980 int reply_length = reply_string.length();
14982 std::string headers;
14983 headers +=
"HTTP/1.1 200 OK\n";
14984 if (origin_header.length() > 0)
14985 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14987 headers +=
"Access-Control-Allow-Origin: *\n";
14988 headers +=
"Access-Control-Allow-Credentials: true\n";
14989 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14990 headers +=
"Content-Type: application/json\n";
14996 std::string send = headers +
"\n" + reply_string;
15000 mg_send(nc, send.c_str(), send.length());
15045 const std::string origin_header =
find_header_mg(msg,
"Origin");
15048 printf(
"handle_http_options_cors: origin [%s]\n", origin_header.c_str());
15050 std::string headers;
15051 headers +=
"HTTP/1.1 200 OK\n";
15053 if (origin_header.length() > 0)
15054 headers +=
"Access-Control-Allow-Origin: " + origin_header +
"\n";
15056 headers +=
"Access-Control-Allow-Origin: *\n";
15057 headers +=
"Access-Control-Allow-Headers: Content-Type\n";
15058 headers +=
"Access-Control-Allow-Credentials: true\n";
15059 headers +=
"Access-Control-Max-Age: 120\n";
15060 headers +=
"Content-Length: 0\n";
15061 headers +=
"Content-Type: text/plain\n";
15065 std::string send = headers +
"\n";
15069 mg_send(nc, send.c_str(), send.length());
15078#ifdef HAVE_MONGOOSE616
15079static MVOdb* gProxyOdb = NULL;
15086 std::string uri_encoded =
mgstr(&msg->
uri);
15087 std::string uri =
UrlDecode(uri_encoded.c_str());
15090 printf(
"handle_http_message: method [%s] uri [%s] proto [%s]\n", method.c_str(), uri.c_str(),
mgstr(&msg->
proto).c_str());
15096 t->
fQuery = query_string;
15100 if (method ==
"OPTIONS" && query_string ==
"mjsonrpc" &&
mg_get_http_header(msg,
"Access-Control-Request-Method") != NULL) {
15123 printf(
"handle_http_message: auth user: \"%s\"\n", username.c_str());
15125 if (username.length() == 0) {
15127 printf(
"handle_http_message: method [%s] uri [%s] query [%s] proto [%s], sending auth request for realm \"%s\"\n", method.c_str(), uri.c_str(), query_string.c_str(),
mgstr(&msg->
proto).c_str(),
gAuthMg->
realm.c_str());
15139#ifdef HAVE_MONGOOSE616
15141 std::string::size_type p1 = uri.find(
"/", 1);
15142 if (p1 == uri.length()-1) {
15143 std::string
response =
"404 Not Found (Proxy name is missing)";
15149 std::string::size_type p2 = uri.find(
"/", p1+1);
15150 if (p2 == std::string::npos) {
15151 std::string
response =
"404 Not Found (Proxy URL should end with a slash)";
15157 std::string p = uri.substr(p1+1, p2-p1-1);
15159 if (p.length() < 1) {
15160 std::string
response =
"404 Not Found (Double-slash or Proxy name is too short)";
15166 std::string destination;
15167 gProxyOdb->RS(p.c_str(), &destination);
15168 if (destination.length() < 1) {
15169 std::string
response =
"404 Not Found (Proxy not found in ODB)";
15174 }
else if (destination[0] ==
'#') {
15175 std::string
response =
"404 Not Found (Proxy commented-out in ODB)";
15181 std::string
response =
"404 Not Found (Proxy address should not end with a slash)";
15187 std::string
response =
"404 Not Found (Proxy address does not start with http";
15200 printf(
"proxy: uri [%s] mount [%s] upstream [%s]\n", uri.c_str(),
mgstr(&mount).c_str(),
mgstr(&upstream).c_str());
15202 mg_http_reverse_proxy(nc, msg, mount, upstream);
15211 if (method ==
"GET")
15213 else if (method ==
"POST")
15218 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15220 std::string
response =
"501 Not Implemented";
15231#ifdef HAVE_MONGOOSE6
15233static void handle_http_event_mg(
struct mg_connection *nc,
int ev,
void *ev_data)
15238 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15243 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15248static void handle_http_redirect(
struct mg_connection *nc,
int ev,
void *ev_data)
15255 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15257 mg_printf(nc,
"HTTP/1.1 302 Found\r\nLocation: https://%s%s\r\n\r\n",
15258 ((std::string*)(nc->
user_data))->c_str(),
15265 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15271#ifdef HAVE_MONGOOSE616
15276static std::atomic_bool s_shutdown{
false};
15277static struct mg_mgr s_mgr;
15278static std::atomic_int s_rseqno{1};
15279static std::mutex s_mg_broadcast_mutex;
15283struct work_request {
15285 MongooseWorkObject* w;
15290struct work_result {
15292 uint32_t check = 0x12345678;
15294 MongooseWorkObject* w = NULL;
15295 const char* p1 = NULL;
15297 const char* p2 = NULL;
15299 bool close_flag =
false;
15300 bool send_501 =
false;
15304static void mongoose_queue(
void *nc, MongooseWorkObject *w)
15306 struct work_request req = {nc, w};
15310 if (
write(s_sock[0], &req,
sizeof(req)) < 0) {
15311 fprintf(stderr,
"mongoose_queue: Error: write(s_sock(0)) error %d (%s)\n", errno, strerror(errno));
15317static void on_work_complete(
struct mg_connection *nc,
int ev,
void *ev_data)
15320 struct work_result *res = (
struct work_result *)ev_data;
15322 assert(res != NULL);
15323 assert(res->w != NULL);
15334 if (GetNcSeqno(nc) != res->w->wncseqno)
15339 if (res->send_501) {
15340 std::string
response =
"501 Not Implemented";
15346 mg_send(nc, res->p1, res->s1);
15349 mg_send(nc, res->p2, res->s2);
15351 if (res->close_flag) {
15358 res->w->send_done =
true;
15361static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag)
15364 struct work_result res;
15367 res.rseqno = s_rseqno++;
15372 res.close_flag = close_flag;
15373 res.send_501 =
false;
15415 s_mg_broadcast_mutex.lock();
15416 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15417 s_mg_broadcast_mutex.unlock();
15420static void mongoose_send_501(
mg_connection* nc, MongooseWorkObject* w)
15422 struct work_result res;
15425 res.rseqno = s_rseqno++;
15430 res.close_flag =
false;
15431 res.send_501 =
true;
15434 s_mg_broadcast_mutex.lock();
15435 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15436 s_mg_broadcast_mutex.unlock();
15440void *worker_thread_proc(
void *
param)
15443 struct work_request req = {0};
15445 while ((!
_abort) && (! s_shutdown)) {
15446 int rd =
read(s_sock[1], &req,
sizeof(req));
15452 if (
_abort || s_shutdown) {
15455 fprintf(stderr,
"worker_thread_proc: Error: read(s_sock(1)) returned %d, error %d (%s)\n", rd, errno, strerror(errno));
15462 int response = thread_work_function(req.nc, req.w);
15466 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15467 mongoose_send_501(req.nc, req.w);
15470 req.w->t->fCompleted =
true;
15482static void mongoose_thread(MongooseThreadObject* to)
15486 std::unique_lock<std::mutex> ulm(to->fMutex, std::defer_lock);
15488 to->fIsRunning =
true;
15490 while ((!
_abort) && (! s_shutdown)) {
15491 MongooseWorkObject *w = NULL;
15494 while (to->fQueue.empty()) {
15496 to->fNotify.wait(ulm);
15497 if (
_abort || s_shutdown) {
15502 if (
_abort || s_shutdown) {
15506 w = to->fQueue.front();
15507 to->fQueue.pop_front();
15512 int response = thread_work_function(w->nc, w);
15516 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15517 mongoose_send_501(w->nc, w);
15522 if (!w->send_done) {
15528 w->t->fCompleted =
true;
15536 to->fIsRunning =
false;
15541static bool mongoose_hostlist_enabled(
const struct mg_connection *nc);
15543static void ev_handler(
struct mg_connection *nc,
int ev,
void *ev_data)
15557 printf(
"ev_handler: connection %p, event %d\n", nc, ev);
15563 nc->
user_data =
new MongooseNcUserData();
15566 printf(
"ev_handler: connection %p, MG_EV_ACCEPT, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15571 }
else if (mongoose_hostlist_enabled(nc)) {
15572 if (!mongoose_check_hostlist(&nc->
sa)) {
15579 printf(
"ev_handler: connection %p, MG_EV_RECV, %d bytes\n", nc, *(
int*)ev_data);
15588 printf(
"ev_handler: connection %p, MG_EV_SEND, %d bytes\n", nc, *(
int*)ev_data);
15593 printf(
"ev_handler: connection %p, MG_EV_HTTP_CHUNK\n", nc);
15604 printf(
"ev_handler: connection %p, MG_EV_HTTP_REQUEST \"%s\" \"%s\"\n", nc,
mgstr(&msg->
method).c_str(),
mgstr(&msg->
uri).c_str());
15616 printf(
"ev_handler: connection %p, MG_EV_CLOSE, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15621 MongooseNcUserData* ncud = (MongooseNcUserData*)nc->
user_data;
15630#define FLAG_HTTPS MG_F_USER_1
15631#define FLAG_PASSWORDS MG_F_USER_2
15632#define FLAG_HOSTLIST MG_F_USER_3
15641 return flags & FLAG_PASSWORDS;
15644static bool mongoose_hostlist_enabled(
const struct mg_connection *nc)
15651 return flags & FLAG_HOSTLIST;
15654static int mongoose_listen(
const char* address,
int flags)
15658 if (flags & FLAG_HTTPS) {
15659 cm_msg(
MERROR,
"mongoose_listen",
"https port \"%s\" requested, but mhttpd compiled without MG_ENABLE_SSL", address);
15666 cm_msg(
MERROR,
"mongoose_listen",
"Cannot mg_bind address \"%s\"", address);
15670 if (
flags & FLAG_HTTPS) {
15672 std::string cert_file;
15677 cm_msg(
MERROR,
"mongoose_listen",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
15678 cm_msg(
MERROR,
"mongoose_listen",
"please create SSL certificate file using openssl: cd $MIDASSYS; openssl req -new -nodes -newkey rsa:2048 -sha256 -out ssl_cert.csr -keyout ssl_cert.key -subj \"/C=/ST=/L=/O=midas/OU=mhttpd/CN=localhost\"; openssl x509 -req -days 365 -sha256 -in ssl_cert.csr -signkey ssl_cert.key -out ssl_cert.pem; cat ssl_cert.key >> ssl_cert.pem");
15679 cm_msg(
MERROR,
"mongoose_listen",
"or using certbot (recommened): setup certbot per Let's Encrypt instructions, certificates are typically saved in /etc/letsencrypt/live/$HOSTNAME/, copy fullchain.pem and privkey.pem to $MIDASSYS; cd $MIDASSYS; cat fullchain.pem privkey.pem > ssl_cert.pem");
15683 printf(
"Mongoose web server will use https certificate file \"%s\"\n", cert_file.c_str());
15685 const char* errmsg =
mg_set_ssl(nc, cert_file.c_str(), NULL);
15687 cm_msg(
MERROR,
"mongoose_listen",
"Cannot enable https with certificate file \"%s\", error: %s", cert_file.c_str(), errmsg);
15701 printf(
"Listening on \"%s://%s\", passwords %s, hostlist %s\n", (
flags&FLAG_HTTPS)?
"https":
"http", address, (
flags&FLAG_PASSWORDS)?
"enabled":
"OFF", (
flags&FLAG_HOSTLIST)?
"enabled":
"OFF");
15706static int mongoose_init(MVOdb* odb,
bool no_passwords,
bool no_hostlist,
const std::vector<std::string>& user_hostlist)
15708 bool enable_localhost_port =
true;
15709 int localhost_port = 8080;
15710 bool localhost_port_passwords =
false;
15712 bool enable_insecure_port =
false;
15713 int insecure_port = 8081;
15714 bool insecure_port_passwords =
true;
15715 bool insecure_port_hostlist =
true;
15717 bool enable_https_port =
false;
15718 int https_port = 8443;
15719 bool https_port_passwords =
true;
15720 bool https_port_hostlist =
false;
15722 std::vector<std::string> hostlist;
15723 hostlist.push_back(
"localhost");
15725 bool enable_ipv6 =
true;
15727 odb->RB(
"Enable localhost port", &enable_localhost_port,
true);
15728 odb->RI(
"localhost port", &localhost_port,
true);
15729 odb->RB(
"localhost port passwords", &localhost_port_passwords,
true);
15730 odb->RB(
"Enable insecure port", &enable_insecure_port,
true);
15731 odb->RI(
"insecure port", &insecure_port,
true);
15732 odb->RB(
"insecure port passwords", &insecure_port_passwords,
true);
15733 odb->RB(
"insecure port host list", &insecure_port_hostlist,
true);
15734 odb->RB(
"Enable https port", &enable_https_port,
true);
15735 odb->RI(
"https port", &https_port,
true);
15736 odb->RB(
"https port passwords", &https_port_passwords,
true);
15737 odb->RB(
"https port host list", &https_port_hostlist,
true);
15738 odb->RSA(
"Host list", &hostlist,
true, 10, 256);
15739 odb->RB(
"Enable IPv6", &enable_ipv6,
true);
15742 gProxyOdb = odb->Chdir(
"Proxy",
true);
15743 std::string proxy_example =
"#http://localhost:8080";
15744 gProxyOdb->RS(
"example", &proxy_example,
true);
15750 && ((enable_localhost_port && localhost_port_passwords)
15751 || (enable_insecure_port && insecure_port_passwords)
15752 || (enable_https_port && https_port_passwords))) {
15756 printf(
"mongoose_init: Error: Cannot initialize authorization object!\n");
15761 printf(
"Password protection is off\n");
15765 && ((enable_insecure_port && insecure_port_hostlist)
15766 || (enable_https_port && https_port_hostlist))) {
15770 for (
unsigned int i=0;
i<user_hostlist.size();
i++)
15773 for (
unsigned i=0;
i<hostlist.size();
i++) {
15774 std::string s = hostlist[
i];
15775 if (s.length() < 1)
15785 printf(
"Hostlist active, connections will be accepted only from: ");
15793 printf(
"Hostlist off, connections from anywhere will be accepted\n");
15798 bool listen_failed =
false;
15800 if (enable_localhost_port) {
15802 sprintf(
str,
"localhost:%d", localhost_port);
15805 listen_failed =
true;
15807 sprintf(
str,
"[::1]:%d", localhost_port);
15810 listen_failed =
true;
15814 if (enable_insecure_port) {
15817 if (insecure_port_passwords)
15818 flags |= FLAG_PASSWORDS;
15819 if (insecure_port_hostlist)
15820 flags |= FLAG_HOSTLIST;
15822 sprintf(
str,
"[::]:%d", insecure_port);
15825 listen_failed =
true;
15827 sprintf(
str,
"%d", insecure_port);
15830 listen_failed =
true;
15834 if (enable_https_port) {
15837 if (https_port_passwords)
15838 flags |= FLAG_PASSWORDS;
15839 if (https_port_hostlist)
15840 flags |= FLAG_HOSTLIST;
15841 flags |= FLAG_HTTPS;
15843 sprintf(
str,
"[::]:%d", https_port);
15846 listen_failed =
true;
15848 sprintf(
str,
"%d", https_port);
15851 listen_failed =
true;
15855 if (listen_failed) {
15856 cm_msg(
MERROR,
"mongoose_init",
"Failed to listen on a TCP port enabled in ODB /WebServer");
15863static void mongoose_poll(
int msec = 200)
15868static void mongoose_cleanup()
15870 printf(
"Mongoose web server shutting down\n");
15875 if (s_mgr.active_connections) {
15887 for (
auto it : gMongooseThreads) {
15888 MongooseThreadObject* to = it;
15889 to->fNotify.notify_one();
15893 for (
int i=0;
i<10;
i++) {
15894 int count_running = 0;
15895 for (
auto it : gMongooseThreads) {
15896 MongooseThreadObject* to = it;
15898 if (to->fIsRunning) {
15902 printf(
"Mongoose web server shutting down, %d threads still running\n", count_running);
15903 if (count_running == 0)
15905 mongoose_poll(1000);
15909 for (
auto it : gMongooseThreads) {
15910 MongooseThreadObject* to = it;
15912 if (to->fIsRunning) {
15913 cm_msg(
MERROR,
"mongoose",
"thread failed to shut down");
15916 to->fThread->join();
15917 delete to->fThread;
15920 gMongooseThreads.clear();
15928 for (
auto e : gHostlistCache) {
15931 gHostlistCache.clear();
15941 printf(
"Mongoose web server shut down\n");
15946#ifdef HAVE_MONGOOSE6
15953int start_mg(
int user_http_port,
int user_https_port,
int socket_priviledged_port,
int verbose)
15968 int http_port = 8080;
15969 int https_port = 8443;
15970 int http_redirect_to_https = 1;
15972 size =
sizeof(http_port);
15975 size =
sizeof(https_port);
15978 size =
sizeof(http_redirect_to_https);
15981 bool need_cert_file =
false;
15982 bool need_password_file =
false;
15984 if (user_http_port)
15985 http_port = user_http_port;
15987 if (user_https_port)
15988 https_port = user_https_port;
15991 need_cert_file =
true;
15992 need_password_file =
true;
15996 http_redirect_to_https = 0;
15998 if (http_port && !http_redirect_to_https) {
16001 need_password_file =
false;
16004 if (socket_priviledged_port >= 0) {
16006 need_password_file =
false;
16007 printf(
"Mongoose web server password portection is disabled: serving unencrypted http on port 80\n");
16010 bool have_at_least_one_port =
false;
16012 std::string cert_file;
16014 if (need_cert_file) {
16018 cm_msg(
MERROR,
"mongoose",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
16019 cm_msg(
MERROR,
"mongoose",
"please create SSL certificate file: cd $MIDASSYS; openssl req -new -nodes -newkey rsa:2048 -sha256 -out ssl_cert.csr -keyout ssl_cert.key -subj \"/C=/ST=/L=/O=midas/OU=mhttpd/CN=localhost\"; openssl x509 -req -days 365 -sha256 -in ssl_cert.csr -signkey ssl_cert.key -out ssl_cert.pem; cat ssl_cert.key >> ssl_cert.pem");
16023 printf(
"Mongoose web server will use SSL certificate file \"%s\"\n", cert_file.c_str());
16026 if (need_password_file) {
16030 printf(
"Error: Cannot initialize authorization object!\n");
16035 printf(
"Mongoose web server will not use password protection\n");
16039 printf(
"start_mg!\n");
16042 signal(SIGPIPE, SIG_IGN);
16049 if (!request_mutex) {
16057 if (socket_priviledged_port >= 0) {
16060 cm_msg(
MERROR,
"mongoose",
"Cannot create mg_connection for set-uid-root privileged port");
16065#ifdef MG_ENABLE_THREADS
16071 have_at_least_one_port =
true;
16072 printf(
"mongoose web server is listening on the set-uid-root privileged port\n");
16075 if (http_port != 80) {
16077 sprintf(
str,
"%d", http_port);
16080 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", http_port);
16084#ifdef MG_ENABLE_THREADS
16089 if (http_redirect_to_https) {
16092 sprintf(
str,
"%d", https_port);
16093 std::string s = hostname +
":" + std::string(
str);
16096 printf(
"mongoose web server is redirecting HTTP port %d to https://%s\n", http_port, s.c_str());
16101 have_at_least_one_port =
true;
16102 printf(
"mongoose web server is listening on the HTTP port %d\n", http_port);
16106#ifdef MG_ENABLE_SSL
16108 sprintf(
str,
"%d", https_port);
16111 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", https_port);
16116#ifdef MG_ENABLE_THREADS
16122 have_at_least_one_port =
true;
16123 printf(
"mongoose web server is listening on the HTTPS port %d\n", https_port);
16125 cm_msg(
MERROR,
"mongoose",
"https port %d requested, but mhttpd compiled without MG_ENABLE_SSL", https_port);
16130 if (!have_at_least_one_port) {
16131 cm_msg(
MERROR,
"mongoose",
"cannot start: no ports defined");
16141 printf(
"stop_mg!\n");
16147 printf(
"stop_mg done!\n");
16162#ifdef HAVE_MONGOOSE6
16173#ifdef HAVE_MONGOOSE6
16190 doc->
D(
"get current value of mhttpd http_trace");
16191 doc->
P(NULL, 0,
"there are no input parameters");
16192 doc->
R(NULL, MJSON_INT,
"current value of http_trace");
16203 doc->
D(
"set new value of mhttpd http_trace");
16204 doc->
P(NULL, MJSON_INT,
"new value of http_trace");
16205 doc->
R(NULL, MJSON_INT,
"new value of http_trace");
16225#ifdef HAVE_MONGOOSE6
16226 int user_http_port = 0;
16227 int user_https_port = 0;
16229#ifdef HAVE_MONGOOSE616
16230 bool no_passwords =
false;
16231 bool no_hostlist =
false;
16233 const char *myname =
"mhttpd";
16235 setbuf(stdout, NULL);
16236 setbuf(stderr, NULL);
16239 signal(SIGPIPE, SIG_IGN);
16242#ifdef HAVE_MONGOOSE6
16247 int socket_priviledged_port = -1;
16251 if (getuid() != geteuid()) {
16254 printf(
"mhttpd is running in setuid-root mode.\n");
16256 socket_priviledged_port = open_listening_socket(port80);
16257 if (socket_priviledged_port < 0) {
16258 printf(
"Cannot open listening socket on TCP port %d, aborting.\n", port80);
16263 status = setuid(getuid());
16265 printf(
"Cannot give up root privelege, aborting.\n");
16268 status = setuid(getuid());
16270 printf(
"Cannot give up root privelege, aborting.\n");
16277 char midas_hostname[256];
16278 char midas_expt[256];
16281 cm_get_environment(midas_hostname,
sizeof(midas_hostname), midas_expt,
sizeof(midas_expt));
16284#ifdef HAVE_MONGOOSE6
16285 gUserAllowedHosts.clear();
16287 std::vector<std::string> user_hostlist;
16289 for (
int i = 1;
i < argc;
i++) {
16290 if (argv[
i][0] ==
'-' && argv[
i][1] ==
'D')
16292 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'v')
16294 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'E')
16296 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'H') {
16298#ifdef HAVE_MONGOOSE6
16299 }
else if (strcmp(argv[
i],
"--http") == 0) {
16301 user_http_port = atoi(argv[
i+1]);
16303 }
else if (strcmp(argv[
i],
"--https") == 0) {
16305 user_https_port = atoi(argv[
i+1]);
16308 }
else if (strcmp(argv[
i],
"--trace-mg") == 0) {
16312 }
else if (strcmp(argv[
i],
"--trace-mg-verbose") == 0) {
16314 }
else if (strcmp(argv[
i],
"--no-trace-mg-recv") == 0) {
16316 }
else if (strcmp(argv[
i],
"--no-trace-mg-send") == 0) {
16318 }
else if (strcmp(argv[
i],
"--verbose-mg") == 0) {
16320#ifdef HAVE_MONGOOSE616
16321 }
else if (strcmp(argv[
i],
"--no-multithread") == 0) {
16322 multithread_mg =
false;
16323 }
else if (strcmp(argv[
i],
"--no-passwords") == 0) {
16324 no_passwords =
true;
16325 }
else if (strcmp(argv[
i],
"--no-hostlist") == 0) {
16326 no_hostlist =
true;
16328 }
else if (argv[
i][0] ==
'-') {
16329 if (
i + 1 >= argc || argv[
i + 1][0] ==
'-')
16331 if (argv[
i][1] ==
'h')
16332 mstrlcpy(midas_hostname, argv[++
i],
sizeof(midas_hostname));
16333 else if (argv[
i][1] ==
'e')
16334 mstrlcpy(midas_expt, argv[++
i],
sizeof(midas_hostname));
16335 else if (argv[
i][1] ==
'a') {
16336#ifdef HAVE_MONGOOSE6
16337 gUserAllowedHosts.push_back(argv[++
i]);
16339 user_hostlist.push_back(argv[++
i]);
16341 }
else if (argv[
i][1] ==
'p') {
16342 printf(
"Option \"-p port_number\" for the old web server is obsolete.\n");
16343 printf(
"mongoose web server is the new default, port number is set in ODB or with \"--http port_number\".\n");
16344 printf(
"To run the obsolete old web server, please use \"--oldserver\" switch.\n");
16348 printf(
"usage: %s [-h Hostname[:port]] [-e Experiment] [-v] [-D] [-a Hostname]\n\n", argv[0]);
16349 printf(
" -a add hostname to the hostlist of hosts allowed to connect to mhttpd\n");
16350 printf(
" -e experiment to connect to\n");
16351 printf(
" -h connect to midas server (mserver) on given host\n");
16352 printf(
" -v display verbose HTTP communication\n");
16353 printf(
" -D become a daemon\n");
16354 printf(
" -E only display ELog system\n");
16355 printf(
" -H only display history plots\n");
16356#ifdef HAVE_MONGOOSE6
16357 printf(
" --http port - bind to specified HTTP port (default is ODB \"/Experiment/midas http port\")\n");
16358 printf(
" --https port - bind to specified HTTP port (default is ODB \"/Experiment/midas https port\")\n");
16360 printf(
" --verbose-mg - trace mongoose web requests\n");
16361 printf(
" --trace-mg - trace mongoose events\n");
16362 printf(
" --no-trace-mg-recv - do not trace mongoose recv events\n");
16363 printf(
" --no-trace-mg-send - dop not trace mongoose send events\n");
16364#ifdef HAVE_MONGOOSE616
16365 printf(
" --no-multithread - disable mongoose multithreading\n");
16366 printf(
" --no-passwords - disable password protection\n");
16367 printf(
" --no-hostlist - disable access control host list\n");
16375 printf(
"Becoming a daemon...\n");
16381 FILE *
f = fopen(
"/var/run/mhttpd.pid",
"w");
16389 myname =
"mhttpd_history";
16417 MVOdb *odb = MakeMidasOdb(
hDB);
16425 printf(
"check_odb_records() failed, see messages and midas.log, bye!\n");
16430#ifdef HAVE_MONGOOSE6
16431 if (init_allowed_hosts() !=
SUCCESS) {
16432 printf(
"init_allowed_hosts() failed, see messages and midas.log, bye!\n");
16439 printf(
"mhttpd allowed hosts list: ");
16447 printf(
"mhttpd allowed hosts list is empty\n");
16470#ifdef HAVE_MONGOOSE6
16471 status = start_mg(user_http_port, user_https_port, socket_priviledged_port,
verbose);
16474 printf(
"could not start the mongoose web server, see messages and midas.log, bye!\n");
16480#ifdef HAVE_MONGOOSE616
16484 signal(SIGPIPE, SIG_IGN);
16500 MVOdb* o = odb->Chdir(
"WebServer",
true);
16501 status = mongoose_init(o, no_passwords, no_hostlist, user_hostlist);
16504 printf(
"Error: Could not start the mongoose web server, see messages and midas.log, bye!\n");
16512#ifdef HAVE_MONGOOSE6
16517#ifdef HAVE_MONGOOSE616
16538 mongoose_cleanup();
char * attachment_buffer[3]
size_t attachment_size[3]
std::vector< AuthEntry > passwords
std::string passwd_filename
virtual int hs_read(time_t start_time, time_t end_time, time_t interval, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int status[])=0
see hs_read(), returns HS_SUCCESS
virtual int hs_disconnect()=0
disconnect from history, returns HS_SUCCESS
virtual int hs_get_events(time_t time_from, std::vector< std::string > *pevents)=0
get list of events that exist(ed) at given time and later (value 0 means "return all events from begi...
virtual int hs_get_tags(const char *event_name, time_t time_from, std::vector< TAG > *ptags)=0
get list of history variables for given event (use event names returned by hs_get_events()) that exis...
virtual int hs_get_last_written(time_t start_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], time_t last_written[])=0
virtual int hs_clear_cache()=0
clear internal cache, returns HS_SUCCESS
void unsetparam(const char *param)
const char * getparam(const char *param)
char _param[MAX_PARAM][PARAM_LENGTH]
void setparam(const char *param, const char *value)
BOOL isparam(const char *param)
std::string xgetparam(const char *param)
void AddTrace(RequestTrace *t)
void AddTraceMTS(RequestTrace *t)
std::vector< RequestTrace * > fBuf
else strcpy(return_buffer+strlen_retbuf, str)
int return_grow(size_t len)
vsprintf(str,(char *) format, argptr)
void rread(const char *filename, int fh, int len)
void rsprintf(const char *format,...) MATTRPRINTF(2
void rmemcpy(const void *buf, int len)
void rsputs2(const char *str)
void rsputs(const char *str)
assert(strlen(str)< sizeof(str))
static bool exists(const std::string &name)
INT al_get_alarms(std::string *presult)
INT cm_yield(INT millisec)
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
INT cm_connect_client(const char *client_name, HNDLE *hConn)
INT cm_start_watchdog_thread()
INT cm_connect_experiment1(const char *host_name, const char *default_exp_name, const char *client_name, void(*func)(char *), INT odb_size, DWORD watchdog_timeout)
std::string cm_expand_env(const char *str)
int cm_exec_script(const char *odb_path_to_script)
INT cm_disconnect_experiment(void)
std::string cm_get_exptab_filename()
std::string cm_get_path()
std::string cm_get_history_path(const char *history_channel)
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
const char * cm_get_version()
std::string cm_get_experiment_name()
const char * cm_get_revision()
INT cm_exist(const char *name, BOOL bUnique)
INT el_submit(int run, const char *author, const char *type, const char *syst, const char *subject, const char *text, const char *reply_to, const char *encoding, const char *afilename1, const char *buffer1, INT buffer_size1, const char *afilename2, const char *buffer2, INT buffer_size2, const char *afilename3, const char *buffer3, INT buffer_size3, char *tag, INT tag_size)
#define CM_WRONG_PASSWORD
#define DB_STRUCT_MISMATCH
#define DB_INVALID_HANDLE
#define DB_NO_MORE_SUBKEYS
void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
gdImagePtr gdImageCreate(int sx, int sy)
void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, const char *s, int color)
void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
gdImagePtr gdImageCreateFromGif(FILE *fd)
void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, const char *s, int color)
void gdImageDestroy(gdImagePtr im)
gdFontPtr gdFontMediumBold
int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
void gdImageGif(gdImagePtr im, gdGifBuffer *buffer)
void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
void gdImageInterlace(gdImagePtr im, int interlaceArg)
void gdImageFill(gdImagePtr im, int x, int y, int color)
void gdImageColorTransparent(gdImagePtr im, int color)
void D(const char *description)
MJsonNode * mjsonrpc_decode_post_data(const char *post_data)
void P(const char *name, int mjson_type, const char *description)
MJsonNode * mjsonrpc_make_result(MJsonNode *node)
MJsonNode * mjsonrpc_get_schema()
void mjsonrpc_set_std_mutex(void *mutex)
std::string mjsonrpc_schema_to_text(const MJsonNode *schema)
void mjsonrpc_add_handler(const char *method, mjsonrpc_handler_t *handler, bool needs_locking)
void R(const char *name, int mjson_type, const char *description)
int mg_printf(struct mg_connection *, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
time_t mg_mgr_poll(struct mg_mgr *, int milli)
void mg_mgr_free(struct mg_mgr *)
char * cs_md5(char buf[33],...)
struct mg_str header_names[MG_MAX_HTTP_HEADERS]
#define MG_MAX_HTTP_HEADERS
#define MG_F_CLOSE_IMMEDIATELY
void mbuf_remove(struct mbuf *, size_t data_size)
void mg_mgr_init(struct mg_mgr *mgr, void *user_data)
void mg_send_head(struct mg_connection *n, int status_code, int64_t content_length, const char *extra_headers)
const char * mg_set_ssl(struct mg_connection *nc, const char *cert, const char *ca_cert)
void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t)
struct mg_str header_values[MG_MAX_HTTP_HEADERS]
void mg_send(struct mg_connection *, const void *buf, int len)
struct mg_connection * next
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, mg_event_handler_t handler)
struct mg_str query_string
void mg_set_protocol_http_websocket(struct mg_connection *nc)
struct mg_connection * listener
struct mg_connection * mg_bind(struct mg_mgr *, const char *, mg_event_handler_t)
int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf, size_t buf_size)
struct mg_str mg_mk_str(const char *s)
void mg_enable_multithreading(struct mg_connection *nc)
struct mg_str * mg_get_http_header(struct http_message *hm, const char *name)
struct mg_connection * mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t)
#define MG_F_SEND_AND_CLOSE
#define MG_EV_HTTP_REQUEST
std::string ss_gethostname()
INT ss_mutex_release(MUTEX_T *mutex)
time_t ss_mktime(struct tm *tms)
int ss_file_exist(const char *path)
INT ss_mutex_create(MUTEX_T **mutex, BOOL recursive)
INT recv_string(int sock, char *buffer, DWORD buffer_size, INT millisec)
std::string ss_replace_env_variables(const std::string &inputPath)
INT ss_daemon_init(BOOL keep_stdout)
INT ss_sleep(INT millisec)
char * ss_crypt(const char *buf, const char *salt)
void * ss_ctrlc_handler(void(*func)(int))
INT ss_mutex_wait_for(MUTEX_T *mutex, INT timeout)
INT cm_msg1(INT message_type, const char *filename, INT line, const char *facility, const char *routine, const char *format,...)
INT EXPRT cm_msg_facilities(STRING_LIST *list)
std::string cm_get_error(INT code)
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
INT cm_msg_retrieve2(const char *facility, time_t t, INT n_message, char **messages, int *num_messages)
void cm_msg_get_logfile(const char *fac, time_t t, std::string *filename, std::string *linkname, std::string *linktarget)
BOOL equal_ustring(const char *str1, const char *str2)
INT db_sprintfh(char *string, const void *data, INT data_size, INT idx, DWORD type)
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
INT db_find_link(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
INT db_reorder_key(HNDLE hDB, HNDLE hKey, INT idx)
std::string strcomb1(const char **list)
INT db_set_link_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
INT db_get_path(HNDLE hDB, HNDLE hKey, char *path, INT buf_size)
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
INT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, const char *path)
INT db_set_link_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
INT db_copy_xml(HNDLE hDB, HNDLE hKey, char *buffer, int *buffer_size, bool header)
INT db_scan_tree(HNDLE hDB, HNDLE hKey, INT level, INT(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
INT db_get_link(HNDLE hDB, HNDLE hKey, KEY *key)
INT EXPRT db_get_value_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int index, std::string *s, BOOL create, int create_string_length)
INT db_sprintff(char *string, const char *format, const void *data, INT data_size, INT idx, DWORD type)
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
INT db_watch(HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT db_delete(HNDLE hDB, HNDLE hKeyRoot, const char *odb_path)
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
INT db_copy_json_obsolete(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int save_keys, int follow_links, int recurse)
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_get_link_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
INT db_rename_key(HNDLE hDB, HNDLE hKey, const char *name)
INT db_get_key_time(HNDLE hDB, HNDLE hKey, DWORD *delta)
INT db_set_value_index(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT idx, DWORD type, BOOL trunc)
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT EXPRT db_resize_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int num_values, int max_string_length)
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
INT db_sscanf(const char *data_str, void *data, INT *data_size, INT i, DWORD tid)
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
INT db_create_link(HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
INT rpc_client_call(HNDLE hConn, DWORD routine_id,...)
INT rpc_register_functions(const RPC_LIST *new_list, RPC_HANDLER func)
static std::vector< RPC_LIST > rpc_list
const char * rpc_tid_name(INT id)
static std::string q(const char *s)
int hs_read_event_list(std::vector< std::string > *pevents)
int hs_find_reader_channel(HNDLE hDB, HNDLE *hKeyOut, int debug_flag)
int hs_get_history(HNDLE hDB, HNDLE hKey, int flags, int debug_flag, MidasHistoryInterface **mh)
BOOL debug
debug printouts
static void handle_event_mg(struct mg_connection *nc, int ev, void *ev_data)
static void SaveHistPlotToOdb(MVOdb *odb, const HistPlot &hp, const char *group, const char *panel)
static bool trace_mg_send
BOOL is_editable(char *eq_name, char *var_name)
const unsigned char favicon_png[]
void haxis(gdImagePtr im, gdFont *font, int col, int gcol, int x1, int y1, int width, int minor, int major, int text, int label, int grid, double xmin, double xmax)
static bool cmp_vars(const HistVar &a, const HistVar &b)
void output_key(Param *p, Return *r, HNDLE hkey, int index, const char *format)
void get_elog_url(char *url, int len)
static void DeleteHistPlotDeleted(HistPlot &hp)
static void LoadHistPlotFromParam(HistPlot *hp, Param *p)
static void add_rpc_functions()
INT check_odb_records(MVOdb *odb)
static int handle_http_post(struct mg_connection *nc, const http_message *msg, const char *uri, RequestTrace *t)
std::string get_content_type(const char *filename)
static const std::string find_header_mg(const struct http_message *msg, const char *name)
static void xmg_mkmd5resp(const char *method, size_t method_len, const char *uri, size_t uri_len, const char *ha1, size_t ha1_len, const char *nonce, size_t nonce_len, const char *nc, size_t nc_len, const char *cnonce, size_t cnonce_len, const char *qop, size_t qop_len, char *resp)
void strencode(Return *r, const char *text)
static MVOdb * gMimeTypesOdb
static const char default_type_list[20][NAME_LENGTH]
void show_eqtable_page(Param *pp, Return *r, int refresh)
static void history_watch_callback(HNDLE hDB, HNDLE hKey, int index, void *info)
void show_custom_file(Return *r, const char *name)
void show_find_page(Return *r, const char *value)
BOOL check_web_password(Return *r, HNDLE hDB, const char *dec_path, const char *password, const char *redir)
bool send_fp(Return *r, const std::string &path, FILE *fp)
std::vector< std::string > get_resource_paths()
static void SplitEventAndTagNames(std::string var_name, std::string &event_name, std::string &tag_name)
void decode_cookies(Cookies *c, const http_message *msg)
char * stristr(const char *str, const char *pattern)
void submit_elog(MVOdb *odb, Param *pp, Return *r, Attachment *a)
void show_query_page(Param *p, Return *r)
static void urlEncode(char *ps, int ps_size)
static std::string NextHistPlotColour(const HistPlot &hp)
std::string strencode2(const char *text)
void decode_get(Return *rr, char *string, const Cookies *c, const char *url, const char *query_string, RequestTrace *t)
static MJsonNode * get_http_trace(const MJsonNode *params)
void show_error(Return *r, const char *error)
static bool read_passwords(Auth *auth)
void redirect2(Return *r, const char *path)
static void show_cnaf_page(Param *p, Return *rr)
static void SaveMimetypes(MVOdb *odb)
void show_navigation_bar(Return *r, const char *cur_page)
void ctrlc_handler(int sig)
static void PrintHistPlot(const HistPlot &hp)
void javascript_commands(Param *p, Return *r, const char *cookie_cpwd)
static int handle_decode_post(struct mg_connection *nc, const http_message *msg, const char *uri, const char *query_string, RequestTrace *t)
std::string time_to_string(time_t t)
static std::string mgstr(const mg_str *s)
int vaxis(gdImagePtr im, gdFont *font, int col, int gcol, int x1, int y1, int width, int minor, int major, int text, int label, int grid, double ymin, double ymax, BOOL logaxis)
static bool mongoose_passwords_enabled(const struct mg_connection *nc)
static int cmp_names(const void *a, const void *b)
INT sendmail(const char *from_host, const char *smtp_host, const char *from, const char *to, const char *subject, const char *text)
int find_file_mg(const char *filename, std::string &path, FILE **fpp, bool trace)
void decode_query(Param *pp, const char *query_string)
static bool gDoReloadHistory
static std::string check_digest_auth(struct http_message *hm, Auth *auth)
static MidasHistoryInterface * gMh
static bool trace_mg_verbose
static bool gDoSetupHistoryWatch
int get_hist_last_written(MVOdb *odb, const char *group, const char *panel, time_t endtime, int index, int want_all, time_t *plastwritten)
void taxis(gdImagePtr im, gdFont *font, int col, int gcol, int x1, int y1, int width, int xr, int minor, int major, int text, int label, int grid, double xmin, double xmax)
void show_password_page(Return *r, const char *dec_path, const char *password)
time_t string_to_time(const char *str)
void show_header(Return *r, const char *title, const char *method, const char *path, int refresh)
bool send_resource(Return *r, const std::string &name, bool generate_404=true)
void strencode3(Return *r, const char *text)
static std::vector< std::string > gAllowedHosts
bool send_file(Return *r, const std::string &path, bool generate_404=true)
static int xmg_check_nonce(const char *nonce)
void show_text_header(Return *r)
char * find_odb_tag(char *p, char *path, char *format, int *edit, char *type, char *pwd, char *tail)
static std::string UrlDecode(const char *p)
void strencode4(Return *r, const char *text)
void show_elog_attachment(Param *p, Return *r, const char *path)
void Unlock(RequestTrace *t)
int evaluate_src(char *key, char *src, double *fvalue)
void redirect(Return *r, const char *path)
static void urlDecode(char *p)
static std::string add_param_to_url(const char *name, const char *value)
#define READ_HISTORY_DATA
bool starts_with(const std::string &s1, const char *s2)
static const char * cgif_bar_str[]
static MidasHistoryInterface * get_history(bool reset=false)
void show_odb_tag(Param *pp, Return *r, const char *path, const char *keypath1, const char *format, int n_var, int edit, char *type, char *pwd, char *tail)
static int handle_http_get(struct mg_connection *nc, const http_message *msg, const char *uri, RequestTrace *t)
#define READ_HISTORY_RUNMARKER
std::string add_custom_path(const std::string &filename)
void sec_to_label(char *result, int sec, int base, int force_date)
void show_odb_page(Param *pp, Return *r, const char *dec_path, int write_access)
void send_icon(Return *r, const char *icon)
void Lock(RequestTrace *t)
void show_set_page(Param *pp, Return *r, const char *group, int index, const char *value)
void decode_post(Return *rr, const char *header, const char *string, const char *boundary, int length, const Cookies *c, const char *url, RequestTrace *t)
void show_hist_config_page(MVOdb *odb, Param *p, Return *r, const char *hgroup, const char *hpanel)
static const std::string find_cookie_mg(const struct http_message *msg, const char *cookie_name)
void do_jrpc(Param *p, Return *r)
const unsigned char favicon_ico[]
void init_mhttpd_odb(MVOdb *odb)
void check_obsolete_odb(HNDLE hDB, const char *odb_path)
void do_jrpc_rev1(Param *p, Return *r)
static RequestTraceBuf * gTraceBuf
const char * mhttpd_revision(void)
void show_hist_page(MVOdb *odb, Param *p, Return *r, const char *dec_path, char *buffer, int *buffer_size, int refresh)
static int handle_decode_get(struct mg_connection *nc, const http_message *msg, const char *uri, const char *query_string, RequestTrace *t)
void gen_odb_attachment(Return *r, const char *path, std::string &bout)
bool open_resource_file(const char *filename, std::string *ppath, FILE **pfp)
void redirect_307(Return *r, const char *path)
static std::string GetMimetype(const std::string &ext)
static double GetTimeSec()
void show_custom_page(Param *pp, Return *r, const char *cookie_cpwd)
static MJsonNode * set_http_trace(const MJsonNode *params)
const bool cmp_tags(const TAG &a, const TAG &b)
const bool cmp_events1(const std::string &a, const std::string &b)
#define READ_HISTORY_LAST_WRITTEN
int read_history(const HistPlot &hp, int index, int flags, time_t tstart, time_t tend, time_t scale, HistoryData *data)
static std::string toString(int i)
const MimetypeTableEntry gMimetypeTable[]
int time_to_sec(const char *str)
void show_help_page(Return *r, const char *dec_path)
void do_jrpc_rev0(Param *p, Return *r)
INT search_callback(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *info)
void init_menu_buttons(MVOdb *odb)
void generate_hist_graph(MVOdb *odb, Return *rr, const char *hgroup, const char *hpanel, char *buffer, int *buffer_size, int width, int height, time_t xendtime, int scale, int index, int labels, const char *bgcolor, const char *fgcolor, const char *gridcolor)
static const char * cgif_label_str[]
time_t mktime_with_dst(const struct tm *ptms)
int try_file_mg(const char *try_dir, const char *filename, std::string &path, FILE **fpp, bool trace)
void export_hist(MVOdb *odb, Return *r, const char *group, const char *panel, time_t endtime, int scale, int index, int labels)
static void xmg_http_send_digest_auth_request(struct mg_connection *c, const char *domain)
void interprete(Param *p, Return *r, Attachment *a, const Cookies *c, const char *dec_path, RequestTrace *t)
static const char default_system_list[20][NAME_LENGTH]
static void handle_http_options_cors(struct mg_connection *nc, const http_message *msg, RequestTrace *t)
static void SortHistPlotVars(HistPlot &hp)
const bool cmp_events(const std::string &a, const std::string &b)
int xdb_get_data_index(HNDLE hDB, const char *str, void *value, int size, int index, int tid)
void show_error_404(Return *r, const char *error)
static void handle_http_message(struct mg_connection *nc, http_message *msg)
static int xdb_find_key(HNDLE hDB, HNDLE dir, const char *str, HNDLE *hKey, int tid, int size)
static void AddHistPlotSelectedParam(HistPlot &hp, Param *p)
void show_custom_gif(Return *rr, const char *name)
static void LoadHistPlotFromOdb(MVOdb *odb, HistPlot *hp, const char *group, const char *panel)
static bool trace_mg_recv
static int NextHistPlotOrder(const HistPlot &hp)
bool ends_with_char(const std::string &s, char c)
std::string msprintf(const char *format,...)
#define DIR_SEPARATOR_STR
#define DEFAULT_WATCHDOG_TIMEOUT
#define MATTRPRINTF(a, b)
#define EQUIPMENT_COMMON_STR
std::vector< std::string > STRING_LIST
#define RUNINFO_STR(_name)
#define CNAF_INHIBIT_CLEAR
MidasHistoryInterface * mh
#define write(n, a, f, d)
int mg_http_parse_header2(struct mg_str *hdr, const char *var_name, char **buf, size_t buf_size)
int gettimeofday(struct timeval *tp, void *tzp)
std::vector< HistVar > vars
void Allocate(int xnvars)
static te_expr * base(state *s)
static te_expr * list(state *s)