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";
12747 str +=
"Frontend \"";
12749 str +=
"\" not running!";
12756 str +=
"Cannot connect to frontend \"";
12778 if (strncmp(command,
"Next Subrun", 11) == 0) {
12799 mstrlcpy(
str,
"?cmd=set",
sizeof(
str));
12803 const char* group = p->
getparam(
"group");
12825 if (
equal_ustring(command,
"CNAF") || strncmp(dec_path,
"CNAF", 4) == 0) {
12841 std::string external_elog_url;
12842 int size =
sizeof(external_elog);
12845 if (external_elog && (external_elog_url.length() > 0)) {
12846 redirect(r, external_elog_url.c_str());
12856 mstrlcpy(cmdx, command,
sizeof(cmdx));
12865 if (
equal_ustring(command,
"Create ELog from this page")) {
12867 redir +=
"?cmd=New+elog";
12868 redir +=
"&odb_path=";
12891 int refresh = atoi(p->
getparam(
"refr"));
12894 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12901 now += 3600 * 24 * 365;
12904 gmtime_r(&now, &gmt_tms);
12907 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12909 r->
rsprintf(
"Set-Cookie: midas_refr=%d; path=/; expires=%s\r\n", refresh,
str);
12910 r->
rsprintf(
"Location: ./\r\n\r\n<html>redir</html>\r\n");
12957 int write_access =
TRUE;
12958 db_find_key(
hDB, 0,
"/Experiment/Security/Web Password", &hkey);
12961 int size =
sizeof(
str);
12963 if (strcmp(
c->cookie_wpwd.c_str(),
str) == 0)
12964 write_access =
TRUE;
12966 write_access =
FALSE;
12969 std::string odb_path;
12971 odb_path = p->
getparam(
"odb_path");
13002 if ((command[0]==0) && dec_path[0]) {
13004 std::string new_url =
"./?cmd=odb";
13011 if ((command[0]==0) && dec_path[0]) {
13017 for (
const char* s = dec_path; *s; s++) {
13021 std::string new_url;
13026 for (
int i=0;
i<level;
i++) {
13032 new_url +=
"?cmd=odb";
13033 new_url +=
"&odb_path=";
13060 std::string odb_path;
13065 odb_path +=
"/Custom/Images/";
13066 odb_path += dec_path;
13067 odb_path +=
"/Background";
13074 if (strstr(dec_path,
"..")) {
13076 str +=
"Invalid custom gif name \'";
13078 str +=
"\' contains \'..\'";
13089 bool found_custom =
false;
13092 odb_path +=
"/Custom/";
13093 odb_path += dec_path;
13100 found_custom =
true;
13103 odb_path +=
"/Custom/";
13104 odb_path += dec_path;
13112 found_custom =
true;
13115 odb_path +=
"/Custom/";
13116 odb_path += dec_path;
13124 found_custom =
true;
13129 if (found_custom) {
13131 if (strstr(dec_path,
"..")) {
13133 str +=
"Invalid custom page name \'";
13135 str +=
"\' contains \'..\'";
13150 std::string custom_path;
13153 if (strstr(dec_path,
"..")) {
13155 str +=
"Invalid custom file name \'";
13157 str +=
"\' contains \'..\'";
13181 if (strlen(p->
getparam(
"path")) > 0) {
13195 r->
rsprintf(
"HTTP/1.1 400 Bad Request\r\n");
13199 r->
rsprintf(
"Error: Invalid URL \"%s\" or query \"%s\" or command \"%s\"\n", p->
getparam(
"path"), p->
getparam(
"query"), command);
13206 int len = strlen(query_string);
13207 char *buf = (
char *)malloc(len+1);
13208 assert(buf != NULL);
13209 memcpy(buf, query_string, len+1);
13211 p = strtok(p,
"&");
13212 while (p != NULL) {
13214 p = strchr(p,
'=');
13223 p = strtok(NULL,
"&");
13237 param->initparam();
13240 mstrlcpy(path, url + 1,
sizeof(path));
13242 mstrlcpy(path,
string + 1,
sizeof(path));
13244 if (strchr(path,
'?'))
13245 *strchr(path,
'?') = 0;
13248 param->setparam(
"path", path);
13250 assert(query_string != NULL);
13254 param->setparam(
"query", query_string);
13256 char dec_path[256];
13257 mstrlcpy(dec_path, path,
sizeof(dec_path));
13261 param->freeparam();
13269 bool debug_decode_post =
false;
13278 mstrlcpy(path, url + 1,
sizeof(path));
13280 mstrlcpy(path, header + 1,
sizeof(path));
13281 if (strchr(path,
'?'))
13282 *strchr(path,
'?') = 0;
13283 if (strchr(path,
' '))
13284 *strchr(path,
' ') = 0;
13286 param->setparam(
"path", path);
13290 const char* pinit = string;
13296 if (strstr(
string, boundary))
13297 string = strstr(
string, boundary) + strlen(boundary);
13299 if (debug_decode_post)
13300 printf(
"decode_post: -->[%s]<--\n",
string);
13304 if (strstr(
string,
"name=")) {
13305 const char* pitem = strstr(
string,
"name=") + 5;
13306 if (*pitem ==
'\"')
13311 if (strncmp(pitem,
"attfile", 7) == 0) {
13312 int n = pitem[7] -
'1';
13318 if (strstr(pitem,
"filename=")) {
13319 const char* p = strstr(pitem,
"filename=") + 9;
13322 if (strstr(p,
"\r\n\r\n"))
13323 string = strstr(p,
"\r\n\r\n") + 4;
13324 else if (strstr(p,
"\r\r\n\r\r\n"))
13325 string = strstr(p,
"\r\r\n\r\r\n") + 6;
13330 if (strchr(pp,
'\"'))
13331 *strchr(pp,
'\"') = 0;
13335 sprintf(
str,
"attachment%d",
n);
13336 if (debug_decode_post)
13342 const char* ptmp = string;
13343 const char* p = NULL;
13345 while (*ptmp !=
'-')
13348 p = strstr(ptmp, boundary);
13360 ptmp += strlen(ptmp);
13367 char* buf = (
char*)malloc(size+1);
13371 memcpy(buf,
string, size);
13375 if (debug_decode_post)
13379 string = strstr(p, boundary) + strlen(boundary);
13381 const char* p = pitem;
13382 if (strstr(p,
"\r\n\r\n"))
13383 p = strstr(p,
"\r\n\r\n") + 4;
13384 else if (strstr(p,
"\r\r\n\r\r\n"))
13385 p = strstr(p,
"\r\r\n\r\r\n") + 6;
13387 char* ppitem = (
char*)strchr(pitem,
'\"');
13391 char* pb = (
char*)(strstr(p, boundary));
13393 string = pb + strlen(boundary);
13395 char* ptmp = (
char*)(p + (strlen(p) - 1));
13396 while (*ptmp ==
'-' || *ptmp ==
'\n' || *ptmp ==
'\r')
13402 if (debug_decode_post)
13403 printf(
"decode_post: [%s] = [%s]\n", pitem, p);
13404 param->setparam(pitem, p);
13407 while (*
string ==
'-' || *
string ==
'\n' || *
string ==
'\r')
13413 char dec_path[256];
13414 mstrlcpy(dec_path, path,
sizeof(dec_path));
13439 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo corrected successfully");
13441 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13445 cm_msg(
MERROR,
"check_odb_records",
"ODB subtree /Runinfo does not exist");
13448 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo created successfully");
13450 cm_msg(
MERROR,
"check_odb_records",
"Cannot create ODB subtree /Runinfo, db_create_record() status %d",
status);
13454 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13460 for (
i = 0 ;;
i++) {
13470 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Equipment/%s/Common corrected successfully",
key.
name);
13472 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13475 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13495#ifdef HAVE_MONGOOSE6
13496static std::vector<std::string> gUserAllowedHosts;
13499#ifdef HAVE_MONGOOSE6
13500static const std::string gOdbAllowedHosts =
"/Experiment/Security/mhttpd hosts/Allowed hosts";
13503#ifdef HAVE_MONGOOSE6
13507 cm_msg(
MINFO,
"load_allowed_hosts",
"Reloading mhttpd hosts access control list via hotlink callback");
13512 for (
unsigned int i=0;
i<gUserAllowedHosts.size();
i++)
13517 for (
int i=0; ;
i++) {
13526 if (s.length() < 1)
13539 if (
total - last < 5) {
13540 int new_size = last + 10;
13544 cm_msg(
MERROR,
"load_allowed_hosts",
"Cannot resize the allowed hosts access control list, db_resize_string(%d) status %d", new_size,
status);
13549static int init_allowed_hosts()
13563 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot create the mhttpd hosts access control list, db_get_value_string() status %d",
status);
13570 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot find the mhttpd hosts access control list, db_find_key() status %d",
status);
13574 load_allowed_hosts(
hDB, 0, 0, NULL);
13579 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot watch the mhttpd hosts access control list, db_watch() status %d",
status);
13586 int check_midas_acl(
const struct sockaddr *sa,
int len) {
13591 char hname[NI_MAXHOST];
13595 const char* status_string =
"success";
13597 status = getnameinfo(sa, len, hname,
sizeof(hname), NULL, 0, 0);
13600 status_string = gai_strerror(
status);
13605 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
status, status_string);
13610 if (strcmp(hname,
"localhost.localdomain") == 0)
13612 if (strcmp(hname,
"localhost") == 0)
13620 printf(
"Rejecting connection from \'%s\'\n", hname);
13624int open_listening_socket(
int port)
13627 struct sockaddr_in bind_addr;
13630 int lsock =
socket(AF_INET, SOCK_STREAM, 0);
13633 printf(
"Cannot create socket, socket() errno %d (%s)\n", errno, strerror(errno));
13638 memset(&bind_addr, 0,
sizeof(bind_addr));
13639 bind_addr.sin_family = AF_INET;
13640 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
13641 bind_addr.sin_port = htons((
short) port);
13645 status = setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (
char *) &flag,
sizeof(
INT));
13648 printf(
"Cannot setsockopt(SOL_SOCKET, SO_REUSEADDR), errno %d (%s)\n", errno, strerror(errno));
13652 status = bind(lsock, (
struct sockaddr *) &bind_addr,
sizeof(bind_addr));
13655 printf(
"Cannot bind() to port %d, bind() errno %d (%s)\n", port, errno, strerror(errno));
13662 printf(
"Cannot listen() on port %d, errno %d (%s), bye!\n", port, errno, strerror(errno));
13666 printf(
"mhttpd is listening on port %d\n", port);
13674int try_file_mg(
const char* try_dir,
const char* filename, std::string& path, FILE** fpp,
bool trace)
13680 if (strlen(try_dir) < 1)
13688 FILE*
fp = fopen(path.c_str(),
"r");
13692 printf(
"file \"%s\": OK!\n", path.c_str());
13694 printf(
"file \"%s\": not found.\n", path.c_str());
13707int find_file_mg(
const char* filename, std::string& path, FILE** fpp,
bool trace)
13724 try_file_mg(exptdir.c_str(), filename, path, NULL,
false);
13728#ifdef HAVE_MONGOOSE6
13732#ifdef HAVE_MONGOOSE616
13736extern void cs_md5(
char buf[33], ...);
13744#ifdef HAVE_MONGOOSE616
13745static bool multithread_mg =
true;
13748#ifdef HAVE_MONGOOSE6
13749static struct mg_mgr mgr_mg;
13773 if (!exptname.empty())
13791 size_t uri_len,
const char *ha1,
size_t ha1_len,
13792 const char *nonce,
size_t nonce_len,
const char *nc,
13793 size_t nc_len,
const char *cnonce,
size_t cnonce_len,
13794 const char *qop,
size_t qop_len,
char *resp) {
13795 static const char colon[] =
":";
13796 static const size_t one = 1;
13799 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
13800 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
13801 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
13802 colon, one, ha2,
sizeof(ha2) - 1, NULL);
13812 unsigned long now = (
unsigned long) time(NULL);
13813 unsigned long val = (
unsigned long) strtoul(nonce, NULL, 16);
13814 return now < val || now - val < 3600;
13823 const char *domain) {
13825 "HTTP/1.1 401 Unauthorized\r\n"
13826 "WWW-Authenticate: Digest qop=\"auth\", "
13827 "realm=\"%s\", nonce=\"%lu\"\r\n"
13828 "Content-Length: 0\r\n\r\n",
13829 domain, (
unsigned long) time(NULL));
13842 cm_msg(
MERROR,
"mongoose",
"mongoose web server cannot find password file \"%s\"", path.c_str());
13843 cm_msg(
MERROR,
"mongoose",
"please create password file: touch %s", path.c_str());
13847 bool have_realm =
false;
13855 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
13857 char f_domain[256];
13860 if (sscanf(buf,
"%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3) {
13863 e.username = f_user;
13864 e.password = f_ha1;
13866 if (
e.realm == auth->
realm) {
13878#ifdef HAVE_MONGOOSE6
13879std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13881 assert(!
"this code is untested!");
13887 if (buf_size == 0) {
13889 buf = (
char*)malloc(buf_size);
13890 assert(buf != NULL);
13900 if (size < buf_size) {
13901 std::string s = buf;
13906 buf_size = buf_size*2 + 16;
13907 buf = (
char*)realloc(buf, buf_size);
13908 assert(buf != NULL);
13913#ifdef HAVE_MONGOOSE616
13914std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13921 assert(buf != NULL);
13922 std::string s = buf;
13930 char expected_response[33];
13942 std::string user = find_var_mg(hdr,
"username");
13943 std::string cnonce = find_var_mg(hdr,
"cnonce");
13944 std::string
response = find_var_mg(hdr,
"response");
13945 std::string uri = find_var_mg(hdr,
"uri");
13946 std::string qop = find_var_mg(hdr,
"qop");
13947 std::string nc = find_var_mg(hdr,
"nc");
13948 std::string nonce = find_var_mg(hdr,
"nonce");
13950 if (user.length()<1)
return "";
13951 if (cnonce.length()<1)
return "";
13952 if (
response.length()<1)
return "";
13953 if (uri.length()<1)
return "";
13954 if (qop.length()<1)
return "";
13955 if (nc.length()<1)
return "";
13956 if (nonce.length()<1)
return "";
13963 const char* uri_end = strchr(hm->
uri.
p,
' ');
13964 if (!uri_end)
return "";
13966 size_t uri_length = uri_end - hm->
uri.
p;
13968 if (uri_length != uri.length())
13971 int cmp = strncmp(hm->
uri.
p, uri.c_str(), uri_length);
13980 if (
e->username != user)
13982 if (
e->realm != auth->
realm)
13984 const char* f_ha1 =
e->password.c_str();
13985 int uri_len = hm->
uri.
len;
13986 if (hm->
uri.
p[uri_len] ==
'?')
13989 hm->
uri.
p, uri_len,
13990 f_ha1, strlen(f_ha1),
13991 nonce.c_str(), nonce.length(),
13992 nc.c_str(), nc.length(),
13993 cnonce.c_str(), cnonce.length(),
13994 qop.c_str(), qop.length(),
13995 expected_response);
13996 int cmp = strcasecmp(
response.c_str(), expected_response);
13999 return e->username;
14006#ifdef HAVE_MONGOOSE616
14008struct HostlistCacheEntry
14010 time_t time_created = 0;
14011 time_t time_last_used = 0;
14012 int count_used = 0;
14015 uint32_t ipv4addr = 0;
14016 struct in6_addr ipv6addr;
14017 std::string hostname;
14018 int gai_status = 0;
14019 std::string gai_strerror;
14023static std::vector<HostlistCacheEntry*> gHostlistCache;
14025static void print_hostlist_cache()
14027 time_t now = time(NULL);
14029 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14030 HostlistCacheEntry*
e = gHostlistCache[
i];
14036 printf(
"%3d: %s \"%s\", ok %d, count_used %d, age created: %d, last_used %d",
14038 e->ipv4?
"IPv4":(
e->ipv6?
"IPv6":
"????"),
14039 e->hostname.c_str(),
14042 (int)(now -
e->time_created),
14043 (int)(now -
e->time_last_used));
14045 if (
e->gai_status) {
14046 printf(
", getnameinfo() status %d (%s)",
e->gai_status,
e->gai_strerror.c_str());
14053static bool mongoose_check_hostlist(
const union socket_address *sa)
14055 time_t now = time(NULL);
14058 uint32_t ipv4addr = 0;
14059 struct in6_addr ipv6addr;
14061 if (sa->
sa.sa_family == AF_INET) {
14063 ipv4addr = sa->
sin.sin_addr.s_addr;
14064 }
else if (sa->
sa.sa_family == AF_INET6) {
14066 memcpy(&ipv6addr, &sa->
sin6.sin6_addr,
sizeof(ipv6addr));
14068 printf(
"Rejecting connection from unknown address family %d (AF_xxx)\n", sa->
sa.sa_family);
14072 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14073 HostlistCacheEntry*
e = gHostlistCache[
i];
14079 if ((ipv4 ==
e->ipv4) && (ipv4addr ==
e->ipv4addr)) {
14081 e->time_last_used = now;
14086 if ((ipv6 ==
e->ipv6) && (memcmp(&ipv6addr, &
e->ipv6addr,
sizeof(ipv6addr)) == 0)) {
14088 e->time_last_used = now;
14095 if (
e->time_last_used < now - 24*60*60) {
14096 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);
14097 gHostlistCache[
i] = NULL;
14104 assert(ipv4 || ipv6);
14106 HostlistCacheEntry*
e =
new HostlistCacheEntry;
14108 bool found =
false;
14109 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14110 if (gHostlistCache[
i] == NULL) {
14111 gHostlistCache[
i] =
e;
14116 gHostlistCache.push_back(
e);
14119 e->time_created = now;
14120 e->time_last_used = now;
14125 e->ipv4addr = ipv4addr;
14127 memcpy(&
e->ipv6addr, &ipv6addr,
sizeof(ipv6addr));
14130 char hname[NI_MAXHOST];
14133 e->gai_status = getnameinfo(&sa->
sa,
sizeof(*sa), hname,
sizeof(hname), NULL, 0, 0);
14135 if (
e->gai_status) {
14136 e->gai_strerror = gai_strerror(
e->gai_status);
14138 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
e->gai_status,
e->gai_strerror.c_str());
14144 printf(
"connection from \"%s\"\n", hname);
14146 e->hostname = hname;
14149 if (
e->hostname ==
"localhost.localdomain")
14151 else if (
e->hostname ==
"localhost")
14162 printf(
"Rejecting connection from \'%s\'\n", hname);
14165 print_hostlist_cache();
14174 return std::string(s->
p, s->
len);
14179 size_t nlen = strlen(
name);
14193 if (cookies.length() < 1)
14195 const char* p = strstr(cookies.c_str(), cookie_name);
14198 const char* v = p+strlen(cookie_name);
14216 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> accept\n", nc, ev, ev_data);
14220 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);
14229 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> send %d bytes\n", nc, ev, ev_data, *(
int*)ev_data);
14233 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> close\n", nc, ev, ev_data);
14237 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
14246 char cookie_pwd[256];
14247 char cookie_wpwd[256];
14248 char cookie_cpwd[256];
14251 cookie_wpwd[0] = 0;
14252 cookie_cpwd[0] = 0;
14255 if (s.length() > 0) {
14256 mstrlcpy(cookie_pwd, s.c_str(),
sizeof(cookie_pwd));
14257 cookie_pwd[strcspn(cookie_pwd,
" ;\r\n")] = 0;
14262 mstrlcpy(cookie_wpwd, s.c_str(),
sizeof(cookie_pwd));
14263 cookie_wpwd[strcspn(cookie_wpwd,
" ;\r\n")] = 0;
14268 mstrlcpy(cookie_cpwd, s.c_str(),
sizeof(cookie_pwd));
14269 cookie_cpwd[strcspn(cookie_cpwd,
" ;\r\n")] = 0;
14275 if (s.length() > 0)
14276 c->refresh = atoi(s.c_str());
14284 c->cookie_pwd = cookie_pwd;
14285 c->cookie_wpwd = cookie_wpwd;
14286 c->cookie_cpwd = cookie_cpwd;
14289#define RESPONSE_SENT 1
14290#define RESPONSE_QUEUED 2
14291#define RESPONSE_501 3
14301#ifdef HAVE_MONGOOSE6
14316 decode_get(rr, NULL, &cookies, uri, query_string, t);
14325#ifdef HAVE_MONGOOSE6
14337#ifdef HAVE_MONGOOSE6
14357#ifdef HAVE_MONGOOSE616
14359static uint32_t s_ncseqno = 1;
14361struct MongooseNcUserData
14363 uint32_t ncseqno = 0;
14365 MongooseNcUserData()
14367 ncseqno = s_ncseqno++;
14371 ~MongooseNcUserData()
14383 const MongooseNcUserData* ncud = (
const MongooseNcUserData*)nc->
user_data;
14384 return ncud->ncseqno;
14387static uint32_t s_wseqno = 1;
14389struct MongooseWorkObject
14391 uint32_t wseqno = 0;
14393 uint32_t wncseqno = 0;
14394 bool http_get =
false;
14395 bool http_post =
false;
14396 bool mjsonrpc =
false;
14398 std::string origin;
14400 std::string query_string;
14401 std::string post_body;
14402 std::string post_boundary;
14404 bool send_done =
false;
14408 wseqno = s_wseqno++;
14410 wncseqno = GetNcSeqno(nc);
14415 ~MongooseWorkObject()
14425struct MongooseThreadObject
14427 std::atomic_bool fIsRunning{
false};
14428 std::thread* fThread = NULL;
14431 std::deque<MongooseWorkObject*> fQueue;
14432 std::condition_variable fNotify;
14445static std::vector<MongooseThreadObject*> gMongooseThreads;
14447static void mongoose_thread(MongooseThreadObject*);
14449MongooseThreadObject* FindThread(
void* nc)
14453 MongooseThreadObject* last_not_connected = NULL;
14455 for (
auto it : gMongooseThreads) {
14456 MongooseThreadObject* to = it;
14457 if (to->fNc == nc) {
14461 if (to->fNc == NULL) {
14462 last_not_connected = to;
14466 if (last_not_connected) {
14467 MongooseThreadObject* to = last_not_connected;
14473 MongooseThreadObject* to =
new MongooseThreadObject();
14479 gMongooseThreads.push_back(to);
14481 printf(
"Mongoose web server is using %d threads \r", (
int)gMongooseThreads.size());
14484 to->fThread =
new std::thread(mongoose_thread, to);
14489void FreeThread(
void* nc)
14493 for (
auto it : gMongooseThreads) {
14494 MongooseThreadObject* to = it;
14495 if (to->fNc == nc) {
14505static void mongoose_queue(
mg_connection* nc, MongooseWorkObject* w)
14508 MongooseThreadObject* to = FindThread(nc);
14509 assert(to->fNc == nc);
14511 to->fQueue.push_back(w);
14512 to->fMutex.unlock();
14513 to->fNotify.notify_one();
14516static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag =
false);
14520 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14521 w->http_get =
true;
14524 w->query_string = query_string;
14527 mongoose_queue(nc, w);
14534 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14535 w->http_post =
true;
14538 w->query_string = query_string;
14540 w->post_boundary = boundary;
14543 mongoose_queue(nc, w);
14548static int queue_mjsonrpc(
struct mg_connection *nc,
const std::string& origin,
const std::string& post_body,
RequestTrace* t)
14550 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14551 w->mjsonrpc =
true;
14552 w->origin = origin;
14553 w->post_body = post_body;
14556 mongoose_queue(nc, w);
14561static int thread_http_get(
mg_connection *nc, MongooseWorkObject *w)
14578 decode_get(rr, NULL, &w->cookies, w->uri.c_str(), w->query_string.c_str(), w->t);
14599 bool close_flag =
false;
14617static int thread_http_post(
mg_connection *nc, MongooseWorkObject *w)
14619 const char* post_data = w->post_body.c_str();
14620 int post_data_len = w->post_body.length();
14635 decode_post(rr, NULL, (
char*)post_data, w->post_boundary.c_str(), post_data_len, &w->cookies, w->uri.c_str(), w->t);
14638 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14651 bool close_flag =
false;
14667static int thread_mjsonrpc(
mg_connection *nc, MongooseWorkObject *w)
14669 w->t->fRPC = w->post_body;
14684 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14687 reply->GetArrayBuffer(&ptr, &size);
14689 std::string headers;
14690 headers +=
"HTTP/1.1 200 OK\n";
14691 if (w->origin.length() > 0)
14692 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14694 headers +=
"Access-Control-Allow-Origin: *\n";
14695 headers +=
"Access-Control-Allow-Credentials: true\n";
14696 headers +=
"Content-Length: " +
toString(size) +
"\n";
14697 headers +=
"Content-Type: application/octet-stream\n";
14703 std::string send = headers +
"\n";
14707 mongoose_send(nc, w, send.c_str(), send.length(), ptr, size);
14716 std::string reply_string = reply->Stringify();
14717 int reply_length = reply_string.length();
14719 std::string headers;
14720 headers +=
"HTTP/1.1 200 OK\n";
14721 if (w->origin.length() > 0)
14722 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14724 headers +=
"Access-Control-Allow-Origin: *\n";
14725 headers +=
"Access-Control-Allow-Credentials: true\n";
14726 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14727 headers +=
"Content-Type: application/json\n";
14731 printf(
"-----------------------\nSending headers: %s", headers.c_str());
14732 std::string r = reply_string.substr(0, 128);
14733 printf(
"-----------------------\nSending reply (%d bytes): %s\n\n\n", (
int)reply_string.size(), r.c_str());
14736 std::string send = headers +
"\n" + reply_string;
14740 mongoose_send(nc, w, send.c_str(), send.length(), NULL, 0);
14749static int thread_work_function(
mg_connection *nc, MongooseWorkObject *w)
14752 return thread_http_get(nc, w);
14753 else if (w->http_post)
14754 return thread_http_post(nc, w);
14755 else if (w->mjsonrpc)
14756 return thread_mjsonrpc(nc, w);
14766 char boundary[256];
14769 if (ct.length() > 0) {
14770 const char* s = strstr(ct.c_str(),
"boundary=");
14772 mstrlcpy(boundary, s+9,
sizeof(boundary));
14775#ifdef HAVE_MONGOOSE616
14776 if (multithread_mg)
14777 return queue_decode_post(nc, msg, boundary, uri, query_string, t);
14784 const char* post_data = msg->
body.
p;
14785 int post_data_len = msg->
body.
len;
14789#ifdef HAVE_MONGOOSE6
14802 decode_post(rr, NULL, (
char*)post_data, boundary, post_data_len, &cookies, uri, t);
14805 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14808#ifdef HAVE_MONGOOSE6
14818#ifdef HAVE_MONGOOSE6
14841 printf(
"handle_http_get: uri [%s], query [%s]\n", uri, query_string.c_str());
14843 if (query_string ==
"mjsonrpc_schema") {
14845 std::string reply = s->Stringify();
14848 int reply_length = reply.length();
14850 const std::string origin_header =
find_header_mg(msg,
"Origin");
14852 std::string headers;
14853 headers +=
"HTTP/1.1 200 OK\n";
14854 if (origin_header.length() > 0)
14855 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14857 headers +=
"Access-Control-Allow-Origin: *\n";
14858 headers +=
"Access-Control-Allow-Credentials: true\n";
14859 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14860 headers +=
"Content-Type: application/json\n";
14866 std::string send = headers +
"\n" + reply;
14870 mg_send(nc, send.c_str(), send.length());
14877 if (query_string ==
"mjsonrpc_schema_text") {
14882 int reply_length = reply.length();
14884 const std::string origin_header =
find_header_mg(msg,
"Origin");
14886 std::string headers;
14887 headers +=
"HTTP/1.1 200 OK\n";
14888 if (origin_header.length() > 0)
14889 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14891 headers +=
"Access-Control-Allow-Origin: *\n";
14892 headers +=
"Access-Control-Allow-Credentials: true\n";
14893 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14894 headers +=
"Content-Type: text/plain\n";
14900 std::string send = headers +
"\n" + reply;
14904 mg_send(nc, send.c_str(), send.length());
14911#ifdef HAVE_MONGOOSE616
14912 if (multithread_mg)
14913 return queue_decode_get(nc, msg, uri, query_string.c_str(), t);
14922 std::string post_data =
mgstr(&msg->
body);
14925 printf(
"handle_http_post: uri [%s], query [%s], post data %d bytes\n", uri, query_string.c_str(), (
int)post_data.length());
14927 printf(
"handle_http_post: post data = \n%s\n", post_data.c_str());
14929 if (query_string.substr(0, 8) ==
"mjsonrpc") {
14930 const std::string origin_header =
find_header_mg(msg,
"Origin");
14931 const std::string ctype_header =
find_header_mg(msg,
"Content-Type");
14933 if (strstr(ctype_header.c_str(),
"application/json") == NULL) {
14934 std::string headers;
14935 headers +=
"HTTP/1.1 415 Unsupported Media Type\n";
14942 printf(
"handle_http_post: unsupported media type \"%s\"\n", ctype_header.c_str());
14944 std::string send = headers +
"\n";
14948 mg_send(nc, send.c_str(), send.length());
14955#ifdef HAVE_MONGOOSE616
14956 if (multithread_mg)
14957 return queue_mjsonrpc(nc, origin_header, post_data, t);
14962 t->
fRPC = post_data;
14964#ifdef HAVE_MONGOOSE6
14975#ifdef HAVE_MONGOOSE6
14979 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14982 reply->GetArrayBuffer(&ptr, &size);
14984 std::string headers;
14985 headers +=
"HTTP/1.1 200 OK\n";
14986 if (origin_header.length() > 0)
14987 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14989 headers +=
"Access-Control-Allow-Origin: *\n";
14990 headers +=
"Access-Control-Allow-Credentials: true\n";
14991 headers +=
"Content-Length: " +
toString(size) +
"\n";
14992 headers +=
"Content-Type: application/octet-stream\n";
14998 std::string send = headers +
"\n";
15002 mg_send(nc, send.c_str(), send.length());
15012 std::string reply_string = reply->Stringify();
15013 int reply_length = reply_string.length();
15015 std::string headers;
15016 headers +=
"HTTP/1.1 200 OK\n";
15017 if (origin_header.length() > 0)
15018 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
15020 headers +=
"Access-Control-Allow-Origin: *\n";
15021 headers +=
"Access-Control-Allow-Credentials: true\n";
15022 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
15023 headers +=
"Content-Type: application/json\n";
15029 std::string send = headers +
"\n" + reply_string;
15033 mg_send(nc, send.c_str(), send.length());
15078 const std::string origin_header =
find_header_mg(msg,
"Origin");
15081 printf(
"handle_http_options_cors: origin [%s]\n", origin_header.c_str());
15083 std::string headers;
15084 headers +=
"HTTP/1.1 200 OK\n";
15086 if (origin_header.length() > 0)
15087 headers +=
"Access-Control-Allow-Origin: " + origin_header +
"\n";
15089 headers +=
"Access-Control-Allow-Origin: *\n";
15090 headers +=
"Access-Control-Allow-Headers: Content-Type\n";
15091 headers +=
"Access-Control-Allow-Credentials: true\n";
15092 headers +=
"Access-Control-Max-Age: 120\n";
15093 headers +=
"Content-Length: 0\n";
15094 headers +=
"Content-Type: text/plain\n";
15098 std::string send = headers +
"\n";
15102 mg_send(nc, send.c_str(), send.length());
15111#ifdef HAVE_MONGOOSE616
15112static MVOdb* gProxyOdb = NULL;
15119 std::string uri_encoded =
mgstr(&msg->
uri);
15120 std::string uri =
UrlDecode(uri_encoded.c_str());
15125 user =
mgstr(user_mg_str);
15128 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());
15134 t->
fQuery = query_string;
15138 if (method ==
"OPTIONS" && query_string ==
"mjsonrpc" &&
mg_get_http_header(msg,
"Access-Control-Request-Method") != NULL) {
15161 printf(
"handle_http_message: auth user: \"%s\"\n", username.c_str());
15163 if (username.length() == 0) {
15165 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());
15177#ifdef HAVE_MONGOOSE616
15179 std::string::size_type p1 = uri.find(
"/", 1);
15180 if (p1 == uri.length()-1) {
15181 std::string
response =
"404 Not Found (Proxy name is missing)";
15187 std::string::size_type p2 = uri.find(
"/", p1+1);
15188 if (p2 == std::string::npos) {
15189 std::string
response =
"404 Not Found (Proxy URL should end with a slash)";
15195 std::string p = uri.substr(p1+1, p2-p1-1);
15197 if (p.length() < 1) {
15198 std::string
response =
"404 Not Found (Double-slash or Proxy name is too short)";
15204 std::string destination;
15205 gProxyOdb->RS(p.c_str(), &destination);
15206 if (destination.length() < 1) {
15207 std::string
response =
"404 Not Found (Proxy not found in ODB)";
15212 }
else if (destination[0] ==
'#') {
15213 std::string
response =
"404 Not Found (Proxy commented-out in ODB)";
15219 std::string
response =
"404 Not Found (Proxy address should not end with a slash)";
15225 std::string
response =
"404 Not Found (Proxy address does not start with http";
15238 printf(
"proxy: uri [%s] mount [%s] upstream [%s]\n", uri.c_str(),
mgstr(&mount).c_str(),
mgstr(&upstream).c_str());
15240 mg_http_reverse_proxy(nc, msg, mount, upstream);
15249 if (method ==
"GET")
15251 else if (method ==
"POST")
15256 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15258 std::string
response =
"501 Not Implemented";
15269#ifdef HAVE_MONGOOSE6
15271static void handle_http_event_mg(
struct mg_connection *nc,
int ev,
void *ev_data)
15276 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15281 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15286static void handle_http_redirect(
struct mg_connection *nc,
int ev,
void *ev_data)
15293 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15295 mg_printf(nc,
"HTTP/1.1 302 Found\r\nLocation: https://%s%s\r\n\r\n",
15296 ((std::string*)(nc->
user_data))->c_str(),
15303 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15309#ifdef HAVE_MONGOOSE616
15314static std::atomic_bool s_shutdown{
false};
15315static struct mg_mgr s_mgr;
15316static std::atomic_int s_rseqno{1};
15317static std::mutex s_mg_broadcast_mutex;
15321struct work_request {
15323 MongooseWorkObject* w;
15328struct work_result {
15330 uint32_t check = 0x12345678;
15332 MongooseWorkObject* w = NULL;
15333 const char* p1 = NULL;
15335 const char* p2 = NULL;
15337 bool close_flag =
false;
15338 bool send_501 =
false;
15342static void mongoose_queue(
void *nc, MongooseWorkObject *w)
15344 struct work_request req = {nc, w};
15348 if (
write(s_sock[0], &req,
sizeof(req)) < 0) {
15349 fprintf(stderr,
"mongoose_queue: Error: write(s_sock(0)) error %d (%s)\n", errno, strerror(errno));
15355static void on_work_complete(
struct mg_connection *nc,
int ev,
void *ev_data)
15358 struct work_result *res = (
struct work_result *)ev_data;
15360 assert(res != NULL);
15361 assert(res->w != NULL);
15372 if (GetNcSeqno(nc) != res->w->wncseqno)
15377 if (res->send_501) {
15378 std::string
response =
"501 Not Implemented";
15384 mg_send(nc, res->p1, res->s1);
15387 mg_send(nc, res->p2, res->s2);
15389 if (res->close_flag) {
15396 res->w->send_done =
true;
15399static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag)
15402 struct work_result res;
15405 res.rseqno = s_rseqno++;
15410 res.close_flag = close_flag;
15411 res.send_501 =
false;
15453 s_mg_broadcast_mutex.lock();
15454 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15455 s_mg_broadcast_mutex.unlock();
15458static void mongoose_send_501(
mg_connection* nc, MongooseWorkObject* w)
15460 struct work_result res;
15463 res.rseqno = s_rseqno++;
15468 res.close_flag =
false;
15469 res.send_501 =
true;
15472 s_mg_broadcast_mutex.lock();
15473 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15474 s_mg_broadcast_mutex.unlock();
15478void *worker_thread_proc(
void *
param)
15481 struct work_request req = {0};
15483 while ((!
_abort) && (! s_shutdown)) {
15484 int rd =
read(s_sock[1], &req,
sizeof(req));
15490 if (
_abort || s_shutdown) {
15493 fprintf(stderr,
"worker_thread_proc: Error: read(s_sock(1)) returned %d, error %d (%s)\n", rd, errno, strerror(errno));
15500 int response = thread_work_function(req.nc, req.w);
15504 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15505 mongoose_send_501(req.nc, req.w);
15508 req.w->t->fCompleted =
true;
15520static void mongoose_thread(MongooseThreadObject* to)
15524 std::unique_lock<std::mutex> ulm(to->fMutex, std::defer_lock);
15526 to->fIsRunning =
true;
15528 while ((!
_abort) && (! s_shutdown)) {
15529 MongooseWorkObject *w = NULL;
15532 while (to->fQueue.empty()) {
15534 to->fNotify.wait(ulm);
15535 if (
_abort || s_shutdown) {
15540 if (
_abort || s_shutdown) {
15544 w = to->fQueue.front();
15545 to->fQueue.pop_front();
15550 int response = thread_work_function(w->nc, w);
15554 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15555 mongoose_send_501(w->nc, w);
15560 if (!w->send_done) {
15566 w->t->fCompleted =
true;
15574 to->fIsRunning =
false;
15579static bool mongoose_hostlist_enabled(
const struct mg_connection *nc);
15581static void ev_handler(
struct mg_connection *nc,
int ev,
void *ev_data)
15595 printf(
"ev_handler: connection %p, event %d\n", nc, ev);
15601 nc->
user_data =
new MongooseNcUserData();
15604 printf(
"ev_handler: connection %p, MG_EV_ACCEPT, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15609 }
else if (mongoose_hostlist_enabled(nc)) {
15610 if (!mongoose_check_hostlist(&nc->
sa)) {
15617 printf(
"ev_handler: connection %p, MG_EV_RECV, %d bytes\n", nc, *(
int*)ev_data);
15626 printf(
"ev_handler: connection %p, MG_EV_SEND, %d bytes\n", nc, *(
int*)ev_data);
15631 printf(
"ev_handler: connection %p, MG_EV_HTTP_CHUNK\n", nc);
15642 printf(
"ev_handler: connection %p, MG_EV_HTTP_REQUEST \"%s\" \"%s\"\n", nc,
mgstr(&msg->
method).c_str(),
mgstr(&msg->
uri).c_str());
15654 printf(
"ev_handler: connection %p, MG_EV_CLOSE, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15659 MongooseNcUserData* ncud = (MongooseNcUserData*)nc->
user_data;
15668#define FLAG_HTTPS MG_F_USER_1
15669#define FLAG_PASSWORDS MG_F_USER_2
15670#define FLAG_HOSTLIST MG_F_USER_3
15679 return flags & FLAG_PASSWORDS;
15682static bool mongoose_hostlist_enabled(
const struct mg_connection *nc)
15689 return flags & FLAG_HOSTLIST;
15692static int mongoose_listen(
const char* address,
int flags)
15696 if (flags & FLAG_HTTPS) {
15697 cm_msg(
MERROR,
"mongoose_listen",
"https port \"%s\" requested, but mhttpd compiled without MG_ENABLE_SSL", address);
15704 cm_msg(
MERROR,
"mongoose_listen",
"Cannot mg_bind address \"%s\"", address);
15708 if (
flags & FLAG_HTTPS) {
15710 std::string cert_file;
15715 cm_msg(
MERROR,
"mongoose_listen",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
15716 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");
15717 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");
15721 printf(
"Mongoose web server will use https certificate file \"%s\"\n", cert_file.c_str());
15723 const char* errmsg =
mg_set_ssl(nc, cert_file.c_str(), NULL);
15725 cm_msg(
MERROR,
"mongoose_listen",
"Cannot enable https with certificate file \"%s\", error: %s", cert_file.c_str(), errmsg);
15739 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");
15744static int mongoose_init(MVOdb* odb,
bool no_passwords,
bool no_hostlist,
const std::vector<std::string>& user_hostlist)
15746 bool enable_localhost_port =
true;
15747 int localhost_port = 8080;
15748 bool localhost_port_passwords =
false;
15750 bool enable_insecure_port =
false;
15751 int insecure_port = 8081;
15752 bool insecure_port_passwords =
true;
15753 bool insecure_port_hostlist =
true;
15755 bool enable_https_port =
false;
15756 int https_port = 8443;
15757 bool https_port_passwords =
true;
15758 bool https_port_hostlist =
false;
15760 std::vector<std::string> hostlist;
15761 hostlist.push_back(
"localhost");
15763 bool enable_ipv6 =
true;
15765 odb->RB(
"Enable localhost port", &enable_localhost_port,
true);
15766 odb->RI(
"localhost port", &localhost_port,
true);
15767 odb->RB(
"localhost port passwords", &localhost_port_passwords,
true);
15768 odb->RB(
"Enable insecure port", &enable_insecure_port,
true);
15769 odb->RI(
"insecure port", &insecure_port,
true);
15770 odb->RB(
"insecure port passwords", &insecure_port_passwords,
true);
15771 odb->RB(
"insecure port host list", &insecure_port_hostlist,
true);
15772 odb->RB(
"Enable https port", &enable_https_port,
true);
15773 odb->RI(
"https port", &https_port,
true);
15774 odb->RB(
"https port passwords", &https_port_passwords,
true);
15775 odb->RB(
"https port host list", &https_port_hostlist,
true);
15776 odb->RSA(
"Host list", &hostlist,
true, 10, 256);
15777 odb->RB(
"Enable IPv6", &enable_ipv6,
true);
15780 gProxyOdb = odb->Chdir(
"Proxy",
true);
15781 std::string proxy_example =
"#http://localhost:8080";
15782 gProxyOdb->RS(
"example", &proxy_example,
true);
15788 && ((enable_localhost_port && localhost_port_passwords)
15789 || (enable_insecure_port && insecure_port_passwords)
15790 || (enable_https_port && https_port_passwords))) {
15794 printf(
"mongoose_init: Error: Cannot initialize authorization object!\n");
15799 printf(
"Password protection is off\n");
15803 && ((enable_insecure_port && insecure_port_hostlist)
15804 || (enable_https_port && https_port_hostlist))) {
15808 for (
unsigned int i=0;
i<user_hostlist.size();
i++)
15811 for (
unsigned i=0;
i<hostlist.size();
i++) {
15812 std::string s = hostlist[
i];
15813 if (s.length() < 1)
15823 printf(
"Hostlist active, connections will be accepted only from: ");
15831 printf(
"Hostlist off, connections from anywhere will be accepted\n");
15836 bool listen_failed =
false;
15838 if (enable_localhost_port) {
15840 sprintf(
str,
"localhost:%d", localhost_port);
15843 listen_failed =
true;
15845 sprintf(
str,
"[::1]:%d", localhost_port);
15848 listen_failed =
true;
15852 if (enable_insecure_port) {
15855 if (insecure_port_passwords)
15856 flags |= FLAG_PASSWORDS;
15857 if (insecure_port_hostlist)
15858 flags |= FLAG_HOSTLIST;
15860 sprintf(
str,
"[::]:%d", insecure_port);
15863 listen_failed =
true;
15865 sprintf(
str,
"%d", insecure_port);
15868 listen_failed =
true;
15872 if (enable_https_port) {
15875 if (https_port_passwords)
15876 flags |= FLAG_PASSWORDS;
15877 if (https_port_hostlist)
15878 flags |= FLAG_HOSTLIST;
15879 flags |= FLAG_HTTPS;
15881 sprintf(
str,
"[::]:%d", https_port);
15884 listen_failed =
true;
15886 sprintf(
str,
"%d", https_port);
15889 listen_failed =
true;
15893 if (listen_failed) {
15894 cm_msg(
MERROR,
"mongoose_init",
"Failed to listen on a TCP port enabled in ODB /WebServer");
15901static void mongoose_poll(
int msec = 200)
15906static void mongoose_cleanup()
15908 printf(
"Mongoose web server shutting down\n");
15913 if (s_mgr.active_connections) {
15925 for (
auto it : gMongooseThreads) {
15926 MongooseThreadObject* to = it;
15927 to->fNotify.notify_one();
15931 for (
int i=0;
i<10;
i++) {
15932 int count_running = 0;
15933 for (
auto it : gMongooseThreads) {
15934 MongooseThreadObject* to = it;
15936 if (to->fIsRunning) {
15940 printf(
"Mongoose web server shutting down, %d threads still running\n", count_running);
15941 if (count_running == 0)
15943 mongoose_poll(1000);
15947 for (
auto it : gMongooseThreads) {
15948 MongooseThreadObject* to = it;
15950 if (to->fIsRunning) {
15951 cm_msg(
MERROR,
"mongoose",
"thread failed to shut down");
15954 to->fThread->join();
15955 delete to->fThread;
15958 gMongooseThreads.clear();
15966 for (
auto e : gHostlistCache) {
15969 gHostlistCache.clear();
15979 printf(
"Mongoose web server shut down\n");
15984#ifdef HAVE_MONGOOSE6
15991int start_mg(
int user_http_port,
int user_https_port,
int socket_priviledged_port,
int verbose)
16006 int http_port = 8080;
16007 int https_port = 8443;
16008 int http_redirect_to_https = 1;
16010 size =
sizeof(http_port);
16013 size =
sizeof(https_port);
16016 size =
sizeof(http_redirect_to_https);
16019 bool need_cert_file =
false;
16020 bool need_password_file =
false;
16022 if (user_http_port)
16023 http_port = user_http_port;
16025 if (user_https_port)
16026 https_port = user_https_port;
16029 need_cert_file =
true;
16030 need_password_file =
true;
16034 http_redirect_to_https = 0;
16036 if (http_port && !http_redirect_to_https) {
16039 need_password_file =
false;
16042 if (socket_priviledged_port >= 0) {
16044 need_password_file =
false;
16045 printf(
"Mongoose web server password portection is disabled: serving unencrypted http on port 80\n");
16048 bool have_at_least_one_port =
false;
16050 std::string cert_file;
16052 if (need_cert_file) {
16056 cm_msg(
MERROR,
"mongoose",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
16057 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");
16061 printf(
"Mongoose web server will use SSL certificate file \"%s\"\n", cert_file.c_str());
16064 if (need_password_file) {
16068 printf(
"Error: Cannot initialize authorization object!\n");
16073 printf(
"Mongoose web server will not use password protection\n");
16077 printf(
"start_mg!\n");
16080 signal(SIGPIPE, SIG_IGN);
16087 if (!request_mutex) {
16095 if (socket_priviledged_port >= 0) {
16098 cm_msg(
MERROR,
"mongoose",
"Cannot create mg_connection for set-uid-root privileged port");
16103#ifdef MG_ENABLE_THREADS
16109 have_at_least_one_port =
true;
16110 printf(
"mongoose web server is listening on the set-uid-root privileged port\n");
16113 if (http_port != 80) {
16115 sprintf(
str,
"%d", http_port);
16118 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", http_port);
16122#ifdef MG_ENABLE_THREADS
16127 if (http_redirect_to_https) {
16130 sprintf(
str,
"%d", https_port);
16131 std::string s = hostname +
":" + std::string(
str);
16134 printf(
"mongoose web server is redirecting HTTP port %d to https://%s\n", http_port, s.c_str());
16139 have_at_least_one_port =
true;
16140 printf(
"mongoose web server is listening on the HTTP port %d\n", http_port);
16144#ifdef MG_ENABLE_SSL
16146 sprintf(
str,
"%d", https_port);
16149 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", https_port);
16154#ifdef MG_ENABLE_THREADS
16160 have_at_least_one_port =
true;
16161 printf(
"mongoose web server is listening on the HTTPS port %d\n", https_port);
16163 cm_msg(
MERROR,
"mongoose",
"https port %d requested, but mhttpd compiled without MG_ENABLE_SSL", https_port);
16168 if (!have_at_least_one_port) {
16169 cm_msg(
MERROR,
"mongoose",
"cannot start: no ports defined");
16179 printf(
"stop_mg!\n");
16185 printf(
"stop_mg done!\n");
16200#ifdef HAVE_MONGOOSE6
16211#ifdef HAVE_MONGOOSE6
16228 doc->
D(
"get current value of mhttpd http_trace");
16229 doc->
P(NULL, 0,
"there are no input parameters");
16230 doc->
R(NULL, MJSON_INT,
"current value of http_trace");
16241 doc->
D(
"set new value of mhttpd http_trace");
16242 doc->
P(NULL, MJSON_INT,
"new value of http_trace");
16243 doc->
R(NULL, MJSON_INT,
"new value of http_trace");
16263#ifdef HAVE_MONGOOSE6
16264 int user_http_port = 0;
16265 int user_https_port = 0;
16267#ifdef HAVE_MONGOOSE616
16268 bool no_passwords =
false;
16269 bool no_hostlist =
false;
16271 const char *myname =
"mhttpd";
16273 setbuf(stdout, NULL);
16274 setbuf(stderr, NULL);
16277 signal(SIGPIPE, SIG_IGN);
16280#ifdef HAVE_MONGOOSE6
16285 int socket_priviledged_port = -1;
16289 if (getuid() != geteuid()) {
16292 printf(
"mhttpd is running in setuid-root mode.\n");
16294 socket_priviledged_port = open_listening_socket(port80);
16295 if (socket_priviledged_port < 0) {
16296 printf(
"Cannot open listening socket on TCP port %d, aborting.\n", port80);
16301 status = setuid(getuid());
16303 printf(
"Cannot give up root privelege, aborting.\n");
16306 status = setuid(getuid());
16308 printf(
"Cannot give up root privelege, aborting.\n");
16315 char midas_hostname[256];
16316 char midas_expt[256];
16317 std::string expdir;
16320 cm_get_environment(midas_hostname,
sizeof(midas_hostname), midas_expt,
sizeof(midas_expt));
16323#ifdef HAVE_MONGOOSE6
16324 gUserAllowedHosts.clear();
16326 std::vector<std::string> user_hostlist;
16328 for (
int i = 1;
i < argc;
i++) {
16329 if (argv[
i][0] ==
'-' && argv[
i][1] ==
'D')
16331 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'v')
16333 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'E')
16335 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'H') {
16337#ifdef HAVE_MONGOOSE6
16338 }
else if (strcmp(argv[
i],
"--http") == 0) {
16340 user_http_port = atoi(argv[
i+1]);
16342 }
else if (strcmp(argv[
i],
"--https") == 0) {
16344 user_https_port = atoi(argv[
i+1]);
16347 }
else if (strcmp(argv[
i],
"--trace-mg") == 0) {
16351 }
else if (strcmp(argv[
i],
"--trace-mg-verbose") == 0) {
16353 }
else if (strcmp(argv[
i],
"--no-trace-mg-recv") == 0) {
16355 }
else if (strcmp(argv[
i],
"--no-trace-mg-send") == 0) {
16357 }
else if (strcmp(argv[
i],
"--verbose-mg") == 0) {
16359#ifdef HAVE_MONGOOSE616
16360 }
else if (strcmp(argv[
i],
"--no-multithread") == 0) {
16361 multithread_mg =
false;
16362 }
else if (strcmp(argv[
i],
"--no-passwords") == 0) {
16363 no_passwords =
true;
16364 }
else if (strcmp(argv[
i],
"--no-hostlist") == 0) {
16365 no_hostlist =
true;
16367 }
else if (strcmp(argv[
i],
"--expdir") == 0) {
16368 expdir = argv[
i+1];
16370 }
else if (argv[
i][0] ==
'-') {
16371 if (
i + 1 >= argc || argv[
i + 1][0] ==
'-')
16373 if (argv[
i][1] ==
'h')
16374 mstrlcpy(midas_hostname, argv[++
i],
sizeof(midas_hostname));
16375 else if (argv[
i][1] ==
'e')
16376 mstrlcpy(midas_expt, argv[++
i],
sizeof(midas_hostname));
16377 else if (argv[
i][1] ==
'a') {
16378#ifdef HAVE_MONGOOSE6
16379 gUserAllowedHosts.push_back(argv[++
i]);
16381 user_hostlist.push_back(argv[++
i]);
16383 }
else if (argv[
i][1] ==
'p') {
16384 printf(
"Option \"-p port_number\" for the old web server is obsolete.\n");
16385 printf(
"mongoose web server is the new default, port number is set in ODB or with \"--http port_number\".\n");
16386 printf(
"To run the obsolete old web server, please use \"--oldserver\" switch.\n");
16390 printf(
"usage: %s [-h Hostname[:port]] [-e Experiment] [-v] [-D] [-a Hostname] [--expdir EXPDIR]\n\n", argv[0]);
16391 printf(
" -a add hostname to the hostlist of hosts allowed to connect to mhttpd\n");
16392 printf(
" -e experiment to connect to\n");
16393 printf(
" -h connect to midas server (mserver) on given host\n");
16394 printf(
" --expdir EXPDIR specify experiment directory if connected to mserver\n");
16395 printf(
" -v display verbose HTTP communication\n");
16396 printf(
" -D become a daemon\n");
16397 printf(
" -E only display ELog system\n");
16398 printf(
" -H only display history plots\n");
16399#ifdef HAVE_MONGOOSE6
16400 printf(
" --http port - bind to specified HTTP port (default is ODB \"/Experiment/midas http port\")\n");
16401 printf(
" --https port - bind to specified HTTP port (default is ODB \"/Experiment/midas https port\")\n");
16403 printf(
" --verbose-mg - trace mongoose web requests\n");
16404 printf(
" --trace-mg - trace mongoose events\n");
16405 printf(
" --no-trace-mg-recv - do not trace mongoose recv events\n");
16406 printf(
" --no-trace-mg-send - dop not trace mongoose send events\n");
16407#ifdef HAVE_MONGOOSE616
16408 printf(
" --no-multithread - disable mongoose multithreading\n");
16409 printf(
" --no-passwords - disable password protection\n");
16410 printf(
" --no-hostlist - disable access control host list\n");
16419 FILE *
f = fopen(
"/var/run/mhttpd.pid",
"w");
16427 myname =
"mhttpd_history";
16443 if (expdir.empty()) {
16445 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");
16449 cm_msg(
MERROR,
"main",
"Experiment directory \"%s\" does not exist", expdir.c_str());
16455 cm_msg(
MINFO,
"main",
"This mhttpd is connected via the mserver, using expriment path \"%s\"", expdir.c_str());
16471 MVOdb *odb = MakeMidasOdb(
hDB);
16479 printf(
"check_odb_records() failed, see messages and midas.log, bye!\n");
16484#ifdef HAVE_MONGOOSE6
16485 if (init_allowed_hosts() !=
SUCCESS) {
16486 printf(
"init_allowed_hosts() failed, see messages and midas.log, bye!\n");
16493 printf(
"mhttpd allowed hosts list: ");
16501 printf(
"mhttpd allowed hosts list is empty\n");
16524#ifdef HAVE_MONGOOSE6
16525 status = start_mg(user_http_port, user_https_port, socket_priviledged_port,
verbose);
16528 printf(
"could not start the mongoose web server, see messages and midas.log, bye!\n");
16534#ifdef HAVE_MONGOOSE616
16538 signal(SIGPIPE, SIG_IGN);
16554 MVOdb* o = odb->Chdir(
"WebServer",
true);
16555 status = mongoose_init(o, no_passwords, no_hostlist, user_hostlist);
16558 printf(
"Error: Could not start the mongoose web server, see messages and midas.log, bye!\n");
16568 printf(
"Becoming a daemon...\n");
16574#ifdef HAVE_MONGOOSE6
16579#ifdef HAVE_MONGOOSE616
16600 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_exist(const char *name, BOOL bClientName)
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 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)