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 +=
"?cmd=Show+Elog&tag=";
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);
11496 char* fbuffer = (
char*)
M_MALLOC(fsize);
11497 assert(fbuffer != NULL);
11508 }
else if (atoi(pmag) > 0) {
11509 width = atoi(pmag);
11514 generate_hist_graph(odb, r, hgroup, hpanel, fbuffer, &fsize, width, height, endtime, scale,
index, labels, bgcolor.c_str(), fgcolor.c_str(), gridcolor.c_str());
11519 if (dir.length() > 0 && dir[dir.length()-1] !=
DIR_SEPARATOR)
11522 time_t now = time(NULL);
11523 localtime_r(&now, &tms);
11526 tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday,
11527 tms.tm_hour, tms.tm_min, tms.tm_sec, hpanel);
11531 fh = open(fname.c_str(), O_CREAT | O_RDWR |
O_BINARY, 0644);
11533 cm_msg(
MERROR,
"show_hist_page",
"Cannot write attachment file \"%s\", open() errno %d (%s)", fname.c_str(), errno, strerror(errno));
11535 int wr =
write(fh, fbuffer, fsize);
11537 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));
11543 if (strlen(url) > 1 && url[strlen(url)-1] !=
'/')
11544 mstrlcat(url,
"/",
sizeof(url));
11545 mstrlcat(url,
"?cmd=New&fa=",
sizeof(url));
11554 std::string
str =
msprintf(
"\\HS\\%s.gif", hpanel);
11558 if (strchr(
str.c_str(),
'?'))
11572 if (strchr(
str.c_str(),
'?'))
11579 if (strchr(
str.c_str(),
'?'))
11586 show_elog_new(r, hpanel, NULL,
FALSE,
str.c_str(),
"../../EL/");
11597 if (strstr(dec_path,
".gif")) {
11606 }
else if (atoi(pwidth) > 0) {
11607 width = atoi(pwidth);
11608 if (atoi(pheight) > 0)
11609 height = atoi(pheight);
11611 height = (int)(0.625 * width);
11616 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());
11624 time_t now = time(NULL);
11630 time_t last_written = 0;
11633 endtime = last_written + scale/2;
11639 time_t last_written = 0;
11642 if (last_written != endtime)
11643 endtime = last_written + scale/2;
11649 endtime -= scale/2;
11656 endtime += scale/2;
11668 endtime -= scale / 4;
11675 endtime += scale / 2;
11681 int xrefresh = refresh;
11686 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
11687 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
11690 r->
rsprintf(
"<table class=\"mtable\">");
11691 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>History</th></tr>");
11697 path +=
"/History/Display/";
11703 r->
rsprintf(
"<h1>Error: History panel \"%s\" in group \"%s\" does not exist</h1>\n", hpanel, hgroup);
11707 r->
rsprintf(
"</body></html>\r\n");
11713 if (pscale && *pscale)
11714 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%d>\n", scale);
11717 if (hpanel[0] && !
equal_ustring(hpanel,
"All") && hgroup[0]) {
11719 path +=
"/History/Display/";
11723 path +=
"/Timescale";
11725 std::string scalestr =
"1h";
11734 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%s>\n", scalestr.c_str());
11741 if (pwidth && *pwidth)
11742 r->
rsprintf(
"<input type=hidden name=hwidth id=hwidth value=%s>\n", pwidth);
11743 if (pheight && *pheight)
11744 r->
rsprintf(
"<input type=hidden name=hheight id=hheight value=%s>\n", pheight);
11745 if (pindex && *pindex)
11746 r->
rsprintf(
"<input type=hidden name=hindex id=hindex value=%s>\n", pindex);
11750 if (hgroup[0] == 0) {
11752 r->
rsprintf(
"<tr><td colspan=2><input type=\"button\" name=\"New\" value=\"New\" ");
11753 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New'\"></td></tr>\n");
11756 r->
rsprintf(
"<tr><td colspan=2 style=\"text-align:left;\">\n");
11758 r->
rsprintf(
"<b>Please select panel:</b><br>\n");
11761 r->
rsprintf(
"<table class=\"historyTable\">");
11764 r->
rsprintf(
"<tr><td colspan=2 class=\"titleCell\">\n");
11768 r->
rsprintf(
"<a href=\"?cmd=oldhistory&group=All\">ALL</a>\n");
11776 strcpy(
str,
"System:Trigger per sec.");
11796 for (
i = 0;;
i++) {
11805 char enc_name[256];
11806 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11812 r->
rsprintf(
"<tr><td class=\"titleCell\"><a href=\"?cmd=oldhistory&group=%s\">%s</a></td>\n<td>", enc_name,
key.
name);
11814 for (
j = 0;;
j++) {
11825 char enc_iname[256];
11826 mstrlcpy(enc_iname, ikey.
name,
sizeof(enc_iname));
11827 urlEncode(enc_iname,
sizeof(enc_iname));
11830 r->
rsprintf(
"<small><b>%s</b></small> ", ikey.
name);
11832 r->
rsprintf(
"<small><a href=\"?cmd=oldhistory&group=%s&panel=%s\">%s</a></small> \n", enc_name, enc_iname, ikey.
name);
11843 r->
rsprintf(
"<tr><td colspan=2>\n");
11847 r->
rsprintf(
"<select title=\"Select group\" id=\"fgroup\" onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value;\">\n");
11852 for (
i = 0;;
i++) {
11872 r->
rsprintf(
"<option selected value=\"%s\">%s\n",
"ALL",
"ALL");
11874 r->
rsprintf(
"<option value=\"%s\">%s\n",
"ALL",
"ALL");
11878 r->
rsprintf(
" Panel:\n");
11879 r->
rsprintf(
"<select title=\"Select panel\" id=\"fpanel\" ");
11880 r->
rsprintf(
"onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value+");
11881 r->
rsprintf(
"'&panel='+document.getElementById('fpanel').value;\">\n");
11885 for (
i = 0;;
i++) {
11904 r->
rsprintf(
"<option value=\"\">- all -\n");
11906 r->
rsprintf(
"<option selected value=\"\">- all -\n");
11912 r->
rsprintf(
"<input type=submit value=\"Go\">\n");
11915 r->
rsprintf(
" <input type=\"button\" name=\"New\" value=\"New\" ");
11916 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New&group=%s'\">\n", hgroup);
11918 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Reset\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Reset&group=%s&panel=%s'\">\n", hgroup, hpanel);
11920 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Query\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Query&group=%s&panel=%s'\">\n", hgroup, hpanel);
11922 double xendtime = endtime;
11925 double xstarttime = xendtime - scale;
11927 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);
11935 if (hgroup[0] && !
equal_ustring(hgroup,
"ALL") && hpanel[0] == 0) {
11936 std::string strwidth =
"Small";
11940 path +=
"/History/Display/";
11944 for (
i = 0 ;;
i++) {
11952 char enc_name[256];
11953 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11957 ref +=
"graph.gif?width=";
11959 ref +=
"&cmd=oldhistory&group=";
11965 ref2 +=
"?cmd=oldhistory&group=";
11970 if (endtime != 0) {
11972 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
11980 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
11982 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
11986 r->
rsprintf(
"Group \"%s\" not found", hgroup);
11996 path +=
"/History/Display/";
12000 path +=
"/Buttons";
12002 if (hkeybutton == 0) {
12007 cm_msg(
MERROR,
"show_hist_page",
"Cannot create history panel with invalid ODB path \"%s\"", path.c_str());
12014 r->
rsprintf(
"function histDisp(p) {\n");
12015 r->
rsprintf(
" var params = '?cmd=oldhistory&group=%s&panel=%s';\n", hgroup, hpanel);
12016 r->
rsprintf(
" params += '&'+p;\n");
12017 r->
rsprintf(
" if (document.getElementById(\'hscale\') !== null)\n");
12018 r->
rsprintf(
" params += '&hscale='+document.getElementById(\'hscale\').value;\n");
12019 r->
rsprintf(
" if (document.getElementById(\'htime\') !== null)\n");
12020 r->
rsprintf(
" params += '&htime='+document.getElementById(\'htime\').value;\n");
12021 r->
rsprintf(
" if (document.getElementById(\'hwdith\') !== null)\n");
12022 r->
rsprintf(
" params += '&hwidth='+document.getElementById(\'hwidth\').value;\n");
12023 r->
rsprintf(
" if (document.getElementById(\'hindex\') !== null)\n");
12024 r->
rsprintf(
" params += '&hindex='+document.getElementById(\'hindex\').value;\n");
12025 r->
rsprintf(
" window.location.search = params;\n");
12033 size =
sizeof(
str);
12035 r->
rsprintf(
"<input type=\"button\" title=\"display last %s\" value=%s onclick=\"histDisp('scale=%s')\">\n",
str,
str,
str);
12038 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')\">");
12039 r->
rsprintf(
"<input type=\"button\" value=\"<<\" title=\"go back in time to last available data\" onclick=\"histDisp('shift=leftmax')\">");
12040 r->
rsprintf(
"<input type=\"button\" value=\"<\" title=\"go back in time\" onclick=\"histDisp('shift=left')\">");
12042 r->
rsprintf(
"<input type=\"button\" value=\" + \" title=\"zoom in\" onclick=\"histDisp('shift=zoomin')\">");
12043 r->
rsprintf(
"<input type=\"button\" value=\" - \" title=\"zoom out\" onclick=\"histDisp('shift=zoomout')\">");
12045 if (endtime != 0) {
12046 r->
rsprintf(
"<input type=\"button\" value=\">\" title=\"go forward in time\" onclick=\"histDisp('shift=right')\">");
12047 r->
rsprintf(
"<input type=\"button\" value=\">>\" title=\"go to currently updated fresh data\" onclick=\"histDisp('shift=rightmax')\">");
12051 r->
rsprintf(
"<input type=\"button\" value=\"Large\" title=\"large display\" onclick=\"histDisp('width=Large')\">\n");
12052 r->
rsprintf(
"<input type=\"button\" value=\"Small\" title=\"large display\" onclick=\"histDisp('width=Small')\">\n");
12053 r->
rsprintf(
"<input type=\"button\" value=\"Create Elog\" title=\"large display\" onclick=\"histDisp('hcmd=Create Elog')\">\n");
12054 r->
rsprintf(
"<input type=\"button\" value=\"Config\" title=\"large display\" onclick=\"histDisp('hcmd=Config')\">\n");
12055 r->
rsprintf(
"<input type=\"button\" value=\"Export\" title=\"large display\" onclick=\"histDisp('hcmd=Export')\">\n");
12058 char paramstr[256];
12061 sprintf(paramstr + strlen(paramstr),
"&scale=%d", scale);
12063 sprintf(paramstr + strlen(paramstr),
"&time=%s",
time_to_string(endtime).c_str());
12064 if (pwidth && *pwidth)
12065 sprintf(paramstr + strlen(paramstr),
"&width=%s", pwidth);
12067 std::string wi =
"640";
12069 sprintf(paramstr + strlen(paramstr),
"&width=%s", wi.c_str());
12071 if (pheight && *pheight)
12072 sprintf(paramstr + strlen(paramstr),
"&height=%s", pheight);
12075 r->
rsprintf(
"<map name=\"%s\">\r\n", hpanel);
12077 if (!(pindex && *pindex)) {
12079 path +=
"/History/Display/";
12083 path +=
"/Variables";
12096 ref +=
"?cmd=oldhistory&group=";
12107 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());
12111 std::string ref =
"?cmd=oldhistory&group=";
12125 else if (atoi(pwidth) > 0)
12126 width = atoi(pwidth);
12130 r->
rsprintf(
" <area shape=rect coords=\"%d,%d,%d,%d\" href=\"%s\">\r\n", 0, 0, width, 20, ref.c_str());
12136 if (pindex && *pindex)
12137 sprintf(paramstr + strlen(paramstr),
"&index=%s", pindex);
12141 ref +=
"graph.gif?cmd=oldhistory&group=";
12148 r->
rsprintf(
"<tr><td colspan=2><img src=\"%s\" usemap=\"#%s\"></tr>\n", ref.c_str(), hpanel);
12155 for (
i = 0,
k = 0;;
i++) {
12163 char enc_group_name[256];
12164 mstrlcpy(enc_group_name,
key.
name,
sizeof(enc_group_name));
12165 urlEncode(enc_group_name,
sizeof(enc_group_name));
12167 for (
j = 0;;
j++,
k++) {
12176 char enc_panel_name[256];
12177 mstrlcpy(enc_panel_name, ikey.
name,
sizeof(enc_panel_name));
12178 urlEncode(enc_panel_name,
sizeof(enc_panel_name));
12181 ref +=
"graph.gif?width=Small";
12182 ref +=
"&cmd=oldhistory&group=";
12183 ref += enc_group_name;
12185 ref += enc_panel_name;
12188 ref2 +=
"?cmd=oldhistory&group=";
12189 ref2 += enc_group_name;
12191 ref2 += enc_panel_name;
12193 if (endtime != 0) {
12195 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
12203 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
12205 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
12212 r->
rsprintf(
"</body></html>\r\n");
12221 const unsigned char *picon;
12222 char str[256], format[256];
12225 if (strstr(icon,
"favicon.ico") != 0) {
12228 }
else if (strstr(icon,
"favicon.png") != 0) {
12234 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
12236 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
12240 now += (int) (3600 * 24);
12242 gmtime_r(&now, &gmt_tms);
12243 strcpy(format,
"%A, %d-%b-%y %H:%M:%S GMT");
12244 strftime(
str,
sizeof(
str), format, &gmt_tms);
12248 r->
rsprintf(
"Content-Type: image/x-icon\r\n");
12250 r->
rsprintf(
"Content-Type: image/png\r\n");
12252 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
12298 if (strstr(dec_path,
"favicon.ico") != 0 ||
12299 strstr(dec_path,
"favicon.png")) {
12304 const char* password = p->
getparam(
"pwd");
12305 const char* wpassword = p->
getparam(
"wpwd");
12306 const char* command = p->
getparam(
"cmd");
12329 if (!password[0] && hkey) {
12331 int size =
sizeof(
str);
12335 db_find_key(
hDB, 0,
"/Experiment/Security/Allowed programs/mhttpd", &hkey);
12336 if (hkey == 0 && strcmp(
c->cookie_pwd.c_str(),
str) != 0) {
12347 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12356 gmtime_r(&now, &gmt_tms);
12359 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12361 r->
rsprintf(
"Set-Cookie: midas_pwd=%s; path=/; expires=%s\r\n",
12364 r->
rsprintf(
"Location: ./\n\n<html>redir</html>\r\n");
12368 if (wpassword[0]) {
12373 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12382 gmtime_r(&now, &gmt_tms);
12385 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:%M:%S GMT", &gmt_tms);
12387 r->
rsprintf(
"Set-Cookie: midas_wpwd=%s; path=/; expires=%s\r\n",
ss_crypt(wpassword,
"mi"),
str);
12390 r->
rsprintf(
"Location: %s\n\n<html>redir</html>\r\n",
str);
12396 if (strlen(dec_path) > 3 &&
12397 dec_path[strlen(dec_path)-3] ==
'm' &&
12398 dec_path[strlen(dec_path)-2] ==
'p' &&
12399 dec_path[strlen(dec_path)-1] ==
'3') {
12400 if (strrchr(dec_path,
'/'))
12409 if (strstr(dec_path,
"midas.js")) {
12414 if (strstr(dec_path,
"midas.css")) {
12421 if (strstr(dec_path,
"mhttpd.js")) {
12428 if (strstr(dec_path,
"obsolete.js")) {
12435 if (strstr(dec_path,
"mhttpd.css")) {
12442 if (strstr(dec_path,
"controls.js")) {
12475 path +=
"/Script/";
12501 path +=
"/CustomScript/";
12502 path += p->
getparam(
"customscript");
12529 std::string filename = custom[
"Status"];
12573 !(dec_path[0] ==
'H' && dec_path[1] ==
'S' && dec_path[2] ==
'/')) {
12689 show_mscb_page(p, r,
c->refresh);
12691 show_error(r,
"MSCB support not compiled into this version of mhttpd");
12709 if (strncmp(command,
"Trigger", 7) == 0) {
12722 mstrlcpy(eq_name, command + 8,
sizeof(eq_name));
12723 if (strchr(eq_name,
' '))
12724 *strchr(eq_name,
' ') = 0;
12728 path +=
"/Equipment/";
12730 path +=
"/Common/Frontend name";
12737 path +=
"/Equipment/";
12739 path +=
"/Common/Event ID";
12746 str +=
"Frontend \"";
12748 str +=
"\" not running!";
12755 str +=
"Cannot connect to frontend \"";
12777 if (strncmp(command,
"Next Subrun", 11) == 0) {
12798 mstrlcpy(
str,
"?cmd=set",
sizeof(
str));
12802 const char* group = p->
getparam(
"group");
12824 if (
equal_ustring(command,
"CNAF") || strncmp(dec_path,
"CNAF", 4) == 0) {
12840 std::string external_elog_url;
12841 int size =
sizeof(external_elog);
12844 if (external_elog && (external_elog_url.length() > 0)) {
12845 redirect(r, external_elog_url.c_str());
12855 mstrlcpy(cmdx, command,
sizeof(cmdx));
12864 if (
equal_ustring(command,
"Create ELog from this page")) {
12866 redir +=
"?cmd=New+elog";
12867 redir +=
"&odb_path=";
12890 int refresh = atoi(p->
getparam(
"refr"));
12893 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12900 now += 3600 * 24 * 365;
12903 gmtime_r(&now, &gmt_tms);
12906 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12908 r->
rsprintf(
"Set-Cookie: midas_refr=%d; path=/; expires=%s\r\n", refresh,
str);
12909 r->
rsprintf(
"Location: ./\r\n\r\n<html>redir</html>\r\n");
12956 int write_access =
TRUE;
12957 db_find_key(
hDB, 0,
"/Experiment/Security/Web Password", &hkey);
12960 int size =
sizeof(
str);
12962 if (strcmp(
c->cookie_wpwd.c_str(),
str) == 0)
12963 write_access =
TRUE;
12965 write_access =
FALSE;
12968 std::string odb_path;
12970 odb_path = p->
getparam(
"odb_path");
13001 if ((command[0]==0) && dec_path[0]) {
13003 std::string new_url =
"./?cmd=odb";
13010 if ((command[0]==0) && dec_path[0]) {
13016 for (
const char* s = dec_path; *s; s++) {
13020 std::string new_url;
13025 for (
int i=0;
i<level;
i++) {
13031 new_url +=
"?cmd=odb";
13032 new_url +=
"&odb_path=";
13059 std::string odb_path;
13064 odb_path +=
"/Custom/Images/";
13065 odb_path += dec_path;
13066 odb_path +=
"/Background";
13073 if (strstr(dec_path,
"..")) {
13075 str +=
"Invalid custom gif name \'";
13077 str +=
"\' contains \'..\'";
13088 bool found_custom =
false;
13091 odb_path +=
"/Custom/";
13092 odb_path += dec_path;
13099 found_custom =
true;
13102 odb_path +=
"/Custom/";
13103 odb_path += dec_path;
13111 found_custom =
true;
13114 odb_path +=
"/Custom/";
13115 odb_path += dec_path;
13123 found_custom =
true;
13128 if (found_custom) {
13130 if (strstr(dec_path,
"..")) {
13132 str +=
"Invalid custom page name \'";
13134 str +=
"\' contains \'..\'";
13149 std::string custom_path;
13152 if (strstr(dec_path,
"..")) {
13154 str +=
"Invalid custom file name \'";
13156 str +=
"\' contains \'..\'";
13180 if (strlen(p->
getparam(
"path")) > 0) {
13194 r->
rsprintf(
"HTTP/1.1 400 Bad Request\r\n");
13198 r->
rsprintf(
"Error: Invalid URL \"%s\" or query \"%s\" or command \"%s\"\n", p->
getparam(
"path"), p->
getparam(
"query"), command);
13205 int len = strlen(query_string);
13206 char *buf = (
char *)malloc(len+1);
13207 assert(buf != NULL);
13208 memcpy(buf, query_string, len+1);
13210 p = strtok(p,
"&");
13211 while (p != NULL) {
13213 p = strchr(p,
'=');
13222 p = strtok(NULL,
"&");
13236 param->initparam();
13239 mstrlcpy(path, url + 1,
sizeof(path));
13241 mstrlcpy(path,
string + 1,
sizeof(path));
13243 if (strchr(path,
'?'))
13244 *strchr(path,
'?') = 0;
13247 param->setparam(
"path", path);
13249 assert(query_string != NULL);
13253 param->setparam(
"query", query_string);
13255 char dec_path[256];
13256 mstrlcpy(dec_path, path,
sizeof(dec_path));
13260 param->freeparam();
13268 bool debug_decode_post =
false;
13277 mstrlcpy(path, url + 1,
sizeof(path));
13279 mstrlcpy(path, header + 1,
sizeof(path));
13280 if (strchr(path,
'?'))
13281 *strchr(path,
'?') = 0;
13282 if (strchr(path,
' '))
13283 *strchr(path,
' ') = 0;
13285 param->setparam(
"path", path);
13289 const char* pinit = string;
13295 if (strstr(
string, boundary))
13296 string = strstr(
string, boundary) + strlen(boundary);
13298 if (debug_decode_post)
13299 printf(
"decode_post: -->[%s]<--\n",
string);
13303 if (strstr(
string,
"name=")) {
13304 const char* pitem = strstr(
string,
"name=") + 5;
13305 if (*pitem ==
'\"')
13310 if (strncmp(pitem,
"attfile", 7) == 0) {
13311 int n = pitem[7] -
'1';
13317 if (strstr(pitem,
"filename=")) {
13318 const char* p = strstr(pitem,
"filename=") + 9;
13321 if (strstr(p,
"\r\n\r\n"))
13322 string = strstr(p,
"\r\n\r\n") + 4;
13323 else if (strstr(p,
"\r\r\n\r\r\n"))
13324 string = strstr(p,
"\r\r\n\r\r\n") + 6;
13329 if (strchr(pp,
'\"'))
13330 *strchr(pp,
'\"') = 0;
13334 sprintf(
str,
"attachment%d",
n);
13335 if (debug_decode_post)
13341 const char* ptmp = string;
13342 const char* p = NULL;
13344 while (*ptmp !=
'-')
13347 p = strstr(ptmp, boundary);
13359 ptmp += strlen(ptmp);
13366 char* buf = (
char*)malloc(size+1);
13370 memcpy(buf,
string, size);
13374 if (debug_decode_post)
13378 string = strstr(p, boundary) + strlen(boundary);
13380 const char* p = pitem;
13381 if (strstr(p,
"\r\n\r\n"))
13382 p = strstr(p,
"\r\n\r\n") + 4;
13383 else if (strstr(p,
"\r\r\n\r\r\n"))
13384 p = strstr(p,
"\r\r\n\r\r\n") + 6;
13386 char* ppitem = (
char*)strchr(pitem,
'\"');
13390 char* pb = (
char*)(strstr(p, boundary));
13392 string = pb + strlen(boundary);
13394 char* ptmp = (
char*)(p + (strlen(p) - 1));
13395 while (*ptmp ==
'-' || *ptmp ==
'\n' || *ptmp ==
'\r')
13401 if (debug_decode_post)
13402 printf(
"decode_post: [%s] = [%s]\n", pitem, p);
13403 param->setparam(pitem, p);
13406 while (*
string ==
'-' || *
string ==
'\n' || *
string ==
'\r')
13412 char dec_path[256];
13413 mstrlcpy(dec_path, path,
sizeof(dec_path));
13438 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo corrected successfully");
13440 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13444 cm_msg(
MERROR,
"check_odb_records",
"ODB subtree /Runinfo does not exist");
13447 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo created successfully");
13449 cm_msg(
MERROR,
"check_odb_records",
"Cannot create ODB subtree /Runinfo, db_create_record() status %d",
status);
13453 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13459 for (
i = 0 ;;
i++) {
13469 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Equipment/%s/Common corrected successfully",
key.
name);
13471 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13474 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13494#ifdef HAVE_MONGOOSE6
13495static std::vector<std::string> gUserAllowedHosts;
13498#ifdef HAVE_MONGOOSE6
13499static const std::string gOdbAllowedHosts =
"/Experiment/Security/mhttpd hosts/Allowed hosts";
13502#ifdef HAVE_MONGOOSE6
13506 cm_msg(
MINFO,
"load_allowed_hosts",
"Reloading mhttpd hosts access control list via hotlink callback");
13511 for (
unsigned int i=0;
i<gUserAllowedHosts.size();
i++)
13516 for (
int i=0; ;
i++) {
13525 if (s.length() < 1)
13538 if (
total - last < 5) {
13539 int new_size = last + 10;
13543 cm_msg(
MERROR,
"load_allowed_hosts",
"Cannot resize the allowed hosts access control list, db_resize_string(%d) status %d", new_size,
status);
13548static int init_allowed_hosts()
13562 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot create the mhttpd hosts access control list, db_get_value_string() status %d",
status);
13569 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot find the mhttpd hosts access control list, db_find_key() status %d",
status);
13573 load_allowed_hosts(
hDB, 0, 0, NULL);
13578 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot watch the mhttpd hosts access control list, db_watch() status %d",
status);
13585 int check_midas_acl(
const struct sockaddr *sa,
int len) {
13590 char hname[NI_MAXHOST];
13594 const char* status_string =
"success";
13596 status = getnameinfo(sa, len, hname,
sizeof(hname), NULL, 0, 0);
13599 status_string = gai_strerror(
status);
13604 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
status, status_string);
13609 if (strcmp(hname,
"localhost.localdomain") == 0)
13611 if (strcmp(hname,
"localhost") == 0)
13619 printf(
"Rejecting connection from \'%s\'\n", hname);
13623int open_listening_socket(
int port)
13626 struct sockaddr_in bind_addr;
13629 int lsock =
socket(AF_INET, SOCK_STREAM, 0);
13632 printf(
"Cannot create socket, socket() errno %d (%s)\n", errno, strerror(errno));
13637 memset(&bind_addr, 0,
sizeof(bind_addr));
13638 bind_addr.sin_family = AF_INET;
13639 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
13640 bind_addr.sin_port = htons((
short) port);
13644 status = setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (
char *) &flag,
sizeof(
INT));
13647 printf(
"Cannot setsockopt(SOL_SOCKET, SO_REUSEADDR), errno %d (%s)\n", errno, strerror(errno));
13651 status = bind(lsock, (
struct sockaddr *) &bind_addr,
sizeof(bind_addr));
13654 printf(
"Cannot bind() to port %d, bind() errno %d (%s)\n", port, errno, strerror(errno));
13661 printf(
"Cannot listen() on port %d, errno %d (%s), bye!\n", port, errno, strerror(errno));
13665 printf(
"mhttpd is listening on port %d\n", port);
13673int try_file_mg(
const char* try_dir,
const char* filename, std::string& path, FILE** fpp,
bool trace)
13679 if (strlen(try_dir) < 1)
13687 FILE*
fp = fopen(path.c_str(),
"r");
13691 printf(
"file \"%s\": OK!\n", path.c_str());
13693 printf(
"file \"%s\": not found.\n", path.c_str());
13706int find_file_mg(
const char* filename, std::string& path, FILE** fpp,
bool trace)
13723 try_file_mg(exptdir.c_str(), filename, path, NULL,
false);
13727#ifdef HAVE_MONGOOSE6
13731#ifdef HAVE_MONGOOSE616
13735extern void cs_md5(
char buf[33], ...);
13743#ifdef HAVE_MONGOOSE616
13744static bool multithread_mg =
true;
13747#ifdef HAVE_MONGOOSE6
13748static struct mg_mgr mgr_mg;
13772 if (!exptname.empty())
13790 size_t uri_len,
const char *ha1,
size_t ha1_len,
13791 const char *nonce,
size_t nonce_len,
const char *nc,
13792 size_t nc_len,
const char *cnonce,
size_t cnonce_len,
13793 const char *qop,
size_t qop_len,
char *resp) {
13794 static const char colon[] =
":";
13795 static const size_t one = 1;
13798 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
13799 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
13800 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
13801 colon, one, ha2,
sizeof(ha2) - 1, NULL);
13811 unsigned long now = (
unsigned long) time(NULL);
13812 unsigned long val = (
unsigned long) strtoul(nonce, NULL, 16);
13813 return now < val || now - val < 3600;
13822 const char *domain) {
13824 "HTTP/1.1 401 Unauthorized\r\n"
13825 "WWW-Authenticate: Digest qop=\"auth\", "
13826 "realm=\"%s\", nonce=\"%lu\"\r\n"
13827 "Content-Length: 0\r\n\r\n",
13828 domain, (
unsigned long) time(NULL));
13841 cm_msg(
MERROR,
"mongoose",
"mongoose web server cannot find password file \"%s\"", path.c_str());
13842 cm_msg(
MERROR,
"mongoose",
"please create password file: touch %s", path.c_str());
13846 bool have_realm =
false;
13854 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
13856 char f_domain[256];
13859 if (sscanf(buf,
"%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3) {
13862 e.username = f_user;
13863 e.password = f_ha1;
13865 if (
e.realm == auth->
realm) {
13877#ifdef HAVE_MONGOOSE6
13878std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13880 assert(!
"this code is untested!");
13886 if (buf_size == 0) {
13888 buf = (
char*)malloc(buf_size);
13889 assert(buf != NULL);
13899 if (size < buf_size) {
13900 std::string s = buf;
13905 buf_size = buf_size*2 + 16;
13906 buf = (
char*)realloc(buf, buf_size);
13907 assert(buf != NULL);
13912#ifdef HAVE_MONGOOSE616
13913std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13920 assert(buf != NULL);
13921 std::string s = buf;
13929 char expected_response[33];
13941 std::string user = find_var_mg(hdr,
"username");
13942 std::string cnonce = find_var_mg(hdr,
"cnonce");
13943 std::string
response = find_var_mg(hdr,
"response");
13944 std::string uri = find_var_mg(hdr,
"uri");
13945 std::string qop = find_var_mg(hdr,
"qop");
13946 std::string nc = find_var_mg(hdr,
"nc");
13947 std::string nonce = find_var_mg(hdr,
"nonce");
13949 if (user.length()<1)
return "";
13950 if (cnonce.length()<1)
return "";
13951 if (
response.length()<1)
return "";
13952 if (uri.length()<1)
return "";
13953 if (qop.length()<1)
return "";
13954 if (nc.length()<1)
return "";
13955 if (nonce.length()<1)
return "";
13962 const char* uri_end = strchr(hm->
uri.
p,
' ');
13963 if (!uri_end)
return "";
13965 size_t uri_length = uri_end - hm->
uri.
p;
13967 if (uri_length != uri.length())
13970 int cmp = strncmp(hm->
uri.
p, uri.c_str(), uri_length);
13979 if (
e->username != user)
13981 if (
e->realm != auth->
realm)
13983 const char* f_ha1 =
e->password.c_str();
13984 int uri_len = hm->
uri.
len;
13985 if (hm->
uri.
p[uri_len] ==
'?')
13988 hm->
uri.
p, uri_len,
13989 f_ha1, strlen(f_ha1),
13990 nonce.c_str(), nonce.length(),
13991 nc.c_str(), nc.length(),
13992 cnonce.c_str(), cnonce.length(),
13993 qop.c_str(), qop.length(),
13994 expected_response);
13995 int cmp = strcasecmp(
response.c_str(), expected_response);
13998 return e->username;
14005#ifdef HAVE_MONGOOSE616
14007struct HostlistCacheEntry
14009 time_t time_created = 0;
14010 time_t time_last_used = 0;
14011 int count_used = 0;
14014 uint32_t ipv4addr = 0;
14015 struct in6_addr ipv6addr;
14016 std::string hostname;
14017 int gai_status = 0;
14018 std::string gai_strerror;
14022static std::vector<HostlistCacheEntry*> gHostlistCache;
14024static void print_hostlist_cache()
14026 time_t now = time(NULL);
14028 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14029 HostlistCacheEntry*
e = gHostlistCache[
i];
14035 printf(
"%3d: %s \"%s\", ok %d, count_used %d, age created: %d, last_used %d",
14037 e->ipv4?
"IPv4":(
e->ipv6?
"IPv6":
"????"),
14038 e->hostname.c_str(),
14041 (int)(now -
e->time_created),
14042 (int)(now -
e->time_last_used));
14044 if (
e->gai_status) {
14045 printf(
", getnameinfo() status %d (%s)",
e->gai_status,
e->gai_strerror.c_str());
14052static bool mongoose_check_hostlist(
const union socket_address *sa)
14054 time_t now = time(NULL);
14057 uint32_t ipv4addr = 0;
14058 struct in6_addr ipv6addr;
14060 if (sa->
sa.sa_family == AF_INET) {
14062 ipv4addr = sa->
sin.sin_addr.s_addr;
14063 }
else if (sa->
sa.sa_family == AF_INET6) {
14065 memcpy(&ipv6addr, &sa->
sin6.sin6_addr,
sizeof(ipv6addr));
14067 printf(
"Rejecting connection from unknown address family %d (AF_xxx)\n", sa->
sa.sa_family);
14071 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14072 HostlistCacheEntry*
e = gHostlistCache[
i];
14078 if ((ipv4 ==
e->ipv4) && (ipv4addr ==
e->ipv4addr)) {
14080 e->time_last_used = now;
14085 if ((ipv6 ==
e->ipv6) && (memcmp(&ipv6addr, &
e->ipv6addr,
sizeof(ipv6addr)) == 0)) {
14087 e->time_last_used = now;
14094 if (
e->time_last_used < now - 24*60*60) {
14095 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);
14096 gHostlistCache[
i] = NULL;
14103 assert(ipv4 || ipv6);
14105 HostlistCacheEntry*
e =
new HostlistCacheEntry;
14107 bool found =
false;
14108 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14109 if (gHostlistCache[
i] == NULL) {
14110 gHostlistCache[
i] =
e;
14115 gHostlistCache.push_back(
e);
14118 e->time_created = now;
14119 e->time_last_used = now;
14124 e->ipv4addr = ipv4addr;
14126 memcpy(&
e->ipv6addr, &ipv6addr,
sizeof(ipv6addr));
14129 char hname[NI_MAXHOST];
14132 e->gai_status = getnameinfo(&sa->
sa,
sizeof(*sa), hname,
sizeof(hname), NULL, 0, 0);
14134 if (
e->gai_status) {
14135 e->gai_strerror = gai_strerror(
e->gai_status);
14137 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
e->gai_status,
e->gai_strerror.c_str());
14143 printf(
"connection from \"%s\"\n", hname);
14145 e->hostname = hname;
14148 if (
e->hostname ==
"localhost.localdomain")
14150 else if (
e->hostname ==
"localhost")
14161 printf(
"Rejecting connection from \'%s\'\n", hname);
14164 print_hostlist_cache();
14173 return std::string(s->
p, s->
len);
14178 size_t nlen = strlen(
name);
14192 if (cookies.length() < 1)
14194 const char* p = strstr(cookies.c_str(), cookie_name);
14197 const char* v = p+strlen(cookie_name);
14215 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> accept\n", nc, ev, ev_data);
14219 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);
14228 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> send %d bytes\n", nc, ev, ev_data, *(
int*)ev_data);
14232 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> close\n", nc, ev, ev_data);
14236 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
14245 char cookie_pwd[256];
14246 char cookie_wpwd[256];
14247 char cookie_cpwd[256];
14250 cookie_wpwd[0] = 0;
14251 cookie_cpwd[0] = 0;
14254 if (s.length() > 0) {
14255 mstrlcpy(cookie_pwd, s.c_str(),
sizeof(cookie_pwd));
14256 cookie_pwd[strcspn(cookie_pwd,
" ;\r\n")] = 0;
14261 mstrlcpy(cookie_wpwd, s.c_str(),
sizeof(cookie_pwd));
14262 cookie_wpwd[strcspn(cookie_wpwd,
" ;\r\n")] = 0;
14267 mstrlcpy(cookie_cpwd, s.c_str(),
sizeof(cookie_pwd));
14268 cookie_cpwd[strcspn(cookie_cpwd,
" ;\r\n")] = 0;
14274 if (s.length() > 0)
14275 c->refresh = atoi(s.c_str());
14283 c->cookie_pwd = cookie_pwd;
14284 c->cookie_wpwd = cookie_wpwd;
14285 c->cookie_cpwd = cookie_cpwd;
14288#define RESPONSE_SENT 1
14289#define RESPONSE_QUEUED 2
14290#define RESPONSE_501 3
14300#ifdef HAVE_MONGOOSE6
14315 decode_get(rr, NULL, &cookies, uri, query_string, t);
14324#ifdef HAVE_MONGOOSE6
14336#ifdef HAVE_MONGOOSE6
14356#ifdef HAVE_MONGOOSE616
14358static uint32_t s_ncseqno = 1;
14360struct MongooseNcUserData
14362 uint32_t ncseqno = 0;
14364 MongooseNcUserData()
14366 ncseqno = s_ncseqno++;
14370 ~MongooseNcUserData()
14382 const MongooseNcUserData* ncud = (
const MongooseNcUserData*)nc->
user_data;
14383 return ncud->ncseqno;
14386static uint32_t s_wseqno = 1;
14388struct MongooseWorkObject
14390 uint32_t wseqno = 0;
14392 uint32_t wncseqno = 0;
14393 bool http_get =
false;
14394 bool http_post =
false;
14395 bool mjsonrpc =
false;
14397 std::string origin;
14399 std::string query_string;
14400 std::string post_body;
14401 std::string post_boundary;
14403 bool send_done =
false;
14407 wseqno = s_wseqno++;
14409 wncseqno = GetNcSeqno(nc);
14414 ~MongooseWorkObject()
14424struct MongooseThreadObject
14426 std::atomic_bool fIsRunning{
false};
14427 std::thread* fThread = NULL;
14430 std::deque<MongooseWorkObject*> fQueue;
14431 std::condition_variable fNotify;
14444static std::vector<MongooseThreadObject*> gMongooseThreads;
14446static void mongoose_thread(MongooseThreadObject*);
14448MongooseThreadObject* FindThread(
void* nc)
14452 MongooseThreadObject* last_not_connected = NULL;
14454 for (
auto it : gMongooseThreads) {
14455 MongooseThreadObject* to = it;
14456 if (to->fNc == nc) {
14460 if (to->fNc == NULL) {
14461 last_not_connected = to;
14465 if (last_not_connected) {
14466 MongooseThreadObject* to = last_not_connected;
14472 MongooseThreadObject* to =
new MongooseThreadObject();
14478 gMongooseThreads.push_back(to);
14480 printf(
"Mongoose web server is using %d threads \r", (
int)gMongooseThreads.size());
14483 to->fThread =
new std::thread(mongoose_thread, to);
14488void FreeThread(
void* nc)
14492 for (
auto it : gMongooseThreads) {
14493 MongooseThreadObject* to = it;
14494 if (to->fNc == nc) {
14504static void mongoose_queue(
mg_connection* nc, MongooseWorkObject* w)
14507 MongooseThreadObject* to = FindThread(nc);
14508 assert(to->fNc == nc);
14510 to->fQueue.push_back(w);
14511 to->fMutex.unlock();
14512 to->fNotify.notify_one();
14515static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag =
false);
14519 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14520 w->http_get =
true;
14523 w->query_string = query_string;
14526 mongoose_queue(nc, w);
14533 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14534 w->http_post =
true;
14537 w->query_string = query_string;
14539 w->post_boundary = boundary;
14542 mongoose_queue(nc, w);
14547static int queue_mjsonrpc(
struct mg_connection *nc,
const std::string& origin,
const std::string& post_body,
RequestTrace* t)
14549 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14550 w->mjsonrpc =
true;
14551 w->origin = origin;
14552 w->post_body = post_body;
14555 mongoose_queue(nc, w);
14560static int thread_http_get(
mg_connection *nc, MongooseWorkObject *w)
14577 decode_get(rr, NULL, &w->cookies, w->uri.c_str(), w->query_string.c_str(), w->t);
14598 bool close_flag =
false;
14616static int thread_http_post(
mg_connection *nc, MongooseWorkObject *w)
14618 const char* post_data = w->post_body.c_str();
14619 int post_data_len = w->post_body.length();
14634 decode_post(rr, NULL, (
char*)post_data, w->post_boundary.c_str(), post_data_len, &w->cookies, w->uri.c_str(), w->t);
14637 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14650 bool close_flag =
false;
14666static int thread_mjsonrpc(
mg_connection *nc, MongooseWorkObject *w)
14668 w->t->fRPC = w->post_body;
14683 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14686 reply->GetArrayBuffer(&ptr, &size);
14688 std::string headers;
14689 headers +=
"HTTP/1.1 200 OK\n";
14690 if (w->origin.length() > 0)
14691 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14693 headers +=
"Access-Control-Allow-Origin: *\n";
14694 headers +=
"Access-Control-Allow-Credentials: true\n";
14695 headers +=
"Content-Length: " +
toString(size) +
"\n";
14696 headers +=
"Content-Type: application/octet-stream\n";
14702 std::string send = headers +
"\n";
14706 mongoose_send(nc, w, send.c_str(), send.length(), ptr, size);
14715 std::string reply_string = reply->Stringify();
14716 int reply_length = reply_string.length();
14718 std::string headers;
14719 headers +=
"HTTP/1.1 200 OK\n";
14720 if (w->origin.length() > 0)
14721 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14723 headers +=
"Access-Control-Allow-Origin: *\n";
14724 headers +=
"Access-Control-Allow-Credentials: true\n";
14725 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14726 headers +=
"Content-Type: application/json\n";
14730 printf(
"-----------------------\nSending headers: %s", headers.c_str());
14731 std::string r = reply_string.substr(0, 128);
14732 printf(
"-----------------------\nSending reply (%d bytes): %s\n\n\n", (
int)reply_string.size(), r.c_str());
14735 std::string send = headers +
"\n" + reply_string;
14739 mongoose_send(nc, w, send.c_str(), send.length(), NULL, 0);
14748static int thread_work_function(
mg_connection *nc, MongooseWorkObject *w)
14751 return thread_http_get(nc, w);
14752 else if (w->http_post)
14753 return thread_http_post(nc, w);
14754 else if (w->mjsonrpc)
14755 return thread_mjsonrpc(nc, w);
14765 char boundary[256];
14768 if (ct.length() > 0) {
14769 const char* s = strstr(ct.c_str(),
"boundary=");
14771 mstrlcpy(boundary, s+9,
sizeof(boundary));
14774#ifdef HAVE_MONGOOSE616
14775 if (multithread_mg)
14776 return queue_decode_post(nc, msg, boundary, uri, query_string, t);
14783 const char* post_data = msg->
body.
p;
14784 int post_data_len = msg->
body.
len;
14788#ifdef HAVE_MONGOOSE6
14801 decode_post(rr, NULL, (
char*)post_data, boundary, post_data_len, &cookies, uri, t);
14804 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14807#ifdef HAVE_MONGOOSE6
14817#ifdef HAVE_MONGOOSE6
14840 printf(
"handle_http_get: uri [%s], query [%s]\n", uri, query_string.c_str());
14842 if (query_string ==
"mjsonrpc_schema") {
14844 std::string reply = s->Stringify();
14847 int reply_length = reply.length();
14849 const std::string origin_header =
find_header_mg(msg,
"Origin");
14851 std::string headers;
14852 headers +=
"HTTP/1.1 200 OK\n";
14853 if (origin_header.length() > 0)
14854 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14856 headers +=
"Access-Control-Allow-Origin: *\n";
14857 headers +=
"Access-Control-Allow-Credentials: true\n";
14858 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14859 headers +=
"Content-Type: application/json\n";
14865 std::string send = headers +
"\n" + reply;
14869 mg_send(nc, send.c_str(), send.length());
14876 if (query_string ==
"mjsonrpc_schema_text") {
14881 int reply_length = reply.length();
14883 const std::string origin_header =
find_header_mg(msg,
"Origin");
14885 std::string headers;
14886 headers +=
"HTTP/1.1 200 OK\n";
14887 if (origin_header.length() > 0)
14888 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14890 headers +=
"Access-Control-Allow-Origin: *\n";
14891 headers +=
"Access-Control-Allow-Credentials: true\n";
14892 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14893 headers +=
"Content-Type: text/plain\n";
14899 std::string send = headers +
"\n" + reply;
14903 mg_send(nc, send.c_str(), send.length());
14910#ifdef HAVE_MONGOOSE616
14911 if (multithread_mg)
14912 return queue_decode_get(nc, msg, uri, query_string.c_str(), t);
14921 std::string post_data =
mgstr(&msg->
body);
14924 printf(
"handle_http_post: uri [%s], query [%s], post data %d bytes\n", uri, query_string.c_str(), (
int)post_data.length());
14926 printf(
"handle_http_post: post data = \n%s\n", post_data.c_str());
14928 if (query_string.substr(0, 8) ==
"mjsonrpc") {
14929 const std::string origin_header =
find_header_mg(msg,
"Origin");
14930 const std::string ctype_header =
find_header_mg(msg,
"Content-Type");
14932 if (strstr(ctype_header.c_str(),
"application/json") == NULL) {
14933 std::string headers;
14934 headers +=
"HTTP/1.1 415 Unsupported Media Type\n";
14941 printf(
"handle_http_post: unsupported media type \"%s\"\n", ctype_header.c_str());
14943 std::string send = headers +
"\n";
14947 mg_send(nc, send.c_str(), send.length());
14954#ifdef HAVE_MONGOOSE616
14955 if (multithread_mg)
14956 return queue_mjsonrpc(nc, origin_header, post_data, t);
14961 t->
fRPC = post_data;
14963#ifdef HAVE_MONGOOSE6
14974#ifdef HAVE_MONGOOSE6
14978 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14981 reply->GetArrayBuffer(&ptr, &size);
14983 std::string headers;
14984 headers +=
"HTTP/1.1 200 OK\n";
14985 if (origin_header.length() > 0)
14986 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14988 headers +=
"Access-Control-Allow-Origin: *\n";
14989 headers +=
"Access-Control-Allow-Credentials: true\n";
14990 headers +=
"Content-Length: " +
toString(size) +
"\n";
14991 headers +=
"Content-Type: application/octet-stream\n";
14997 std::string send = headers +
"\n";
15001 mg_send(nc, send.c_str(), send.length());
15011 std::string reply_string = reply->Stringify();
15012 int reply_length = reply_string.length();
15014 std::string headers;
15015 headers +=
"HTTP/1.1 200 OK\n";
15016 if (origin_header.length() > 0)
15017 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
15019 headers +=
"Access-Control-Allow-Origin: *\n";
15020 headers +=
"Access-Control-Allow-Credentials: true\n";
15021 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
15022 headers +=
"Content-Type: application/json\n";
15028 std::string send = headers +
"\n" + reply_string;
15032 mg_send(nc, send.c_str(), send.length());
15077 const std::string origin_header =
find_header_mg(msg,
"Origin");
15080 printf(
"handle_http_options_cors: origin [%s]\n", origin_header.c_str());
15082 std::string headers;
15083 headers +=
"HTTP/1.1 200 OK\n";
15085 if (origin_header.length() > 0)
15086 headers +=
"Access-Control-Allow-Origin: " + origin_header +
"\n";
15088 headers +=
"Access-Control-Allow-Origin: *\n";
15089 headers +=
"Access-Control-Allow-Headers: Content-Type\n";
15090 headers +=
"Access-Control-Allow-Credentials: true\n";
15091 headers +=
"Access-Control-Max-Age: 120\n";
15092 headers +=
"Content-Length: 0\n";
15093 headers +=
"Content-Type: text/plain\n";
15097 std::string send = headers +
"\n";
15101 mg_send(nc, send.c_str(), send.length());
15110#ifdef HAVE_MONGOOSE616
15111static MVOdb* gProxyOdb = NULL;
15118 std::string uri_encoded =
mgstr(&msg->
uri);
15119 std::string uri =
UrlDecode(uri_encoded.c_str());
15124 user =
mgstr(user_mg_str);
15127 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());
15133 t->
fQuery = query_string;
15137 if (method ==
"OPTIONS" && query_string ==
"mjsonrpc" &&
mg_get_http_header(msg,
"Access-Control-Request-Method") != NULL) {
15160 printf(
"handle_http_message: auth user: \"%s\"\n", username.c_str());
15162 if (username.length() == 0) {
15164 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());
15176#ifdef HAVE_MONGOOSE616
15178 std::string::size_type p1 = uri.find(
"/", 1);
15179 if (p1 == uri.length()-1) {
15180 std::string
response =
"404 Not Found (Proxy name is missing)";
15186 std::string::size_type p2 = uri.find(
"/", p1+1);
15187 if (p2 == std::string::npos) {
15188 std::string
response =
"404 Not Found (Proxy URL should end with a slash)";
15194 std::string p = uri.substr(p1+1, p2-p1-1);
15196 if (p.length() < 1) {
15197 std::string
response =
"404 Not Found (Double-slash or Proxy name is too short)";
15203 std::string destination;
15204 gProxyOdb->RS(p.c_str(), &destination);
15205 if (destination.length() < 1) {
15206 std::string
response =
"404 Not Found (Proxy not found in ODB)";
15211 }
else if (destination[0] ==
'#') {
15212 std::string
response =
"404 Not Found (Proxy commented-out in ODB)";
15218 std::string
response =
"404 Not Found (Proxy address should not end with a slash)";
15224 std::string
response =
"404 Not Found (Proxy address does not start with http";
15237 printf(
"proxy: uri [%s] mount [%s] upstream [%s]\n", uri.c_str(),
mgstr(&mount).c_str(),
mgstr(&upstream).c_str());
15239 mg_http_reverse_proxy(nc, msg, mount, upstream);
15248 if (method ==
"GET")
15250 else if (method ==
"POST")
15255 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15257 std::string
response =
"501 Not Implemented";
15268#ifdef HAVE_MONGOOSE6
15270static void handle_http_event_mg(
struct mg_connection *nc,
int ev,
void *ev_data)
15275 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15280 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15285static void handle_http_redirect(
struct mg_connection *nc,
int ev,
void *ev_data)
15292 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15294 mg_printf(nc,
"HTTP/1.1 302 Found\r\nLocation: https://%s%s\r\n\r\n",
15295 ((std::string*)(nc->
user_data))->c_str(),
15302 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15308#ifdef HAVE_MONGOOSE616
15313static std::atomic_bool s_shutdown{
false};
15314static struct mg_mgr s_mgr;
15315static std::atomic_int s_rseqno{1};
15316static std::mutex s_mg_broadcast_mutex;
15320struct work_request {
15322 MongooseWorkObject* w;
15327struct work_result {
15329 uint32_t check = 0x12345678;
15331 MongooseWorkObject* w = NULL;
15332 const char* p1 = NULL;
15334 const char* p2 = NULL;
15336 bool close_flag =
false;
15337 bool send_501 =
false;
15341static void mongoose_queue(
void *nc, MongooseWorkObject *w)
15343 struct work_request req = {nc, w};
15347 if (
write(s_sock[0], &req,
sizeof(req)) < 0) {
15348 fprintf(stderr,
"mongoose_queue: Error: write(s_sock(0)) error %d (%s)\n", errno, strerror(errno));
15354static void on_work_complete(
struct mg_connection *nc,
int ev,
void *ev_data)
15357 struct work_result *res = (
struct work_result *)ev_data;
15359 assert(res != NULL);
15360 assert(res->w != NULL);
15371 if (GetNcSeqno(nc) != res->w->wncseqno)
15376 if (res->send_501) {
15377 std::string
response =
"501 Not Implemented";
15383 mg_send(nc, res->p1, res->s1);
15386 mg_send(nc, res->p2, res->s2);
15388 if (res->close_flag) {
15395 res->w->send_done =
true;
15398static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag)
15401 struct work_result res;
15404 res.rseqno = s_rseqno++;
15409 res.close_flag = close_flag;
15410 res.send_501 =
false;
15452 s_mg_broadcast_mutex.lock();
15453 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15454 s_mg_broadcast_mutex.unlock();
15457static void mongoose_send_501(
mg_connection* nc, MongooseWorkObject* w)
15459 struct work_result res;
15462 res.rseqno = s_rseqno++;
15467 res.close_flag =
false;
15468 res.send_501 =
true;
15471 s_mg_broadcast_mutex.lock();
15472 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15473 s_mg_broadcast_mutex.unlock();
15477void *worker_thread_proc(
void *
param)
15480 struct work_request req = {0};
15482 while ((!
_abort) && (! s_shutdown)) {
15483 int rd =
read(s_sock[1], &req,
sizeof(req));
15489 if (
_abort || s_shutdown) {
15492 fprintf(stderr,
"worker_thread_proc: Error: read(s_sock(1)) returned %d, error %d (%s)\n", rd, errno, strerror(errno));
15499 int response = thread_work_function(req.nc, req.w);
15503 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15504 mongoose_send_501(req.nc, req.w);
15507 req.w->t->fCompleted =
true;
15519static void mongoose_thread(MongooseThreadObject* to)
15523 std::unique_lock<std::mutex> ulm(to->fMutex, std::defer_lock);
15525 to->fIsRunning =
true;
15527 while ((!
_abort) && (! s_shutdown)) {
15528 MongooseWorkObject *w = NULL;
15531 while (to->fQueue.empty()) {
15533 to->fNotify.wait(ulm);
15534 if (
_abort || s_shutdown) {
15539 if (
_abort || s_shutdown) {
15543 w = to->fQueue.front();
15544 to->fQueue.pop_front();
15549 int response = thread_work_function(w->nc, w);
15553 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15554 mongoose_send_501(w->nc, w);
15559 if (!w->send_done) {
15565 w->t->fCompleted =
true;
15573 to->fIsRunning =
false;
15578static bool mongoose_hostlist_enabled(
const struct mg_connection *nc);
15580static void ev_handler(
struct mg_connection *nc,
int ev,
void *ev_data)
15594 printf(
"ev_handler: connection %p, event %d\n", nc, ev);
15600 nc->
user_data =
new MongooseNcUserData();
15603 printf(
"ev_handler: connection %p, MG_EV_ACCEPT, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15608 }
else if (mongoose_hostlist_enabled(nc)) {
15609 if (!mongoose_check_hostlist(&nc->
sa)) {
15616 printf(
"ev_handler: connection %p, MG_EV_RECV, %d bytes\n", nc, *(
int*)ev_data);
15625 printf(
"ev_handler: connection %p, MG_EV_SEND, %d bytes\n", nc, *(
int*)ev_data);
15630 printf(
"ev_handler: connection %p, MG_EV_HTTP_CHUNK\n", nc);
15641 printf(
"ev_handler: connection %p, MG_EV_HTTP_REQUEST \"%s\" \"%s\"\n", nc,
mgstr(&msg->
method).c_str(),
mgstr(&msg->
uri).c_str());
15653 printf(
"ev_handler: connection %p, MG_EV_CLOSE, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15658 MongooseNcUserData* ncud = (MongooseNcUserData*)nc->
user_data;
15667#define FLAG_HTTPS MG_F_USER_1
15668#define FLAG_PASSWORDS MG_F_USER_2
15669#define FLAG_HOSTLIST MG_F_USER_3
15678 return flags & FLAG_PASSWORDS;
15681static bool mongoose_hostlist_enabled(
const struct mg_connection *nc)
15688 return flags & FLAG_HOSTLIST;
15691static int mongoose_listen(
const char* address,
int flags)
15695 if (flags & FLAG_HTTPS) {
15696 cm_msg(
MERROR,
"mongoose_listen",
"https port \"%s\" requested, but mhttpd compiled without MG_ENABLE_SSL", address);
15703 cm_msg(
MERROR,
"mongoose_listen",
"Cannot mg_bind address \"%s\"", address);
15707 if (
flags & FLAG_HTTPS) {
15709 std::string cert_file;
15714 cm_msg(
MERROR,
"mongoose_listen",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
15715 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");
15716 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");
15720 printf(
"Mongoose web server will use https certificate file \"%s\"\n", cert_file.c_str());
15722 const char* errmsg =
mg_set_ssl(nc, cert_file.c_str(), NULL);
15724 cm_msg(
MERROR,
"mongoose_listen",
"Cannot enable https with certificate file \"%s\", error: %s", cert_file.c_str(), errmsg);
15738 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");
15743static int mongoose_init(MVOdb* odb,
bool no_passwords,
bool no_hostlist,
const std::vector<std::string>& user_hostlist)
15745 bool enable_localhost_port =
true;
15746 int localhost_port = 8080;
15747 bool localhost_port_passwords =
false;
15749 bool enable_insecure_port =
false;
15750 int insecure_port = 8081;
15751 bool insecure_port_passwords =
true;
15752 bool insecure_port_hostlist =
true;
15754 bool enable_https_port =
false;
15755 int https_port = 8443;
15756 bool https_port_passwords =
true;
15757 bool https_port_hostlist =
false;
15759 std::vector<std::string> hostlist;
15760 hostlist.push_back(
"localhost");
15762 bool enable_ipv6 =
true;
15764 odb->RB(
"Enable localhost port", &enable_localhost_port,
true);
15765 odb->RI(
"localhost port", &localhost_port,
true);
15766 odb->RB(
"localhost port passwords", &localhost_port_passwords,
true);
15767 odb->RB(
"Enable insecure port", &enable_insecure_port,
true);
15768 odb->RI(
"insecure port", &insecure_port,
true);
15769 odb->RB(
"insecure port passwords", &insecure_port_passwords,
true);
15770 odb->RB(
"insecure port host list", &insecure_port_hostlist,
true);
15771 odb->RB(
"Enable https port", &enable_https_port,
true);
15772 odb->RI(
"https port", &https_port,
true);
15773 odb->RB(
"https port passwords", &https_port_passwords,
true);
15774 odb->RB(
"https port host list", &https_port_hostlist,
true);
15775 odb->RSA(
"Host list", &hostlist,
true, 10, 256);
15776 odb->RB(
"Enable IPv6", &enable_ipv6,
true);
15779 gProxyOdb = odb->Chdir(
"Proxy",
true);
15780 std::string proxy_example =
"#http://localhost:8080";
15781 gProxyOdb->RS(
"example", &proxy_example,
true);
15787 && ((enable_localhost_port && localhost_port_passwords)
15788 || (enable_insecure_port && insecure_port_passwords)
15789 || (enable_https_port && https_port_passwords))) {
15793 printf(
"mongoose_init: Error: Cannot initialize authorization object!\n");
15798 printf(
"Password protection is off\n");
15802 && ((enable_insecure_port && insecure_port_hostlist)
15803 || (enable_https_port && https_port_hostlist))) {
15807 for (
unsigned int i=0;
i<user_hostlist.size();
i++)
15810 for (
unsigned i=0;
i<hostlist.size();
i++) {
15811 std::string s = hostlist[
i];
15812 if (s.length() < 1)
15822 printf(
"Hostlist active, connections will be accepted only from: ");
15830 printf(
"Hostlist off, connections from anywhere will be accepted\n");
15835 bool listen_failed =
false;
15837 if (enable_localhost_port) {
15839 sprintf(
str,
"localhost:%d", localhost_port);
15842 listen_failed =
true;
15844 sprintf(
str,
"[::1]:%d", localhost_port);
15847 listen_failed =
true;
15851 if (enable_insecure_port) {
15854 if (insecure_port_passwords)
15855 flags |= FLAG_PASSWORDS;
15856 if (insecure_port_hostlist)
15857 flags |= FLAG_HOSTLIST;
15859 sprintf(
str,
"[::]:%d", insecure_port);
15862 listen_failed =
true;
15864 sprintf(
str,
"%d", insecure_port);
15867 listen_failed =
true;
15871 if (enable_https_port) {
15874 if (https_port_passwords)
15875 flags |= FLAG_PASSWORDS;
15876 if (https_port_hostlist)
15877 flags |= FLAG_HOSTLIST;
15878 flags |= FLAG_HTTPS;
15880 sprintf(
str,
"[::]:%d", https_port);
15883 listen_failed =
true;
15885 sprintf(
str,
"%d", https_port);
15888 listen_failed =
true;
15892 if (listen_failed) {
15893 cm_msg(
MERROR,
"mongoose_init",
"Failed to listen on a TCP port enabled in ODB /WebServer");
15900static void mongoose_poll(
int msec = 200)
15905static void mongoose_cleanup()
15907 printf(
"Mongoose web server shutting down\n");
15912 if (s_mgr.active_connections) {
15924 for (
auto it : gMongooseThreads) {
15925 MongooseThreadObject* to = it;
15926 to->fNotify.notify_one();
15930 for (
int i=0;
i<10;
i++) {
15931 int count_running = 0;
15932 for (
auto it : gMongooseThreads) {
15933 MongooseThreadObject* to = it;
15935 if (to->fIsRunning) {
15939 printf(
"Mongoose web server shutting down, %d threads still running\n", count_running);
15940 if (count_running == 0)
15942 mongoose_poll(1000);
15946 for (
auto it : gMongooseThreads) {
15947 MongooseThreadObject* to = it;
15949 if (to->fIsRunning) {
15950 cm_msg(
MERROR,
"mongoose",
"thread failed to shut down");
15953 to->fThread->join();
15954 delete to->fThread;
15957 gMongooseThreads.clear();
15965 for (
auto e : gHostlistCache) {
15968 gHostlistCache.clear();
15978 printf(
"Mongoose web server shut down\n");
15983#ifdef HAVE_MONGOOSE6
15990int start_mg(
int user_http_port,
int user_https_port,
int socket_priviledged_port,
int verbose)
16005 int http_port = 8080;
16006 int https_port = 8443;
16007 int http_redirect_to_https = 1;
16009 size =
sizeof(http_port);
16012 size =
sizeof(https_port);
16015 size =
sizeof(http_redirect_to_https);
16018 bool need_cert_file =
false;
16019 bool need_password_file =
false;
16021 if (user_http_port)
16022 http_port = user_http_port;
16024 if (user_https_port)
16025 https_port = user_https_port;
16028 need_cert_file =
true;
16029 need_password_file =
true;
16033 http_redirect_to_https = 0;
16035 if (http_port && !http_redirect_to_https) {
16038 need_password_file =
false;
16041 if (socket_priviledged_port >= 0) {
16043 need_password_file =
false;
16044 printf(
"Mongoose web server password portection is disabled: serving unencrypted http on port 80\n");
16047 bool have_at_least_one_port =
false;
16049 std::string cert_file;
16051 if (need_cert_file) {
16055 cm_msg(
MERROR,
"mongoose",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
16056 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");
16060 printf(
"Mongoose web server will use SSL certificate file \"%s\"\n", cert_file.c_str());
16063 if (need_password_file) {
16067 printf(
"Error: Cannot initialize authorization object!\n");
16072 printf(
"Mongoose web server will not use password protection\n");
16076 printf(
"start_mg!\n");
16079 signal(SIGPIPE, SIG_IGN);
16086 if (!request_mutex) {
16094 if (socket_priviledged_port >= 0) {
16097 cm_msg(
MERROR,
"mongoose",
"Cannot create mg_connection for set-uid-root privileged port");
16102#ifdef MG_ENABLE_THREADS
16108 have_at_least_one_port =
true;
16109 printf(
"mongoose web server is listening on the set-uid-root privileged port\n");
16112 if (http_port != 80) {
16114 sprintf(
str,
"%d", http_port);
16117 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", http_port);
16121#ifdef MG_ENABLE_THREADS
16126 if (http_redirect_to_https) {
16129 sprintf(
str,
"%d", https_port);
16130 std::string s = hostname +
":" + std::string(
str);
16133 printf(
"mongoose web server is redirecting HTTP port %d to https://%s\n", http_port, s.c_str());
16138 have_at_least_one_port =
true;
16139 printf(
"mongoose web server is listening on the HTTP port %d\n", http_port);
16143#ifdef MG_ENABLE_SSL
16145 sprintf(
str,
"%d", https_port);
16148 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", https_port);
16153#ifdef MG_ENABLE_THREADS
16159 have_at_least_one_port =
true;
16160 printf(
"mongoose web server is listening on the HTTPS port %d\n", https_port);
16162 cm_msg(
MERROR,
"mongoose",
"https port %d requested, but mhttpd compiled without MG_ENABLE_SSL", https_port);
16167 if (!have_at_least_one_port) {
16168 cm_msg(
MERROR,
"mongoose",
"cannot start: no ports defined");
16178 printf(
"stop_mg!\n");
16184 printf(
"stop_mg done!\n");
16199#ifdef HAVE_MONGOOSE6
16210#ifdef HAVE_MONGOOSE6
16227 doc->
D(
"get current value of mhttpd http_trace");
16228 doc->
P(NULL, 0,
"there are no input parameters");
16229 doc->
R(NULL, MJSON_INT,
"current value of http_trace");
16240 doc->
D(
"set new value of mhttpd http_trace");
16241 doc->
P(NULL, MJSON_INT,
"new value of http_trace");
16242 doc->
R(NULL, MJSON_INT,
"new value of http_trace");
16262#ifdef HAVE_MONGOOSE6
16263 int user_http_port = 0;
16264 int user_https_port = 0;
16266#ifdef HAVE_MONGOOSE616
16267 bool no_passwords =
false;
16268 bool no_hostlist =
false;
16270 const char *myname =
"mhttpd";
16272 setbuf(stdout, NULL);
16273 setbuf(stderr, NULL);
16276 signal(SIGPIPE, SIG_IGN);
16279#ifdef HAVE_MONGOOSE6
16284 int socket_priviledged_port = -1;
16288 if (getuid() != geteuid()) {
16291 printf(
"mhttpd is running in setuid-root mode.\n");
16293 socket_priviledged_port = open_listening_socket(port80);
16294 if (socket_priviledged_port < 0) {
16295 printf(
"Cannot open listening socket on TCP port %d, aborting.\n", port80);
16300 status = setuid(getuid());
16302 printf(
"Cannot give up root privelege, aborting.\n");
16305 status = setuid(getuid());
16307 printf(
"Cannot give up root privelege, aborting.\n");
16314 char midas_hostname[256];
16315 char midas_expt[256];
16316 std::string expdir;
16319 cm_get_environment(midas_hostname,
sizeof(midas_hostname), midas_expt,
sizeof(midas_expt));
16322#ifdef HAVE_MONGOOSE6
16323 gUserAllowedHosts.clear();
16325 std::vector<std::string> user_hostlist;
16327 for (
int i = 1;
i < argc;
i++) {
16328 if (argv[
i][0] ==
'-' && argv[
i][1] ==
'D')
16330 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'v')
16332 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'E')
16334 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'H') {
16336#ifdef HAVE_MONGOOSE6
16337 }
else if (strcmp(argv[
i],
"--http") == 0) {
16339 user_http_port = atoi(argv[
i+1]);
16341 }
else if (strcmp(argv[
i],
"--https") == 0) {
16343 user_https_port = atoi(argv[
i+1]);
16346 }
else if (strcmp(argv[
i],
"--trace-mg") == 0) {
16350 }
else if (strcmp(argv[
i],
"--trace-mg-verbose") == 0) {
16352 }
else if (strcmp(argv[
i],
"--no-trace-mg-recv") == 0) {
16354 }
else if (strcmp(argv[
i],
"--no-trace-mg-send") == 0) {
16356 }
else if (strcmp(argv[
i],
"--verbose-mg") == 0) {
16358#ifdef HAVE_MONGOOSE616
16359 }
else if (strcmp(argv[
i],
"--no-multithread") == 0) {
16360 multithread_mg =
false;
16361 }
else if (strcmp(argv[
i],
"--no-passwords") == 0) {
16362 no_passwords =
true;
16363 }
else if (strcmp(argv[
i],
"--no-hostlist") == 0) {
16364 no_hostlist =
true;
16366 }
else if (strcmp(argv[
i],
"--expdir") == 0) {
16367 expdir = argv[
i+1];
16369 }
else if (argv[
i][0] ==
'-') {
16370 if (
i + 1 >= argc || argv[
i + 1][0] ==
'-')
16372 if (argv[
i][1] ==
'h')
16373 mstrlcpy(midas_hostname, argv[++
i],
sizeof(midas_hostname));
16374 else if (argv[
i][1] ==
'e')
16375 mstrlcpy(midas_expt, argv[++
i],
sizeof(midas_hostname));
16376 else if (argv[
i][1] ==
'a') {
16377#ifdef HAVE_MONGOOSE6
16378 gUserAllowedHosts.push_back(argv[++
i]);
16380 user_hostlist.push_back(argv[++
i]);
16382 }
else if (argv[
i][1] ==
'p') {
16383 printf(
"Option \"-p port_number\" for the old web server is obsolete.\n");
16384 printf(
"mongoose web server is the new default, port number is set in ODB or with \"--http port_number\".\n");
16385 printf(
"To run the obsolete old web server, please use \"--oldserver\" switch.\n");
16389 printf(
"usage: %s [-h Hostname[:port]] [-e Experiment] [-v] [-D] [-a Hostname] [--expdir EXPDIR]\n\n", argv[0]);
16390 printf(
" -a add hostname to the hostlist of hosts allowed to connect to mhttpd\n");
16391 printf(
" -e experiment to connect to\n");
16392 printf(
" -h connect to midas server (mserver) on given host\n");
16393 printf(
" --expdir EXPDIR specify experiment directory if connected to mserver\n");
16394 printf(
" -v display verbose HTTP communication\n");
16395 printf(
" -D become a daemon\n");
16396 printf(
" -E only display ELog system\n");
16397 printf(
" -H only display history plots\n");
16398#ifdef HAVE_MONGOOSE6
16399 printf(
" --http port - bind to specified HTTP port (default is ODB \"/Experiment/midas http port\")\n");
16400 printf(
" --https port - bind to specified HTTP port (default is ODB \"/Experiment/midas https port\")\n");
16402 printf(
" --verbose-mg - trace mongoose web requests\n");
16403 printf(
" --trace-mg - trace mongoose events\n");
16404 printf(
" --no-trace-mg-recv - do not trace mongoose recv events\n");
16405 printf(
" --no-trace-mg-send - dop not trace mongoose send events\n");
16406#ifdef HAVE_MONGOOSE616
16407 printf(
" --no-multithread - disable mongoose multithreading\n");
16408 printf(
" --no-passwords - disable password protection\n");
16409 printf(
" --no-hostlist - disable access control host list\n");
16417 printf(
"Becoming a daemon...\n");
16423 FILE *
f = fopen(
"/var/run/mhttpd.pid",
"w");
16431 myname =
"mhttpd_history";
16447 if (expdir.empty()) {
16449 printf(
"mhttpd is connected to the mserver, this is not the normal configuration and it will likely crash unless experiment directory is also specified via --expdir EXPDIR\n");
16453 cm_msg(
MERROR,
"main",
"Experiment directory \"%s\" does not exist", expdir.c_str());
16459 cm_msg(
MINFO,
"main",
"This mhttpd is connected via the mserver, using expriment path \"%s\"", expdir.c_str());
16475 MVOdb *odb = MakeMidasOdb(
hDB);
16483 printf(
"check_odb_records() failed, see messages and midas.log, bye!\n");
16488#ifdef HAVE_MONGOOSE6
16489 if (init_allowed_hosts() !=
SUCCESS) {
16490 printf(
"init_allowed_hosts() failed, see messages and midas.log, bye!\n");
16497 printf(
"mhttpd allowed hosts list: ");
16505 printf(
"mhttpd allowed hosts list is empty\n");
16528#ifdef HAVE_MONGOOSE6
16529 status = start_mg(user_http_port, user_https_port, socket_priviledged_port,
verbose);
16532 printf(
"could not start the mongoose web server, see messages and midas.log, bye!\n");
16538#ifdef HAVE_MONGOOSE616
16542 signal(SIGPIPE, SIG_IGN);
16558 MVOdb* o = odb->Chdir(
"WebServer",
true);
16559 status = mongoose_init(o, no_passwords, no_hostlist, user_hostlist);
16562 printf(
"Error: Could not start the mongoose web server, see messages and midas.log, bye!\n");
16570#ifdef HAVE_MONGOOSE6
16575#ifdef HAVE_MONGOOSE616
16596 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_set_path(const char *path)
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)
int ss_dir_exist(const char *path)
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)
INT cm_msg_flush_buffer()
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)