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, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff,
222 0x61, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59,
223 0x73, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
224 0xa0, 0x01, 0x5d, 0x7e, 0xbb, 0xa3, 0x00, 0x00,
225 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f,
226 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x00, 0x77,
227 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63,
228 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b,
229 0xee, 0x3c, 0x1a, 0x00, 0x00, 0x01, 0xab, 0x49,
230 0x44, 0x41, 0x54, 0x38, 0x8d, 0x95, 0x92, 0x3d,
231 0x68, 0x14, 0x61, 0x10, 0x86, 0x9f, 0xf9, 0x76,
232 0xef, 0x27, 0x26, 0x5b, 0x28, 0xb1, 0x31, 0x55,
233 0x0a, 0x15, 0xce, 0xbd, 0x58, 0x1c, 0x36, 0x36,
234 0x62, 0xe3, 0x1d, 0x88, 0x4a, 0x2e, 0xb9, 0x2b,
235 0x2c, 0xc4, 0x46, 0x2b, 0x5b, 0x2b, 0xd1, 0x3a,
236 0xbd, 0x85, 0x68, 0x95, 0x80, 0x8d, 0xb7, 0x47,
237 0x40, 0x21, 0xf1, 0x12, 0x41, 0x22, 0x16, 0x42,
238 0x10, 0x8b, 0xf5, 0x12, 0x4d, 0xa7, 0x58, 0xab,
239 0x88, 0x8a, 0x3f, 0x7b, 0x3b, 0x63, 0x11, 0x02,
240 0x2a, 0xb7, 0x97, 0xdc, 0xc0, 0x54, 0xf3, 0xce,
241 0xc3, 0xfb, 0x0e, 0x83, 0x99, 0x91, 0xd5, 0xd3,
242 0xcb, 0xf1, 0xa9, 0xf3, 0x0f, 0xdf, 0x06, 0x83,
243 0x34, 0x8e, 0x8c, 0xaa, 0x77, 0xba, 0x75, 0x4f,
244 0xa4, 0x9d, 0x2b, 0x24, 0xcf, 0x2f, 0x3c, 0xda,
245 0x0a, 0xb2, 0x74, 0x7d, 0x01, 0x33, 0x9d, 0x8d,
246 0x13, 0x4e, 0xb8, 0x67, 0x30, 0x8e, 0x11, 0xe6,
247 0xf2, 0xc9, 0xd3, 0xa1, 0x00, 0xde, 0xd7, 0xcd,
248 0x57, 0x18, 0x2f, 0x11, 0x7e, 0x02, 0x1f, 0x55,
249 0xdd, 0xcd, 0x2c, 0x80, 0x98, 0x59, 0xdf, 0x41,
250 0x33, 0x8a, 0x3c, 0x0d, 0x4a, 0x5d, 0x4d, 0xed,
251 0xc6, 0xe2, 0xd9, 0x70, 0x71, 0x28, 0x07, 0x00,
252 0xad, 0x46, 0x23, 0x15, 0xec, 0x81, 0x25, 0xbd,
253 0x4c, 0xfb, 0x03, 0x01, 0xdb, 0xa5, 0xf9, 0xdc,
254 0x48, 0x7e, 0xa0, 0xa6, 0x6f, 0x84, 0x66, 0xf4,
255 0x62, 0x44, 0x83, 0xe0, 0x9a, 0xc0, 0x11, 0xc5,
256 0x7c, 0x4f, 0xbc, 0x3b, 0xad, 0x6a, 0x69, 0x7d,
257 0xcf, 0x0e, 0x34, 0x08, 0xe6, 0x80, 0x95, 0xa8,
258 0x16, 0x5e, 0x19, 0x3f, 0xf8, 0xfb, 0xaa, 0xa2,
259 0x97, 0x67, 0x9f, 0xbc, 0x39, 0x3c, 0x54, 0x84,
260 0x76, 0x2d, 0x8c, 0x01, 0xee, 0x56, 0x2a, 0x89,
261 0x99, 0x74, 0xb1, 0x9e, 0xb7, 0x27, 0xc0, 0xa5,
262 0xd5, 0x78, 0x14, 0x98, 0xac, 0xaf, 0xc6, 0x21,
263 0xc0, 0xe9, 0xb5, 0x35, 0x5f, 0xc4, 0x2a, 0xa2,
264 0xb9, 0x52, 0x3f, 0xc0, 0x3f, 0x37, 0x98, 0x7d,
265 0xbc, 0x71, 0xce, 0xb0, 0xe9, 0x3c, 0xee, 0x76,
266 0x8f, 0xf4, 0x0c, 0x22, 0x13, 0x86, 0x04, 0x42,
267 0xb2, 0xa0, 0xe6, 0x97, 0x45, 0x6c, 0xd2, 0x15,
268 0xbd, 0x5b, 0xf6, 0x23, 0x39, 0x69, 0xf8, 0x85,
269 0xf2, 0xfa, 0xb1, 0x25, 0x99, 0x59, 0x7e, 0xfd,
270 0x1e, 0xcc, 0x33, 0x71, 0x22, 0xa4, 0xcf, 0xda,
271 0xb5, 0xa9, 0x8b, 0x3b, 0xc0, 0xe6, 0xca, 0xe6,
272 0x81, 0xa8, 0x5a, 0xfa, 0x6c, 0x60, 0x00, 0xcd,
273 0x4e, 0x7c, 0x54, 0x8d, 0x05, 0xc4, 0x95, 0x01,
274 0x87, 0xb0, 0xe4, 0x10, 0x53, 0x44, 0x26, 0x04,
275 0x3b, 0x84, 0xb8, 0x2f, 0x7f, 0xdb, 0x6b, 0x55,
276 0x4b, 0x9f, 0x76, 0x96, 0x01, 0x5a, 0xb5, 0xa9,
277 0x2d, 0x9c, 0x1b, 0x05, 0xf6, 0x01, 0x45, 0x8c,
278 0xe3, 0x4e, 0x4c, 0x76, 0xf9, 0x85, 0xff, 0x32,
279 0xc3, 0x3b, 0x81, 0x14, 0x50, 0x84, 0x0f, 0xbe,
280 0x39, 0x99, 0x17, 0xd3, 0xfd, 0xdb, 0x43, 0xbd,
281 0xbf, 0x1b, 0x60, 0xac, 0x30, 0xd6, 0xf8, 0xf6,
282 0xeb, 0xfb, 0x75, 0x55, 0x2b, 0xf8, 0x45, 0x37,
283 0xf7, 0x07, 0x3b, 0x67, 0xc6, 0x0c, 0xa4, 0x18,
284 0xfd, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
285 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
289 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10,
290 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xe4, 0x01,
291 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x89, 0x50,
292 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00,
293 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00,
294 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06,
295 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00,
296 0x00, 0x01, 0xab, 0x49, 0x44, 0x41, 0x54, 0x78,
297 0x9c, 0x95, 0x92, 0x3d, 0x68, 0x14, 0x61, 0x10,
298 0x86, 0x9f, 0xf9, 0x76, 0xef, 0x27, 0x26, 0x5b,
299 0x28, 0xb1, 0x31, 0x55, 0x0a, 0x15, 0xce, 0xbd,
300 0x58, 0x1c, 0x36, 0x36, 0x62, 0xe3, 0x1d, 0x88,
301 0x4a, 0x2e, 0xb9, 0x2b, 0x2c, 0xc4, 0x46, 0x2b,
302 0x5b, 0x2b, 0xd1, 0x3a, 0xbd, 0x85, 0x68, 0x95,
303 0x80, 0x8d, 0xb7, 0x47, 0x40, 0x21, 0xf1, 0x12,
304 0x41, 0x22, 0x16, 0x42, 0x10, 0x8b, 0xf5, 0x12,
305 0x4d, 0xa7, 0x58, 0xab, 0x88, 0x8a, 0x3f, 0x7b,
306 0x3b, 0x63, 0x11, 0x02, 0x2a, 0xb7, 0x97, 0xdc,
307 0xc0, 0x54, 0xf3, 0xce, 0xc3, 0xfb, 0x0e, 0x83,
308 0x99, 0x91, 0xd5, 0xd3, 0xcb, 0xf1, 0xa9, 0xf3,
309 0x0f, 0xdf, 0x06, 0x83, 0x34, 0x8e, 0x8c, 0xaa,
310 0x77, 0xba, 0x75, 0x4f, 0xa4, 0x9d, 0x2b, 0x24,
311 0xcf, 0x2f, 0x3c, 0xda, 0x0a, 0xb2, 0x74, 0x7d,
312 0x01, 0x33, 0x9d, 0x8d, 0x13, 0x4e, 0xb8, 0x67,
313 0x30, 0x8e, 0x11, 0xe6, 0xf2, 0xc9, 0xd3, 0xa1,
314 0x00, 0xde, 0xd7, 0xcd, 0x57, 0x18, 0x2f, 0x11,
315 0x7e, 0x02, 0x1f, 0x55, 0xdd, 0xcd, 0x2c, 0x80,
316 0x98, 0x59, 0xdf, 0x41, 0x33, 0x8a, 0x3c, 0x0d,
317 0x4a, 0x5d, 0x4d, 0xed, 0xc6, 0xe2, 0xd9, 0x70,
318 0x71, 0x28, 0x07, 0x00, 0xad, 0x46, 0x23, 0x15,
319 0xec, 0x81, 0x25, 0xbd, 0x4c, 0xfb, 0x03, 0x01,
320 0xdb, 0xa5, 0xf9, 0xdc, 0x48, 0x7e, 0xa0, 0xa6,
321 0x6f, 0x84, 0x66, 0xf4, 0x62, 0x44, 0x83, 0xe0,
322 0x9a, 0xc0, 0x11, 0xc5, 0x7c, 0x4f, 0xbc, 0x3b,
323 0xad, 0x6a, 0x69, 0x7d, 0xcf, 0x0e, 0x34, 0x08,
324 0xe6, 0x80, 0x95, 0xa8, 0x16, 0x5e, 0x19, 0x3f,
325 0xf8, 0xfb, 0xaa, 0xa2, 0x97, 0x67, 0x9f, 0xbc,
326 0x39, 0x3c, 0x54, 0x84, 0x76, 0x2d, 0x8c, 0x01,
327 0xee, 0x56, 0x2a, 0x89, 0x99, 0x74, 0xb1, 0x9e,
328 0xb7, 0x27, 0xc0, 0xa5, 0xd5, 0x78, 0x14, 0x98,
329 0xac, 0xaf, 0xc6, 0x21, 0xc0, 0xe9, 0xb5, 0x35,
330 0x5f, 0xc4, 0x2a, 0xa2, 0xb9, 0x52, 0x3f, 0xc0,
331 0x3f, 0x37, 0x98, 0x7d, 0xbc, 0x71, 0xce, 0xb0,
332 0xe9, 0x3c, 0xee, 0x76, 0x8f, 0xf4, 0x0c, 0x22,
333 0x13, 0x86, 0x04, 0x42, 0xb2, 0xa0, 0xe6, 0x97,
334 0x45, 0x6c, 0xd2, 0x15, 0xbd, 0x5b, 0xf6, 0x23,
335 0x39, 0x69, 0xf8, 0x85, 0xf2, 0xfa, 0xb1, 0x25,
336 0x99, 0x59, 0x7e, 0xfd, 0x1e, 0xcc, 0x33, 0x71,
337 0x22, 0xa4, 0xcf, 0xda, 0xb5, 0xa9, 0x8b, 0x3b,
338 0xc0, 0xe6, 0xca, 0xe6, 0x81, 0xa8, 0x5a, 0xfa,
339 0x6c, 0x60, 0x00, 0xcd, 0x4e, 0x7c, 0x54, 0x8d,
340 0x05, 0xc4, 0x95, 0x01, 0x87, 0xb0, 0xe4, 0x10,
341 0x53, 0x44, 0x26, 0x04, 0x3b, 0x84, 0xb8, 0x2f,
342 0x7f, 0xdb, 0x6b, 0x55, 0x4b, 0x9f, 0x76, 0x96,
343 0x01, 0x5a, 0xb5, 0xa9, 0x2d, 0x9c, 0x1b, 0x05,
344 0xf6, 0x01, 0x45, 0x8c, 0xe3, 0x4e, 0x4c, 0x76,
345 0xf9, 0x85, 0xff, 0x32, 0xc3, 0x3b, 0x81, 0x14,
346 0x50, 0x84, 0x0f, 0xbe, 0x39, 0x99, 0x17, 0xd3,
347 0xfd, 0xdb, 0x43, 0xbd, 0xbf, 0x1b, 0x60, 0xac,
348 0x30, 0xd6, 0xf8, 0xf6, 0xeb, 0xfb, 0x75, 0x55,
349 0x2b, 0xf8, 0x45, 0x37, 0xf7, 0x07, 0x3b, 0x67,
350 0xc6, 0x0c, 0xb9, 0x56, 0xe3, 0x39, 0x00, 0x00,
351 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
361 int minor,
int major,
int text,
int label,
int grid,
double ymin,
double ymax,
364 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax);
366void show_header(
Return* r,
const char *title,
const char *method,
const char *path,
int refresh);
373 char c1, c2, *ps, *pp;
375 if (
str == NULL || pattern == NULL)
380 pp = (
char *) pattern;
383 if (toupper(c1) == toupper(c2)) {
388 if (toupper(c1) != toupper(c2))
410 return tv.tv_sec*1.0 +
tv.tv_usec/1000000.0;
456 printf(
"M %s ",
fMethod.c_str());
457 printf(
"URL %s ",
fUri.c_str());
458 if (
fRPC.length() > 0) {
459 printf(
"RPC %s ",
fRPC.c_str());
471 std::vector<RequestTrace*>
fBuf;
507 for (
unsigned i=0;
i<
fBuf.size();
i++) {
516 for (
unsigned i=0;
i<
fBuf.size();
i++) {
518 if (
fBuf[
k] != NULL) {
520 if (
fBuf[
k] == NULL) {
527 if (
fBuf[
k] == NULL) {
541#define WEB_BUFFER_SIZE (6*1024*1024)
590 for (
int i=0;
i<1000;
i++) {
602 assert(!
"Cannot happen!");
618void rread(
const char* filename,
int fh,
int len)
623 cm_msg(
MERROR,
"rread",
"Cannot read file \'%s\', read of %d returned %d, errno %d (%s)", filename, len, rd, errno, strerror(errno));
634 size_t len = strlen(
str);
653 size_t len = strlen(
str);
662 for (
size_t i = 0;
i < len;
i++) {
663 if (strncmp(
str +
i,
"http://", 7) == 0) {
666 char* p = (
char *) (
str +
i + 7);
669 for (
k = 0; *p && *p !=
' ' && *p !=
'\n';
k++,
i++)
673 sprintf(
return_buffer +
j,
"<a href=\"http://%s\">http://%s</a>", link, link);
728#define PARAM_LENGTH 256
729#define TEXT_SIZE 50000
762 printf(
"Error: parameter value too big\n");
776 int size = strlen(
value)+1;
777 _value[
i] = (
char*)malloc(size);
782 printf(
"Error: parameter array too small\n");
886 if (isxdigit(p[0]) && isxdigit(p[1])) {
892 sscanf(
str,
"%02X", &
i);
898 }
else if (*p ==
'+') {
928 if (isxdigit(p[0]) && isxdigit(p[1])) {
932 sscanf(
str,
"%02X", &
i);
938 }
else if (*p ==
'+') {
958 int len = strlen(ps);
959 char *
str = (
char*)malloc(len*3 + 10);
967 sprintf(pd,
"%%%02X", (*p)&0xFF);
975 printf(
"urlEncode [");
976 for (p=ps; *p!=0; p++)
977 printf(
"0x%02x ", (*p)&0xFF);
980 printf(
"urlEncode [%s] -> [%s]\n", ps,
str);
983 mstrlcpy(ps,
str, ps_size);
995 const char* p = text;
1001 sprintf(buf,
"%%%02X", (*p)&0xFF);
1008 printf(
"urlEncode [");
1009 for (p=text; *p!=0; p++)
1010 printf(
"0x%02x ", (*p)&0xFF);
1013 printf(
"urlEncode [%s] -> [%s]\n", text, encoded.c_str());
1028 std::vector<std::string> paths;
1034 paths.push_back(buf);
1042 paths.push_back(buf);
1046 paths.push_back(cwd +
"/");
1047 paths.push_back(cwd +
"/resources/");
1051 char *m = getenv(
"MIDASSYS");
1053 paths.push_back(std::string(m) +
"/resources/");
1067 if (strlen(filename) < 1) {
1068 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' is too short",
1074 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' starting with \'%c\' which is not allowed",
1079 if (strstr(filename,
"..") != NULL) {
1080 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' containing \'..\' which is not allowed",
1087 std::vector<std::string> paths_not_found;
1089 for (
unsigned i=0;
i<paths.size();
i++) {
1090 std::string path = paths[
i];
1091 if (path.length() < 1)
1109 FILE*
fp = fopen(xpath.c_str(),
"r");
1111 struct stat statbuf;
1112 int status = fstat(fileno(
fp), &statbuf);
1114 cm_msg(
MERROR,
"open_resource_file",
"Cannot fstat() file \'%s\', error %d (%s)", xpath.c_str(), errno, strerror(errno));
1119 if (statbuf.st_mode & S_IFREG) {
1125 }
else if (statbuf.st_mode & S_IFDIR) {
1126 cm_msg(
MERROR,
"open_resource_file",
"File \'%s\' for resource \'%s\' is a directory", xpath.c_str(), filename);
1130 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);
1149 paths_not_found.push_back(xpath);
1153 for (
unsigned i=0;
i<paths_not_found.size();
i++) {
1156 s += paths_not_found[
i];
1159 cm_msg(
MERROR,
"open_resource_file",
"Cannot find resource file \'%s\', tried %s", filename, s.c_str());
1167 std::string ext_upper;
1168 const char* p = filename;
1169 const char* last_dot = NULL;
1180 ext_upper += toupper(*p);
1186 if (
type.length() > 0)
1189 cm_msg(
MERROR,
"get_content_type",
"Unknown HTTP Content-Type for resource file \'%s\', file extension \'%s\'", filename, ext_upper.c_str());
1191 return "text/plain";
1202 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1204 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
1208 time_t now = time(NULL);
1209 now += (int) (3600 * 24);
1211 gmtime_r(&now, &gmt_tms);
1212 const char* format =
"%A, %d-%b-%y %H:%M:%S GMT";
1215 strftime(
str,
sizeof(
str), format, &gmt_tms);
1224 struct stat stat_buf;
1225 fstat(fileno(
fp), &stat_buf);
1226 int length = stat_buf.st_size;
1227 r->
rsprintf(
"Content-Length: %d\r\n", length);
1235 r->
rread(path.c_str(), fileno(
fp), length);
1244 FILE *
fp = fopen(path.c_str(),
"rb");
1249 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1253 r->
rsprintf(
"Error: Cannot read \"%s\", fopen() errno %d (%s)\n", path.c_str(), errno, strerror(errno));
1271 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1275 r->
rsprintf(
"Error: resource file \"%s\" not found, see messages\n",
name.c_str());
1285INT sendmail(
const char* from_host,
const char *smtp_host,
const char *from,
const char *to,
const char *subject,
const char *text)
1287 struct sockaddr_in bind_addr;
1288 struct hostent *phe;
1290 char *
str, buf[256];
1293 printf(
"\n\nEmail from %s to %s, SMTP host %s:\n", from, to, smtp_host);
1296 s =
socket(AF_INET, SOCK_STREAM, 0);
1301 memset(&bind_addr, 0,
sizeof(bind_addr));
1302 bind_addr.sin_family = AF_INET;
1303 bind_addr.sin_port = htons((
short) 25);
1305 phe = gethostbyname(smtp_host);
1308 memcpy((
char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
1310 if (connect(s, (
const sockaddr*)&bind_addr,
sizeof(bind_addr)) < 0) {
1316 str = (
char*)malloc(strsize);
1318 assert(
str != NULL);
1332 sprintf(
str,
"HELO %s\r\n", from_host);
1333 send(s,
str, strlen(
str), 0);
1340 if (strchr(from,
'<')) {
1341 mstrlcpy(buf, strchr(from,
'<') + 1,
sizeof(buf));
1342 if (strchr(buf,
'>'))
1343 *strchr(buf,
'>') = 0;
1345 mstrlcpy(buf, from,
sizeof(buf));
1347 sprintf(
str,
"MAIL FROM: %s\n", buf);
1348 send(s,
str, strlen(
str), 0);
1355 sprintf(
str,
"RCPT TO: <%s>\r\n", to);
1356 send(s,
str, strlen(
str), 0);
1363 sprintf(
str,
"DATA\r\n");
1364 send(s,
str, strlen(
str), 0);
1371 sprintf(
str,
"To: %s\r\nFrom: %s\r\nSubject: %s\r\n", to, from, subject);
1372 send(s,
str, strlen(
str), 0);
1377 send(s,
str, strlen(
str), 0);
1385 localtime_r(&now, &tms);
1386 strftime(buf,
sizeof(buf),
"%a, %d %b %Y %H:%M:%S", &tms);
1387 offset = (-(int) timezone);
1390 sprintf(
str,
"Date: %s %+03d%02d\r\n", buf, (
int) (
offset / 3600),
1391 (
int) ((abs((
int)
offset) / 60) % 60));
1392 send(s,
str, strlen(
str), 0);
1396 sprintf(
str,
"Content-Type: TEXT/PLAIN; charset=US-ASCII\r\n\r\n");
1397 send(s,
str, strlen(
str), 0);
1402 const char* p = text;
1404 while (strstr(p,
"\r\n.\r\n")) {
1406 mstrlcat(
str, p,
i);
1408 mstrlcat(
str,
"\r\n..\r\n", strsize);
1410 mstrlcat(
str, p, strsize);
1411 mstrlcat(
str,
"\r\n", strsize);
1412 send(s,
str, strlen(
str), 0);
1417 sprintf(
str,
".\r\n");
1418 send(s,
str, strlen(
str), 0);
1425 sprintf(
str,
"QUIT\n");
1426 send(s,
str, strlen(
str), 0);
1447 mstrlcpy(
str, path,
sizeof(
str));
1452 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
1456 if (strncmp(path,
"http:", 5) == 0)
1457 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1458 else if (strncmp(path,
"https:", 6) == 0)
1459 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1461 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1470 r->
rsprintf(
"HTTP/1.1 307 Temporary Redirect\r\n");
1473 r->
rsprintf(
"Location: %s\r\n", path);
1475 r->
rsprintf(
"<html>redirect to %s</html>\r\n", path);
1508 for (
i = 0; search_name[
i] ;
i++)
1509 str2[
i] = toupper(search_name[
i]);
1512 if (strstr(xstr1, str2) != NULL) {
1515 std::string path_encoded =
urlEncode(path.c_str());
1519 r->
rsprintf(
"<tr><td class=\"ODBkey\"><a href=\"?cmd=odb&odb_path=/%s\">/%s</a></tr>\n", path_encoded.c_str(), path.c_str());
1522 char* p =
const_cast<char *
>(path.data() + path.length() - 1);
1523 while (*p && *p !=
'/')
1530 size =
sizeof(
data);
1532 std::string data_str;
1534 data_str =
"<no read access>";
1538 r->
rsprintf(
"<tr><td class=\"ODBkey\">");
1539 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=/%s\">/%s/%s</a></td>", path_encoded.c_str(), path.c_str(),
key->
name);
1540 r->
rsprintf(
"<td class=\"ODBvalue\">%s</td></tr>\n", data_str.c_str());
1546 r->
rsprintf(
"<tr><td rowspan=%d class=\"ODBkey\">",
i);
1547 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=/%s\">/%s/%s\n", path_encoded.c_str(), path.c_str(),
key->
name);
1550 size =
sizeof(
data);
1558 r->
rsprintf(
"<td class=\"ODBvalue\">[%d] %s</td></tr>\n",
i, data_str.c_str());
1581 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
1582 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
1585 r->
rsprintf(
"<table class=\"mtable\" style=\"width: 95%%\">\n");
1587 r->
rsprintf(
" <td class=\"mtableheader\">MIDAS Help Page</td>\n");
1594 r->
rsprintf(
" <td style=\"text-align:right;\">Documentation:</td>\n");
1595 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://midas.triumf.ca\">https://midas.triumf.ca</a></td>\n");
1598 r->
rsprintf(
" <td style=\"text-align:right;\">Discussion Forum:</td>\n");
1599 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://midas.triumf.ca/forum/\">https://midas.triumf.ca/forum/</a></td>\n");
1602 r->
rsprintf(
" <td style=\"text-align:right;\">Code:</td>\n");
1603 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://bitbucket.org/tmidas/midas/\">https://bitbucket.org/tmidas/midas/</a></td>\n");
1606 r->
rsprintf(
" <td style=\"text-align:right;\">Report a bug:</td>\n");
1607 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://bitbucket.org/tmidas/midas/issues/\">https://bitbucket.org/tmidas/midas/issues/</a></td>\n");
1611 r->
rsprintf(
" <td style=\"text-align:right;\">Version:</td>\n");
1615 r->
rsprintf(
" <td style=\"text-align:right;\">Revision:</td>\n");
1617 std::string url =
"https://bitbucket.org/tmidas/midas/commits/";
1623 std::string::size_type pos = rev.find(
"-g");
1624 if (pos != std::string::npos) {
1625 std::string hash = rev.substr(pos+2);
1626 pos = hash.find(
"-dirty");
1627 if (pos != std::string::npos) {
1628 hash = hash.substr(0, pos);
1630 pos = hash.find(
" ");
1631 if (pos != std::string::npos) {
1632 hash = hash.substr(0, pos);
1635 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"%s\">%s</a></td>\n", url.c_str(), rev.c_str());
1637 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", rev.c_str());
1642 r->
rsprintf(
" <td style=\"text-align:right;\">MIDASSYS:</td>\n");
1643 s = getenv(
"MIDASSYS");
1644 if (!s) s =
"(unset)";
1645 mstrlcpy(
str, s,
sizeof(
str));
1646 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n",
str);
1650 r->
rsprintf(
" <td style=\"text-align:right;\">mhttpd current directory:</td>\n");
1652 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", cwd.c_str());
1656 r->
rsprintf(
" <td style=\"text-align:right;\">Exptab file:</td>\n");
1661 r->
rsprintf(
" <td style=\"text-align:right;\">Experiment:</td>\n");
1666 r->
rsprintf(
" <td style=\"text-align:right;\">Experiment directory:</td>\n");
1674 if (
list.size() == 1) {
1676 r->
rsprintf(
" <td style=\"text-align:right;\">System logfile:</td>\n");
1679 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", s.c_str());
1683 r->
rsprintf(
" <td style=\"text-align:right;\">Logfiles:</td>\n");
1684 r->
rsprintf(
" <td style=\"text-align:left;\">\n");
1685 for (
unsigned i=0 ;
i<
list.size() ;
i++) {
1698 r->
rsprintf(
" <td style=\"text-align:right;\">Image history:</td>\n");
1703 r->
rsprintf(
" <td style=\"text-align:right;\">Resource paths:</td>\n");
1704 r->
rsprintf(
" <td style=\"text-align:left;\">");
1706 for (
unsigned i=0;
i<resource_paths.size();
i++) {
1709 r->
rsputs(resource_paths[
i].c_str());
1712 if (exp != resource_paths[
i]) {
1724 r->
rsprintf(
" <td style=\"text-align:right;\">midas.css:</td>\n");
1726 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1728 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1732 r->
rsprintf(
" <td style=\"text-align:right;\">midas.js:</td>\n");
1734 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1736 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1740 r->
rsprintf(
" <td style=\"text-align:right;\">controls.js:</td>\n");
1742 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1744 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1748 r->
rsprintf(
" <td style=\"text-align:right;\">mhttpd.js:</td>\n");
1750 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1752 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1756 r->
rsprintf(
" <td style=\"text-align:right;\">obsolete.js:</td>\n");
1758 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1760 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1764 r->
rsprintf(
" <td style=\"text-align:right;\">Obsolete mhttpd.css:</td>\n");
1766 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1768 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1772 r->
rsprintf(
" <td style=\"text-align:right;\">JSON-RPC schema:</td>\n");
1773 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");
1777 r->
rsprintf(
" <td style=\"text-align:right;\">JavaScript examples:</td>\n");
1778 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=example\">example.html</a></td>\n");
1782 r->
rsprintf(
" <td style=\"text-align:right;\">Custom page example:</td>\n");
1783 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=custom_example\">custom_example.html</a></td>\n");
1791 r->
rsprintf(
"<table class=\"mtable\" style=\"width: 95%%\">\n");
1793 r->
rsprintf(
" <td class=\"mtableheader\">Contributions</td>\n");
1797 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");
1817 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1819 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
1820 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
1823 r->
rsprintf(
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n");
1827 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
1828 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
1829 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
1833 r->
rsprintf(
"<meta http-equiv=\"Refresh\" content=\"%02d\">\n", refresh);
1835 r->
rsprintf(
"<title>%s</title></head>\n", title);
1837 mstrlcpy(
str, path,
sizeof(
str));
1842 (
"<body><form name=\"form1\" method=\"POST\" action=\"%s\" enctype=\"multipart/form-data\">\n\n",
1845 r->
rsprintf(
"<body><form name=\"form1\" method=\"GET\" action=\"%s\">\n\n",
str);
1849 std::string exptname;
1858 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1860 r->
rsprintf(
"Access-Control-Allow-Origin: *\r\n");
1861 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
1862 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
1871 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1876 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
1877 r->
rsprintf(
"<title>MIDAS error</title></head>\n");
1878 r->
rsprintf(
"<body><H1>%s</H1></body></html>\n", error);
1886 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1888 r->
rsprintf(
"Content-Type: text/plain\r\n");
1891 r->
rsprintf(
"MIDAS error: %s\n", error);
1899 r->
rsprintf(
"window.addEventListener(\"load\", function(e) { mhttpd_init('%s', 1000); });\n", cur_page);
1902 r->
rsprintf(
"<!-- header and side navigation will be filled in mhttpd_init -->\n");
1903 r->
rsprintf(
"<div id=\"mheader\"></div>\n");
1904 r->
rsprintf(
"<div id=\"msidenav\"></div>\n");
1905 r->
rsprintf(
"<div id=\"mmain\">\n");
1915 cm_msg(
MERROR,
"check_obsolete_odb",
"ODB \"%s\" is obsolete, please delete it.", odb_path);
1924 int size =
sizeof(true_value);
1970 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/Base URL\" is obsolete, please delete it.");
1975 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/CSS File\" is obsolete, please delete it.");
1980 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/JS File\" is obsolete, please delete it.");
1985 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/Start-Stop Buttons\" is obsolete, please delete it.");
1988 bool xdefault =
true;
1989 odb->RB(
"Experiment/Pause-Resume Buttons", &xdefault,
true);
1991#ifdef HAVE_MONGOOSE616
2000 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.");
2016 std::string external_elog_url;
2018 size =
sizeof(external_elog);
2024 size =
sizeof(
BOOL);
2030 const char def_button[][
NAME_LENGTH] = {
"8h",
"24h",
"7d" };
2051 size_t len = strlen(text);
2052 for (
size_t i = 0;
i < len;
i++) {
2080 size_t len = strlen(text);
2081 for (
size_t i = 0;
i < len;
i++) {
2110 size_t len = strlen(text);
2111 for (
size_t i = 0;
i < len;
i++) {
2135 size_t len = strlen(text);
2136 for (
size_t i = 0;
i < len;
i++) {
2182 bout +=
"<table border=3 cellpadding=1 class=\"dialogTable\">\n";
2184 ctime_r(&now, ctimebuf);
2185 bout +=
msprintf(
"<tr><th colspan=2>%s</tr>\n", ctimebuf);
2186 bout +=
msprintf(
"<tr><th colspan=2>%s</tr>\n", path);
2207 size =
sizeof(
data);
2213 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2214 data_str =
"(empty)";
2218 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
2222 bout +=
"</td><td>";
2226 bout +=
")</td></tr>\n";
2230 bout +=
"</td></tr>\n";
2237 size =
sizeof(
data);
2242 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2243 data_str =
"(empty)";
2251 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
2259 bout +=
")<br></td></tr>\n";
2266 bout +=
"<br></td></tr>\n";
2273 bout +=
"</table>\n";
2280 char path[256], path1[256];
2281 char mail_to[256], mail_from[256], mail_list[256],
2282 smtp_host[256], tag[80], mail_param[1000];
2285 char att_file[3][256];
2286 int fh, size, n_mail;
2287 char mhttpd_full_url[256];
2290 mstrlcpy(att_file[0], pp->
getparam(
"attachment0"),
sizeof(att_file[0]));
2291 mstrlcpy(att_file[1], pp->
getparam(
"attachment1"),
sizeof(att_file[1]));
2292 mstrlcpy(att_file[2], pp->
getparam(
"attachment2"),
sizeof(att_file[2]));
2295 for (
int i = 0;
i < 3;
i++) {
2297 sprintf(
str,
"attachment%d",
i);
2302 mstrlcpy(path1, path,
sizeof(path1));
2303 while (strchr(path,
'\\'))
2304 *strchr(path,
'\\') =
'/';
2310 int bufsize = bout.length()+1;
2311 char* buf = (
char*)
M_MALLOC(bufsize);
2312 memcpy(buf, bout.c_str(), bufsize);
2313 mstrlcpy(att_file[
i], path,
sizeof(att_file[0]));
2314 mstrlcat(att_file[
i],
".html",
sizeof(att_file[0]));
2319 else if ((fh = open(path1, O_RDONLY |
O_BINARY)) >= 0) {
2320 size = lseek(fh, 0, SEEK_END);
2322 lseek(fh, 0, SEEK_SET);
2323 int rd =
read(fh, buf, size);
2327 mstrlcpy(att_file[
i], path,
sizeof(att_file[0]));
2330 }
else if (strncmp(path,
"/HS/", 4) == 0) {
2331 char* buf = (
char*)
M_MALLOC(100000);
2333 mstrlcpy(
str, path + 4,
sizeof(
str));
2334 if (strchr(
str,
'?')) {
2335 p = strchr(
str,
'?') + 1;
2347 p = strtok(NULL,
"&");
2350 *strchr(
str,
'?') = 0;
2353 mstrlcpy(att_file[
i],
str,
sizeof(att_file[0]));
2361 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
2366 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
2367 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
2368 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
2369 r->
rsprintf(
"<title>ELog Error</title></head>\n");
2370 r->
rsprintf(
"<i>Error: Attachment file <i>%s</i> not valid.</i><p>\n", pp->
getparam(
str));
2371 r->
rsprintf(
"Please go back and enter a proper filename (use the <b>Browse</b> button).\n");
2372 r->
rsprintf(
"<body></body></html>\n");
2378 int edit = atoi(pp->
getparam(
"edit"));
2383 mstrlcpy(tag, pp->
getparam(
"orig"),
sizeof(tag));
2393 *pp->
getparam(
"html") ?
"HTML" :
"plain",
2406 std::string elog_host_name;
2413 sprintf(mhttpd_full_url,
"http://%s/", elog_host_name.c_str());
2421 str +=
"/Elog/Email ";
2428 size =
sizeof(mail_list);
2432 show_error(r,
"No SMTP host defined under /Elog/SMTP host");
2435 size =
sizeof(smtp_host);
2438 p = strtok(mail_list,
",");
2440 mstrlcpy(mail_to, p,
sizeof(mail_to));
2442 std::string exptname;
2445 sprintf(mail_from,
"MIDAS %s <MIDAS@%s>", exptname.c_str(), elog_host_name.c_str());
2447 std::string mail_text;
2448 mail_text +=
"A new entry has been submitted by ";
2449 mail_text += pp->
getparam(
"author");
2453 mail_text +=
"Experiment : ";
2454 mail_text += exptname.c_str();
2457 mail_text +=
"Type : ";
2461 mail_text +=
"System : ";
2462 mail_text += pp->
getparam(
"system");
2465 mail_text +=
"Subject : ";
2466 mail_text += pp->
getparam(
"subject");
2469 mail_text +=
"Link : ";
2470 mail_text += mhttpd_full_url;
2471 mail_text +=
"/EL/";
2480 sendmail(elog_host_name.c_str(), smtp_host, mail_from, mail_to, pp->
getparam(
"type"), mail_text.c_str());
2482 if (mail_param[0] == 0)
2483 mstrlcpy(mail_param,
"?",
sizeof(mail_param));
2485 mstrlcat(mail_param,
"&",
sizeof(mail_param));
2486 sprintf(mail_param + strlen(mail_param),
"mail%d=%s", n_mail++, mail_to);
2488 p = strtok(NULL,
",");
2497 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
2506 r->
rsprintf(
"Location: ?cmd=Show+elog&tag=%s&%s\n\n<html>redir</html>\r\n", tag, mail_param + 1);
2508 r->
rsprintf(
"Location: ?cmd=Show+elog&tag=%s\n\n<html>redir</html>\r\n", tag);
2538 lseek(fh, 0, SEEK_END);
2539 int length =
TELL(fh);
2540 lseek(fh, 0, SEEK_SET);
2542 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
2544 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
2549 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
2569 sprintf(
str,
"/Equipment/%s/Settings/Editable", eq_name);
2591 int i,
j,
k, colspan, size, n_var, i_edit, i_set, line;
2592 char eq_name[32], group[32];
2602 i_edit = atoi(pp->
getparam(
"index"));
2607 i_set = atoi(pp->
getparam(
"index"));
2611 mstrlcpy(eq_name, pp->
getparam(
"eq"),
sizeof(eq_name));
2612 mstrlcpy(group,
"All",
sizeof(group));
2614 mstrlcpy(group, pp->
getparam(
"group"),
sizeof(group));
2619 sprintf(
str,
"/Equipment/%s/Settings", eq_name);
2622 HNDLE hkeynames = 0;
2633 if (strncmp(
key.
name,
"Names", 5) == 0)
2639 if (!hkeyset || !hkeynames) {
2641 sprintf(
str,
"?cmd=odb&odb_path=/Equipment/%s/Variables", eq_name);
2648 show_header(r,
"MIDAS slow control",
"", group, i_edit == -1 ? refresh : 0);
2649 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
2650 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
2651 r->
rsprintf(
"<script type=\"text/javascript\" src=\"obsolete.js\"></script>\n");
2656 r->
rsprintf(
"<tr><td colspan=15>\n");
2659 r->
rsprintf(
"<input type=submit name=cmd value=Set>\n");
2664 r->
rsprintf(
"<table class=\"ODBtable\" style=\"max-width:700px;\">");
2668 r->
rsprintf(
"<tr><td class=\"subStatusTitle\" colspan=15><i>Equipment:</i> \n");
2696 if (strncmp(
key.
name,
"Names", 5) == 0) {
2717 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names", eq_name);
2724 r->
rsprintf(
"<tr><td colspan=15><i>Groups:</i> ");
2728 r->
rsprintf(
"<b>All</b> ");
2730 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s\">All</a> ",
urlEncode(eq_name).c_str());
2734 memset(group_name, 0,
sizeof(group_name));
2738 for (
int level = 0; ; level++) {
2739 bool next_level =
false;
2742 size =
sizeof(name_str);
2745 char *s = strchr(name_str,
'%');
2746 for (
int k=0; s &&
k<level;
k++)
2747 s = strchr(s+1,
'%');
2751 if (strchr(s+1,
'%'))
2761 mstrlcpy(group_name[
j], name_str,
sizeof(group_name[0]));
2771 r->
rsprintf(
"<b>%s</b> ", group_name[
i]);
2773 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]);
2777 r->
rsprintf(
"<i>ODB:</i> ");
2778 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Common\">Common</a> ",
urlEncode(eq_name).c_str());
2779 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Settings\">Settings</a> ",
urlEncode(eq_name).c_str());
2780 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Variables\">Variables</a> ",
urlEncode(eq_name).c_str());
2784 std::string vars_path =
msprintf(
"/Equipment/%s/Variables", eq_name);
2798 if (
i == 0 ||
i > 15) {
2805 r->
rsprintf(
"<tr class=\"subStatusTitle\"><th colspan=%d>Names", colspan);
2808 for (
int i = 0;;
i++) {
2823 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names", eq_name);
2832 for (
int i = 0;
i < num_values;
i++) {
2833 char names_str[256];
2834 size =
sizeof(names_str);
2838 mstrlcpy(
name, names_str,
sizeof(
name));
2844 char *s = strstr(
name, group);
2847 if (
name[strlen(group)] !=
'%')
2851 if (strlen(
name) < 1)
2852 sprintf(
name,
"[%d]",
i);
2855 r->
rsprintf(
"<tr class=\"ODBtableEven\"><td colspan=%d><nobr>%s</nobr>", colspan,
name);
2857 r->
rsprintf(
"<tr class=\"ODBtableOdd\"><td colspan=%d><nobr>%s</nobr>", colspan,
name);
2859 for (
int j = 0;;
j++) {
2872 size =
sizeof(
data);
2877 if (n_var == i_set) {
2889 if (n_var == i_edit) {
2891 r->
rsprintf(
"<input type=text size=10 maxlenth=80 name=value value=\"%s\">\n", data_str.c_str());
2892 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set>\n");
2893 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", i_edit);
2896 sprintf(odb_path,
"Equipment/%s/Variables/%s[%d]", eq_name, varkey.
name,
i);
2898 r->
rsprintf(
"<a href=\"#\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\', 0);return false;\" >%s</a>", odb_path, data_str.c_str());
2902 r->
rsprintf(
"<td align=center>%s", data_str.c_str());
2909 r->
rsprintf(
"<tr><td colspan=15><i>Groups:</i> ");
2913 r->
rsprintf(
"<b>All</b> ");
2915 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s\">All</a> ", eq_name);
2919 std::string vars_path =
msprintf(
"/Equipment/%s/Variables", eq_name);
2924 for (
int i = 0;;
i++) {
2942 r->
rsprintf(
"<i>ODB:</i> ");
2943 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Common\">Common</a> ",
urlEncode(eq_name).c_str());
2944 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Settings\">Settings</a> ",
urlEncode(eq_name).c_str());
2945 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Variables\">Variables</a> ",
urlEncode(eq_name).c_str());
2955 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
2957 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
2969 r->
rsprintf(
"<tr class=\"subStatusTitle\"><th colspan=9>Names<th>%s</tr>\n", varkey.
name);
2972 HNDLE hkeyroot = hkey;
2985 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<br></tr>\n", style,
key.
name);
2989 size =
sizeof(
data);
2995 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2996 data_str =
"(empty)";
3000 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
3002 (
"<tr class=\"%s\" ><td colspan=9>%s<td align=center>%s (%s)<br></tr>\n",
3003 style,
key.
name, data_str.c_str(), hex_str.c_str());
3005 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<td align=center>%s<br></tr>\n",
3006 style,
key.
name, data_str.c_str());
3014 size =
sizeof(
data);
3019 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
3020 data_str =
"(empty)";
3027 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
3028 r->
rsprintf(
"<td>[%d] %s (%s)<br></tr>\n",
k, data_str.c_str(), hex_str.c_str());
3030 r->
rsprintf(
"<td>[%d] %s<br></tr>\n",
k, data_str.c_str());
3038 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names %s", eq_name, varkey.
name);
3046 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<td align=center><i>... %d values ...</i>",
3052 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
3054 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
3058 size =
sizeof(
name);
3061 sprintf(
name,
"%s[%d]", varkey.
name,
j);
3064 if (strlen(
name) < 1) {
3065 sprintf(
name,
"%s[%d]", varkey.
name,
j);
3068 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s", style,
name);
3070 size =
sizeof(
data);
3075 if (n_var == i_set) {
3084 sprintf(
str,
"%s", group);
3088 if (n_var == i_edit) {
3089 r->
rsprintf(
"<td align=center><input type=text size=10 maxlenth=80 name=value value=\"%s\">\n", data_str.c_str());
3090 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set></tr>\n");
3091 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", i_edit);
3092 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
3095 sprintf(odb_path,
"Equipment/%s/Variables/%s[%d]", eq_name, varkey.
name,
j);
3098 r->
rsprintf(
"<a href=\"#\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\', 0);return false;\" >%s</a>", odb_path, data_str.c_str());
3103 r->
rsprintf(
"<td align=center>%s\n", data_str.c_str());
3125 char str[256], *ps, *pt;
3133 strcpy(
type,
"text");
3135 while (*p && *p !=
'<')
3143 while (*p && ((*p ==
' ') || iscntrl(*p)))
3161 while (*p && ((*p ==
' ') || iscntrl(*p)))
3171 while (*p && *p !=
'\"')
3177 while (*p && *p !=
' ' && *p !=
'>')
3190 while (*p && *p !=
'\"')
3196 while (*p && *p !=
' ' && *p !=
'>')
3217 while (*p && *p !=
' ' && *p !=
'>')
3229 while (*p && *p !=
'\"')
3235 while (*p && *p !=
' ' && *p !=
'>')
3246 while (*p && *p !=
'\"')
3252 while (*p && *p !=
' ' && *p !=
'>')
3257 if (strchr(p,
'=')) {
3258 mstrlcpy(
str, p,
sizeof(
str));
3259 pt = strchr(
str,
'=')+1;
3262 while (*pt && *pt !=
'\"')
3268 while (*pt && *pt !=
' ' && *pt !=
'>')
3273 mstrlcat(tail,
" ", 256);
3274 mstrlcat(tail,
str, 256);
3276 mstrlcat(tail,
str, 256);
3286 while (*p && ((*p ==
' ') || iscntrl(*p)))
3290 cm_msg(
MERROR,
"find_odb_tag",
"Invalid odb tag '%s'", ps);
3293 }
while (*p !=
'>');
3298 while (*p && *p !=
'>')
3309 int size,
index, i_edit, i_set;
3317 i_edit = atoi(pp->
getparam(
"index"));
3322 i_set = atoi(pp->
getparam(
"index"));
3325 mstrlcpy(full_keypath, keypath1,
sizeof(full_keypath));
3326 mstrlcpy(keypath, keypath1,
sizeof(keypath));
3329 if (strchr(keypath,
'[') && strchr(keypath,
']')) {
3330 for (p = strchr(keypath,
'[') + 1; *p && *p !=
']'; p++)
3334 if (*p && *p ==
']') {
3335 index = atoi(strchr(keypath,
'[') + 1);
3336 *strchr(keypath,
'[') = 0;
3343 r->
rsprintf(
"<b>Key \"%s\" not found in ODB</b>\n", keypath);
3346 size =
sizeof(
data);
3349 std::string data_str;
3350 if (format && strlen(format)>0)
3359 if (n_var == i_set) {
3362 if (data_str[0] ==
'y')
3367 if (atoi(data_str.c_str()) > 0)
3377 std::string options;
3378 if (data_str[0] ==
'y' || atoi(data_str.c_str()) > 0)
3379 options +=
"checked ";
3381 options +=
"disabled ";
3384 options +=
"onClick=\"o=document.createElement('input');o.type='hidden';o.name='cbi';o.value='";
3386 options +=
"';document.form1.appendChild(o);";
3387 options +=
"document.form1.submit();\" ";
3394 r->
rsprintf(
"<input type=\"checkbox\" %s>\n", options.c_str());
3399 if (n_var == i_set) {
3407 size =
sizeof(
data);
3412 if (n_var == i_edit) {
3413 r->
rsprintf(
"<input type=text size=10 maxlength=80 name=value value=\"%s\">\n", data_str.c_str());
3414 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set>\n");
3415 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", n_var);
3416 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
3420 r->
rsprintf(
"<a href=\"#\" %s>", tail);
3424 r->
rsprintf(
"<a onClick=\"promptpwd('%s?cmd=Edit&index=%d&pnam=%s')\" href=\"#\">", path, n_var,
pwd);
3426 r->
rsprintf(
"<a href=\"%s?cmd=Edit&index=%d\" %s>", path, n_var, tail);
3430 r->
rsputs(data_str.c_str());
3433 }
else if (edit == 2) {
3434 r->
rsprintf(
"<a href=\"#\" onclick=\"ODBEdit('%s')\">\n", full_keypath);
3435 r->
rsputs(data_str.c_str());
3439 r->
rsputs(data_str.c_str());
3461 "Src = STRING : [256] ",
3462 "Format = STRING : [32] %1.1f",
3463 "Font = STRING : [32] Medium",
3467 "FGColor = STRING : [8] 000000",
3468 "BGColor = STRING : [8] FFFFFF",
3501 "Src = STRING : [256] ",
3505 "Height = INT : 100",
3506 "Direction = INT : 0",
3508 "Logscale = BOOL : n",
3510 "Max = DOUBLE : 10",
3511 "FGColor = STRING : [8] 000000",
3512 "BGColor = STRING : [8] FFFFFF",
3513 "BDColor = STRING : [8] 808080",
3519 int x, y, width, height, direction,
axis;
3533 int i,
n, size, ivalue;
3539 for (
i=0 ;
i<(int)strlen(src) ;
i++)
3540 if (src[
i] ==
'>' || src[
i] ==
'&')
3542 strncpy(
str, src,
i);
3546 while (strlen(
str) > 0 &&
str[strlen(
str)-1] ==
' ')
3551 cm_msg(
MERROR,
"evaluate_src",
"Invalid Src key \"%s\" for Fill \"%s\"",
3557 size =
sizeof(
data);
3564 *fvalue = (
value[0] ==
'y');
3566 *fvalue = atof(
value.c_str());
3570 if (src[
i] ==
'>' && src[
i+1] ==
'>') {
3573 while (src[
i] ==
' ' || isdigit(src[
i]))
3575 ivalue = (int)*fvalue;
3580 if (src[
i] ==
'&') {
3582 while (src[
i] ==
' ')
3584 if (src[
i] ==
'0' && src[
i+1] ==
'x')
3585 sscanf(src+2+
i,
"%x", &
n);
3588 while (src[
i] ==
' ' || isxdigit(src[
i]) || src[
i] ==
'x')
3590 ivalue = (int)*fvalue;
3606 if (filename[0] ==
'/')
3614 std::string custom_path =
"";
3621 if (custom_path.length() < 1)
3625 cm_msg(
MERROR,
"add_custom_path",
"ODB /Custom/Path has a forbidden value \"%s\", please change it", custom_path.c_str());
3631 std::string full_filename = custom_path;
3632 if (full_filename[full_filename.length()-1] !=
DIR_SEPARATOR)
3634 full_filename += filename;
3636 return full_filename;
3644 std::string filename;
3650 sprintf(
str,
"/Custom/%s",
name);
3654 sprintf(
str,
"/Custom/%s&",
name);
3657 sprintf(
str,
"/Custom/%s!",
name);
3663 sprintf(
str,
"show_custom_file: Invalid custom page: \"/Custom/%s\" not found in ODB",
name);
3675 sprintf(errtext,
"show_custom_file: Error: db_get_key() for \"%s\" status %d",
str,
status);
3681 char* ctext = (
char*)malloc(size);
3687 sprintf(errtext,
"show_custom_file: Error: db_get_data() for \"%s\" status %d",
str,
status);
3706 char str[256],
data[256], src[256];
3707 int i,
index, length,
status, size, width, height, bgcol, fgcol, bdcol, r, g, b, x, y;
3708 HNDLE hDB, hkeygif, hkeyroot, hkey, hkeyval;
3709 double fvalue, ratio;
3721 sprintf(
str,
"/Custom/Images/%s",
name);
3732 std::string filename;
3737 f = fopen(full_filename.c_str(),
"rb");
3739 sprintf(
str,
"show_custom_gif: Cannot open file \"%s\"", full_filename.c_str());
3748 sprintf(
str,
"show_custom_gif: File \"%s\" is not a GIF image", filename.c_str());
3765 size =
sizeof(label);
3768 cm_msg(
MERROR,
"show_custom_gif",
"Cannot open data record for label \"%s\"",
3773 if (label.
src[0] == 0) {
3780 cm_msg(
MERROR,
"show_custom_gif",
"Invalid Src key \"%s\" for label \"%s\"",
3786 size =
sizeof(
data);
3799 if (strstr(label.
format,
"%c"))
3808 sscanf(label.
fgcolor,
"%02x%02x%02x", &r, &g, &b);
3813 sscanf(label.
bgcolor,
"%02x%02x%02x", &r, &g, &b);
3828 width =
value.length() * pfont->
w + 5 + 5;
3829 height = pfont->
h + 2 + 2;
3831 if (label.
align == 0) {
3834 label.
y + height, bgcol);
3838 }
else if (label.
align == 1) {
3841 label.
y + height, bgcol);
3843 label.
y + height, fgcol);
3848 label.
y + height, bgcol);
3869 cm_msg(
MERROR,
"show_custom_gif",
"Cannot open data record for bar \"%s\"",
3874 if (bar.
src[0] == 0) {
3881 cm_msg(
MERROR,
"show_custom_gif",
"Invalid Src key \"%s\" for bar \"%s\"",
3887 size =
sizeof(
data);
3893 fvalue = atof(
value.c_str());
3895 sscanf(bar.
fgcolor,
"%02x%02x%02x", &r, &g, &b);
3900 sscanf(bar.
bgcolor,
"%02x%02x%02x", &r, &g, &b);
3905 sscanf(bar.
bdcolor,
"%02x%02x%02x", &r, &g, &b);
3916 ratio = (log(fvalue) - log(bar.
min)) / (log(bar.
max) - log(bar.
min));
3918 ratio = (fvalue - bar.
min) / (bar.
max - bar.
min);
3927 r = (int) (ratio + 0.5);
3934 bar.
y + bar.
height - 1, fgcol);
3939 else if (bar.
axis == 2)
3945 ratio = ratio * (bar.
height - 2);
3946 r = (int) (ratio + 0.5);
3949 bar.
y + bar.
width, bgcol);
3953 bar.
y + bar.
width - 1, fgcol);
3956 haxis(im,
gdFontSmall, bdcol, 0, bar.
x, bar.
y, bar.
height, -3, -5, -7, -18,
3958 else if (bar.
axis == 2)
3960 5, 7, 8, 0, bar.
min, bar.
max);
3992 size =
sizeof(
data);
3995 cm_msg(
MERROR,
"show_custom_gif",
"No \"Limits\" entry for Fill \"%s\"",
3999 for (
i = 0;
i < size / (int)
sizeof(
double);
i++)
4000 if (*((
double *)
data +
i) > fvalue)
4007 cm_msg(
MERROR,
"show_custom_gif",
"No \"Fillcolors\" entry for Fill \"%s\"",
4012 size =
sizeof(
data);
4013 strcpy(
data,
"FFFFFF");
4016 sscanf(
data,
"%02x%02x%02x", &r, &g, &b);
4031 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
4034 rr->
rsprintf(
"Content-Type: image/gif\r\n");
4035 rr->
rsprintf(
"Content-Length: %d\r\n", length);
4036 rr->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
4037 rr->
rsprintf(
"Expires: Fri, 01-Jan-1983 00:00:00 GMT\r\n\r\n");
4049 { 9999,
"mhttpd_jrpc_rev0", {
4064 int count = 0, substring = 0, rpc;
4066 const char *xname = p->
getparam(
"name");
4067 const char *srpc = p->
getparam(
"rpc");
4069 if (!srpc || !xname) {
4071 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4076 mstrlcpy(sname, xname,
sizeof(sname));
4078 if (sname[strlen(sname)-1]==
'*') {
4079 sname[strlen(sname)-1] = 0;
4095 r->
rsprintf(
"calling rpc %d | ", rpc);
4100 HNDLE hDB, hrootkey, hsubkey, hkey;
4112 sprintf(
str,
"RPC/%d", rpc);
4119 size =
sizeof(client_name);
4124 if (strlen(sname) > 0) {
4126 if (strstr(client_name, sname) != client_name)
4129 if (strcmp(sname, client_name) != 0)
4136 r->
rsprintf(
"client %s", client_name);
4174 { 9998,
"mhttpd_jrpc_rev1", {
4191 int status, substring = 0, rpc;
4193 const char *xname = p->
getparam(
"name");
4194 const char *srpc = p->
getparam(
"rpc");
4196 if (!srpc || !xname) {
4198 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4203 mstrlcpy(sname, xname,
sizeof(sname));
4205 if (sname[strlen(sname)-1]==
'*') {
4206 sname[strlen(sname)-1] = 0;
4225 std::string reply_header;
4226 std::string reply_body;
4234 HNDLE hDB, hrootkey, hsubkey, hkey;
4238 int buf_length = 1024;
4240 int max_reply_length = atoi(p->
getparam(
"max_reply_length"));
4241 if (max_reply_length > buf_length)
4242 buf_length = max_reply_length;
4244 char* buf = (
char*)malloc(buf_length);
4246 assert(buf != NULL);
4251 for (
int i=0; ;
i++) {
4257 sprintf(
str,
"RPC/%d", rpc);
4264 size =
sizeof(client_name);
4269 if (strlen(sname) > 0) {
4271 if (strstr(client_name, sname) != client_name)
4274 if (strcmp(sname, client_name) != 0)
4282 int connect_status = -1;
4283 int call_status = -1;
4284 int call_length = 0;
4285 int disconnect_status = -1;
4316 call_length = strlen(buf);
4326 if (reply_header.length() > 0)
4327 reply_header +=
" | ";
4330 sprintf(tmp,
"%s %d %d %d %d", client_name, connect_status, call_status, disconnect_status, call_length);
4331 reply_header += tmp;
4342 if (reply_header.length() > 0) {
4343 r->
rsputs(reply_header.c_str());
4345 r->
rsputs(reply_body.c_str());
4357 const char *cmd = p->
getparam(
"rcmd");
4358 const char *args = p->
getparam(
"rarg");
4360 if (!
name || !cmd || !args) {
4362 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4368 int buf_length = 1024;
4370 int max_reply_length = atoi(p->
getparam(
"max_reply_length"));
4371 if (max_reply_length > buf_length)
4372 buf_length = max_reply_length;
4374 char* buf = (
char*)malloc(buf_length);
4375 assert(buf != NULL);
4384 r->
rsprintf(
"<RPC_CONNECT_ERROR>%d</RPC_CONNECT_ERROR>",
status);
4425 size =
sizeof(
data);
4435 std::string data_str;
4436 if (format && format[0])
4440 r->
rsputs(data_str.c_str());
4448 r->
rsputs(
"<DB_OUT_OF_RANGE>");
4450 std::string data_str;
4455 r->
rsputs(data_str.c_str());
4467 if (s1.length() < strlen(s2))
4469 return (strncasecmp(s1.c_str(), s2, strlen(s2)) == 0);
4486 char str[
TEXT_SIZE], format[256], facility[256], user[256];
4495 const int ENCODING_NONE = 0;
4496 const int ENCODING_ODB = 1;
4497 const int ENCODING_XML = 2;
4498 const int ENCODING_JSON = 3;
4500 std::string cmd_parameter;
4501 std::string encoding_parameter;
4502 int encoding = ENCODING_NONE;
4504 std::string jsonp_callback;
4505 bool single =
false;
4506 bool multiple =
false;
4507 std::vector<std::string> odb;
4512 cmd_parameter = p->
getparam(
"cmd");
4516 encoding_parameter = p->
getparam(
"encoding");
4519 if (encoding_parameter.length() > 0) {
4521 encoding = ENCODING_ODB;
4523 encoding = ENCODING_XML;
4525 encoding = ENCODING_JSON;
4528 if (encoding == ENCODING_JSON) {
4531 jsonp_callback = p->
getparam(
"callback");
4542 for (
int i=0 ; ;
i++) {
4544 sprintf(ppath,
"odb%d",
i);
4552 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());
4560 ppath +=
"/Custom/Pwd/";
4571 if (strchr(
str,
'[')) {
4572 if (*(strchr(
str,
'[')+1) ==
'*')
4576 *strchr(
str,
'[') = 0;
4585 const char* ptr = p->
getparam(
"value");
4586 for (
i=0 ; ptr != NULL ;
i++) {
4587 size =
sizeof(
data);
4589 if (strchr(
data,
','))
4590 *strchr(
data,
',') = 0;
4592 ptr = strchr(ptr,
',');
4597 size =
sizeof(
data);
4626 size =
sizeof(
data);
4647 if (strchr(
str,
'[')) {
4648 if (*(strchr(
str,
'[')+1) ==
'*')
4652 *strchr(
str,
'[') = 0;
4663 r->
rsputs(
"<DB_NO_KEY>");
4670 sprintf(ppath,
"odb%d",
i);
4671 sprintf(format,
"format%d",
i);
4674 if (strchr(
str,
'[')) {
4675 if (*(strchr(
str,
'[')+1) ==
'*')
4679 *strchr(
str,
'[') = 0;
4687 r->
rsputs(
"<DB_NO_KEY>");
4700 bool fmt_odb =
false;
4701 bool fmt_xml =
false;
4702 bool fmt_json =
true;
4703 bool fmt_jsonp =
false;
4704 int follow_links = 1;
4707 const char* fmt = NULL;
4708 const char* jsonp_callback =
"callback";
4712 }
else if (p->
isparam(
"format")) {
4719 fmt_json = (strstr(fmt,
"json") != NULL);
4722 fmt_xml = fmt_json =
false;
4724 fmt_odb = fmt_json =
false;
4726 fmt_odb = fmt_xml =
false;
4729 fmt_jsonp = (strstr(fmt,
"-p") != NULL);
4730 if (fmt_jsonp && p->
isparam(
"callback"))
4731 jsonp_callback = p->
getparam(
"callback");
4732 if (fmt_json && strstr(fmt,
"-nofollowlinks"))
4734 if (fmt_json && strstr(fmt,
"-nokeys"))
4736 if (fmt_json && strstr(fmt,
"-nolastwritten"))
4738 if (fmt_json && strstr(fmt,
"-norecurse"))
4754 r->
rsputs(jsonp_callback);
4760 char* buf = (
char *)malloc(bufsize);
4767 db_copy(
hDB, hkey, buf, &bufsize, (
char *)
"");
4776 r->
rsputs(
"<DB_NO_KEY>");
4782 r->
rsputs(jsonp_callback);
4789 }
else if (fmt_json)
4793 for (
int i=0 ; ;
i++) {
4795 sprintf(ppath,
"odb%d",
i);
4802 r->
rsputs(
"</data>\n<data>\n");
4815 r->
rsputs(
"<DB_NO_KEY/>\n");
4816 else if (fmt_json) {
4818 sprintf(tmp,
"{ \"/error\" : %d }\n",
status);
4821 r->
rsputs(
"<DB_NO_KEY>\n");
4827 char* buf = (
char *)malloc(bufsize);
4831 const char* s = strstr(buf,
"-->");
4837 }
else if (fmt_json) {
4841 db_copy(
hDB, hkey, buf, &bufsize, (
char *)
"");
4849 r->
rsputs(
"</data>\n</jcopy>\n");
4871 r->
rsputs(jsonp_callback.c_str());
4885 for (
unsigned i=0;
i<odb.size();
i++) {
4891 if (multiple &&
i>0)
4900 r->
rsputs(
"<DB_NO_KEY>\n");
4904 if (multiple &&
i>0)
4954 r->
rsputs(jsonp_callback.c_str());
4967 for (
unsigned i=0;
i<odb.size();
i++) {
4970 int arraylength = 0;
4975 arraylength = atoi(p->
getparam(
"arraylen"));
4976 strlength = atoi(p->
getparam(
"strlen"));
4978 else if (multiple) {
4980 sprintf(buf,
"type%d",
i);
4982 sprintf(buf,
"arraylen%d",
i);
4983 arraylength = atoi(p->
getparam(buf));
4984 sprintf(buf,
"strlen%d",
i);
4985 strlength = atoi(p->
getparam(buf));
4995 char* s = (
char*)calloc(strlength, 1);
5007 if (multiple &&
i>0)
5043 r->
rsputs(jsonp_callback.c_str());
5056 for (
unsigned i=0;
i<odb.size();
i++) {
5059 int arraylength = 0;
5063 arraylength = atoi(p->
getparam(
"arraylen"));
5064 strlength = atoi(p->
getparam(
"strlen"));
5066 else if (multiple) {
5068 sprintf(buf,
"arraylen%d",
i);
5069 arraylength = atoi(p->
getparam(buf));
5070 sprintf(buf,
"strlen%d",
i);
5071 strlength = atoi(p->
getparam(buf));
5082 char* olddata = (
char*)malloc(oldsize);
5088 char* s = (
char*)calloc(newsize, 1);
5107 if (multiple &&
i>0)
5140 r->
rsputs(jsonp_callback.c_str());
5153 for (
unsigned i=0;
i<odb.size();
i++) {
5154 const char*
name = NULL;
5157 else if (multiple) {
5159 sprintf(buf,
"name%d",
i);
5169 if (multiple &&
i>0)
5202 r->
rsputs(jsonp_callback.c_str());
5215 for (
unsigned i=0;
i<odb.size();
i++) {
5216 const char* dest = NULL;
5219 else if (multiple) {
5221 sprintf(buf,
"dest%d",
i);
5230 if (multiple &&
i>0)
5263 r->
rsputs(jsonp_callback.c_str());
5276 for (
unsigned i=0;
i<odb.size();
i++) {
5280 else if (multiple) {
5282 sprintf(buf,
"index%d",
i);
5294 if (multiple &&
i>0)
5327 r->
rsputs(jsonp_callback.c_str());
5340 for (
unsigned i=0;
i<odb.size();
i++) {
5345 if (multiple &&
i>0)
5372 mstrlcpy(facility, p->
getparam(
"f"),
sizeof(facility));
5374 mstrlcpy(facility,
"midas",
sizeof(facility));
5385 char* messages = NULL;
5386 int num_messages = 0;
5399 mstrlcpy(facility, p->
getparam(
"facility"),
sizeof(facility));
5401 mstrlcpy(facility,
"midas",
sizeof(facility));
5404 mstrlcpy(user, p->
getparam(
"user"),
sizeof(user));
5406 mstrlcpy(user,
"javascript_commands",
sizeof(user));
5418 r->
rsputs(
"Message successfully created\n");
5428 r->
rsputs(alarms.c_str());
5455 int size, n_var,
index, edit;
5456 char keypath[256],
type[32], *p, *ps;
5457 char pwd[256], tail[256];
5462 std::string path = pp->
getparam(
"page");
5465 show_error_404(r,
"show_custom_page: Invalid custom page: \"page\" parameter is empty");
5469 if (strstr(path.c_str(),
"..")) {
5471 str +=
"Invalid custom page name \'";
5473 str +=
"\' contains \'..\'";
5478 if (strstr(path.c_str(),
".gif")) {
5483 if (strchr(path.c_str(),
'.')) {
5490 std::string xpath = std::string(
"/Custom/") + path;
5493 xpath = std::string(
"/Custom/") + path +
"&";
5496 xpath = std::string(
"/Custom/") + path +
"!";
5508 ctext = (
char*)malloc(size);
5511 std::string errtext =
msprintf(
"show_custom_page: Error: db_get_data() for \"%s\" status %d", xpath.c_str(),
status);
5517 std::string content_type =
"text/html";
5520 if (std::string(ctext).substr(0, 5) ==
"?cmd=") {
5527 if (strchr(ctext,
'\n') == 0) {
5529 int fh = open(full_filename.c_str(), O_RDONLY |
O_BINARY);
5531 std::string
str =
msprintf(
"show_custom_page: Cannot open file \"%s\", open() errno %d (%s)", full_filename.c_str(), errno, strerror(errno));
5538 off_t off = lseek(fh, 0, SEEK_END);
5540 std::string
str =
msprintf(
"show_custom_page: Cannot open file \"%s\", lseek(SEEK_END) errno %d (%s)", full_filename.c_str(), errno, strerror(errno));
5547 lseek(fh, 0, SEEK_SET);
5548 ctext = (
char*)malloc(size+1);
5549 ssize_t rd =
read(fh, ctext, size);
5572 ps = strchr(p,
'>') + 1;
5574 if (
pwd[0] && n_var == atoi(pp->
getparam(
"index"))) {
5577 mstrlcpy(
str, path.c_str(),
sizeof(
str));
5578 if (strlen(
str)>0 &&
str[strlen(
str)-1] ==
'&')
5581 ppath +=
"/Custom/Pwd/";
5598 }
while (p != NULL);
5606 ppath +=
"/Custom/Pwd/";
5616 std::string podb = pp->
getparam(
"odb");
5617 std::string::size_type pos = podb.find(
'[');
5618 if (pos != std::string::npos) {
5619 index = atoi(podb.substr(pos+1).c_str());
5629 size =
sizeof(
data);
5632 if (atoi(data_str.c_str()) == 0)
5647 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
5663 ps = strchr(p + 1,
'>') + 1;
5668 }
while (p != NULL);
5679 std::string
str =
msprintf(
"Invalid custom page: Page \"%s\" not found in ODB", path.c_str());
5690 int c,
n, a, f,
d,
q, x, r, ia, id, w;
5692 HNDLE hDB, hrootkey, hsubkey, hkey;
5695 static HNDLE hconn = 0;
5712 size =
sizeof(client_name);
5719 if (client_name[0]) {
5727 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
5732 rr->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
5733 rr->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
5734 rr->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
5735 rr->
rsprintf(
"<title>MIDAS CAMAC interface</title></head>\n");
5736 rr->
rsprintf(
"<body><form method=\"GET\" action=\"CNAF\">\n\n");
5744 rr->
rsprintf(
"<table border=3 cellpadding=1>\n");
5745 rr->
rsprintf(
"<tr><th colspan=3>MIDAS experiment \"%s\"",
str);
5747 if (client_name[0] == 0)
5748 rr->
rsprintf(
"<th colspan=3 class=\"redLight\">No CAMAC server running</tr>\n");
5749 else if (hconn == 0)
5750 rr->
rsprintf(
"<th colspan=3 class=\"redLight\">Cannot connect to %s</tr>\n", client_name);
5752 rr->
rsprintf(
"<th colspan=3>CAMAC server: %s</tr>\n", client_name);
5756 a = f =
d =
q = x = 0;
5762 rr->
rsprintf(
"<tr><td colspan=3>\n");
5763 rr->
rsprintf(
"<input type=submit name=cmd value=Execute>\n");
5766 rr->
rsprintf(
"<input type=submit name=cmd value=ODB>\n");
5767 rr->
rsprintf(
"<input type=submit name=cmd value=Status>\n");
5768 rr->
rsprintf(
"<input type=submit name=cmd value=Help>\n");
5775 rr->
rsprintf(
"<th colspan=3>Data");
5780 const char* cmd = p->
getparam(
"cmd");
5782 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_CRATE_CLEAR, 0, 0, 0, 0, 0, &
d, &size, &x,
5785 rr->
rsprintf(
"<tr><td colspan=6 class=\"greenLight\">C cycle executed sucessfully</tr>\n");
5787 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_CRATE_ZINIT, 0, 0, 0, 0, 0, &
d, &size, &x,
5790 rr->
rsprintf(
"<tr><td colspan=6 class=\"greenLight\">Z cycle executed sucessfully</tr>\n");
5792 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_INHIBIT_CLEAR, 0, 0, 0, 0, 0, &
d, &size, &x,
5796 (
"<tr><td colspan=6 class=\"greenLight\">Clear inhibit executed sucessfully</tr>\n");
5798 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_INHIBIT_SET, 0, 0, 0, 0, 0, &
d, &size, &x,
5802 (
"<tr><td colspan=6 class=\"greenLight\">Set inhibit executed sucessfully</tr>\n");
5814 if (strncmp(pd,
"0x", 2) == 0)
5815 sscanf(pd + 2,
"%x", &
d);
5827 for (
i = 0;
i < r;
i++) {
5833 rpc_client_call(hconn,
RPC_CNAF24,
CNAF, 0,
c,
n, a, f, &
d, &size, &x,
5846 status =
rpc_client_call(hconn,
RPC_CNAF24,
CNAF, 0,
c,
n, a, f, &
d, &size, &x, &
q);
5853 (
"<tr><td colspan=6 class=\"redLight\">Error executing function, code = %d</tr>",
5856 rr->
rsprintf(
"<tr align=center><td>%d",
n);
5859 rr->
rsprintf(
"<td colspan=3>%d / 0x%04X Q%d X%d",
d,
d,
q, x);
5872 (
"<tr align=center><td><input type=text size=3 name=N value=%d>\n",
5874 rr->
rsprintf(
"<td><input type=text size=3 name=A value=%d>\n", a);
5875 rr->
rsprintf(
"<td><input type=text size=3 name=F value=%d>\n", f);
5877 (
"<td colspan=3><input type=text size=8 name=D value=%d></tr>\n",
5881 rr->
rsprintf(
"<tr><td colspan=2>Repeat");
5882 rr->
rsprintf(
"<td><input type=text size=3 name=R value=%d>\n", r);
5885 (
"<td align=center colspan=3><input type=submit name=cmd value=\"C cycle\">\n");
5886 rr->
rsprintf(
"<input type=submit name=cmd value=\"Z cycle\">\n");
5888 rr->
rsprintf(
"<tr><td colspan=2>Repeat delay [ms]");
5889 rr->
rsprintf(
"<td><input type=text size=3 name=W value=%d>\n", w);
5892 (
"<td align=center colspan=3><input type=submit name=cmd value=\"Set inhibit\">\n");
5893 rr->
rsprintf(
"<input type=submit name=cmd value=\"Clear inhibit\">\n");
5895 rr->
rsprintf(
"<tr><td colspan=2>Data increment");
5896 rr->
rsprintf(
"<td><input type=text size=3 name=ID value=%d>\n",
id);
5899 (
"<td colspan=3 align=center>Branch <input type=text size=3 name=B value=0>\n");
5901 rr->
rsprintf(
"<tr><td colspan=2>A increment");
5902 rr->
rsprintf(
"<td><input type=text size=3 name=IA value=%d>\n", ia);
5905 (
"<td colspan=3 align=center>Crate <input type=text size=3 name=C value=%d>\n",
5908 rr->
rsprintf(
"</table></body>\r\n");
5920static const NAME_TABLE prefix_table[] = {
5921 {PRFX_PICO,
"pico",},
5922 {PRFX_NANO,
"nano",},
5923 {PRFX_MICRO,
"micro",},
5924 {PRFX_MILLI,
"milli",},
5926 {PRFX_KILO,
"kilo",},
5927 {PRFX_MEGA,
"mega",},
5928 {PRFX_GIGA,
"giga",},
5929 {PRFX_TERA,
"tera",},
5933static const NAME_TABLE unit_table[] = {
5935 {UNIT_METER,
"meter",},
5936 {UNIT_GRAM,
"gram",},
5937 {UNIT_SECOND,
"second",},
5938 {UNIT_MINUTE,
"minute",},
5939 {UNIT_HOUR,
"hour",},
5940 {UNIT_AMPERE,
"ampere",},
5941 {UNIT_KELVIN,
"kelvin",},
5942 {UNIT_CELSIUS,
"deg. celsius",},
5943 {UNIT_FARENHEIT,
"deg. farenheit",},
5945 {UNIT_HERTZ,
"hertz",},
5946 {UNIT_PASCAL,
"pascal",},
5948 {UNIT_WATT,
"watt",},
5949 {UNIT_VOLT,
"volt",},
5951 {UNIT_TESLA,
"tesls",},
5952 {UNIT_LITERPERSEC,
"liter/sec",},
5954 {UNIT_FARAD,
"farad",},
5956 {UNIT_BOOLEAN,
"boolean",},
5957 {UNIT_BYTE,
"byte",},
5958 {UNIT_WORD,
"word",},
5959 {UNIT_DWORD,
"dword",},
5960 {UNIT_ASCII,
"ascii",},
5961 {UNIT_STRING,
"string",},
5962 {UNIT_BAUD,
"baud",},
5964 {UNIT_PERCENT,
"percent",},
5966 {UNIT_COUNT,
"counts",},
5967 {UNIT_FACTOR,
"factor",},
5973void print_mscb_var(
char *
value,
char *evalue,
char *unit, MSCB_INFO_VAR *info_chn,
void *pdata)
5977 unsigned short usdata;
5979 unsigned int uidata;
5986 if (info_chn->unit == UNIT_STRING) {
5987 memset(
str, 0,
sizeof(
str));
5988 strncpy(
str, (
char *)pdata, info_chn->width);
5989 for (
i = 0;
i < (int) strlen(
str);
i++)
5992 strcat(
value,
"\\001");
5995 strcat(
value,
"\\002");
5998 strcat(
value,
"\\t");
6001 strcat(
value,
"\\n");
6004 strcat(
value,
"\\r");
6011 mstrlcpy(evalue,
value, 256);
6013 switch (info_chn->width) {
6016 strcpy(evalue,
"0");
6020 if (info_chn->flags & MSCBF_SIGNED) {
6021 sprintf(
value,
"%d (0x%02X/", *((
signed char *)pdata), *((
signed char *)pdata));
6022 sprintf(evalue,
"%d", *((
signed char *)pdata));
6024 sprintf(
value,
"%u (0x%02X/", *((
unsigned char *)pdata), *((
unsigned char *)pdata));
6025 sprintf(evalue,
"%u", *((
unsigned char *)pdata));
6028 for (
i = 0;
i < 8;
i++)
6029 if (*((
unsigned char *)pdata) & (0x80 >>
i))
6037 if (info_chn->flags & MSCBF_SIGNED) {
6038 sdata = *((
signed short *)pdata);
6040 sprintf(
value,
"%d (0x%04X)", sdata, sdata);
6041 sprintf(evalue,
"%d", sdata);
6043 usdata = *((
unsigned short *)pdata);
6045 sprintf(
value,
"%u (0x%04X)", usdata, usdata);
6046 sprintf(evalue,
"%u", usdata);
6051 if (info_chn->flags & MSCBF_FLOAT) {
6052 fdata = *((
float *)pdata);
6054 sprintf(
value,
"%1.6lg", fdata);
6055 sprintf(evalue,
"%1.6lg", fdata);
6057 if (info_chn->flags & MSCBF_SIGNED) {
6058 idata = *((
signed int *)pdata);
6060 sprintf(
value,
"%d (0x%08X)", idata, idata);
6061 sprintf(evalue,
"%d", idata);
6063 uidata = *((
unsigned int *)pdata);
6065 sprintf(
value,
"%u (0x%08X)", uidata, uidata);
6066 sprintf(evalue,
"%u", uidata);
6075 if (info_chn->prefix) {
6076 for (
i = 0; prefix_table[
i].id != 99;
i++)
6077 if ((
unsigned char)prefix_table[
i].
id == info_chn->prefix)
6079 if (prefix_table[
i].
id)
6080 strcpy(unit, prefix_table[
i].
name);
6084 if (info_chn->unit && info_chn->unit != UNIT_STRING) {
6085 for (
i = 0; unit_table[
i].id;
i++)
6086 if ((
unsigned char)unit_table[
i].
id == info_chn->unit)
6088 if (unit_table[
i].
id)
6089 strcat(unit, unit_table[
i].
name);
6093static int cmp_int(
const void *a,
const void *b)
6095 return *((
int *)a) > *((
int *)b);
6100void create_mscb_tree()
6104 int i,
j,
k, l, size, address[1000], dev_badr[1000], dev_adr[1000], dev_chn[1000],
6105 n_address, n_dev_adr;
6106 char mscb_dev[256], mscb_pwd[32], eq_name[32];
6132 size =
sizeof(mscb_dev);
6135 size =
sizeof(mscb_pwd);
6139 size =
sizeof(dev_adr);
6141 n_dev_adr = size /
sizeof(int);
6144 size =
sizeof(mscb_dev);
6147 size =
sizeof(mscb_pwd);
6152 size =
sizeof(dev_badr);
6154 size =
sizeof(dev_chn);
6156 for (
k=0 ;
k<size/(int)
sizeof(
int) && n_dev_adr < (int)(
sizeof(dev_adr)/
sizeof(int)) ;
k++) {
6157 for (l=0 ; l<dev_chn[
k] ; l++)
6158 dev_adr[n_dev_adr++] = dev_badr[
k]+l;
6173 size =
sizeof(address);
6175 n_address = size /
sizeof(
int);
6180 for (
k=0 ;
k<n_dev_adr ;
k++) {
6181 for (l=0 ; l<n_address ; l++)
6182 if (address[l] == dev_adr[
k])
6186 address[n_address++] = dev_adr[
k];
6190 qsort(address, n_address,
sizeof(
int), cmp_int);
6204void show_mscb_page(
Param* p,
Return* r,
int refresh)
6206 int i,
j,
n, ind, fi, fd,
status, size, n_addr, cur_node, adr, show_hidden;
6207 unsigned int uptime;
6208 BOOL comment_created;
6211 char dbuf[256], evalue[256], unit[256], cur_subm_name[256];
6212 HNDLE hDB, hKeySubm, hKeyCurSubm,
hKey, hKeyAddr, hKeyComm;
6215 MSCB_INFO_VAR info_var;
6216 int ping_addr[0x10000];
6224 mstrlcpy(cur_subm_name, p->
getparam(
"subm"),
sizeof(cur_subm_name));
6225 if (cur_subm_name[0] == 0) {
6229 sprintf(errorstr,
"No submaster defined under /MSCB/Submaster");
6234 strcpy(cur_subm_name,
key.
name);
6239 cur_node = atoi(p->
getparam(
"node"));
6254 std::vector<int>
addr;
6255 std::vector<char> node_comment;
6260 addr.resize(n_addr);
6261 size =
sizeof(int)*n_addr;
6271 comment_created =
FALSE;
6283 node_comment.resize(32);
6284 comment_created =
TRUE;
6287 fd = mscb_init(cur_subm_name, 0,
"",
FALSE);
6290 for (
i=0 ;
i<0x10000 ;
i++)
6292 for (
i=0 ;
i<1000 ;
i++)
6294 for (
i=0 ;
i<0x10000 ;
i+=100)
6296 for (
i=0 ;
i<0x10000 ;
i+= 0x100)
6298 for (
i=0xFF00 ;
i<0x10000 ;
i++)
6301 for (ind =
n = 0; ind < 0x10000; ind++) {
6302 if (!ping_addr[ind])
6305 status = mscb_ping(fd, (
unsigned short) ind, 1, 0);
6306 if (
status == MSCB_SUCCESS) {
6309 for (
j=ind;
j<ind+100 &&
j<0x10000 ;
j++)
6313 status = mscb_info(fd, (
unsigned short) ind, &
info);
6315 if (
status == MSCB_SUCCESS) {
6317 for (
j=0 ;
j<n_addr ;
j++)
6321 addr.resize(n_addr+1);
6323 node_comment.resize(32*(n_addr+1));
6325 strncpy(node_comment.data()+n_addr*32,
info.node_name, 32);
6327 }
else if (comment_created) {
6328 node_comment.resize(32*n_addr);
6330 strncpy(node_comment.data()+
j*32,
info.node_name, 32);
6340 sprintf(redirstr,
"?cmd=mscb&subm=%s", cur_subm_name);
6346 sprintf(errorstr,
"Cannot talk to submaster \"%s\"", cur_subm_name);
6359 fd = mscb_init(cur_subm_name, 0,
"",
FALSE);
6361 status = mscb_info_variable(fd,
6362 (
unsigned short) cur_node, (
unsigned char)
i, &info_var);
6363 if (
status == MSCB_SUCCESS) {
6364 if (info_var.unit == UNIT_STRING) {
6366 mstrlcpy(valstr,
value,
sizeof(valstr));
6367 if (strlen(valstr) > 0 && valstr[strlen(valstr) - 1] ==
'\n')
6368 valstr[strlen(valstr) - 1] = 0;
6370 status = mscb_write(fd, (
unsigned short) cur_node,
6371 (
unsigned char)
i, valstr, strlen(valstr) + 1);
6373 if (info_var.flags & MSCBF_FLOAT) {
6374 fvalue = (float) atof(
value);
6375 memcpy(&dbuf, &fvalue,
sizeof(
float));
6377 if (
value[1] ==
'x')
6378 sscanf(
value + 2,
"%x", (
int *)&dbuf);
6380 *((
int *)dbuf) = atoi(
value);
6383 status = mscb_write(fd, (
unsigned short) cur_node,
6384 (
unsigned char)
i, dbuf, info_var.width);
6389 sprintf(redirstr,
"?cmd=mscb&subm=%s&node=%d", cur_subm_name, cur_node);
6395 show_hidden = atoi(p->
getparam(
"hidden"));
6397 show_hidden =
FALSE;
6400 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
6401 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
6405 r->
rsprintf(
"<style type=\"text/css\">\r\n");
6406 r->
rsprintf(
"select { width:150px; background-color:#FFFFE0; font-size:12px; }\r\n");
6408 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6410 r->
rsprintf(
" vertical-align:top;\r\n");
6411 r->
rsprintf(
" font-size:16px;\r\n");
6412 r->
rsprintf(
" border-right:1px solid #808080;\r\n");
6415 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6417 r->
rsprintf(
" vertical-align:top;\r\n");
6418 r->
rsprintf(
" font-size:16px;\r\n");
6419 r->
rsprintf(
" border-right:1px solid #808080;\r\n");
6422 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6424 r->
rsprintf(
" vertical-align:top;\r\n");
6425 r->
rsprintf(
" font-size:10px;\r\n");
6429 r->
rsprintf(
" font-weight:bold;\r\n");
6430 r->
rsprintf(
" font-size:12px;\r\n");
6433 r->
rsprintf(
" background-color:#F0F0F0;\r\n");
6435 r->
rsprintf(
" font-size:12px;\r\n");
6436 r->
rsprintf(
" border:1px solid #808080;\r\n");
6437 r->
rsprintf(
" border-right:1px solid #FFFFFF;\r\n");
6438 r->
rsprintf(
" border-bottom:1px solid #FFFFFF;\r\n");
6442 r->
rsprintf(
" font-size:12px;\r\n");
6447 r->
rsprintf(
"<script type=\"text/javascript\">\r\n");
6448 r->
rsprintf(
"function mscb_edit(index, value)\r\n");
6450 r->
rsprintf(
" var new_value = prompt('Please enter new value', value);\r\n");
6451 r->
rsprintf(
" if (new_value != undefined) {\r\n");
6452 r->
rsprintf(
" window.location.search = '?cmd=mscb&subm=%s&node=%d&idx='+index+'&value='+new_value;\n", cur_subm_name, cur_node);
6459 r->
rsprintf(
"<table class=\"mtable\">");
6460 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>MSCB</th><tr>");
6464 r->
rsprintf(
"<tr><td colspan=2>\n");
6465 r->
rsprintf(
"<table width=100%%><tr>\n");
6466 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());
6468 r->
rsprintf(
"<tr><td colspan=\"2\" cellpadding=\"0\" cellspacing=\"0\">\r\n");
6472 r->
rsprintf(
"<h1>No MSCB Submasters defined in ODB</h1>\r\n");
6483 r->
rsprintf(
"<table width=\"100%%\" cellpadding=\"0\" cellspacing=\"0\">");
6486 r->
rsprintf(
"<tr><td class=\"subm\">\r\n");
6498 r->
rsprintf(
"<select name=\"subm\" id=\"subm\" size=%d ",
i);
6499 r->
rsprintf(
"onChange=\"window.location.search='?cmd=mscb&subm='+document.getElementById('subm').value;\">\r\n");
6509 size =
sizeof(comment);
6511 mstrlcat(
str,
": ",
sizeof(
str));
6512 mstrlcat(
str, comment,
sizeof(
str));
6516 (cur_subm_name[0] == 0 &&
i == 0)) {
6525 r->
rsprintf(
"<td class=\"node\">\r\n");
6528 r->
rsprintf(
"<script type=\"text/javascript\">\n");
6530 r->
rsprintf(
"function rescan()\n");
6532 r->
rsprintf(
" flag = confirm('Rescan can take up to one minute.');\n");
6533 r->
rsprintf(
" if (flag == true)\n");
6534 r->
rsprintf(
" window.location.href = '?cmd=mscb&mcmd=Rescan&subm=%s';\n", cur_subm_name);
6539 r->
rsprintf(
"<input type=button name=cmd value=\"Rescan\" onClick=\"rescan();\">");
6543 r->
rsprintf(
"No submaster found in ODB\r\n");
6564 if (hKeyComm == 0) {
6578 r->
rsprintf(
"<select name=\"node\" id=\"node\" size=%d ",
i);
6579 r->
rsprintf(
"onChange=\"window.location.search='?cmd=mscb&subm=%s&node='+document.getElementById('node').value;\">\r\n", cur_subm_name);
6589 if (adr == cur_node)
6601 size =
sizeof(comment);
6603 sprintf(
str,
"%d: %s", adr, comment);
6605 sprintf(
str,
"%d", adr);
6607 if (cur_node == 0 &&
i == 0)
6609 if (adr == cur_node)
6610 r->
rsprintf(
"<option selected>%s</option>\r\n",
str);
6618 r->
rsprintf(
"<td class=\"vars\">\r\n");
6622 r->
rsprintf(
"<tr><td colspan=3 align=center><b>%s:%d</b>",
key.
name, cur_node);
6634 if (fd == EMSCB_WRONG_PASSWORD)
6635 r->
rsprintf(
"<tr><td colspan=3><b>Invalid password</b></td>");
6637 r->
rsprintf(
"<tr><td colspan=3><b>Submaster does not respond</b></td>");
6640 mscb_set_eth_max_retry(fd, 3);
6641 mscb_set_max_retry(1);
6643 status = mscb_ping(fd, cur_node, 0, 1);
6644 if (
status != MSCB_SUCCESS) {
6645 r->
rsprintf(
"<tr><td colspan=3><b>No response from node</b></td>");
6648 status = mscb_info(fd, (
unsigned short) cur_node, &
info);
6649 if (
status != MSCB_SUCCESS) {
6650 r->
rsprintf(
"<tr><td colspan=3><b>No response from node</b></td>");
6654 mstrlcpy(tr16,
info.node_name,
sizeof(tr16));
6655 r->
rsprintf(
"<tr><td class=\"v1\">Node name<td colspan=2 class=\"v2\">%s</tr>\n", tr16);
6656 r->
rsprintf(
"<tr><td class=\"v1\">GIT revision<td colspan=2 class=\"v2\">%d</tr>\n",
info.revision);
6658 if (
info.rtc[0] &&
info.rtc[0] != 0xFF) {
6659 for (
i=0 ;
i<6 ;
i++)
6661 r->
rsprintf(
"<tr><td class=\"v1\">Real Time Clock<td colspan=2 class=\"v2\">%02d-%02d-%02d %02d:%02d:%02d</td>\n",
6666 status = mscb_uptime(fd, (
unsigned short) cur_node, &uptime);
6667 if (
status == MSCB_SUCCESS)
6668 r->
rsprintf(
"<tr><td class=\"v1\">Uptime<td colspan=2 class=\"v2\">%dd %02dh %02dm %02ds</tr>\n",
6669 uptime / (3600 * 24),
6670 (uptime % (3600 * 24)) / 3600, (uptime % 3600) / 60,
6673 r->
rsprintf(
"<tr><td colspan=3><hr></td></tr>\r\n");
6676 for (
i=0 ;
i <
info.n_variables ;
i++) {
6677 mscb_info_variable(fd, cur_node,
i, &info_var);
6678 if (info_var.flags & MSCBF_HIDDEN)
6681 if (
i <
info.n_variables) {
6683 strcpy(
str, show_hidden ?
" checked" :
"");
6684 r->
rsprintf(
"<tr><td colspan=3><input type=checkbox%s name=\"hidden\" value=\"1\"",
str);
6685 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);
6689 for (fi=0 ; fi <
info.n_variables ; ) {
6690 for (
i=fi,size=0 ;
i <
info.n_variables && size < 100;
i++) {
6691 mscb_info_variable(fd, cur_node,
i, &info_var);
6692 size += info_var.width;
6695 size =
sizeof(dbuf);
6696 status = mscb_read_range(fd, cur_node, fi,
i-1, dbuf, &size);
6697 if (
status != MSCB_SUCCESS) {
6698 r->
rsprintf(
"<tr><td colspan=3><b>Error reading data from node</b></td>");
6703 for (
j=fi ;
j<
i ;
j++) {
6704 status = mscb_info_variable(fd, cur_node,
j, &info_var);
6705 if ((info_var.flags & MSCBF_HIDDEN) == 0 || show_hidden) {
6707 mstrlcpy(tr8, info_var.name,
sizeof(tr8));
6708 r->
rsprintf(
"<tr><td class=\"v1\">%s</td>\r\n", tr8);
6709 r->
rsprintf(
"<td class=\"v2\">\r\n");
6711 print_mscb_var(
value, evalue, unit, &info_var, pd);
6712 r->
rsprintf(
"<a href=\"#\" onClick=\"mscb_edit(%d,'%s')\">%s</a>",
6714 r->
rsprintf(
"</td><td class=\"v3\">%s</td>", unit);
6717 pd += info_var.width;
6725 r->
rsprintf(
"</td></tr></table>\r\n");
6726 r->
rsprintf(
"</td></tr></table>\r\n");
6727 r->
rsprintf(
"</td></tr></table>\r\n");
6728 r->
rsprintf(
"</div></body></html>\r\n");
6737 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
6742 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
6743 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
6744 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
6745 r->
rsprintf(
"<title>Enter password</title></head><body>\n\n");
6747 r->
rsprintf(
"<form method=\"GET\" action=\".\">\n\n");
6750 r->
rsprintf(
"<table class=\"headerTable\"><tr><td></td><tr></table>\n");
6752 r->
rsprintf(
"<table class=\"dialogTable\">\n");
6754 r->
rsprintf(
"<tr><th class=\"redLight\">Wrong password!</tr>\n");
6756 r->
rsprintf(
"<tr><th>Please enter password</tr>\n");
6757 r->
rsprintf(
"<tr><td align=center><input type=password name=pwd></tr>\n");
6758 r->
rsprintf(
"<tr><td align=center><input type=submit value=Submit></tr>");
6780 if (strcmp(password,
str) == 0)
6784 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
6789 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
6790 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
6791 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
6792 r->
rsprintf(
"<title>Enter password</title></head><body>\n\n");
6794 r->
rsprintf(
"<form method=\"GET\" action=\".\">\n\n");
6798 r->
rsprintf(
"<input type=hidden name=redir value=\"%s\">\n", redir);
6801 r->
rsprintf(
"<table class=\"headerTable\"><tr><td></td><tr></table>\n");
6803 r->
rsprintf(
"<table class=\"dialogTable\">\n");
6806 r->
rsprintf(
"<tr><th class=\"redLight\">Wrong password!</tr>\n");
6809 (
"<tr><th>Please enter password to obtain write access</tr>\n");
6810 r->
rsprintf(
"<tr><td align=center><input type=password name=wpwd></tr>\n");
6811 r->
rsprintf(
"<tr><td align=center><input type=submit value=Submit></tr>");
6828 int keyPresent, size,
status, line, link_index;
6839 if (strcmp(dec_path,
"root") == 0) {
6844 mstrlcpy(xdecpath, dec_path,
sizeof(xdecpath));
6845 if (strrchr(xdecpath,
'/'))
6846 mstrlcpy(xdecpath, strrchr(xdecpath,
'/')+1,
sizeof(xdecpath));
6847 if (xdecpath[0] == 0)
6848 mstrlcpy(xdecpath,
"root",
sizeof(xdecpath));
6849 show_header(r,
"MIDAS online database",
"", xdecpath, 0);
6852 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
6853 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
6854 r->
rsprintf(
"<script type=\"text/javascript\" src=\"obsolete.js\"></script>\n");
6855 r->
rsprintf(
"<script type=\"text/javascript\" src=\"controls.js\"></script>\n");
6860 r->
rsprintf(
"Error: cannot find key %s<P>\n", dec_path);
6870 mstrlcpy(xdec_path, dec_path,
sizeof(xdec_path));
6873 char* p = xdec_path + strlen(xdec_path) - 1;
6874 while (*p && *p !=
'/')
6881 r->
rsprintf(
"Error: cannot find key %s<P>\n", xdec_path);
6886 dec_path = xdec_path;
6899 r->
rsprintf(
"<table class=\"mtableheader\">\n");
6900 r->
rsprintf(
"<tr><td colspan=%d>\n", colspan);
6901 r->
rsprintf(
"<input type=button value=ELog onclick=\"self.location=\'?cmd=Alarms\';\">\n");
6902 r->
rsprintf(
"</td></tr></table>\n\n");
6908 r->
rsprintf(
"<table class=\"mtable\" style=\"border-spacing:0px;\">\n");
6909 r->
rsprintf(
"<tr><th colspan=%d class=\"mtableheader\">Online Database Browser</tr>\n", colspan);
6912 r->
rsprintf(
"<tr><td colspan=%d>\n", colspan);
6913 r->
rsprintf(
"<input type=button value=Find onclick=\"self.location=\'?cmd=Find\';\">\n");
6914 r->
rsprintf(
"<input type=button value=Create onclick=\"dlgShow('dlgCreate')\">\n");
6915 r->
rsprintf(
"<input type=button value=Link onclick=\"dlgShow('dlgLink')\">\n");
6916 r->
rsprintf(
"<input type=button value=Delete onclick=\"dlgShow('dlgDelete')\">\n");
6917 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());
6918 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());
6919 r->
rsprintf(
"<input type=button value=\"Show ODB clients\" onclick=\"self.location=\'?cmd=odb_scl\';\">\n");
6925 std::string dd =
"";
6927 dd +=
"<!-- Demo dialog -->\n";
6928 dd +=
"<div id=\"dlgDelete\" class=\"dlgFrame\">\n";
6929 dd +=
"<div class=\"dlgTitlebar\">Delete ODB entry</div>\n";
6930 dd +=
"<div class=\"dlgPanel\">\n";
6931 dd +=
"<div id=odbpath>";
6933 dd += MJsonNode::Encode(odbpath.c_str());
6936 dd +=
"<div><br></div>\n";
6938 dd +=
"<table class=\"dialogTable\">\n";
6939 dd +=
"<th colspan=2>Delete ODB entries:</th>\n";
6941 std::vector<std::string> delete_list;
6943 int count_delete = 0;
6948 r->
rsprintf(
"<tr><td colspan=%d class='ODBpath'><b>", colspan);
6949 r->
rsprintf(
"<a href=\"?cmd=oldodb\">/</a> \n");
6951 std::string enc_root_path;
6955 const char* p = dec_path;
6958 while (*p && *p !=
'/')
6963 if (pd.length() > 0)
6964 r->
rsprintf(
"<a href=\"?cmd=oldodb&odb_path=%s\">%s</a>\n / ", enc_root_path.c_str(), pd.c_str());
6966 enc_root_path +=
"/";
6976 for(
int scan=0; scan<2; scan++){
6977 if(scan==1 && keyPresent==1) {
6978 r->
rsprintf(
"<tr class=\"titleRow\">\n");
6979 r->
rsprintf(
"<th class=\"ODBkey\">Key</th>\n");
6980 r->
rsprintf(
"<th class=\"ODBvalue\">Value ");
6981 r->
rsprintf(
"<script type=\"text/javascript\">\n");
6982 r->
rsprintf(
"function expand()\n");
6984 r->
rsprintf(
" var n = document.getElementsByName('ext');\n");
6985 r->
rsprintf(
" for (i=0 ; i<n.length ; i++) {\n");
6986 r->
rsprintf(
" if (n[i].style.display == 'none')\n");
6987 r->
rsprintf(
" n[i].style.display = 'table-cell';\n");
6989 r->
rsprintf(
" n[i].style.display = 'none';\n");
6991 r->
rsprintf(
" if (document.getElementById('expp').expflag === true) {\n");
6992 r->
rsprintf(
" document.getElementById('expp').expflag = false;\n");
6993 r->
rsprintf(
" document.getElementById('expp').innerHTML = '⇥';\n");
6995 r->
rsprintf(
" document.getElementById('expp').expflag = true;\n");
6996 r->
rsprintf(
" document.getElementById('expp').innerHTML = '⇤';\n");
7000 r->
rsprintf(
"<div style=\"display:inline;float:right\"><a id=\"expp\"href=\"#\" onClick=\"expand();return false;\">⇥</div>");
7002 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Type</th>\n");
7003 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">#Val</th>\n");
7004 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Size</th>\n");
7005 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Written</th>\n");
7006 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Mode</th>\n");
7010 for (
int i = 0;;
i++) {
7017 delete_list.push_back(
key.
name);
7021 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
7023 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
7025 std::string keyname =
key.
name;
7028 std::string enc_full_path = enc_root_path + enc_keyname;
7030 std::string odb_path = dec_path;
7031 if (odb_path.length() > 0 && odb_path[odb_path.length() - 1] !=
'/')
7036 std::string enc_link_ref;
7041 size =
sizeof(link_name);
7050 enc_link_ref =
"?cmd=Set&odb_path=";
7051 enc_link_ref += enc_full_path;
7055 sprintf(link_name,
"%s",
"(empty)");
7059 std::string enc_ref;
7062 if (enc_root_path.back() ==
'/' && link_name[0] ==
'/') {
7065 enc_ref +=
"?cmd=Set&odb_path=";
7066 enc_ref += enc_root_path;
7071 enc_ref +=
"?cmd=Set&odb_path=";
7072 enc_ref += enc_root_path;
7078 enc_ref +=
"?cmd=Set&odb_path=";
7079 enc_ref += enc_full_path;
7084 r->
rsprintf(
"<tr><td class=\"yellowLight\">");
7085 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)");
7091 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());
7093 r->
rsprintf(
"<i>→ <a href=\"%s\">%s</a></i>", enc_link_ref.c_str(), link_name);
7097 if (strchr(link_name,
'['))
7098 link_index = atoi(strchr(link_name,
'[')+1);
7105 size =
sizeof(
data);
7108 std::string data_str;
7110 if (link_index != -1)
7116 if (size ==
sizeof(
data)) {
7117 data_str +=
"...(truncated)";
7121 std::string hex_str;
7124 if (link_index != -1)
7130 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
7131 data_str =
"(empty)";
7136 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
7138 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7139 r->
rsprintf(
"%s <i>→ ", keyname.c_str());
7140 r->
rsprintf(
"<a href=\"%s\">%s</a></i>\n", enc_link_ref.c_str(), link_name);
7141 r->
rsprintf(
"<td class=\"%s\">\n", style);
7143 r->
rsprintf(
"%s (%s)", data_str.c_str(), hex_str.c_str());
7145 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7146 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">%s (%s)</a>\n", odb_path.c_str(), data_str.c_str(), hex_str.c_str());
7149 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7150 r->
rsprintf(
"%s<td class=\"%s\">", keyname.c_str(), style);
7152 r->
rsprintf(
"%s (%s)", data_str.c_str(), hex_str.c_str());
7154 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7155 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">%s (%s)</a>\n", odb_path.c_str(), data_str.c_str(), hex_str.c_str());
7159 if (strchr(data_str.c_str(),
'\n')) {
7161 r->
rsprintf(
"<td class=\"ODBkey\">");
7162 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td class=\"ODBvalue\">", keyname.c_str(), enc_link_ref.c_str(), link_name);
7164 r->
rsprintf(
"<td class=\"ODBkey\">%s<td class=\"%s\">", keyname.c_str(), style);
7168 if (strlen(
data) > data_str.length())
7169 r->
rsprintf(
"<i>... (%d bytes total)<p>\n", (
int)strlen(
data));
7171 r->
rsprintf(
"<a href=\"%s\">Edit</a>\n", enc_ref.c_str());
7174 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7175 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td class=\"%s\">", keyname.c_str(), enc_link_ref.c_str(), link_name, style);
7179 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7180 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", odb_path.c_str());
7185 r->
rsprintf(
"<td class=\"ODBkey\">%s<td class=\"%s\">", keyname.c_str(), style);
7186 if (!write_access) {
7189 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7190 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", odb_path.c_str());
7199 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7203 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7207 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7211 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7215 else if (delta < 3600)
7216 r->
rsprintf(
"%1.0lfm", delta / 60.0);
7217 else if (delta < 86400)
7218 r->
rsprintf(
"%1.0lfh", delta / 3600.0);
7219 else if (delta < 86400 * 99)
7220 r->
rsprintf(
"%1.0lfd", delta / 86400.0);
7225 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7241 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);
7245 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);
7251 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
7253 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
7256 size =
sizeof(
data);
7260 std::string hex_str;
7268 if (size ==
sizeof(
data)) {
7269 data_str +=
"...(truncated)";
7273 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
7274 data_str =
"(empty)";
7280 enc_ref +=
"?cmd=Set&odb_path=";
7281 enc_ref += enc_full_path;
7282 enc_ref +=
"&index=";
7295 r->
rsprintf(
"<td class=\"%s\">[%d] ", style,
j);
7297 r->
rsprintf(
"<a href=\"%s\">", enc_ref.c_str());
7299 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), tmpstr.c_str());
7300 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", tmpstr.c_str());
7302 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
7303 r->
rsprintf(
"%s (%s)</a>\n", data_str.c_str(), hex_str.c_str());
7305 r->
rsprintf(
"%s</a>\n", data_str.c_str());
7309 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7313 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7317 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7321 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7325 else if (delta < 3600)
7326 r->
rsprintf(
"%1.0lfm", delta / 60.0);
7327 else if (delta < 86400)
7328 r->
rsprintf(
"%1.0lfh", delta / 3600.0);
7329 else if (delta < 86400 * 99)
7330 r->
rsprintf(
"%1.0lfh", delta / 86400.0);
7335 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7363 std::sort(delete_list.begin(), delete_list.end());
7365 for (
unsigned i=0;
i<delete_list.size();
i++) {
7366 std::string
name = delete_list[
i];
7368 dd +=
"<tr><td style=\"text-align:left;\" align=left><input align=left type=checkbox id=delete";
7372 dd += MJsonNode::Encode(
name.c_str());
7376 dd +=
"</input></td></tr>\n";
7380 dd +=
"<input type=button value=Delete onClick='mhttpd_delete_page_handle_delete(event);'>\n";
7381 dd +=
"<input type=button value=Cancel onClick='mhttpd_delete_page_handle_cancel(event);'>\n";
7389 std::string cd =
"";
7391 cd +=
"<!-- Demo dialog -->\n";
7392 cd +=
"<div id=\"dlgCreate\" class=\"dlgFrame\">\n";
7393 cd +=
"<div class=\"dlgTitlebar\">Create ODB entry</div>\n";
7394 cd +=
"<div class=\"dlgPanel\">\n";
7396 cd +=
"<div id=odbpath>";
7398 cd += MJsonNode::Encode(odbpath.c_str());
7401 cd +=
"<div><br></div>\n";
7403 cd +=
"<table class=\"dialogTable\">\n";
7404 cd +=
"<th colspan=2>Create ODB entry:</th>\n";
7408 cd +=
"<select type=text size=1 id=create_tid name=type>";
7409 cd +=
"<option value=7>Integer (32-bit)";
7410 cd +=
"<option value=9>Float (4 Bytes)";
7411 cd +=
"<option value=12>String";
7412 cd +=
"<option selected value=15>Subdirectory";
7413 cd +=
"<option value=1>Byte";
7414 cd +=
"<option value=2>Signed byte";
7415 cd +=
"<option value=3>Character (8-bit)";
7416 cd +=
"<option value=4>Word (16-bit)";
7417 cd +=
"<option value=5>Short integer (16-bit)";
7418 cd +=
"<option value=6>Double Word (32-bit)";
7419 cd +=
"<option value=8>Boolean";
7420 cd +=
"<option value=10>Double float (8 Bytes)";
7424 cd +=
"<tr><td>Name<td><input type=text size=31 maxlength=31 id=create_name name=value></tr>\n";
7425 cd +=
"<tr><td>Array size<td><input type=text size=31 maxlength=31 id=create_array_length name=index value=1></tr>\n";
7426 cd +=
"<tr><td>String length<td><input type=text size=31 maxlength=31 id=create_strlen name=strlen value=32></tr>\n";
7428 cd +=
"<input type=button value=Create onClick='mhttpd_create_page_handle_create(event);'>\n";
7429 cd +=
"<input type=button value=Cancel onClick='mhttpd_create_page_handle_cancel(event);'>\n";
7437 std::string ld =
"";
7439 ld +=
"<!-- Demo dialog -->\n";
7440 ld +=
"<div id=\"dlgLink\" class=\"dlgFrame\">\n";
7441 ld +=
"<div class=\"dlgTitlebar\">Create a link to an ODB entry</div>\n";
7442 ld +=
"<div class=\"dlgPanel\">\n";
7444 ld +=
"<div id=link_odbpath>";
7446 ld += MJsonNode::Encode(odbpath.c_str());
7449 ld +=
"<div><br></div>\n";
7451 ld +=
"<table class=\"dialogTable\">\n";
7452 ld +=
"<th colspan=2>Create a link to an ODB entry:</th>\n";
7453 ld +=
"<tr><td>Name<td><input type=text size=31 maxlength=31 id=link_name name=value></tr>\n";
7454 ld +=
"<tr><td>Link target<td><input type=text size=31 maxlength=256 id=link_target name=target></tr>\n";
7456 ld +=
"<input type=button value=Link onClick='mhttpd_link_page_handle_link(event);'>\n";
7457 ld +=
"<input type=button value=Cancel onClick='mhttpd_link_page_handle_cancel(event);'>\n";
7475 std::string odb_path = pp->
getparam(
"odb_path");
7485 r->
rsprintf(
"Error: cannot find key %s<P>\n", odb_path.c_str());
7495 r->
rsprintf(
"<table class=\"dialogTable\">");
7498 r->
rsprintf(
"<input type=hidden name=index value=\"%d\">\n",
index);
7503 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", group);
7505 r->
rsprintf(
"<input type=hidden name=odb_path value=\"%s\">\n", odb_path.c_str());
7513 str1 = odb_path.c_str();
7515 r->
rsprintf(
"<tr><th colspan=2>Set new value - type = %s</tr>\n", data_str1.c_str());
7516 r->
rsprintf(
"<tr><td>%s<td>\n", str1.c_str());
7519 size =
sizeof(
data);
7526 if (strchr(data_str.c_str(),
'\n') != NULL) {
7527 r->
rsprintf(
"<textarea rows=20 cols=80 name=\"text\">\n");
7532 if ((
int) data_str.length() > size)
7533 size = data_str.length() + 3;
7537 r->
rsprintf(
"<input type=\"text\" size=%d maxlength=256 name=\"value\" value=\"", size);
7544 r->
rsprintf(
"<tr><td align=center colspan=2>");
7545 r->
rsprintf(
"<input type=submit name=cmd value=Set>");
7546 r->
rsprintf(
"<input type=submit name=cmd value=Cancel>");
7550 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
7561 r->
rsprintf(
"Error: cannot find key %s<P>\n", odb_path.c_str());
7590 r->
rsprintf(
"<h2>Write access not allowed</h2>\n");
7606 if (
value[0] == 0) {
7614 r->
rsprintf(
"<table class=\"dialogTable\">");
7616 r->
rsprintf(
"<tr><th colspan=2>Find string in Online Database</tr>\n");
7617 r->
rsprintf(
"<tr><td>Enter substring (case insensitive)\n");
7619 r->
rsprintf(
"<td><input type=\"text\" size=\"20\" maxlength=\"80\" name=\"value\">\n");
7622 r->
rsprintf(
"<tr><td align=center colspan=2>");
7623 r->
rsprintf(
"<input type=submit name=cmd value=Find>");
7624 r->
rsprintf(
"<input type=submit name=cmd value=Cancel>");
7628 r->
rsprintf(
"<input type=hidden name=cmd value=Find>");
7636 r->
rsprintf(
"<table class=\"mtable\">\n");
7637 r->
rsprintf(
"<tr><th colspan=2 class=\"mtableheader\">");
7638 r->
rsprintf(
"Results of search for substring \"%s\"</tr>\n",
value);
7639 r->
rsprintf(
"<tr><th class=\"titlerow\">Key<th>Value</tr>\n");
7661#define LN10 2.302585094
7662#define LOG2 0.301029996
7663#define LOG5 0.698970005
7666 int x1,
int y1,
int width,
7667 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax)
7669 double dx, int_dx, frac_dx, x_act, label_dx, major_dx, x_screen, maxwidth;
7670 int tick_base, major_base, label_base, n_sig1, n_sig2, xs;
7672 double base[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
7674 if (xmax <= xmin || width <= 0)
7678 dx = (xmax - xmin) / (
double) (width / 5);
7680 frac_dx = modf(log(dx) /
LN10, &int_dx);
7686 tick_base = frac_dx <
LOG2 ? 1 : frac_dx <
LOG5 ? 2 : 3;
7687 major_base = label_base = tick_base + 1;
7690 dx = pow(10, int_dx) *
base[tick_base];
7691 major_dx = pow(10, int_dx) *
base[major_base];
7692 label_dx = major_dx;
7698 n_sig1 = (int) floor(log(fabs(xmin)) /
LN10) - (
int) floor(log(fabs(label_dx)) /
LN10) + 1;
7704 (int) floor(log(fabs(xmax)) /
LN10) - (
int) floor(log(fabs(label_dx)) /
LN10) + 1;
7706 n_sig1 =
MAX(n_sig1, n_sig2);
7707 n_sig1 =
MAX(n_sig1, 4);
7710 sprintf(
str,
"%1.*lG", n_sig1, floor(xmin / dx) * dx);
7711 maxwidth = font->
h / 2 * strlen(
str);
7712 sprintf(
str,
"%1.*lG", n_sig1, floor(xmax / dx) * dx);
7713 maxwidth =
MAX(maxwidth, font->
h / 2 * strlen(
str));
7714 sprintf(
str,
"%1.*lG", n_sig1, floor(xmax / dx) * dx + label_dx);
7715 maxwidth =
MAX(maxwidth, font->
h / 2 * strlen(
str));
7718 while (maxwidth > 0.7 * label_dx / (xmax - xmin) * width) {
7720 label_dx = pow(10, int_dx) *
base[label_base];
7721 if (label_base % 3 == 2 && major_base % 3 == 1) {
7723 major_dx = pow(10, int_dx) *
base[major_base];
7727 x_act = floor(xmin / dx) * dx;
7732 x_screen = (x_act - xmin) / (xmax - xmin) * width + x1;
7733 xs = (int) (x_screen + 0.5);
7735 if (x_screen > x1 + width + 0.001)
7738 if (x_screen >= x1) {
7739 if (fabs(floor(x_act / major_dx + 0.5) - x_act / major_dx) <
7740 dx / major_dx / 10.0) {
7742 if (fabs(floor(x_act / label_dx + 0.5) - x_act / label_dx) <
7743 dx / label_dx / 10.0) {
7748 if (grid != 0 && xs > x1 && xs < x1 + width)
7753 sprintf(
str,
"%1.*lG", n_sig1, x_act);
7755 y1 + label,
str, col);
7762 if (grid != 0 && xs > x1 && xs < x1 + width)
7775 if (fabs(x_act) < dx / 100)
7788 t_sec = (time_t) sec;
7791 localtime_r(&t_sec, &tms);
7792 strcpy(mon,
mname[tms.tm_mon]);
7797 sprintf(result,
"%02d %s %02d %02d:%02d:%02d",
7798 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min,
7800 else if (
base < 3600 * 24)
7801 sprintf(result,
"%02d %s %02d %02d:%02d",
7802 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min);
7804 sprintf(result,
"%02d %s %02d", tms.tm_mday, mon, tms.tm_year % 100);
7807 sprintf(result,
"%02d:%02d:%02d", tms.tm_hour, tms.tm_min, tms.tm_sec);
7808 else if (
base < 3600 * 3)
7809 sprintf(result,
"%02d:%02d", tms.tm_hour, tms.tm_min);
7810 else if (
base < 3600 * 24)
7811 sprintf(result,
"%02d %s %02d %02d:%02d",
7812 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min);
7814 sprintf(result,
"%02d %s %02d", tms.tm_mday, mon, tms.tm_year % 100);
7819 int x1,
int y1,
int width,
int xr,
7820 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax)
7822 int dx, x_act, label_dx, major_dx, x_screen, maxwidth;
7823 int tick_base, major_base, label_base, xs, xl;
7825 const int base[] = { 1, 5, 10, 60, 300, 600, 1800, 3600, 3600 * 6, 3600 * 12, 3600 * 24, 0 };
7827 int force_date, d1, d2;
7830 if (xmax <= xmin || width <= 0)
7835 localtime_r(<ime, &tms);
7837 ltime = (time_t) xmax;
7838 localtime_r(<ime, &tms);
7840 force_date = (d1 != d2);
7843 dx = (int) ((xmax - xmin) / (double) (width / 5) + 0.5);
7845 for (tick_base = 0;
base[tick_base]; tick_base++) {
7846 if (
base[tick_base] > dx)
7849 if (!
base[tick_base])
7851 dx =
base[tick_base];
7853 if (
base[tick_base + 1])
7854 major_base = tick_base + 1;
7856 major_base = tick_base;
7857 major_dx =
base[major_base];
7859 if (
base[major_base + 1])
7860 label_base = major_base + 1;
7862 label_base = major_base;
7863 label_dx =
base[label_base];
7867 maxwidth = font->
h / 2 * strlen(
str);
7870 if (maxwidth > 0.7 * label_dx / (xmax - xmin) * width) {
7871 if (
base[label_base + 1])
7872 label_dx =
base[++label_base];
7874 label_dx += 3600 * 24;
7885 x_screen = (int) ((x_act - xmin) / (xmax - xmin) * width + x1 + 0.5);
7886 xs = (int) (x_screen + 0.5);
7888 if (x_screen > x1 + width + 0.001)
7891 if (x_screen >= x1) {
7898 if (grid != 0 && xs > x1 && xs < x1 + width)
7906 xl = (int) xs - font->
w * strlen(
str) / 2;
7909 if (xl + font->
w * (
int) strlen(
str) > xr)
7910 xl = xr - font->
w * strlen(
str);
7918 if (grid != 0 && xs > x1 && xs < x1 + width)
7931 if (fabs((
double)x_act) < dx / 100)
7940 int x1,
int y1,
int width,
7941 int minor,
int major,
int text,
int label,
int grid,
double ymin,
double ymax,
7944 double dy, int_dy, frac_dy, y_act, label_dy, major_dy, y_screen, y_next;
7945 int tick_base, major_base, label_base, n_sig1, n_sig2, ys, max_width;
7948 const double base[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
7950 if (ymax <= ymin || width <= 0)
7954 if (fabs(ymax - ymin) <= 1
e-10)
7958 dy = pow(10, floor(log(ymin) /
LN10));
7963 dy = (ymax - ymin) / (
double) (width / 5);
7965 frac_dy = modf(log(dy) /
LN10, &int_dy);
7971 tick_base = frac_dy <
LOG2 ? 1 : frac_dy <
LOG5 ? 2 : 3;
7972 major_base = label_base = tick_base + 1;
7975 dy = pow(10, int_dy) *
base[tick_base];
7976 major_dy = pow(10, int_dy) *
base[major_base];
7977 label_dy = major_dy;
7984 (int) floor(log(fabs(ymin)) /
LN10) -
7985 (
int) floor(log(fabs(label_dy)) /
LN10) + 1;
7991 (int) floor(log(fabs(ymax)) /
LN10) -
7992 (
int) floor(log(fabs(label_dy)) /
LN10) + 1;
7994 n_sig1 =
MAX(n_sig1, n_sig2);
7995 n_sig1 =
MAX(n_sig1, 4);
7998 while (label_dy / (ymax - ymin) * width < 1.5 * font->h) {
8000 label_dy = pow(10, int_dy) *
base[label_base];
8001 if (label_base % 3 == 2 && major_base % 3 == 1) {
8003 major_dy = pow(10, int_dy) *
base[major_base];
8009 y_act = floor(ymin / dy) * dy;
8011 if (x1 != 0 || y1 != 0)
8014 last_label_y = y1 + 2 * font->
h;
8018 y_screen = y1 - (log(y_act) - log(ymin)) / (log(ymax) - log(ymin)) * width;
8020 y_screen = y1 - (y_act - ymin) / (ymax - ymin) * width;
8021 ys = (int) (y_screen + 0.5);
8023 if (y_screen < y1 - width - 0.001)
8026 if (y_screen <= y1 + 0.001) {
8027 if (fabs(floor(y_act / major_dy + 0.5) - y_act / major_dy) <
8028 dy / major_dy / 10.0) {
8029 if (fabs(floor(y_act / label_dy + 0.5) - y_act / label_dy) <
8030 dy / label_dy / 10.0) {
8031 if (x1 != 0 || y1 != 0) {
8036 if (grid != 0 && y_screen < y1 && y_screen > y1 - width) {
8045 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8048 ys - font->
h / 2,
str, col);
8052 last_label_y = ys - font->
h / 2;
8055 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8056 max_width =
MAX(max_width, (
int) (font->
w * strlen(
str)));
8059 if (x1 != 0 || y1 != 0) {
8064 if (grid != 0 && y_screen < y1 && y_screen > y1 - width)
8075 if (x1 != 0 || y1 != 0) {
8083 if (x1 != 0 || y1 != 0) {
8085 y_next = pow(10, floor(log(y_act) /
LN10) + 1);
8088 (log(y_next) - log(ymin)) / (log(ymax) -
8089 log(ymin)) * width + 0.5);
8091 if (ys + font->
h / 2 < last_label_y
8092 && ys - font->
h / 2 > y_screen + font->
h / 2) {
8093 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8096 ys - font->
h / 2,
str, col);
8102 last_label_y = ys - font->
h / 2;
8104 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8105 max_width =
MAX(max_width, (
int) (font->
w * strlen(
str)));
8115 if (fabs(y_act) < dy / 100)
8120 return max_width + abs(label);
8130 switch (
str[strlen(
str) - 1]) {
8153 for (; *
str != 0;
str++) {
8169 sprintf(buf,
"%.0f", (
double)t);
8182 cm_msg(
MINFO,
"history_watch_callback",
"History configuration may have changed, will reconnect");
8249 cm_msg(
MERROR,
"get_history",
"Cannot configure history, hs_get_history() status %d",
status);
8267#define ALLOC(t,n) (t*)calloc(sizeof(t),(n))
8268#define DELETE(x) if (x) { free(x); (x)=NULL; }
8269#define DELETEA(x, n) if (x) { for (int i=0; i<(n); i++) { free((x)[i]); (x)[i]=NULL; }; DELETE(x); }
8270#define STRDUP(x) strdup(x)
8326 printf(
"this %p, nvars %d. tstart %d, tend %d, scale %d\n",
this,
nvars, (
int)
tstart, (
int)
tend, (
int)
scale);
8353#define READ_HISTORY_DATA 0x1
8354#define READ_HISTORY_RUNMARKER 0x2
8355#define READ_HISTORY_LAST_WRITTEN 0x4
8415 cm_msg(
MERROR,
"read_history",
"Cannot find \'/History/Display\' in ODB, status %d",
status);
8422 cm_msg(
MERROR,
"read_history",
"Cannot find \'%s\' in ODB, status %d", path,
status);
8428 cm_msg(
MERROR,
"read_history",
"Cannot find \'%s/Variables\' in ODB, status %d", path,
status);
8438 data->tstart = tstart;
8440 data->scale = scale;
8442 for (
size_t i=0;
i<hp.
vars.size();
i++) {
8472 char *
q = strchr(
data->var_names[
data->nvars],
'[');
8474 data->var_index[
data->nvars] = atoi(
q+1);
8490 data->var_index[
data->nvars+0] = 0;
8491 data->var_index[
data->nvars+1] = 0;
8493 data->odb_index[
data->nvars+0] = -1;
8494 data->odb_index[
data->nvars+1] = -2;
8499 bool get_last_written =
false;
8513 printf(
"read_history: nvars %d, hs_read() status %d\n",
data->nvars,
status);
8514 for (
int i=0;
i<
data->nvars;
i++) {
8515 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]);
8520 cm_msg(
MERROR,
"read_history",
"Complete history failure, hs_read() status %d, see messages",
status);
8524 for (
int i=0;
i<
data->nvars;
i++) {
8526 get_last_written =
true;
8533 get_last_written =
true;
8535 if (get_last_written) {
8536 data->have_last_written =
true;
8544 data->last_written);
8547 data->have_last_written =
false;
8589 time_t tmin = endtime;
8592 for (
int k=0;
k<hsdata->
nvars;
k++) {
8623 *plastwritten = tmin;
8625 *plastwritten = tmax;
8632 printf(
"get_hist_last_written: elapsed time %f ms\n", tend-tstart);
8638 int width,
int height,
8642 int labels,
const char *bgcolor,
const char *fgcolor,
const char *gridcolor)
8650 int size,
status, r, g, b;
8653 int white, grey, red;
8655 int fgcol, bgcol, gridcol;
8675 time_t starttime, endtime;
8686 std::vector<int> var_index; var_index.resize(hp.
vars.size());
8688 for (
size_t i=0;
i<hp.
vars.size();
i++) {
8690 const char *vp = strchr(hp.
vars[
i].tag_name.c_str(),
'[');
8692 var_index[
i] = atoi(vp + 1);
8700 if ((minvalue == 0) && (maxvalue == 0)) {
8701 minvalue = -HUGE_VAL;
8702 maxvalue = +HUGE_VAL;
8717 sscanf(bgcolor,
"%02x%02x%02x", &r, &g, &b);
8719 sscanf(fgcolor,
"%02x%02x%02x", &r, &g, &b);
8721 sscanf(gridcolor,
"%02x%02x%02x", &r, &g, &b);
8758 sprintf(
str,
"History is not configured, see messages");
8782 if (hp.
vars.empty()) {
8783 sprintf(
str,
"No variables in panel %s/%s", hgroup, hpanel);
8789 sprintf(
str,
"Too many variables in panel %s/%s", hgroup, hpanel);
8797 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
8858 if (hp.
vars[
i].colour[0] ==
'#') {
8859 const char*
str = hp.
vars[
i].colour.c_str();
8866 r = strtoul(sss, NULL, 16);
8870 g = strtoul(sss, NULL, 16);
8874 b = strtoul(sss, NULL, 16);
8950 std::string odbpath;
8966 sprintf(
str,
"Variables/%s", hp.
vars[
i].tag_name.c_str());
8972 odbpath +=
"/Equipment/";
8973 odbpath += hp.
vars[
i].event_name;
8974 odbpath +=
"/Variables/";
8975 odbpath += hp.
vars[
i].tag_name;
8984 mstrlcpy(
str, hp.
vars[
i].tag_name.c_str(),
sizeof(
str));
8985 p =
str + strlen(
str) - 1;
8986 while (p >
str && *p !=
' ')
8988 std::string key_name = p + 1;
8991 std::string varname =
str;
9001 odbpath +=
"/Equipment/";
9002 odbpath += hp.
vars[
i].event_name;
9003 odbpath +=
"/Variables/";
9004 odbpath += key_name;
9026 std::string key_name =
key.
name;
9030 path +=
"Settings/Names ";
9043 odbpath +=
"/Equipment/";
9044 odbpath += hp.
vars[
i].event_name;
9045 odbpath +=
"/Variables/";
9046 odbpath += key_name;
9094 upper_limit[
i] = lower_limit[
i] = -12345;
9096 if (odbpath.length() > 0 && hkeyroot) {
9107 if (strstr(
str, odbpath.c_str())) {
9108 if (strchr(
str,
'<')) {
9109 p = strchr(
str,
'<') + 1;
9113 lower_limit[
i] = (hp.
vars[
i].factor * (atof(p) - hp.
vars[
i].voffset) + hp.
vars[
i].offset);
9115 lower_limit[
i] = atof(p);
9118 if (strchr(
str,
'>')) {
9119 p = strchr(
str,
'>') + 1;
9123 upper_limit[
i] = (hp.
vars[
i].factor * (atof(p) - hp.
vars[
i].voffset) + hp.
vars[
i].offset);
9125 upper_limit[
i] = atof(p);
9136 starttime = xendtime - scale;
9148 sprintf(
str,
"Complete history failure, read_history() status %d, see messages",
status);
9156 for (
int k=0;
k<hsdata->
nvars;
k++) {
9167 var_status[
i][0] = 0;
9169 sprintf(var_status[
i],
"not found in history");
9172 sprintf(var_status[
i],
"hs_read() error %d, see messages", hsdata->
status[
k]);
9178 int xx = (int)(hsdata->
t[
k][
j]);
9179 double yy = hsdata->
v[
k][
j];
9195 yy = hp.
vars[
i].factor * (yy - hp.
vars[
i].voffset) + hp.
vars[
i].offset;
9199 if ((
i == 0 ||
index != -1) && n_vp == 0)
9219 assert(x[
i].size() == y[
i].size());
9228 double yb1, yb2, yf1, yf2;
9237 if (ymin < minvalue)
9240 if (ymax > maxvalue)
9253 if (logaxis && ymin > 0 && ymax > 0) {
9254 yb1 = pow(10, floor(log(ymin) /
LN10));
9255 yf1 = floor(ymin / yb1);
9256 yb2 = pow(10, floor(log(ymax) /
LN10));
9257 yf2 = floor(ymax / yb2);
9259 if (yb1 == yb2 && yf1 == yf2)
9263 ybase = pow(10, floor(log(ymin) /
LN10));
9264 ymin = (floor(ymin / ybase) * ybase);
9265 ybase = pow(10, floor(log(ymax) /
LN10));
9266 ymax = ((floor(ymax / ybase) + 1) * ybase);
9279 if (ymin == 0 && ymax == 0) {
9284 ymax += (ymax - ymin) / 20.f;
9287 ymin -= (ymax - ymin) / 20.f;
9309 aoffset =
vaxis(im,
gdFontSmall, fgcol, gridcol, 0, 0, height, -3, -5, -7, -8, 0, ymin, ymax, logaxis);
9320 taxis(im,
gdFontSmall, fgcol, gridcol, x1, y1, x2 - x1, width, 3, 5, 9, 10, 0, (
double)starttime, (
double)endtime);
9322 vaxis(im,
gdFontSmall, fgcol, gridcol, x1, y1, y1 - y2, -3, -5, -7, -8, x2 - x1, ymin, ymax, logaxis);
9326 xs = ys = xold = yold = 0;
9333 const char* event_names[] = {
9338 const char* tag_names[] = {
9343 const int tag_indexes[] = {
9357 2, event_names, tag_names, tag_indexes,
9358 num_entries, tbuf, dbuf, st);
9362 int n_marker = num_entries[0];
9367 for (
j = 0;
j < (int) n_marker;
j++) {
9381 xs = (int) ((tbuf[1][
j] - starttime) / (scale/1.0) * (x2 - x1) + x1 + 0.5);
9394 if (dbuf[0][
j] == 1)
9396 else if (dbuf[0][
j] == 2)
9398 else if (dbuf[0][
j] == 3)
9421 if (num_entries[0]) {
9428 if (num_entries[1]) {
9439 int index_state = -1;
9440 int index_run_number = -1;
9442 for (
int k=0;
k<hsdata->
nvars;
k++) {
9447 index_run_number =
k;
9453 ok = (index_state >= 0) && (index_run_number >= 0);
9462 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]);
9469 if (ok && n_marker > 0 && n_marker < 100) {
9472 for (
j = 0;
j < (int) n_marker;
j++) {
9486 xs = (int) ((hsdata->
t[index_state][
j] - starttime) / (scale/1.0) * (x2 - x1) + x1 + 0.5);
9499 int state = (int)hsdata->
v[index_state][
j];
9503 else if (
state == 2)
9505 else if (
state == 3)
9529 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
9534 if (lower_limit[
i] != -12345) {
9536 if (lower_limit[
i] <= 0)
9539 ys = (int) (y1 - (log(lower_limit[
i]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9541 ys = (int) (y1 - (lower_limit[
i] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9553 if (ys > y2 && ys < y1) {
9566 if (upper_limit[
i] != -12345) {
9568 if (upper_limit[
i] <= 0)
9571 ys = (int) (y1 - (log(upper_limit[
i]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9573 ys = (int) (y1 - (upper_limit[
i] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9585 if (ys > y2 && ys < y1) {
9599 for (
j = 0;
j < (int) n_point[
i];
j++) {
9605 xs = (int) (((x[
i][
j] - starttime)/1.0) / (1.0*scale) * (x2 - x1) + x1 + 0.5);
9611 ys = (int) (y1 - (log(y[
i][
j]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9613 ys = (int) (y1 - (y[
i][
j] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9631 if (n_point[
i] > 0) {
9634 poly[1].
x = xs + 12;
9636 poly[2].
x = xs + 12;
9644 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
9655 std::string
str = hp.
vars[
i].label.c_str();
9661 if (hp.
vars[
i].voffset > 0)
9663 else if (hp.
vars[
i].voffset < 0)
9666 if (hp.
vars[
i].factor != 1) {
9667 if (hp.
vars[
i].voffset == 0)
9674 if (hp.
vars[
i].offset > 0)
9676 else if (hp.
vars[
i].offset < 0)
9685 for (
int j=0;
j<hsdata->
nvars;
j++)
9692 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]);
9697 if (n_point[
i] > 0) {
9698 sprintf(xstr,
" = %g", y[
i][n_point[
i]-1]);
9700 sprintf(xstr,
" = all data is NaN or INF");
9705 sprintf(xstr,
" = last data %s", ctimebuf);
9707 char*s = strchr(xstr,
'\n');
9711 var_status[
i][0] = 0;
9713 sprintf(xstr,
" = no data ever");
9716 sprintf(xstr,
" = no data");
9721 if (strlen(var_status[
i]) > 1) {
9725 row =
index == -1 ?
i : 0;
9755 if (buffer == NULL) {
9756 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
9759 rr->
rsprintf(
"Content-Type: image/gif\r\n");
9760 rr->
rsprintf(
"Content-Length: %d\r\n", length);
9761 rr->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
9762 rr->
rsprintf(
"Expires: Fri, 01-Jan-1983 00:00:00 GMT\r\n\r\n");
9766 if (length > *buffer_size) {
9767 printf(
"return buffer too small\n");
9771 memcpy(buffer, gb.
data, length);
9772 *buffer_size = length;
9797 struct tm tms = *ptms;
9800 localtime_r(&t1, &tms2);
9801 tms2.tm_year = ptms->tm_year;
9802 tms2.tm_mon = ptms->tm_mon;
9803 tms2.tm_mday = ptms->tm_mday;
9804 tms2.tm_hour = ptms->tm_hour;
9805 tms2.tm_min = ptms->tm_min;
9831 memset(&tms, 0,
sizeof(
struct tm));
9833 tms.tm_year = atoi(p->
getparam(
"y1")) % 100;
9835 std::string m1 = p->
getparam(
"m1");
9836 for (
i = 0;
i < 12;
i++)
9843 tms.tm_mday = atoi(p->
getparam(
"d1"));
9844 tms.tm_hour = atoi(p->
getparam(
"h1"));
9846 if (tms.tm_year < 90)
9851 memset(&tms, 0,
sizeof(
struct tm));
9852 tms.tm_year = atoi(p->
getparam(
"y2")) % 100;
9854 std::string m2 = p->
getparam(
"m2");
9855 for (
i = 0;
i < 12;
i++)
9862 tms.tm_mday = atoi(p->
getparam(
"d2"));
9863 tms.tm_hour = atoi(p->
getparam(
"h2"));
9865 if (tms.tm_year < 90)
9870 if (ltime_end == ltime_start)
9871 ltime_end += 3600 * 24;
9874 redir +=
"?cmd=oldhistory&";
9895 time_t now = time(NULL);
9897 time_t starttime = now - 3600 * 24;
9898 time_t endtime = now;
9899 bool full_day =
true;
9905 starttime = endtime - atoi(p->
getparam(
"hscale"));
9908 starttime = endtime - 3600 * 24;
9914 r->
rsprintf(
"<tr><td colspan=2>\n");
9915 r->
rsprintf(
"<input type=hidden name=cmd value=OldHistory>\n");
9916 r->
rsprintf(
"<input type=submit name=hcmd value=Query>\n");
9917 r->
rsprintf(
"<input type=submit name=hcmd value=Cancel>\n");
9919 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", p->
getparam(
"group"));
9921 r->
rsprintf(
"<input type=hidden name=panel value=\"%s\">\n", p->
getparam(
"panel"));
9923 r->
rsprintf(
"<input type=hidden name=htime value=\"%s\">\n", p->
getparam(
"htime"));
9925 r->
rsprintf(
"<input type=hidden name=hscale value=\"%s\">\n", p->
getparam(
"hscale"));
9927 r->
rsprintf(
"<input type=hidden name=hindex value=\"%s\">\n", p->
getparam(
"hindex"));
9931 r->
rsprintf(
"<table class=\"dialogTable\">");
9934 localtime_r(&starttime, &tms);
9935 tms.tm_year += 1900;
9937 r->
rsprintf(
"<tr><td nowrap>Start date:</td>");
9939 r->
rsprintf(
"<td>Month: <select name=\"m1\">\n");
9940 r->
rsprintf(
"<option value=\"\">\n");
9941 for (
i = 0;
i < 12;
i++)
9942 if (
i == tms.tm_mon)
9948 r->
rsprintf(
" Day: <select name=\"d1\">");
9949 r->
rsprintf(
"<option selected value=\"\">\n");
9950 for (
i = 0;
i < 31;
i++)
9951 if (
i + 1 == tms.tm_mday)
9952 r->
rsprintf(
"<option selected value=%d>%d\n",
i + 1,
i + 1);
9954 r->
rsprintf(
"<option value=%d>%d\n",
i + 1,
i + 1);
9957 int start_hour = tms.tm_hour;
9961 r->
rsprintf(
" Hour: <input type=\"text\" size=5 maxlength=5 name=\"h1\" value=\"%d\">", start_hour);
9963 r->
rsprintf(
" Year: <input type=\"text\" size=5 maxlength=5 name=\"y1\" value=\"%d\">", tms.tm_year);
9966 r->
rsprintf(
"<tr><td nowrap>End date:</td>");
9968 localtime_r(&endtime, &tms);
9969 tms.tm_year += 1900;
9971 r->
rsprintf(
"<td>Month: <select name=\"m2\">\n");
9972 r->
rsprintf(
"<option value=\"\">\n");
9973 for (
i = 0;
i < 12;
i++)
9974 if (
i == tms.tm_mon)
9980 r->
rsprintf(
" Day: <select name=\"d2\">");
9981 r->
rsprintf(
"<option selected value=\"\">\n");
9982 for (
i = 0;
i < 31;
i++)
9983 if (
i + 1 == tms.tm_mday)
9984 r->
rsprintf(
"<option selected value=%d>%d\n",
i + 1,
i + 1);
9986 r->
rsprintf(
"<option value=%d>%d\n",
i + 1,
i + 1);
9989 int end_hour = tms.tm_hour;
9993 r->
rsprintf(
" Hour: <input type=\"text\" size=5 maxlength=5 name=\"h2\" value=\"%d\">", end_hour);
9995 r->
rsprintf(
" Year: <input type=\"text\" size=5 maxlength=5 name=\"y2\" value=\"%d\">", tms.tm_year);
10001 r->
rsprintf(
"</body></html>\r\n");
10011 const char*sa = (
const char*)a;
10012 const char*sb = (
const char*)b;
10021 printf(
"compare [%s] and [%s]\n", sa, sb);
10024 if (sa[
i]==0 && sb[
i]==0)
10029 if (isdigit(sa[
i]) && isdigit(sb[
i])) {
10030 int va = atoi(sa+
i);
10031 int vb = atoi(sb+
i);
10034 printf(
"index %d, values %d %d\n",
i, va, vb);
10045 if (sa[
i]==sb[
i]) {
10050 printf(
"index %d, char [%c] [%c]\n",
i, sa[
i], sb[
i]);
10054 else if (sb[
i] == 0)
10068 return cmp_names(a.c_str(), b.c_str()) < 0;
10082static int cmp_tags(
const void *a,
const void *b)
10084 const TAG*sa = (
const TAG*)a;
10085 const TAG*sb = (
const TAG*)b;
10089static void sort_tags(
int ntags,
TAG* tags)
10121 str =
"bad_xdb_find_key";
10141 printf(
"hist plot: %d variables\n", (
int)hp.
vars.size());
10142 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);
10144 for (
size_t i=0;
i<hp.
vars.size();
i++) {
10145 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);
10151 const char*
const colour[] =
10153 "#00AAFF",
"#FF9000",
"#FF00A0",
"#00C030",
10154 "#A0C0D0",
"#D0A060",
"#C04010",
"#807060",
10155 "#F0C000",
"#2090A0",
"#D040D0",
"#90B000",
10156 "#B0B040",
"#B0B0FF",
"#FFA0A0",
"#A0FFA0",
10159 for (
int i=0; colour[
i];
i++) {
10160 bool in_use =
false;
10162 for (
size_t j=0;
j<hp.
vars.size();
j++)
10163 if (hp.
vars[
j].colour == colour[
i]) {
10178 for (
size_t i=0;
i<hp.
vars.size();
i++)
10179 if (hp.
vars[
i].order > order)
10180 order = hp.
vars[
i].order;
10188 std::vector<size_t> colons;
10192 colons.push_back(
i);
10196 if (colons.size() == 0) {
10201 size_t slash_pos =
var_name.find(
"/");
10202 bool uses_per_variable_naming = (slash_pos != std::string::npos);
10204 if (uses_per_variable_naming && colons.size() % 2 == 1) {
10205 size_t middle_colon_pos = colons[colons.size() / 2];
10206 std::string slash_to_mid =
var_name.substr(slash_pos + 1, middle_colon_pos - slash_pos - 1);
10207 std::string mid_to_end =
var_name.substr(middle_colon_pos + 1);
10209 if (slash_to_mid == mid_to_end) {
10213 split_pos = middle_colon_pos;
10216 split_pos = colons[0];
10220 split_pos = colons[0];
10223 event_name =
var_name.substr(0, split_pos);
10224 tag_name =
var_name.substr(split_pos + 1);
10230 std::string path =
"History/Display/";
10235 MVOdb* o = odb->Chdir(path.c_str());
10241 o->RD(
"Minimum", &hp->
minimum);
10242 o->RD(
"Maximum", &hp->
maximum);
10252 std::vector<std::string> hist_vars;
10253 std::vector<std::string> hist_formula;
10254 std::vector<std::string> hist_colour;
10255 std::vector<std::string> hist_label;
10256 std::vector<bool> hist_show_raw_value;
10257 std::vector<double> hist_factor;
10258 std::vector<double> hist_offset;
10259 std::vector<double> hist_voffset;
10261 o->RSA(
"Variables", &hist_vars);
10262 o->RSA(
"Formula", &hist_formula);
10263 o->RSA(
"Colour", &hist_colour);
10264 o->RSA(
"Label", &hist_label);
10265 o->RBA(
"Show raw value", &hist_show_raw_value);
10266 o->RDA(
"Factor", &hist_factor);
10267 o->RDA(
"Offset", &hist_offset);
10268 o->RDA(
"VOffset", &hist_voffset);
10274 bool all_zero =
true;
10275 for (
size_t i=0;
i<hist_factor.size();
i++) {
10276 if (hist_factor[
i] != 0)
10280 for (
size_t i=0;
i<hist_factor.size();
i++) {
10281 hist_factor[
i] = 1.0;
10286 size_t num = std::max(hist_vars.size(), hist_formula.size());
10287 num = std::max(num, hist_colour.size());
10288 num = std::max(num, hist_label.size());
10289 num = std::max(num, hist_show_raw_value.size());
10290 num = std::max(num, hist_factor.size());
10291 num = std::max(num, hist_offset.size());
10292 num = std::max(num, hist_voffset.size());
10294 hist_vars.resize(num);
10295 hist_formula.resize(num);
10296 hist_colour.resize(num);
10297 hist_label.resize(num);
10298 hist_show_raw_value.resize(num);
10299 hist_factor.resize(num, 1.0);
10300 hist_offset.resize(num, 0.0);
10301 hist_voffset.resize(num, 0.0);
10303 for (
size_t i=0;
i<num;
i++) {
10310 v.
label = hist_label[
i];
10324 hp->
vars.push_back(v);
10397 hp->
vars.push_back(v);
10412 int seln = atoi(p->
getparam(
"seln"));
10413 for (
int i=0;
i<seln;
i++) {
10415 sprintf(
str,
"sel%d",
i);
10418 if (par.length() < 1)
10421 std::string event_name, tag_name;
10424 if (tag_name ==
"")
10434 hp.
vars.push_back(v);
10440 if (strlen(group) < 1) {
10441 cm_msg(
MERROR,
"SaveHistPlotToOdb",
"Error: Cannot write history plot to ODB, group \"%s\", panel \"%s\", invalid group name", group, panel);
10445 if (strlen(panel) < 1) {
10446 cm_msg(
MERROR,
"SaveHistPlotToOdb",
"Error: Cannot write history plot to ODB, group \"%s\", panel \"%s\", invalid panel name", group, panel);
10450 std::string path =
"History/Display/";
10458 MVOdb* o = odb->Chdir(path.c_str(),
true);
10460 o->WS(
"Timescale", hp.
timescale.c_str());
10461 o->WD(
"Minimum", hp.
minimum);
10462 o->WD(
"Maximum", hp.
maximum);
10471 std::vector<std::string> hist_vars;
10472 std::vector<std::string> hist_formula;
10473 std::vector<std::string> hist_colour;
10474 std::vector<std::string> hist_label;
10475 std::vector<bool> hist_show_raw_value;
10476 std::vector<double> hist_factor;
10477 std::vector<double> hist_offset;
10478 std::vector<double> hist_voffset;
10480 for (
size_t i=0;
i<hp.
vars.size();
i++) {
10481 hist_vars.push_back(hp.
vars[
i].event_name +
":" + hp.
vars[
i].tag_name);
10482 hist_formula.push_back(hp.
vars[
i].formula);
10483 hist_colour.push_back(hp.
vars[
i].colour);
10484 hist_label.push_back(hp.
vars[
i].label);
10485 hist_show_raw_value.push_back(hp.
vars[
i].show_raw_value);
10486 hist_factor.push_back(hp.
vars[
i].factor);
10487 hist_offset.push_back(hp.
vars[
i].offset);
10488 hist_voffset.push_back(hp.
vars[
i].voffset);
10491 if (hp.
vars.size() > 0) {
10492 o->WSA(
"Variables", hist_vars, 64);
10493 o->WSA(
"Formula", hist_formula, 64);
10496 o->WBA(
"Show raw value", hist_show_raw_value);
10497 o->WDA(
"Factor", hist_factor);
10498 o->WDA(
"Offset", hist_offset);
10499 o->WDA(
"VOffset", hist_voffset);
10501 o->Delete(
"Variables");
10502 o->Delete(
"Formula");
10503 o->Delete(
"Colour");
10504 o->Delete(
"Label");
10505 o->Delete(
"Show raw value");
10506 o->Delete(
"Factor");
10507 o->Delete(
"Offset");
10508 o->Delete(
"VOffset");
10519 bool something_deleted =
false;
10520 for (
unsigned i=0;
i<hp.
vars.size();
i++) {
10521 if (hp.
vars[
i].order <= 0) {
10523 something_deleted =
true;
10526 if (!something_deleted)
10535 bool need_sort =
false;
10536 for (
size_t i=1;
i<hp.
vars.size();
i++) {
10537 if (hp.
vars[
i-1].order >= hp.
vars[
i].order) {
10555 int max_display_events = 20;
10556 int max_display_tags = 200;
10557 char str[256], hcmd[256];
10559 odb->RI(
"History/MaxDisplayEvents", &max_display_events,
true);
10560 odb->RI(
"History/MaxDisplayTags", &max_display_tags,
true);
10562 mstrlcpy(hcmd, p->
getparam(
"hcmd"),
sizeof(hcmd));
10566 strcpy(hcmd,
"Refresh");
10586 if (strlen(p->
getparam(
"seln")) > 0)
10597 sprintf(
str,
"?cmd=oldhistory&group=%s&panel=%s", hgroup, hpanel);
10606 r->
rsprintf(
"<table class=\"mtable\">");
10608 r->
rsprintf(
"<tr><th colspan=11 class=\"subStatusTitle\">History Panel \"%s\" / \"%s\"</th></tr>\n", hgroup, hpanel);
10611 r->
rsprintf(
"<tr><td colspan=11>\n");
10613 r->
rsprintf(
"<input type=button value=Refresh ");
10614 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">\n");
10616 r->
rsprintf(
"<input type=button value=Save ");
10617 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Save';document.form1.submit()\">\n");
10620 r->
rsprintf(
"<input type=button value=Cancel ");
10621 std::string url =
"?cmd=oldhistory&group=";
10625 url +=
"&hcmd=Cancel";
10630 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10633 r->
rsprintf(
"<input type=button value=\"Edit in ODB\"");
10634 std::string url =
"?cmd=odb&odb_path=";
10635 url +=
"/History/Display/";
10639 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10642 r->
rsprintf(
"<input type=button value=\"Edit in new editor\"");
10643 std::string url =
"?cmd=hs_edit";
10652 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10654 r->
rsprintf(
"<input type=button value=\"Clear history cache\"");
10655 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Clear history cache';document.form1.submit()\">\n");
10656 r->
rsprintf(
"<input type=button value=\"Delete panel\"");
10657 r->
rsprintf(
"onclick=\"window.location.search='?cmd=oldhistory&group=%s&panel=%s&hcmd=Delete%%20panel'\">\n", hgroup, hpanel);
10660 r->
rsprintf(
"<tr><td colspan=11>\n");
10663 int sort_vars = *p->
getparam(
"sort_vars");
10664 r->
rsprintf(
"<input type=checkbox %s name=sort_vars value=1 onclick=\"this.form.submit();\">Sort variable names", sort_vars?
"checked":
"");
10667 int old_vars = *p->
getparam(
"old_vars");
10668 r->
rsprintf(
" <input type=checkbox %s name=old_vars value=1 onclick=\"this.form.submit();\">Show deleted and renamed variables", old_vars?
"checked":
"");
10671 r->
rsprintf(
" <input type=checkbox checked name=show_factor value=1 onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">");
10673 r->
rsprintf(
" <input type=checkbox name=show_factor value=1 onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">");
10674 r->
rsprintf(
"Show factor and offset\n");
10677 r->
rsprintf(
"<input type=hidden name=cmd value=Oldhistory>\n");
10678 r->
rsprintf(
"<input type=hidden name=hcmd value=Refresh>\n");
10679 r->
rsprintf(
"<input type=hidden name=panel value=\"%s\">\n", hpanel);
10680 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", hgroup);
10683 r->
rsprintf(
"<input type=hidden name=redir value=\"%s\">\n", p->
getparam(
"redir"));
10687 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Time scale (in units 'm', 'h', 'd'):</td>\n");
10688 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());
10690 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Minimum (set to '-inf' for autoscale):</td>\n");
10691 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=minimum value=%f></td><td colspan=4></td></tr>\n", hp.
minimum);
10693 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Maximum (set to 'inf' for autoscale):</td>\n");
10694 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=maximum value=%f></td><td colspan=4></td></tr>\n", hp.
maximum);
10696 r->
rsprintf(
"<tr><td colspan=11>");
10699 r->
rsprintf(
"<input type=checkbox checked name=zero_ylow value=1>");
10701 r->
rsprintf(
"<input type=checkbox name=zero_ylow value=1>");
10702 r->
rsprintf(
"Zero Y; axis\n");
10705 r->
rsprintf(
"<input type=checkbox checked name=log_axis value=1>");
10707 r->
rsprintf(
"<input type=checkbox name=log_axis value=1>");
10708 r->
rsprintf(
"Logarithmic Y axis\n");
10711 r->
rsprintf(
" <input type=checkbox checked name=run_markers value=1>");
10713 r->
rsprintf(
" <input type=checkbox name=run_markers value=1>");
10714 r->
rsprintf(
"Show run markers\n");
10717 r->
rsprintf(
" <input type=checkbox checked name=show_values value=1>");
10719 r->
rsprintf(
" <input type=checkbox name=show_values value=1>");
10720 r->
rsprintf(
"Show values of variables\n");
10723 r->
rsprintf(
" <input type=checkbox checked name=show_fill value=1>");
10725 r->
rsprintf(
" <input type=checkbox name=show_fill value=1>");
10726 r->
rsprintf(
"Show graph fill\n");
10740 time_t t = time(NULL);
10745 std::vector<std::string> events;
10750 if (events.size() == 0)
10754 for (
unsigned i=0;
i<events.size();
i++)
10755 printf(
"event %d: \"%s\"\n",
i, events[
i].c_str());
10760 std::sort(events.begin(), events.end(),
cmp_events1);
10762 if (strlen(p->
getparam(
"cmdx")) > 0) {
10763 r->
rsprintf(
"<tr><th colspan=8 class=\"subStatusTitle\">List of available history variables</th></tr>\n");
10764 r->
rsprintf(
"<tr><th colspan=1>Sel<th colspan=1>Equipment<th colspan=1>Event<th colspan=1>Variable</tr>\n");
10766 std::string cmdx = p->
xgetparam(
"cmdx");
10767 std::string xeqname;
10770 for (
unsigned e=0;
e<events.size();
e++) {
10771 std::string eqname;
10772 eqname = events[
e].substr(0, events[
e].find(
"/"));
10774 if (eqname.length() < 1)
10775 eqname = events[
e];
10778 if (eqname != xeqname)
10781 std::string qcmd =
"Expand " + eqname;
10785 bool collapsed =
true;
10790 if (strlen(p->
getparam(qcmd.c_str())) > 0)
10794 if (eqname == xeqname)
10799 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10800 r->
rsprintf(
"<td><input type=submit name=cmdx value=\"%s\"></td>\n", qcmd.c_str());
10808 r->
rsprintf(
"<tr><input type=hidden name=\"%s\" value=%d></tr>\n", qcmd.c_str(), 1);
10810 std::string rcmd =
"Expand " + events[
e];
10819 if (strlen(p->
getparam(rcmd.c_str())) > 0)
10825 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10826 r->
rsprintf(
"<td>%s</td>\n", events[
e].c_str());
10827 r->
rsprintf(
"<td><input type=submit name=cmdx value=\"%s\"></td>\n", rcmd.c_str());
10832 r->
rsprintf(
"<tr><input type=hidden name=\"%s\" value=%d></tr>\n", rcmd.c_str(), 1);
10836 std::vector<TAG> tags;
10843 std::sort(tags.begin(), tags.end(),
cmp_tags);
10845 for (
unsigned v=0; v<tags.size(); v++) {
10847 for (
unsigned j=0;
j<tags[v].n_data;
j++) {
10850 if (tags[v].n_data == 1)
10851 sprintf(tagname,
"%s", tags[v].
name);
10853 sprintf(tagname,
"%s[%d]", tags[v].
name,
j);
10855 bool checked =
false;
10866 r->
rsprintf(
"<td><input type=checkbox %s name=\"sel%d\" value=\"%s:%s\"></td>\n", checked?
"checked":
"",
i++, events[
e].c_str(), tagname);
10867 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10868 r->
rsprintf(
"<td>%s</td>\n", events[
e].c_str());
10869 r->
rsprintf(
"<td>%s</td>\n", tagname);
10879 r->
rsprintf(
"<input type=hidden name=seln value=%d>\n",
i);
10880 r->
rsprintf(
"<input type=submit value=\"Add Selected\">\n");
10885 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>New history: displayed_value = formula(history_value)</td></tr>\n");
10886 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>Old history: displayed_value = offset + factor*(history_value - voffset)</td></tr>\n");
10887 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");
10888 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");
10889 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");
10890 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");
10893 r->
rsprintf(
"<th>Col<th>Event<th>Variable<th>Formula<th>Colour<th>Label<th>Raw<th>Order");
10895 r->
rsprintf(
"<th>Factor<th>Offset<th>VOffset");
10901 size_t nvars = hp.
vars.size();
10906 if (
index < nvars) {
10909 r->
rsprintf(
"<td style=\"background-color:%s\"> <td>\n", hp.
vars[
index].colour.c_str());
10916 r->
rsprintf(
"<select name=\"event%d\" size=1 onChange=\"document.form1.submit()\">\n", (
int)
index);
10921 r->
rsprintf(
"<option value=\"/empty\"><empty>\n");
10923 if (
index==nvars) {
10924 for (
unsigned e=0;
e<events.size();
e++) {
10925 const char *p = events[
e].c_str();
10926 r->
rsprintf(
"<option value=\"%s\">%s\n", p, p);
10928 }
else if ((
int)events.size() > max_display_events) {
10930 r->
rsprintf(
"<option>(%d events omitted)\n", (
int)events.size());
10932 bool found =
false;
10933 for (
unsigned e=0;
e<events.size();
e++) {
10934 const char *s =
"";
10935 const char *p = events[
e].c_str();
10940 r->
rsprintf(
"<option %s value=\"%s\">%s\n", s, p, p);
10943 const char *p = hp.
vars[
index].event_name.c_str();
10944 r->
rsprintf(
"<option selected value=\"%s\">%s\n", p, p);
10953 if (
index < nvars) {
10954 bool found_tag =
false;
10955 std::string selected_tag = hp.
vars[
index].tag_name;
10959 std::vector<TAG> tags;
10966 printf(
"Compare %d\n",
cmp_names(
"AAA",
"BBB"));
10967 printf(
"Compare %d\n",
cmp_names(
"BBB",
"AAA"));
10968 printf(
"Compare %d\n",
cmp_names(
"AAA",
"AAA"));
10969 printf(
"Compare %d\n",
cmp_names(
"A",
"AAA"));
10970 printf(
"Compare %d\n",
cmp_names(
"A111",
"A1"));
10971 printf(
"Compare %d\n",
cmp_names(
"A111",
"A2"));
10972 printf(
"Compare %d\n",
cmp_names(
"A111",
"A222"));
10973 printf(
"Compare %d\n",
cmp_names(
"A111a",
"A111b"));
10977 std::sort(tags.begin(), tags.end(),
cmp_tags);
10980 printf(
"Event [%s] %d tags\n", hp.
vars[
index].event_name.c_str(), (
int)tags.size());
10982 for (
unsigned v=0; v<tags.size(); v++) {
10983 printf(
"tag[%d] [%s]\n", v, tags[v].
name);
10987 unsigned count_tags = 0;
10988 for (
unsigned v=0; v<tags.size(); v++)
10989 count_tags += tags[v].n_data;
10993 if ((
int)count_tags < max_display_tags) {
10994 for (
unsigned v=0; v<tags.size(); v++) {
10996 for (
unsigned j=0;
j<tags[v].n_data;
j++) {
10997 std::string tagname;
10999 if (tags[v].n_data == 1)
11000 tagname = tags[v].name;
11003 sprintf(buf,
"[%d]",
j);
11004 tagname = std::string(tags[v].
name) + buf;
11007 if (
equal_ustring(selected_tag.c_str(), tagname.c_str())) {
11008 r->
rsprintf(
"<option selected value=\"%s\">%s\n", tagname.c_str(), tagname.c_str());
11012 r->
rsprintf(
"<option value=\"%s\">%s\n", tagname.c_str(), tagname.c_str());
11021 if (hp.
vars[
index].tag_name.length() > 0)
11025 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());
11026 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());
11029 r->
rsprintf(
"<td><input type=checkbox checked name=\"raw%d\" value=1></td>", (
int)
index);
11031 r->
rsprintf(
"<td><input type=checkbox name=\"raw%d\" value=1></td>", (
int)
index);
11032 r->
rsprintf(
"<td><input type=text size=3 maxlength=32 name=\"ord%d\" value=\"%d\"></td>\n", (
int)
index, hp.
vars[
index].order);
11034 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"factor%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].factor);
11035 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"offset%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].offset);
11036 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"voffset%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].voffset);
11040 r->
rsprintf(
"<input type=hidden name=\"voffset%d\" value=\"%f\">\n", (
int)
index, hp.
vars[
index].voffset);
11043 r->
rsprintf(
"<td colspan=2><input type=submit name=cmdx value=\"List all variables\"></td>\n");
11053 r->
rsprintf(
"</body></html>\r\n");
11073 sprintf(
str,
"/History/Display/%s/%s", group, panel);
11076 sprintf(
str,
"Cannot find /History/Display/%s/%s in ODB\n", group, panel);
11082 BOOL runmarker = 1;
11083 size =
sizeof(runmarker);
11088 std::string
ts =
"1h";
11113 time_t starttime = endtime - scale;
11120 sprintf(
str,
"History error, status %d\n",
status);
11128 int *i_var = (
int *)malloc(
sizeof(
int)*hsdata->
nvars);
11130 assert(i_var != NULL);
11132 for (
int i = 0;
i < hsdata->
nvars;
i++)
11138 for (
int i = 0;
i < hsdata->
nvars;
i++)
11141 if ((t == 0) || (hsdata->
t[
i][0] > t))
11142 t = hsdata->
t[
i][0];
11144 if (t == 0 && hsdata->
nvars > 1) {
11145 show_error(r,
"No history available for choosen period");
11150 int run_index = -1;
11151 int state_index = -1;
11152 int n_run_number = 0;
11153 time_t* t_run_number = NULL;
11155 for (
int i = 0;
i < hsdata->
nvars;
i++) {
11158 t_run_number = hsdata->
t[
i];
11168 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
11170 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
11171 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
11172 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
11173 r->
rsprintf(
"Content-Type: text/plain\r\n");
11174 r->
rsprintf(
"Content-disposition: attachment; filename=\"export.csv\"\r\n");
11179 r->
rsprintf(
"Time, Timestamp, Run, Run State, ");
11183 for (
int i = 0, first = 1;
i < hsdata->
nvars;
i++) {
11200 printf(
"hsdata %p, t %d, irun %d\n", hsdata, (
int)t, i_run);
11204 while (i_run < n_run_number-1 && t_run_number[i_run+1] <= t)
11210 for (
int i = 0;
i < hsdata->
nvars;
i++)
11216 for (
int i = 0 ;
i < hsdata->
nvars ;
i++)
11223 printf(
"step to time %d: ", (
int)t);
11224 for (
int i = 0;
i < hsdata->
nvars;
i++) {
11227 printf(
" done: %d\n",
done);
11234 localtime_r(&t, &tms);
11238 strcpy(fmt,
"%Y.%m.%d %H:%M:%S");
11240 strftime(
str,
sizeof(
str), fmt, &tms);
11242 if (t_run_number && run_index>=0 && state_index>=0) {
11243 if (t_run_number[i_run] <= t)
11244 r->
rsprintf(
"%s, %d, %.0f, %.0f, ",
str, (
int)t, hsdata->
v[run_index][i_run], hsdata->
v[state_index][i_run]);
11251 for (
int i= 0 ;
i < hsdata->
nvars ;
i++)
11252 printf(
" %d (%g)", i_var[
i], hsdata->
v[
i][i_var[
i]]);
11256 for (
int i=0, first=1 ;
i<hsdata->
nvars ;
i++) {
11271 for (
int i = 0 ;
i < hsdata->
nvars ;
i++)
11273 int xdt = hsdata->
t[
i][i_var[
i]+1] - t;
11275 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);
11276 if (dt <= 0 || xdt < dt)
11281 printf(
"dt %d\n", dt);
11297 HNDLE hDB, hkey, hikeyp, hkeyp, hkeybutton;
11300 char hgroup[256], hpanel[256], hcmd[256];
11301 const char def_button[][
NAME_LENGTH] = {
"10m",
"1h",
"3h",
"12h",
"24h",
"3d",
"7d" };
11305 hcmd[0] = hgroup[0] = hpanel[0] = 0;
11308 mstrlcpy(hgroup, p->
getparam(
"group"),
sizeof(hgroup));
11310 mstrlcpy(hpanel, p->
getparam(
"panel"),
sizeof(hpanel));
11312 mstrlcpy(hcmd, p->
getparam(
"hcmd"),
sizeof(hcmd));
11317 redir +=
"?cmd=oldhistory&group=";
11319 redir +=
"&panel=";
11336 redir +=
"?cmd=oldhistory&group=";
11338 redir +=
"&panel=";
11357 r->
rsprintf(
"<table class=\"dialogTable\">");
11358 r->
rsprintf(
"<tr><th class=\"subStatusTitle\" colspan=2>New History Item</th><tr>");
11359 r->
rsprintf(
"<tr><td align=center colspan=2>\n");
11360 r->
rsprintf(
"Select group: ");
11361 r->
rsprintf(
"<select id=\"group\" name=\"group\">\n");
11367 for (
i = 0;;
i++) {
11380 if (!hkey ||
i == 0)
11381 r->
rsprintf(
"<option>Default</option>\n");
11384 r->
rsprintf(
"Or enter new group name: ");
11385 r->
rsprintf(
"<input type=text size=15 maxlength=31 id=new_group name=new_group>\n");
11387 r->
rsprintf(
"<tr><td align=center colspan=2>\n");
11388 r->
rsprintf(
"<br>Panel name: ");
11389 r->
rsprintf(
"<input type=text size=15 maxlength=31 id=panel name=panel><br><br>\n");
11392 r->
rsprintf(
"<tr><td align=center colspan=2>");
11393 std::string
str =
"?cmd=oldhistory&hcmd=createnew";
11394 str +=
"&new_group='+document.getElementById('new_group').value+'";
11395 str +=
"&group='+document.getElementById('group').value+'";
11396 str +=
"&panel='+document.getElementById('panel').value+'";
11397 r->
rsprintf(
"<input type=button value=Submit onclick=\"window.location.search='%s'\">\n",
str.c_str());
11403 r->
rsprintf(
"</body></html>\r\n");
11410 path +=
"/History/Display/";
11422 while (hpanel[0] ==
' ') {
11424 mstrlcpy(
str, hpanel+1,
sizeof(
str));
11425 mstrlcpy(hpanel,
str,
sizeof(hpanel));
11427 while (strlen(hpanel)> 1 && hpanel[strlen(hpanel)-1] ==
' ')
11428 hpanel[strlen(hpanel)-1] = 0;
11432 mstrlcpy(hgroup, p->
getparam(
"new_group"),
sizeof(hgroup));
11439 const char* pscale = p->
getparam(
"scale");
11440 if (pscale == NULL || *pscale == 0)
11442 const char* pwidth = p->
getparam(
"width");
11443 if (pwidth == NULL || *pwidth == 0)
11445 const char* pheight = p->
getparam(
"height");
11446 if (pheight == NULL || *pheight == 0)
11448 const char* pindex = p->
getparam(
"index");
11449 if (pindex == NULL || *pindex == 0)
11456 std::string bgcolor =
"FFFFFF";
11460 std::string fgcolor =
"000000";
11464 std::string gridcolor =
"A0A0A0";
11470 time_t endtime = 0;
11473 else if (p->
isparam(
"htime"))
11476 if (pscale && *pscale)
11482 if (pindex && *pindex)
11483 index = atoi(pindex);
11495 char* fbuffer = (
char*)
M_MALLOC(fsize);
11496 assert(fbuffer != NULL);
11507 }
else if (atoi(pmag) > 0) {
11508 width = atoi(pmag);
11513 generate_hist_graph(odb, r, hgroup, hpanel, fbuffer, &fsize, width, height, endtime, scale,
index, labels, bgcolor.c_str(), fgcolor.c_str(), gridcolor.c_str());
11518 if (dir.length() > 0 && dir[dir.length()-1] !=
DIR_SEPARATOR)
11521 time_t now = time(NULL);
11522 localtime_r(&now, &tms);
11525 tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday,
11526 tms.tm_hour, tms.tm_min, tms.tm_sec, hpanel);
11530 fh = open(fname.c_str(), O_CREAT | O_RDWR |
O_BINARY, 0644);
11532 cm_msg(
MERROR,
"show_hist_page",
"Cannot write attachment file \"%s\", open() errno %d (%s)", fname.c_str(), errno, strerror(errno));
11534 int wr =
write(fh, fbuffer, fsize);
11536 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));
11542 if (strlen(url) > 1 && url[strlen(url)-1] !=
'/')
11543 mstrlcat(url,
"/",
sizeof(url));
11544 mstrlcat(url,
"?cmd=New&fa=",
sizeof(url));
11553 std::string
str =
msprintf(
"\\HS\\%s.gif", hpanel);
11557 if (strchr(
str.c_str(),
'?'))
11571 if (strchr(
str.c_str(),
'?'))
11578 if (strchr(
str.c_str(),
'?'))
11585 show_elog_new(r, hpanel, NULL,
FALSE,
str.c_str(),
"../../EL/");
11596 if (strstr(dec_path,
".gif")) {
11605 }
else if (atoi(pwidth) > 0) {
11606 width = atoi(pwidth);
11607 if (atoi(pheight) > 0)
11608 height = atoi(pheight);
11610 height = (int)(0.625 * width);
11615 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());
11623 time_t now = time(NULL);
11629 time_t last_written = 0;
11632 endtime = last_written + scale/2;
11638 time_t last_written = 0;
11641 if (last_written != endtime)
11642 endtime = last_written + scale/2;
11648 endtime -= scale/2;
11655 endtime += scale/2;
11667 endtime -= scale / 4;
11674 endtime += scale / 2;
11680 int xrefresh = refresh;
11685 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
11686 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
11689 r->
rsprintf(
"<table class=\"mtable\">");
11690 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>History</th></tr>");
11696 path +=
"/History/Display/";
11702 r->
rsprintf(
"<h1>Error: History panel \"%s\" in group \"%s\" does not exist</h1>\n", hpanel, hgroup);
11706 r->
rsprintf(
"</body></html>\r\n");
11712 if (pscale && *pscale)
11713 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%d>\n", scale);
11716 if (hpanel[0] && !
equal_ustring(hpanel,
"All") && hgroup[0]) {
11718 path +=
"/History/Display/";
11722 path +=
"/Timescale";
11724 std::string scalestr =
"1h";
11733 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%s>\n", scalestr.c_str());
11740 if (pwidth && *pwidth)
11741 r->
rsprintf(
"<input type=hidden name=hwidth id=hwidth value=%s>\n", pwidth);
11742 if (pheight && *pheight)
11743 r->
rsprintf(
"<input type=hidden name=hheight id=hheight value=%s>\n", pheight);
11744 if (pindex && *pindex)
11745 r->
rsprintf(
"<input type=hidden name=hindex id=hindex value=%s>\n", pindex);
11749 if (hgroup[0] == 0) {
11751 r->
rsprintf(
"<tr><td colspan=2><input type=\"button\" name=\"New\" value=\"New\" ");
11752 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New'\"></td></tr>\n");
11755 r->
rsprintf(
"<tr><td colspan=2 style=\"text-align:left;\">\n");
11757 r->
rsprintf(
"<b>Please select panel:</b><br>\n");
11760 r->
rsprintf(
"<table class=\"historyTable\">");
11763 r->
rsprintf(
"<tr><td colspan=2 class=\"titleCell\">\n");
11767 r->
rsprintf(
"<a href=\"?cmd=oldhistory&group=All\">ALL</a>\n");
11775 strcpy(
str,
"System:Trigger per sec.");
11795 for (
i = 0;;
i++) {
11804 char enc_name[256];
11805 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11811 r->
rsprintf(
"<tr><td class=\"titleCell\"><a href=\"?cmd=oldhistory&group=%s\">%s</a></td>\n<td>", enc_name,
key.
name);
11813 for (
j = 0;;
j++) {
11824 char enc_iname[256];
11825 mstrlcpy(enc_iname, ikey.
name,
sizeof(enc_iname));
11826 urlEncode(enc_iname,
sizeof(enc_iname));
11829 r->
rsprintf(
"<small><b>%s</b></small> ", ikey.
name);
11831 r->
rsprintf(
"<small><a href=\"?cmd=oldhistory&group=%s&panel=%s\">%s</a></small> \n", enc_name, enc_iname, ikey.
name);
11842 r->
rsprintf(
"<tr><td colspan=2>\n");
11846 r->
rsprintf(
"<select title=\"Select group\" id=\"fgroup\" onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value;\">\n");
11851 for (
i = 0;;
i++) {
11871 r->
rsprintf(
"<option selected value=\"%s\">%s\n",
"ALL",
"ALL");
11873 r->
rsprintf(
"<option value=\"%s\">%s\n",
"ALL",
"ALL");
11877 r->
rsprintf(
" Panel:\n");
11878 r->
rsprintf(
"<select title=\"Select panel\" id=\"fpanel\" ");
11879 r->
rsprintf(
"onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value+");
11880 r->
rsprintf(
"'&panel='+document.getElementById('fpanel').value;\">\n");
11884 for (
i = 0;;
i++) {
11903 r->
rsprintf(
"<option value=\"\">- all -\n");
11905 r->
rsprintf(
"<option selected value=\"\">- all -\n");
11911 r->
rsprintf(
"<input type=submit value=\"Go\">\n");
11914 r->
rsprintf(
" <input type=\"button\" name=\"New\" value=\"New\" ");
11915 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New&group=%s'\">\n", hgroup);
11917 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Reset\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Reset&group=%s&panel=%s'\">\n", hgroup, hpanel);
11919 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Query\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Query&group=%s&panel=%s'\">\n", hgroup, hpanel);
11921 double xendtime = endtime;
11924 double xstarttime = xendtime - scale;
11926 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);
11934 if (hgroup[0] && !
equal_ustring(hgroup,
"ALL") && hpanel[0] == 0) {
11935 std::string strwidth =
"Small";
11939 path +=
"/History/Display/";
11943 for (
i = 0 ;;
i++) {
11951 char enc_name[256];
11952 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11956 ref +=
"graph.gif?width=";
11958 ref +=
"&cmd=oldhistory&group=";
11964 ref2 +=
"?cmd=oldhistory&group=";
11969 if (endtime != 0) {
11971 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
11979 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
11981 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
11985 r->
rsprintf(
"Group \"%s\" not found", hgroup);
11995 path +=
"/History/Display/";
11999 path +=
"/Buttons";
12001 if (hkeybutton == 0) {
12006 cm_msg(
MERROR,
"show_hist_page",
"Cannot create history panel with invalid ODB path \"%s\"", path.c_str());
12013 r->
rsprintf(
"function histDisp(p) {\n");
12014 r->
rsprintf(
" var params = '?cmd=oldhistory&group=%s&panel=%s';\n", hgroup, hpanel);
12015 r->
rsprintf(
" params += '&'+p;\n");
12016 r->
rsprintf(
" if (document.getElementById(\'hscale\') !== null)\n");
12017 r->
rsprintf(
" params += '&hscale='+document.getElementById(\'hscale\').value;\n");
12018 r->
rsprintf(
" if (document.getElementById(\'htime\') !== null)\n");
12019 r->
rsprintf(
" params += '&htime='+document.getElementById(\'htime\').value;\n");
12020 r->
rsprintf(
" if (document.getElementById(\'hwdith\') !== null)\n");
12021 r->
rsprintf(
" params += '&hwidth='+document.getElementById(\'hwidth\').value;\n");
12022 r->
rsprintf(
" if (document.getElementById(\'hindex\') !== null)\n");
12023 r->
rsprintf(
" params += '&hindex='+document.getElementById(\'hindex\').value;\n");
12024 r->
rsprintf(
" window.location.search = params;\n");
12032 size =
sizeof(
str);
12034 r->
rsprintf(
"<input type=\"button\" title=\"display last %s\" value=%s onclick=\"histDisp('scale=%s')\">\n",
str,
str,
str);
12037 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')\">");
12038 r->
rsprintf(
"<input type=\"button\" value=\"<<\" title=\"go back in time to last available data\" onclick=\"histDisp('shift=leftmax')\">");
12039 r->
rsprintf(
"<input type=\"button\" value=\"<\" title=\"go back in time\" onclick=\"histDisp('shift=left')\">");
12041 r->
rsprintf(
"<input type=\"button\" value=\" + \" title=\"zoom in\" onclick=\"histDisp('shift=zoomin')\">");
12042 r->
rsprintf(
"<input type=\"button\" value=\" - \" title=\"zoom out\" onclick=\"histDisp('shift=zoomout')\">");
12044 if (endtime != 0) {
12045 r->
rsprintf(
"<input type=\"button\" value=\">\" title=\"go forward in time\" onclick=\"histDisp('shift=right')\">");
12046 r->
rsprintf(
"<input type=\"button\" value=\">>\" title=\"go to currently updated fresh data\" onclick=\"histDisp('shift=rightmax')\">");
12050 r->
rsprintf(
"<input type=\"button\" value=\"Large\" title=\"large display\" onclick=\"histDisp('width=Large')\">\n");
12051 r->
rsprintf(
"<input type=\"button\" value=\"Small\" title=\"large display\" onclick=\"histDisp('width=Small')\">\n");
12052 r->
rsprintf(
"<input type=\"button\" value=\"Create Elog\" title=\"large display\" onclick=\"histDisp('hcmd=Create Elog')\">\n");
12053 r->
rsprintf(
"<input type=\"button\" value=\"Config\" title=\"large display\" onclick=\"histDisp('hcmd=Config')\">\n");
12054 r->
rsprintf(
"<input type=\"button\" value=\"Export\" title=\"large display\" onclick=\"histDisp('hcmd=Export')\">\n");
12057 char paramstr[256];
12060 sprintf(paramstr + strlen(paramstr),
"&scale=%d", scale);
12062 sprintf(paramstr + strlen(paramstr),
"&time=%s",
time_to_string(endtime).c_str());
12063 if (pwidth && *pwidth)
12064 sprintf(paramstr + strlen(paramstr),
"&width=%s", pwidth);
12066 std::string wi =
"640";
12068 sprintf(paramstr + strlen(paramstr),
"&width=%s", wi.c_str());
12070 if (pheight && *pheight)
12071 sprintf(paramstr + strlen(paramstr),
"&height=%s", pheight);
12074 r->
rsprintf(
"<map name=\"%s\">\r\n", hpanel);
12076 if (!(pindex && *pindex)) {
12078 path +=
"/History/Display/";
12082 path +=
"/Variables";
12095 ref +=
"?cmd=oldhistory&group=";
12106 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());
12110 std::string ref =
"?cmd=oldhistory&group=";
12124 else if (atoi(pwidth) > 0)
12125 width = atoi(pwidth);
12129 r->
rsprintf(
" <area shape=rect coords=\"%d,%d,%d,%d\" href=\"%s\">\r\n", 0, 0, width, 20, ref.c_str());
12135 if (pindex && *pindex)
12136 sprintf(paramstr + strlen(paramstr),
"&index=%s", pindex);
12140 ref +=
"graph.gif?cmd=oldhistory&group=";
12147 r->
rsprintf(
"<tr><td colspan=2><img src=\"%s\" usemap=\"#%s\"></tr>\n", ref.c_str(), hpanel);
12154 for (
i = 0,
k = 0;;
i++) {
12162 char enc_group_name[256];
12163 mstrlcpy(enc_group_name,
key.
name,
sizeof(enc_group_name));
12164 urlEncode(enc_group_name,
sizeof(enc_group_name));
12166 for (
j = 0;;
j++,
k++) {
12175 char enc_panel_name[256];
12176 mstrlcpy(enc_panel_name, ikey.
name,
sizeof(enc_panel_name));
12177 urlEncode(enc_panel_name,
sizeof(enc_panel_name));
12180 ref +=
"graph.gif?width=Small";
12181 ref +=
"&cmd=oldhistory&group=";
12182 ref += enc_group_name;
12184 ref += enc_panel_name;
12187 ref2 +=
"?cmd=oldhistory&group=";
12188 ref2 += enc_group_name;
12190 ref2 += enc_panel_name;
12192 if (endtime != 0) {
12194 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
12202 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
12204 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
12211 r->
rsprintf(
"</body></html>\r\n");
12220 const unsigned char *picon;
12221 char str[256], format[256];
12224 if (strstr(icon,
"favicon.ico") != 0) {
12227 }
else if (strstr(icon,
"favicon.png") != 0) {
12233 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
12235 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
12239 now += (int) (3600 * 24);
12241 gmtime_r(&now, &gmt_tms);
12242 strcpy(format,
"%A, %d-%b-%y %H:%M:%S GMT");
12243 strftime(
str,
sizeof(
str), format, &gmt_tms);
12247 r->
rsprintf(
"Content-Type: image/x-icon\r\n");
12249 r->
rsprintf(
"Content-Type: image/png\r\n");
12251 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
12297 if (strstr(dec_path,
"favicon.ico") != 0 ||
12298 strstr(dec_path,
"favicon.png")) {
12303 const char* password = p->
getparam(
"pwd");
12304 const char* wpassword = p->
getparam(
"wpwd");
12305 const char* command = p->
getparam(
"cmd");
12328 if (!password[0] && hkey) {
12330 int size =
sizeof(
str);
12334 db_find_key(
hDB, 0,
"/Experiment/Security/Allowed programs/mhttpd", &hkey);
12335 if (hkey == 0 && strcmp(
c->cookie_pwd.c_str(),
str) != 0) {
12346 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12355 gmtime_r(&now, &gmt_tms);
12358 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12360 r->
rsprintf(
"Set-Cookie: midas_pwd=%s; path=/; expires=%s\r\n",
12363 r->
rsprintf(
"Location: ./\n\n<html>redir</html>\r\n");
12367 if (wpassword[0]) {
12372 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12381 gmtime_r(&now, &gmt_tms);
12384 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:%M:%S GMT", &gmt_tms);
12386 r->
rsprintf(
"Set-Cookie: midas_wpwd=%s; path=/; expires=%s\r\n",
ss_crypt(wpassword,
"mi"),
str);
12389 r->
rsprintf(
"Location: %s\n\n<html>redir</html>\r\n",
str);
12395 if (strlen(dec_path) > 3 &&
12396 dec_path[strlen(dec_path)-3] ==
'm' &&
12397 dec_path[strlen(dec_path)-2] ==
'p' &&
12398 dec_path[strlen(dec_path)-1] ==
'3') {
12399 if (strrchr(dec_path,
'/'))
12408 if (strstr(dec_path,
"midas.js")) {
12413 if (strstr(dec_path,
"midas.css")) {
12420 if (strstr(dec_path,
"mhttpd.js")) {
12427 if (strstr(dec_path,
"obsolete.js")) {
12434 if (strstr(dec_path,
"mhttpd.css")) {
12441 if (strstr(dec_path,
"controls.js")) {
12474 path +=
"/Script/";
12500 path +=
"/CustomScript/";
12501 path += p->
getparam(
"customscript");
12528 std::string filename = custom[
"Status"];
12572 !(dec_path[0] ==
'H' && dec_path[1] ==
'S' && dec_path[2] ==
'/')) {
12688 show_mscb_page(p, r,
c->refresh);
12690 show_error(r,
"MSCB support not compiled into this version of mhttpd");
12708 if (strncmp(command,
"Trigger", 7) == 0) {
12721 mstrlcpy(eq_name, command + 8,
sizeof(eq_name));
12722 if (strchr(eq_name,
' '))
12723 *strchr(eq_name,
' ') = 0;
12727 path +=
"/Equipment/";
12729 path +=
"/Common/Frontend name";
12736 path +=
"/Equipment/";
12738 path +=
"/Common/Event ID";
12745 str +=
"Frontend \"";
12747 str +=
"\" not running!";
12754 str +=
"Cannot connect to frontend \"";
12776 if (strncmp(command,
"Next Subrun", 11) == 0) {
12797 mstrlcpy(
str,
"?cmd=set",
sizeof(
str));
12801 const char* group = p->
getparam(
"group");
12823 if (
equal_ustring(command,
"CNAF") || strncmp(dec_path,
"CNAF", 4) == 0) {
12839 std::string external_elog_url;
12840 int size =
sizeof(external_elog);
12843 if (external_elog && (external_elog_url.length() > 0)) {
12844 redirect(r, external_elog_url.c_str());
12854 mstrlcpy(cmdx, command,
sizeof(cmdx));
12863 if (
equal_ustring(command,
"Create ELog from this page")) {
12865 redir +=
"?cmd=New+elog";
12866 redir +=
"&odb_path=";
12889 int refresh = atoi(p->
getparam(
"refr"));
12892 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12899 now += 3600 * 24 * 365;
12902 gmtime_r(&now, &gmt_tms);
12905 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12907 r->
rsprintf(
"Set-Cookie: midas_refr=%d; path=/; expires=%s\r\n", refresh,
str);
12908 r->
rsprintf(
"Location: ./\r\n\r\n<html>redir</html>\r\n");
12955 int write_access =
TRUE;
12956 db_find_key(
hDB, 0,
"/Experiment/Security/Web Password", &hkey);
12959 int size =
sizeof(
str);
12961 if (strcmp(
c->cookie_wpwd.c_str(),
str) == 0)
12962 write_access =
TRUE;
12964 write_access =
FALSE;
12967 std::string odb_path;
12969 odb_path = p->
getparam(
"odb_path");
13000 if ((command[0]==0) && dec_path[0]) {
13002 std::string new_url =
"./?cmd=odb";
13009 if ((command[0]==0) && dec_path[0]) {
13015 for (
const char* s = dec_path; *s; s++) {
13019 std::string new_url;
13024 for (
int i=0;
i<level;
i++) {
13030 new_url +=
"?cmd=odb";
13031 new_url +=
"&odb_path=";
13058 std::string odb_path;
13063 odb_path +=
"/Custom/Images/";
13064 odb_path += dec_path;
13065 odb_path +=
"/Background";
13072 if (strstr(dec_path,
"..")) {
13074 str +=
"Invalid custom gif name \'";
13076 str +=
"\' contains \'..\'";
13087 bool found_custom =
false;
13090 odb_path +=
"/Custom/";
13091 odb_path += dec_path;
13098 found_custom =
true;
13101 odb_path +=
"/Custom/";
13102 odb_path += dec_path;
13110 found_custom =
true;
13113 odb_path +=
"/Custom/";
13114 odb_path += dec_path;
13122 found_custom =
true;
13127 if (found_custom) {
13129 if (strstr(dec_path,
"..")) {
13131 str +=
"Invalid custom page name \'";
13133 str +=
"\' contains \'..\'";
13148 std::string custom_path;
13151 if (strstr(dec_path,
"..")) {
13153 str +=
"Invalid custom file name \'";
13155 str +=
"\' contains \'..\'";
13179 if (strlen(p->
getparam(
"path")) > 0) {
13193 r->
rsprintf(
"HTTP/1.1 400 Bad Request\r\n");
13197 r->
rsprintf(
"Error: Invalid URL \"%s\" or query \"%s\" or command \"%s\"\n", p->
getparam(
"path"), p->
getparam(
"query"), command);
13204 int len = strlen(query_string);
13205 char *buf = (
char *)malloc(len+1);
13206 assert(buf != NULL);
13207 memcpy(buf, query_string, len+1);
13209 p = strtok(p,
"&");
13210 while (p != NULL) {
13212 p = strchr(p,
'=');
13221 p = strtok(NULL,
"&");
13235 param->initparam();
13238 mstrlcpy(path, url + 1,
sizeof(path));
13240 mstrlcpy(path,
string + 1,
sizeof(path));
13242 if (strchr(path,
'?'))
13243 *strchr(path,
'?') = 0;
13246 param->setparam(
"path", path);
13248 assert(query_string != NULL);
13252 param->setparam(
"query", query_string);
13254 char dec_path[256];
13255 mstrlcpy(dec_path, path,
sizeof(dec_path));
13259 param->freeparam();
13267 bool debug_decode_post =
false;
13276 mstrlcpy(path, url + 1,
sizeof(path));
13278 mstrlcpy(path, header + 1,
sizeof(path));
13279 if (strchr(path,
'?'))
13280 *strchr(path,
'?') = 0;
13281 if (strchr(path,
' '))
13282 *strchr(path,
' ') = 0;
13284 param->setparam(
"path", path);
13288 const char* pinit = string;
13294 if (strstr(
string, boundary))
13295 string = strstr(
string, boundary) + strlen(boundary);
13297 if (debug_decode_post)
13298 printf(
"decode_post: -->[%s]<--\n",
string);
13302 if (strstr(
string,
"name=")) {
13303 const char* pitem = strstr(
string,
"name=") + 5;
13304 if (*pitem ==
'\"')
13309 if (strncmp(pitem,
"attfile", 7) == 0) {
13310 int n = pitem[7] -
'1';
13316 if (strstr(pitem,
"filename=")) {
13317 const char* p = strstr(pitem,
"filename=") + 9;
13320 if (strstr(p,
"\r\n\r\n"))
13321 string = strstr(p,
"\r\n\r\n") + 4;
13322 else if (strstr(p,
"\r\r\n\r\r\n"))
13323 string = strstr(p,
"\r\r\n\r\r\n") + 6;
13328 if (strchr(pp,
'\"'))
13329 *strchr(pp,
'\"') = 0;
13333 sprintf(
str,
"attachment%d",
n);
13334 if (debug_decode_post)
13340 const char* ptmp = string;
13341 const char* p = NULL;
13343 while (*ptmp !=
'-')
13346 p = strstr(ptmp, boundary);
13357 ptmp += strlen(ptmp);
13364 char* buf = (
char*)malloc(size+1);
13368 memcpy(buf,
string, size);
13372 if (debug_decode_post)
13376 string = strstr(p, boundary) + strlen(boundary);
13378 const char* p = pitem;
13379 if (strstr(p,
"\r\n\r\n"))
13380 p = strstr(p,
"\r\n\r\n") + 4;
13381 else if (strstr(p,
"\r\r\n\r\r\n"))
13382 p = strstr(p,
"\r\r\n\r\r\n") + 6;
13384 char* ppitem = (
char*)strchr(pitem,
'\"');
13388 char* pb = (
char*)(strstr(p, boundary));
13390 string = pb + strlen(boundary);
13392 char* ptmp = (
char*)(p + (strlen(p) - 1));
13393 while (*ptmp ==
'-' || *ptmp ==
'\n' || *ptmp ==
'\r')
13399 if (debug_decode_post)
13400 printf(
"decode_post: [%s] = [%s]\n", pitem, p);
13401 param->setparam(pitem, p);
13404 while (*
string ==
'-' || *
string ==
'\n' || *
string ==
'\r')
13410 char dec_path[256];
13411 mstrlcpy(dec_path, path,
sizeof(dec_path));
13436 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo corrected successfully");
13438 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13442 cm_msg(
MERROR,
"check_odb_records",
"ODB subtree /Runinfo does not exist");
13445 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo created successfully");
13447 cm_msg(
MERROR,
"check_odb_records",
"Cannot create ODB subtree /Runinfo, db_create_record() status %d",
status);
13451 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13457 for (
i = 0 ;;
i++) {
13467 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Equipment/%s/Common corrected successfully",
key.
name);
13469 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13472 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13492#ifdef HAVE_MONGOOSE6
13493static std::vector<std::string> gUserAllowedHosts;
13496#ifdef HAVE_MONGOOSE6
13497static const std::string gOdbAllowedHosts =
"/Experiment/Security/mhttpd hosts/Allowed hosts";
13500#ifdef HAVE_MONGOOSE6
13504 cm_msg(
MINFO,
"load_allowed_hosts",
"Reloading mhttpd hosts access control list via hotlink callback");
13509 for (
unsigned int i=0;
i<gUserAllowedHosts.size();
i++)
13514 for (
int i=0; ;
i++) {
13523 if (s.length() < 1)
13536 if (
total - last < 5) {
13537 int new_size = last + 10;
13541 cm_msg(
MERROR,
"load_allowed_hosts",
"Cannot resize the allowed hosts access control list, db_resize_string(%d) status %d", new_size,
status);
13546static int init_allowed_hosts()
13560 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot create the mhttpd hosts access control list, db_get_value_string() status %d",
status);
13567 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot find the mhttpd hosts access control list, db_find_key() status %d",
status);
13571 load_allowed_hosts(
hDB, 0, 0, NULL);
13576 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot watch the mhttpd hosts access control list, db_watch() status %d",
status);
13583 int check_midas_acl(
const struct sockaddr *sa,
int len) {
13588 char hname[NI_MAXHOST];
13592 const char* status_string =
"success";
13594 status = getnameinfo(sa, len, hname,
sizeof(hname), NULL, 0, 0);
13597 status_string = gai_strerror(
status);
13602 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
status, status_string);
13607 if (strcmp(hname,
"localhost.localdomain") == 0)
13609 if (strcmp(hname,
"localhost") == 0)
13617 printf(
"Rejecting connection from \'%s\'\n", hname);
13621int open_listening_socket(
int port)
13624 struct sockaddr_in bind_addr;
13627 int lsock =
socket(AF_INET, SOCK_STREAM, 0);
13630 printf(
"Cannot create socket, socket() errno %d (%s)\n", errno, strerror(errno));
13635 memset(&bind_addr, 0,
sizeof(bind_addr));
13636 bind_addr.sin_family = AF_INET;
13637 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
13638 bind_addr.sin_port = htons((
short) port);
13642 status = setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (
char *) &flag,
sizeof(
INT));
13645 printf(
"Cannot setsockopt(SOL_SOCKET, SO_REUSEADDR), errno %d (%s)\n", errno, strerror(errno));
13649 status = bind(lsock, (
struct sockaddr *) &bind_addr,
sizeof(bind_addr));
13652 printf(
"Cannot bind() to port %d, bind() errno %d (%s)\n", port, errno, strerror(errno));
13659 printf(
"Cannot listen() on port %d, errno %d (%s), bye!\n", port, errno, strerror(errno));
13663 printf(
"mhttpd is listening on port %d\n", port);
13671int try_file_mg(
const char* try_dir,
const char* filename, std::string& path, FILE** fpp,
bool trace)
13677 if (strlen(try_dir) < 1)
13685 FILE*
fp = fopen(path.c_str(),
"r");
13689 printf(
"file \"%s\": OK!\n", path.c_str());
13691 printf(
"file \"%s\": not found.\n", path.c_str());
13704int find_file_mg(
const char* filename, std::string& path, FILE** fpp,
bool trace)
13721 try_file_mg(exptdir.c_str(), filename, path, NULL,
false);
13725#ifdef HAVE_MONGOOSE6
13729#ifdef HAVE_MONGOOSE616
13733extern void cs_md5(
char buf[33], ...);
13741#ifdef HAVE_MONGOOSE616
13742static bool multithread_mg =
true;
13745#ifdef HAVE_MONGOOSE6
13746static struct mg_mgr mgr_mg;
13770 if (!exptname.empty())
13788 size_t uri_len,
const char *ha1,
size_t ha1_len,
13789 const char *nonce,
size_t nonce_len,
const char *nc,
13790 size_t nc_len,
const char *cnonce,
size_t cnonce_len,
13791 const char *qop,
size_t qop_len,
char *resp) {
13792 static const char colon[] =
":";
13793 static const size_t one = 1;
13796 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
13797 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
13798 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
13799 colon, one, ha2,
sizeof(ha2) - 1, NULL);
13809 unsigned long now = (
unsigned long) time(NULL);
13810 unsigned long val = (
unsigned long) strtoul(nonce, NULL, 16);
13811 return now < val || now - val < 3600;
13820 const char *domain) {
13822 "HTTP/1.1 401 Unauthorized\r\n"
13823 "WWW-Authenticate: Digest qop=\"auth\", "
13824 "realm=\"%s\", nonce=\"%lu\"\r\n"
13825 "Content-Length: 0\r\n\r\n",
13826 domain, (
unsigned long) time(NULL));
13839 cm_msg(
MERROR,
"mongoose",
"mongoose web server cannot find password file \"%s\"", path.c_str());
13840 cm_msg(
MERROR,
"mongoose",
"please create password file: touch %s", path.c_str());
13844 bool have_realm =
false;
13852 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
13854 char f_domain[256];
13857 if (sscanf(buf,
"%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3) {
13860 e.username = f_user;
13861 e.password = f_ha1;
13863 if (
e.realm == auth->
realm) {
13875#ifdef HAVE_MONGOOSE6
13876std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13878 assert(!
"this code is untested!");
13884 if (buf_size == 0) {
13886 buf = (
char*)malloc(buf_size);
13887 assert(buf != NULL);
13897 if (size < buf_size) {
13898 std::string s = buf;
13903 buf_size = buf_size*2 + 16;
13904 buf = (
char*)realloc(buf, buf_size);
13905 assert(buf != NULL);
13910#ifdef HAVE_MONGOOSE616
13911std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13918 assert(buf != NULL);
13919 std::string s = buf;
13927 char expected_response[33];
13939 std::string user = find_var_mg(hdr,
"username");
13940 std::string cnonce = find_var_mg(hdr,
"cnonce");
13941 std::string
response = find_var_mg(hdr,
"response");
13942 std::string uri = find_var_mg(hdr,
"uri");
13943 std::string qop = find_var_mg(hdr,
"qop");
13944 std::string nc = find_var_mg(hdr,
"nc");
13945 std::string nonce = find_var_mg(hdr,
"nonce");
13947 if (user.length()<1)
return "";
13948 if (cnonce.length()<1)
return "";
13949 if (
response.length()<1)
return "";
13950 if (uri.length()<1)
return "";
13951 if (qop.length()<1)
return "";
13952 if (nc.length()<1)
return "";
13953 if (nonce.length()<1)
return "";
13960 const char* uri_end = strchr(hm->
uri.
p,
' ');
13961 if (!uri_end)
return "";
13963 size_t uri_length = uri_end - hm->
uri.
p;
13965 if (uri_length != uri.length())
13968 int cmp = strncmp(hm->
uri.
p, uri.c_str(), uri_length);
13977 if (
e->username != user)
13979 if (
e->realm != auth->
realm)
13981 const char* f_ha1 =
e->password.c_str();
13982 int uri_len = hm->
uri.
len;
13983 if (hm->
uri.
p[uri_len] ==
'?')
13986 hm->
uri.
p, uri_len,
13987 f_ha1, strlen(f_ha1),
13988 nonce.c_str(), nonce.length(),
13989 nc.c_str(), nc.length(),
13990 cnonce.c_str(), cnonce.length(),
13991 qop.c_str(), qop.length(),
13992 expected_response);
13993 int cmp = strcasecmp(
response.c_str(), expected_response);
13996 return e->username;
14003#ifdef HAVE_MONGOOSE616
14005struct HostlistCacheEntry
14007 time_t time_created = 0;
14008 time_t time_last_used = 0;
14009 int count_used = 0;
14012 uint32_t ipv4addr = 0;
14013 struct in6_addr ipv6addr;
14014 std::string hostname;
14015 int gai_status = 0;
14016 std::string gai_strerror;
14020static std::vector<HostlistCacheEntry*> gHostlistCache;
14022static void print_hostlist_cache()
14024 time_t now = time(NULL);
14026 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14027 HostlistCacheEntry*
e = gHostlistCache[
i];
14033 printf(
"%3d: %s \"%s\", ok %d, count_used %d, age created: %d, last_used %d",
14035 e->ipv4?
"IPv4":(
e->ipv6?
"IPv6":
"????"),
14036 e->hostname.c_str(),
14039 (int)(now -
e->time_created),
14040 (int)(now -
e->time_last_used));
14042 if (
e->gai_status) {
14043 printf(
", getnameinfo() status %d (%s)",
e->gai_status,
e->gai_strerror.c_str());
14050static bool mongoose_check_hostlist(
const union socket_address *sa)
14052 time_t now = time(NULL);
14055 uint32_t ipv4addr = 0;
14056 struct in6_addr ipv6addr;
14058 if (sa->
sa.sa_family == AF_INET) {
14060 ipv4addr = sa->
sin.sin_addr.s_addr;
14061 }
else if (sa->
sa.sa_family == AF_INET6) {
14063 memcpy(&ipv6addr, &sa->
sin6.sin6_addr,
sizeof(ipv6addr));
14065 printf(
"Rejecting connection from unknown address family %d (AF_xxx)\n", sa->
sa.sa_family);
14069 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14070 HostlistCacheEntry*
e = gHostlistCache[
i];
14076 if ((ipv4 ==
e->ipv4) && (ipv4addr ==
e->ipv4addr)) {
14078 e->time_last_used = now;
14083 if ((ipv6 ==
e->ipv6) && (memcmp(&ipv6addr, &
e->ipv6addr,
sizeof(ipv6addr)) == 0)) {
14085 e->time_last_used = now;
14092 if (
e->time_last_used < now - 24*60*60) {
14093 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);
14094 gHostlistCache[
i] = NULL;
14101 assert(ipv4 || ipv6);
14103 HostlistCacheEntry*
e =
new HostlistCacheEntry;
14105 bool found =
false;
14106 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14107 if (gHostlistCache[
i] == NULL) {
14108 gHostlistCache[
i] =
e;
14113 gHostlistCache.push_back(
e);
14116 e->time_created = now;
14117 e->time_last_used = now;
14122 e->ipv4addr = ipv4addr;
14124 memcpy(&
e->ipv6addr, &ipv6addr,
sizeof(ipv6addr));
14127 char hname[NI_MAXHOST];
14130 e->gai_status = getnameinfo(&sa->
sa,
sizeof(*sa), hname,
sizeof(hname), NULL, 0, 0);
14132 if (
e->gai_status) {
14133 e->gai_strerror = gai_strerror(
e->gai_status);
14135 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
e->gai_status,
e->gai_strerror.c_str());
14141 printf(
"connection from \"%s\"\n", hname);
14143 e->hostname = hname;
14146 if (
e->hostname ==
"localhost.localdomain")
14148 else if (
e->hostname ==
"localhost")
14159 printf(
"Rejecting connection from \'%s\'\n", hname);
14162 print_hostlist_cache();
14171 return std::string(s->
p, s->
len);
14176 size_t nlen = strlen(
name);
14190 if (cookies.length() < 1)
14192 const char* p = strstr(cookies.c_str(), cookie_name);
14195 const char* v = p+strlen(cookie_name);
14213 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> accept\n", nc, ev, ev_data);
14217 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);
14226 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> send %d bytes\n", nc, ev, ev_data, *(
int*)ev_data);
14230 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> close\n", nc, ev, ev_data);
14234 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
14243 char cookie_pwd[256];
14244 char cookie_wpwd[256];
14245 char cookie_cpwd[256];
14248 cookie_wpwd[0] = 0;
14249 cookie_cpwd[0] = 0;
14252 if (s.length() > 0) {
14253 mstrlcpy(cookie_pwd, s.c_str(),
sizeof(cookie_pwd));
14254 cookie_pwd[strcspn(cookie_pwd,
" ;\r\n")] = 0;
14259 mstrlcpy(cookie_wpwd, s.c_str(),
sizeof(cookie_pwd));
14260 cookie_wpwd[strcspn(cookie_wpwd,
" ;\r\n")] = 0;
14265 mstrlcpy(cookie_cpwd, s.c_str(),
sizeof(cookie_pwd));
14266 cookie_cpwd[strcspn(cookie_cpwd,
" ;\r\n")] = 0;
14272 if (s.length() > 0)
14273 c->refresh = atoi(s.c_str());
14281 c->cookie_pwd = cookie_pwd;
14282 c->cookie_wpwd = cookie_wpwd;
14283 c->cookie_cpwd = cookie_cpwd;
14286#define RESPONSE_SENT 1
14287#define RESPONSE_QUEUED 2
14288#define RESPONSE_501 3
14298#ifdef HAVE_MONGOOSE6
14313 decode_get(rr, NULL, &cookies, uri, query_string, t);
14322#ifdef HAVE_MONGOOSE6
14334#ifdef HAVE_MONGOOSE6
14354#ifdef HAVE_MONGOOSE616
14356static uint32_t s_ncseqno = 1;
14358struct MongooseNcUserData
14360 uint32_t ncseqno = 0;
14362 MongooseNcUserData()
14364 ncseqno = s_ncseqno++;
14368 ~MongooseNcUserData()
14380 const MongooseNcUserData* ncud = (
const MongooseNcUserData*)nc->
user_data;
14381 return ncud->ncseqno;
14384static uint32_t s_wseqno = 1;
14386struct MongooseWorkObject
14388 uint32_t wseqno = 0;
14390 uint32_t wncseqno = 0;
14391 bool http_get =
false;
14392 bool http_post =
false;
14393 bool mjsonrpc =
false;
14395 std::string origin;
14397 std::string query_string;
14398 std::string post_body;
14399 std::string post_boundary;
14401 bool send_done =
false;
14405 wseqno = s_wseqno++;
14407 wncseqno = GetNcSeqno(nc);
14412 ~MongooseWorkObject()
14422struct MongooseThreadObject
14424 std::atomic_bool fIsRunning{
false};
14425 std::thread* fThread = NULL;
14428 std::deque<MongooseWorkObject*> fQueue;
14429 std::condition_variable fNotify;
14442static std::vector<MongooseThreadObject*> gMongooseThreads;
14444static void mongoose_thread(MongooseThreadObject*);
14446MongooseThreadObject* FindThread(
void* nc)
14450 MongooseThreadObject* last_not_connected = NULL;
14452 for (
auto it : gMongooseThreads) {
14453 MongooseThreadObject* to = it;
14454 if (to->fNc == nc) {
14458 if (to->fNc == NULL) {
14459 last_not_connected = to;
14463 if (last_not_connected) {
14464 MongooseThreadObject* to = last_not_connected;
14470 MongooseThreadObject* to =
new MongooseThreadObject();
14476 gMongooseThreads.push_back(to);
14478 printf(
"Mongoose web server is using %d threads \r", (
int)gMongooseThreads.size());
14481 to->fThread =
new std::thread(mongoose_thread, to);
14486void FreeThread(
void* nc)
14490 for (
auto it : gMongooseThreads) {
14491 MongooseThreadObject* to = it;
14492 if (to->fNc == nc) {
14502static void mongoose_queue(
mg_connection* nc, MongooseWorkObject* w)
14505 MongooseThreadObject* to = FindThread(nc);
14506 assert(to->fNc == nc);
14508 to->fQueue.push_back(w);
14509 to->fMutex.unlock();
14510 to->fNotify.notify_one();
14513static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag =
false);
14517 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14518 w->http_get =
true;
14521 w->query_string = query_string;
14524 mongoose_queue(nc, w);
14531 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14532 w->http_post =
true;
14535 w->query_string = query_string;
14537 w->post_boundary = boundary;
14540 mongoose_queue(nc, w);
14545static int queue_mjsonrpc(
struct mg_connection *nc,
const std::string& origin,
const std::string& post_body,
RequestTrace* t)
14547 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14548 w->mjsonrpc =
true;
14549 w->origin = origin;
14550 w->post_body = post_body;
14553 mongoose_queue(nc, w);
14558static int thread_http_get(
mg_connection *nc, MongooseWorkObject *w)
14575 decode_get(rr, NULL, &w->cookies, w->uri.c_str(), w->query_string.c_str(), w->t);
14596 bool close_flag =
false;
14614static int thread_http_post(
mg_connection *nc, MongooseWorkObject *w)
14616 const char* post_data = w->post_body.c_str();
14617 int post_data_len = w->post_body.length();
14632 decode_post(rr, NULL, (
char*)post_data, w->post_boundary.c_str(), post_data_len, &w->cookies, w->uri.c_str(), w->t);
14635 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14648 bool close_flag =
false;
14664static int thread_mjsonrpc(
mg_connection *nc, MongooseWorkObject *w)
14666 w->t->fRPC = w->post_body;
14681 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14684 reply->GetArrayBuffer(&ptr, &size);
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(size) +
"\n";
14694 headers +=
"Content-Type: application/octet-stream\n";
14700 std::string send = headers +
"\n";
14704 mongoose_send(nc, w, send.c_str(), send.length(), ptr, size);
14713 std::string reply_string = reply->Stringify();
14714 int reply_length = reply_string.length();
14716 std::string headers;
14717 headers +=
"HTTP/1.1 200 OK\n";
14718 if (w->origin.length() > 0)
14719 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14721 headers +=
"Access-Control-Allow-Origin: *\n";
14722 headers +=
"Access-Control-Allow-Credentials: true\n";
14723 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14724 headers +=
"Content-Type: application/json\n";
14728 printf(
"-----------------------\nSending headers: %s", headers.c_str());
14729 std::string r = reply_string.substr(0, 128);
14730 printf(
"-----------------------\nSending reply (%d bytes): %s\n\n\n", (
int)reply_string.size(), r.c_str());
14733 std::string send = headers +
"\n" + reply_string;
14737 mongoose_send(nc, w, send.c_str(), send.length(), NULL, 0);
14746static int thread_work_function(
mg_connection *nc, MongooseWorkObject *w)
14749 return thread_http_get(nc, w);
14750 else if (w->http_post)
14751 return thread_http_post(nc, w);
14752 else if (w->mjsonrpc)
14753 return thread_mjsonrpc(nc, w);
14763 char boundary[256];
14766 if (ct.length() > 0) {
14767 const char* s = strstr(ct.c_str(),
"boundary=");
14769 mstrlcpy(boundary, s+9,
sizeof(boundary));
14772#ifdef HAVE_MONGOOSE616
14773 if (multithread_mg)
14774 return queue_decode_post(nc, msg, boundary, uri, query_string, t);
14781 const char* post_data = msg->
body.
p;
14782 int post_data_len = msg->
body.
len;
14786#ifdef HAVE_MONGOOSE6
14799 decode_post(rr, NULL, (
char*)post_data, boundary, post_data_len, &cookies, uri, t);
14802 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14805#ifdef HAVE_MONGOOSE6
14815#ifdef HAVE_MONGOOSE6
14838 printf(
"handle_http_get: uri [%s], query [%s]\n", uri, query_string.c_str());
14840 if (query_string ==
"mjsonrpc_schema") {
14842 std::string reply = s->Stringify();
14845 int reply_length = reply.length();
14847 const std::string origin_header =
find_header_mg(msg,
"Origin");
14849 std::string headers;
14850 headers +=
"HTTP/1.1 200 OK\n";
14851 if (origin_header.length() > 0)
14852 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14854 headers +=
"Access-Control-Allow-Origin: *\n";
14855 headers +=
"Access-Control-Allow-Credentials: true\n";
14856 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14857 headers +=
"Content-Type: application/json\n";
14863 std::string send = headers +
"\n" + reply;
14867 mg_send(nc, send.c_str(), send.length());
14874 if (query_string ==
"mjsonrpc_schema_text") {
14879 int reply_length = reply.length();
14881 const std::string origin_header =
find_header_mg(msg,
"Origin");
14883 std::string headers;
14884 headers +=
"HTTP/1.1 200 OK\n";
14885 if (origin_header.length() > 0)
14886 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14888 headers +=
"Access-Control-Allow-Origin: *\n";
14889 headers +=
"Access-Control-Allow-Credentials: true\n";
14890 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14891 headers +=
"Content-Type: text/plain\n";
14897 std::string send = headers +
"\n" + reply;
14901 mg_send(nc, send.c_str(), send.length());
14908#ifdef HAVE_MONGOOSE616
14909 if (multithread_mg)
14910 return queue_decode_get(nc, msg, uri, query_string.c_str(), t);
14919 std::string post_data =
mgstr(&msg->
body);
14922 printf(
"handle_http_post: uri [%s], query [%s], post data %d bytes\n", uri, query_string.c_str(), (
int)post_data.length());
14924 printf(
"handle_http_post: post data = \n%s\n", post_data.c_str());
14926 if (query_string.substr(0, 8) ==
"mjsonrpc") {
14927 const std::string origin_header =
find_header_mg(msg,
"Origin");
14928 const std::string ctype_header =
find_header_mg(msg,
"Content-Type");
14930 if (strstr(ctype_header.c_str(),
"application/json") == NULL) {
14931 std::string headers;
14932 headers +=
"HTTP/1.1 415 Unsupported Media Type\n";
14939 printf(
"handle_http_post: unsupported media type \"%s\"\n", ctype_header.c_str());
14941 std::string send = headers +
"\n";
14945 mg_send(nc, send.c_str(), send.length());
14952#ifdef HAVE_MONGOOSE616
14953 if (multithread_mg)
14954 return queue_mjsonrpc(nc, origin_header, post_data, t);
14959 t->
fRPC = post_data;
14961#ifdef HAVE_MONGOOSE6
14972#ifdef HAVE_MONGOOSE6
14976 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14979 reply->GetArrayBuffer(&ptr, &size);
14981 std::string headers;
14982 headers +=
"HTTP/1.1 200 OK\n";
14983 if (origin_header.length() > 0)
14984 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14986 headers +=
"Access-Control-Allow-Origin: *\n";
14987 headers +=
"Access-Control-Allow-Credentials: true\n";
14988 headers +=
"Content-Length: " +
toString(size) +
"\n";
14989 headers +=
"Content-Type: application/octet-stream\n";
14995 std::string send = headers +
"\n";
14999 mg_send(nc, send.c_str(), send.length());
15009 std::string reply_string = reply->Stringify();
15010 int reply_length = reply_string.length();
15012 std::string headers;
15013 headers +=
"HTTP/1.1 200 OK\n";
15014 if (origin_header.length() > 0)
15015 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
15017 headers +=
"Access-Control-Allow-Origin: *\n";
15018 headers +=
"Access-Control-Allow-Credentials: true\n";
15019 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
15020 headers +=
"Content-Type: application/json\n";
15026 std::string send = headers +
"\n" + reply_string;
15030 mg_send(nc, send.c_str(), send.length());
15075 const std::string origin_header =
find_header_mg(msg,
"Origin");
15078 printf(
"handle_http_options_cors: origin [%s]\n", origin_header.c_str());
15080 std::string headers;
15081 headers +=
"HTTP/1.1 200 OK\n";
15083 if (origin_header.length() > 0)
15084 headers +=
"Access-Control-Allow-Origin: " + origin_header +
"\n";
15086 headers +=
"Access-Control-Allow-Origin: *\n";
15087 headers +=
"Access-Control-Allow-Headers: Content-Type\n";
15088 headers +=
"Access-Control-Allow-Credentials: true\n";
15089 headers +=
"Access-Control-Max-Age: 120\n";
15090 headers +=
"Content-Length: 0\n";
15091 headers +=
"Content-Type: text/plain\n";
15095 std::string send = headers +
"\n";
15099 mg_send(nc, send.c_str(), send.length());
15108#ifdef HAVE_MONGOOSE616
15109static MVOdb* gProxyOdb = NULL;
15116 std::string uri_encoded =
mgstr(&msg->
uri);
15117 std::string uri =
UrlDecode(uri_encoded.c_str());
15122 user =
mgstr(user_mg_str);
15125 printf(
"handle_http_message: method [%s] uri [%s] proto [%s] user [%s]\n", method.c_str(), uri.c_str(),
mgstr(&msg->
proto).c_str(), user.c_str());
15131 t->
fQuery = query_string;
15135 if (method ==
"OPTIONS" && query_string ==
"mjsonrpc" &&
mg_get_http_header(msg,
"Access-Control-Request-Method") != NULL) {
15158 printf(
"handle_http_message: auth user: \"%s\"\n", username.c_str());
15160 if (username.length() == 0) {
15162 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());
15174#ifdef HAVE_MONGOOSE616
15176 std::string::size_type p1 = uri.find(
"/", 1);
15177 if (p1 == uri.length()-1) {
15178 std::string
response =
"404 Not Found (Proxy name is missing)";
15184 std::string::size_type p2 = uri.find(
"/", p1+1);
15185 if (p2 == std::string::npos) {
15186 std::string
response =
"404 Not Found (Proxy URL should end with a slash)";
15192 std::string p = uri.substr(p1+1, p2-p1-1);
15194 if (p.length() < 1) {
15195 std::string
response =
"404 Not Found (Double-slash or Proxy name is too short)";
15201 std::string destination;
15202 gProxyOdb->RS(p.c_str(), &destination);
15203 if (destination.length() < 1) {
15204 std::string
response =
"404 Not Found (Proxy not found in ODB)";
15209 }
else if (destination[0] ==
'#') {
15210 std::string
response =
"404 Not Found (Proxy commented-out in ODB)";
15216 std::string
response =
"404 Not Found (Proxy address should not end with a slash)";
15222 std::string
response =
"404 Not Found (Proxy address does not start with http";
15235 printf(
"proxy: uri [%s] mount [%s] upstream [%s]\n", uri.c_str(),
mgstr(&mount).c_str(),
mgstr(&upstream).c_str());
15237 mg_http_reverse_proxy(nc, msg, mount, upstream);
15246 if (method ==
"GET")
15248 else if (method ==
"POST")
15253 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15255 std::string
response =
"501 Not Implemented";
15266#ifdef HAVE_MONGOOSE6
15268static void handle_http_event_mg(
struct mg_connection *nc,
int ev,
void *ev_data)
15273 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15278 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15283static void handle_http_redirect(
struct mg_connection *nc,
int ev,
void *ev_data)
15290 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15292 mg_printf(nc,
"HTTP/1.1 302 Found\r\nLocation: https://%s%s\r\n\r\n",
15293 ((std::string*)(nc->
user_data))->c_str(),
15300 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15306#ifdef HAVE_MONGOOSE616
15311static std::atomic_bool s_shutdown{
false};
15312static struct mg_mgr s_mgr;
15313static std::atomic_int s_rseqno{1};
15314static std::mutex s_mg_broadcast_mutex;
15318struct work_request {
15320 MongooseWorkObject* w;
15325struct work_result {
15327 uint32_t check = 0x12345678;
15329 MongooseWorkObject* w = NULL;
15330 const char* p1 = NULL;
15332 const char* p2 = NULL;
15334 bool close_flag =
false;
15335 bool send_501 =
false;
15339static void mongoose_queue(
void *nc, MongooseWorkObject *w)
15341 struct work_request req = {nc, w};
15345 if (
write(s_sock[0], &req,
sizeof(req)) < 0) {
15346 fprintf(stderr,
"mongoose_queue: Error: write(s_sock(0)) error %d (%s)\n", errno, strerror(errno));
15352static void on_work_complete(
struct mg_connection *nc,
int ev,
void *ev_data)
15355 struct work_result *res = (
struct work_result *)ev_data;
15357 assert(res != NULL);
15358 assert(res->w != NULL);
15369 if (GetNcSeqno(nc) != res->w->wncseqno)
15374 if (res->send_501) {
15375 std::string
response =
"501 Not Implemented";
15381 mg_send(nc, res->p1, res->s1);
15384 mg_send(nc, res->p2, res->s2);
15386 if (res->close_flag) {
15393 res->w->send_done =
true;
15396static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag)
15399 struct work_result res;
15402 res.rseqno = s_rseqno++;
15407 res.close_flag = close_flag;
15408 res.send_501 =
false;
15450 s_mg_broadcast_mutex.lock();
15451 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15452 s_mg_broadcast_mutex.unlock();
15455static void mongoose_send_501(
mg_connection* nc, MongooseWorkObject* w)
15457 struct work_result res;
15460 res.rseqno = s_rseqno++;
15465 res.close_flag =
false;
15466 res.send_501 =
true;
15469 s_mg_broadcast_mutex.lock();
15470 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15471 s_mg_broadcast_mutex.unlock();
15475void *worker_thread_proc(
void *
param)
15478 struct work_request req = {0};
15480 while ((!
_abort) && (! s_shutdown)) {
15481 int rd =
read(s_sock[1], &req,
sizeof(req));
15487 if (
_abort || s_shutdown) {
15490 fprintf(stderr,
"worker_thread_proc: Error: read(s_sock(1)) returned %d, error %d (%s)\n", rd, errno, strerror(errno));
15497 int response = thread_work_function(req.nc, req.w);
15501 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15502 mongoose_send_501(req.nc, req.w);
15505 req.w->t->fCompleted =
true;
15517static void mongoose_thread(MongooseThreadObject* to)
15521 std::unique_lock<std::mutex> ulm(to->fMutex, std::defer_lock);
15523 to->fIsRunning =
true;
15525 while ((!
_abort) && (! s_shutdown)) {
15526 MongooseWorkObject *w = NULL;
15529 while (to->fQueue.empty()) {
15531 to->fNotify.wait(ulm);
15532 if (
_abort || s_shutdown) {
15537 if (
_abort || s_shutdown) {
15541 w = to->fQueue.front();
15542 to->fQueue.pop_front();
15547 int response = thread_work_function(w->nc, w);
15551 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15552 mongoose_send_501(w->nc, w);
15557 if (!w->send_done) {
15563 w->t->fCompleted =
true;
15571 to->fIsRunning =
false;
15576static bool mongoose_hostlist_enabled(
const struct mg_connection *nc);
15578static void ev_handler(
struct mg_connection *nc,
int ev,
void *ev_data)
15592 printf(
"ev_handler: connection %p, event %d\n", nc, ev);
15598 nc->
user_data =
new MongooseNcUserData();
15601 printf(
"ev_handler: connection %p, MG_EV_ACCEPT, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15606 }
else if (mongoose_hostlist_enabled(nc)) {
15607 if (!mongoose_check_hostlist(&nc->
sa)) {
15614 printf(
"ev_handler: connection %p, MG_EV_RECV, %d bytes\n", nc, *(
int*)ev_data);
15623 printf(
"ev_handler: connection %p, MG_EV_SEND, %d bytes\n", nc, *(
int*)ev_data);
15628 printf(
"ev_handler: connection %p, MG_EV_HTTP_CHUNK\n", nc);
15639 printf(
"ev_handler: connection %p, MG_EV_HTTP_REQUEST \"%s\" \"%s\"\n", nc,
mgstr(&msg->
method).c_str(),
mgstr(&msg->
uri).c_str());
15651 printf(
"ev_handler: connection %p, MG_EV_CLOSE, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15656 MongooseNcUserData* ncud = (MongooseNcUserData*)nc->
user_data;
15665#define FLAG_HTTPS MG_F_USER_1
15666#define FLAG_PASSWORDS MG_F_USER_2
15667#define FLAG_HOSTLIST MG_F_USER_3
15676 return flags & FLAG_PASSWORDS;
15679static bool mongoose_hostlist_enabled(
const struct mg_connection *nc)
15686 return flags & FLAG_HOSTLIST;
15689static int mongoose_listen(
const char* address,
int flags)
15693 if (flags & FLAG_HTTPS) {
15694 cm_msg(
MERROR,
"mongoose_listen",
"https port \"%s\" requested, but mhttpd compiled without MG_ENABLE_SSL", address);
15701 cm_msg(
MERROR,
"mongoose_listen",
"Cannot mg_bind address \"%s\"", address);
15705 if (
flags & FLAG_HTTPS) {
15707 std::string cert_file;
15712 cm_msg(
MERROR,
"mongoose_listen",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
15713 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");
15714 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");
15718 printf(
"Mongoose web server will use https certificate file \"%s\"\n", cert_file.c_str());
15720 const char* errmsg =
mg_set_ssl(nc, cert_file.c_str(), NULL);
15722 cm_msg(
MERROR,
"mongoose_listen",
"Cannot enable https with certificate file \"%s\", error: %s", cert_file.c_str(), errmsg);
15736 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");
15741static int mongoose_init(MVOdb* odb,
bool no_passwords,
bool no_hostlist,
const std::vector<std::string>& user_hostlist)
15743 bool enable_localhost_port =
true;
15744 int localhost_port = 8080;
15745 bool localhost_port_passwords =
false;
15747 bool enable_insecure_port =
false;
15748 int insecure_port = 8081;
15749 bool insecure_port_passwords =
true;
15750 bool insecure_port_hostlist =
true;
15752 bool enable_https_port =
false;
15753 int https_port = 8443;
15754 bool https_port_passwords =
true;
15755 bool https_port_hostlist =
false;
15757 std::vector<std::string> hostlist;
15758 hostlist.push_back(
"localhost");
15760 bool enable_ipv6 =
true;
15762 odb->RB(
"Enable localhost port", &enable_localhost_port,
true);
15763 odb->RI(
"localhost port", &localhost_port,
true);
15764 odb->RB(
"localhost port passwords", &localhost_port_passwords,
true);
15765 odb->RB(
"Enable insecure port", &enable_insecure_port,
true);
15766 odb->RI(
"insecure port", &insecure_port,
true);
15767 odb->RB(
"insecure port passwords", &insecure_port_passwords,
true);
15768 odb->RB(
"insecure port host list", &insecure_port_hostlist,
true);
15769 odb->RB(
"Enable https port", &enable_https_port,
true);
15770 odb->RI(
"https port", &https_port,
true);
15771 odb->RB(
"https port passwords", &https_port_passwords,
true);
15772 odb->RB(
"https port host list", &https_port_hostlist,
true);
15773 odb->RSA(
"Host list", &hostlist,
true, 10, 256);
15774 odb->RB(
"Enable IPv6", &enable_ipv6,
true);
15777 gProxyOdb = odb->Chdir(
"Proxy",
true);
15778 std::string proxy_example =
"#http://localhost:8080";
15779 gProxyOdb->RS(
"example", &proxy_example,
true);
15785 && ((enable_localhost_port && localhost_port_passwords)
15786 || (enable_insecure_port && insecure_port_passwords)
15787 || (enable_https_port && https_port_passwords))) {
15791 printf(
"mongoose_init: Error: Cannot initialize authorization object!\n");
15796 printf(
"Password protection is off\n");
15800 && ((enable_insecure_port && insecure_port_hostlist)
15801 || (enable_https_port && https_port_hostlist))) {
15805 for (
unsigned int i=0;
i<user_hostlist.size();
i++)
15808 for (
unsigned i=0;
i<hostlist.size();
i++) {
15809 std::string s = hostlist[
i];
15810 if (s.length() < 1)
15820 printf(
"Hostlist active, connections will be accepted only from: ");
15828 printf(
"Hostlist off, connections from anywhere will be accepted\n");
15833 bool listen_failed =
false;
15835 if (enable_localhost_port) {
15837 sprintf(
str,
"localhost:%d", localhost_port);
15840 listen_failed =
true;
15842 sprintf(
str,
"[::1]:%d", localhost_port);
15845 listen_failed =
true;
15849 if (enable_insecure_port) {
15852 if (insecure_port_passwords)
15853 flags |= FLAG_PASSWORDS;
15854 if (insecure_port_hostlist)
15855 flags |= FLAG_HOSTLIST;
15857 sprintf(
str,
"[::]:%d", insecure_port);
15860 listen_failed =
true;
15862 sprintf(
str,
"%d", insecure_port);
15865 listen_failed =
true;
15869 if (enable_https_port) {
15872 if (https_port_passwords)
15873 flags |= FLAG_PASSWORDS;
15874 if (https_port_hostlist)
15875 flags |= FLAG_HOSTLIST;
15876 flags |= FLAG_HTTPS;
15878 sprintf(
str,
"[::]:%d", https_port);
15881 listen_failed =
true;
15883 sprintf(
str,
"%d", https_port);
15886 listen_failed =
true;
15890 if (listen_failed) {
15891 cm_msg(
MERROR,
"mongoose_init",
"Failed to listen on a TCP port enabled in ODB /WebServer");
15898static void mongoose_poll(
int msec = 200)
15903static void mongoose_cleanup()
15905 printf(
"Mongoose web server shutting down\n");
15910 if (s_mgr.active_connections) {
15922 for (
auto it : gMongooseThreads) {
15923 MongooseThreadObject* to = it;
15924 to->fNotify.notify_one();
15928 for (
int i=0;
i<10;
i++) {
15929 int count_running = 0;
15930 for (
auto it : gMongooseThreads) {
15931 MongooseThreadObject* to = it;
15933 if (to->fIsRunning) {
15937 printf(
"Mongoose web server shutting down, %d threads still running\n", count_running);
15938 if (count_running == 0)
15940 mongoose_poll(1000);
15944 for (
auto it : gMongooseThreads) {
15945 MongooseThreadObject* to = it;
15947 if (to->fIsRunning) {
15948 cm_msg(
MERROR,
"mongoose",
"thread failed to shut down");
15951 to->fThread->join();
15952 delete to->fThread;
15955 gMongooseThreads.clear();
15963 for (
auto e : gHostlistCache) {
15966 gHostlistCache.clear();
15976 printf(
"Mongoose web server shut down\n");
15981#ifdef HAVE_MONGOOSE6
15988int start_mg(
int user_http_port,
int user_https_port,
int socket_priviledged_port,
int verbose)
16003 int http_port = 8080;
16004 int https_port = 8443;
16005 int http_redirect_to_https = 1;
16007 size =
sizeof(http_port);
16010 size =
sizeof(https_port);
16013 size =
sizeof(http_redirect_to_https);
16016 bool need_cert_file =
false;
16017 bool need_password_file =
false;
16019 if (user_http_port)
16020 http_port = user_http_port;
16022 if (user_https_port)
16023 https_port = user_https_port;
16026 need_cert_file =
true;
16027 need_password_file =
true;
16031 http_redirect_to_https = 0;
16033 if (http_port && !http_redirect_to_https) {
16036 need_password_file =
false;
16039 if (socket_priviledged_port >= 0) {
16041 need_password_file =
false;
16042 printf(
"Mongoose web server password portection is disabled: serving unencrypted http on port 80\n");
16045 bool have_at_least_one_port =
false;
16047 std::string cert_file;
16049 if (need_cert_file) {
16053 cm_msg(
MERROR,
"mongoose",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
16054 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");
16058 printf(
"Mongoose web server will use SSL certificate file \"%s\"\n", cert_file.c_str());
16061 if (need_password_file) {
16065 printf(
"Error: Cannot initialize authorization object!\n");
16070 printf(
"Mongoose web server will not use password protection\n");
16074 printf(
"start_mg!\n");
16077 signal(SIGPIPE, SIG_IGN);
16084 if (!request_mutex) {
16092 if (socket_priviledged_port >= 0) {
16095 cm_msg(
MERROR,
"mongoose",
"Cannot create mg_connection for set-uid-root privileged port");
16100#ifdef MG_ENABLE_THREADS
16106 have_at_least_one_port =
true;
16107 printf(
"mongoose web server is listening on the set-uid-root privileged port\n");
16110 if (http_port != 80) {
16112 sprintf(
str,
"%d", http_port);
16115 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", http_port);
16119#ifdef MG_ENABLE_THREADS
16124 if (http_redirect_to_https) {
16127 sprintf(
str,
"%d", https_port);
16128 std::string s = hostname +
":" + std::string(
str);
16131 printf(
"mongoose web server is redirecting HTTP port %d to https://%s\n", http_port, s.c_str());
16136 have_at_least_one_port =
true;
16137 printf(
"mongoose web server is listening on the HTTP port %d\n", http_port);
16141#ifdef MG_ENABLE_SSL
16143 sprintf(
str,
"%d", https_port);
16146 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", https_port);
16151#ifdef MG_ENABLE_THREADS
16157 have_at_least_one_port =
true;
16158 printf(
"mongoose web server is listening on the HTTPS port %d\n", https_port);
16160 cm_msg(
MERROR,
"mongoose",
"https port %d requested, but mhttpd compiled without MG_ENABLE_SSL", https_port);
16165 if (!have_at_least_one_port) {
16166 cm_msg(
MERROR,
"mongoose",
"cannot start: no ports defined");
16176 printf(
"stop_mg!\n");
16182 printf(
"stop_mg done!\n");
16197#ifdef HAVE_MONGOOSE6
16208#ifdef HAVE_MONGOOSE6
16225 doc->
D(
"get current value of mhttpd http_trace");
16226 doc->
P(NULL, 0,
"there are no input parameters");
16227 doc->
R(NULL, MJSON_INT,
"current value of http_trace");
16238 doc->
D(
"set new value of mhttpd http_trace");
16239 doc->
P(NULL, MJSON_INT,
"new value of http_trace");
16240 doc->
R(NULL, MJSON_INT,
"new value of http_trace");
16260#ifdef HAVE_MONGOOSE6
16261 int user_http_port = 0;
16262 int user_https_port = 0;
16264#ifdef HAVE_MONGOOSE616
16265 bool no_passwords =
false;
16266 bool no_hostlist =
false;
16268 const char *myname =
"mhttpd";
16270 setbuf(stdout, NULL);
16271 setbuf(stderr, NULL);
16274 signal(SIGPIPE, SIG_IGN);
16277#ifdef HAVE_MONGOOSE6
16282 int socket_priviledged_port = -1;
16286 if (getuid() != geteuid()) {
16289 printf(
"mhttpd is running in setuid-root mode.\n");
16291 socket_priviledged_port = open_listening_socket(port80);
16292 if (socket_priviledged_port < 0) {
16293 printf(
"Cannot open listening socket on TCP port %d, aborting.\n", port80);
16298 status = setuid(getuid());
16300 printf(
"Cannot give up root privelege, aborting.\n");
16303 status = setuid(getuid());
16305 printf(
"Cannot give up root privelege, aborting.\n");
16312 char midas_hostname[256];
16313 char midas_expt[256];
16316 cm_get_environment(midas_hostname,
sizeof(midas_hostname), midas_expt,
sizeof(midas_expt));
16319#ifdef HAVE_MONGOOSE6
16320 gUserAllowedHosts.clear();
16322 std::vector<std::string> user_hostlist;
16324 for (
int i = 1;
i < argc;
i++) {
16325 if (argv[
i][0] ==
'-' && argv[
i][1] ==
'D')
16327 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'v')
16329 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'E')
16331 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'H') {
16333#ifdef HAVE_MONGOOSE6
16334 }
else if (strcmp(argv[
i],
"--http") == 0) {
16336 user_http_port = atoi(argv[
i+1]);
16338 }
else if (strcmp(argv[
i],
"--https") == 0) {
16340 user_https_port = atoi(argv[
i+1]);
16343 }
else if (strcmp(argv[
i],
"--trace-mg") == 0) {
16347 }
else if (strcmp(argv[
i],
"--trace-mg-verbose") == 0) {
16349 }
else if (strcmp(argv[
i],
"--no-trace-mg-recv") == 0) {
16351 }
else if (strcmp(argv[
i],
"--no-trace-mg-send") == 0) {
16353 }
else if (strcmp(argv[
i],
"--verbose-mg") == 0) {
16355#ifdef HAVE_MONGOOSE616
16356 }
else if (strcmp(argv[
i],
"--no-multithread") == 0) {
16357 multithread_mg =
false;
16358 }
else if (strcmp(argv[
i],
"--no-passwords") == 0) {
16359 no_passwords =
true;
16360 }
else if (strcmp(argv[
i],
"--no-hostlist") == 0) {
16361 no_hostlist =
true;
16363 }
else if (argv[
i][0] ==
'-') {
16364 if (
i + 1 >= argc || argv[
i + 1][0] ==
'-')
16366 if (argv[
i][1] ==
'h')
16367 mstrlcpy(midas_hostname, argv[++
i],
sizeof(midas_hostname));
16368 else if (argv[
i][1] ==
'e')
16369 mstrlcpy(midas_expt, argv[++
i],
sizeof(midas_hostname));
16370 else if (argv[
i][1] ==
'a') {
16371#ifdef HAVE_MONGOOSE6
16372 gUserAllowedHosts.push_back(argv[++
i]);
16374 user_hostlist.push_back(argv[++
i]);
16376 }
else if (argv[
i][1] ==
'p') {
16377 printf(
"Option \"-p port_number\" for the old web server is obsolete.\n");
16378 printf(
"mongoose web server is the new default, port number is set in ODB or with \"--http port_number\".\n");
16379 printf(
"To run the obsolete old web server, please use \"--oldserver\" switch.\n");
16383 printf(
"usage: %s [-h Hostname[:port]] [-e Experiment] [-v] [-D] [-a Hostname]\n\n", argv[0]);
16384 printf(
" -a add hostname to the hostlist of hosts allowed to connect to mhttpd\n");
16385 printf(
" -e experiment to connect to\n");
16386 printf(
" -h connect to midas server (mserver) on given host\n");
16387 printf(
" -v display verbose HTTP communication\n");
16388 printf(
" -D become a daemon\n");
16389 printf(
" -E only display ELog system\n");
16390 printf(
" -H only display history plots\n");
16391#ifdef HAVE_MONGOOSE6
16392 printf(
" --http port - bind to specified HTTP port (default is ODB \"/Experiment/midas http port\")\n");
16393 printf(
" --https port - bind to specified HTTP port (default is ODB \"/Experiment/midas https port\")\n");
16395 printf(
" --verbose-mg - trace mongoose web requests\n");
16396 printf(
" --trace-mg - trace mongoose events\n");
16397 printf(
" --no-trace-mg-recv - do not trace mongoose recv events\n");
16398 printf(
" --no-trace-mg-send - dop not trace mongoose send events\n");
16399#ifdef HAVE_MONGOOSE616
16400 printf(
" --no-multithread - disable mongoose multithreading\n");
16401 printf(
" --no-passwords - disable password protection\n");
16402 printf(
" --no-hostlist - disable access control host list\n");
16410 printf(
"Becoming a daemon...\n");
16416 FILE *
f = fopen(
"/var/run/mhttpd.pid",
"w");
16424 myname =
"mhttpd_history";
16452 MVOdb *odb = MakeMidasOdb(
hDB);
16460 printf(
"check_odb_records() failed, see messages and midas.log, bye!\n");
16465#ifdef HAVE_MONGOOSE6
16466 if (init_allowed_hosts() !=
SUCCESS) {
16467 printf(
"init_allowed_hosts() failed, see messages and midas.log, bye!\n");
16474 printf(
"mhttpd allowed hosts list: ");
16482 printf(
"mhttpd allowed hosts list is empty\n");
16505#ifdef HAVE_MONGOOSE6
16506 status = start_mg(user_http_port, user_https_port, socket_priviledged_port,
verbose);
16509 printf(
"could not start the mongoose web server, see messages and midas.log, bye!\n");
16515#ifdef HAVE_MONGOOSE616
16519 signal(SIGPIPE, SIG_IGN);
16535 MVOdb* o = odb->Chdir(
"WebServer",
true);
16536 status = mongoose_init(o, no_passwords, no_hostlist, user_hostlist);
16539 printf(
"Error: Could not start the mongoose web server, see messages and midas.log, bye!\n");
16547#ifdef HAVE_MONGOOSE6
16552#ifdef HAVE_MONGOOSE616
16573 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)