19#include <condition_variable>
39#define DEFAULT_REFRESH 60
42static MUTEX_T* request_mutex = NULL;
60 sprintf(buf,
"%d",
i);
74 for (
int i=0;
i<3;
i++) {
81 for (
int i=0;
i<3;
i++) {
99extern const char *
mname[];
131 {
".ASC",
"text/plain" },
132 {
".CSS",
"text/css" },
133 {
".CSV",
"text/csv" },
134 {
".HTM",
"text/html" },
135 {
".HTML",
"text/html" },
136 {
".TXT",
"text/plain" },
138 {
".BMP",
"image/bmp" },
139 {
".GIF",
"image/gif" },
140 {
".ICO",
"image/x-icon" },
141 {
".JPEG",
"image/jpeg" },
142 {
".JPG",
"image/jpeg" },
143 {
".PNG",
"image/png" },
144 {
".SVG",
"image/svg+xml" },
145 {
".TIF",
"image/tiff" },
146 {
".TIFF",
"image/tiff" },
148 {
".MID",
"audio/midi" },
149 {
".MP3",
"audio/mpeg" },
150 {
".OGA",
"audio/ogg" },
151 {
".OGG",
"audio/ogg" },
152 {
".WAV",
"audio/wav" },
154 {
".BIN",
"application/octet-stream" },
155 {
".BZ",
"application/x-bzip" },
156 {
".BZ2",
"application/x-bzip2" },
157 {
".DOC",
"application/msword" },
158 {
".EPS",
"application/postscript" },
159 {
".GZ",
"application/gzip" },
160 {
".JS",
"application/javascript" },
161 {
".JSON",
"application/json" },
162 {
".MJS",
"application/javascript" },
163 {
".PDF",
"application/pdf" },
164 {
".PHP",
"application/x-httpd-php" },
165 {
".RTF",
"application/rtf" },
166 {
".PS",
"application/postscript" },
167 {
".ROOT",
"application/octet-stream" },
168 {
".XLS",
"application/x-msexcel" },
169 {
".XML",
"application/xml" },
170 {
".ZIP",
"application/zip" },
172 {
".ODP",
"application/vnd.oasis.opendocument.presentation" },
173 {
".ODS",
"application/vnd.oasis.opendocument.spreadsheet" },
174 {
".ODT",
"application/vnd.oasis.opendocument.text" },
184 std::string mimetype;
186 if (mimetype.length() > 0) {
213#define HTTP_ENCODING "UTF-8"
218 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
219 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
220 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
221 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x91, 0x68,
222 0x36, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4D,
223 0x45, 0x07, 0xD4, 0x0B, 0x1A, 0x08, 0x37, 0x07,
224 0x0D, 0x7F, 0x16, 0x5C, 0x00, 0x00, 0x00, 0x09,
225 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x2E, 0x23,
226 0x00, 0x00, 0x2E, 0x23, 0x01, 0x78, 0xA5, 0x3F,
227 0x76, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D,
228 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61,
229 0x05, 0x00, 0x00, 0x01, 0x7D, 0x49, 0x44, 0x41,
230 0x54, 0x78, 0xDA, 0x63, 0xFC, 0xFF, 0xFF, 0x3F,
231 0x03, 0x29, 0x80, 0x09, 0xAB, 0xE8, 0xD2, 0x65,
232 0x77, 0x36, 0x6F, 0x7E, 0x8A, 0x5D, 0xC7, 0x7F,
233 0x0C, 0x30, 0x67, 0xEE, 0x0D, 0x56, 0xCE, 0xCD,
234 0x5C, 0xBC, 0x3B, 0xB6, 0x6D, 0x7F, 0x81, 0x29,
235 0xCB, 0x88, 0xE6, 0x24, 0x20, 0x57, 0x50, 0x7C,
236 0xDD, 0xCF, 0x1F, 0x6C, 0x40, 0xCB, 0xB5, 0xB5,
237 0x05, 0xCF, 0x1C, 0xB7, 0x42, 0xB3, 0x80, 0x05,
238 0x8D, 0xCF, 0xC8, 0xC8, 0x58, 0x5A, 0x2A, 0xFB,
239 0xF6, 0x4D, 0x37, 0x1B, 0xAB, 0xA0, 0xB4, 0x4C,
240 0x0A, 0x51, 0x4E, 0x02, 0x82, 0x85, 0xCB, 0x12,
241 0x0E, 0x1D, 0xAB, 0xC7, 0x2A, 0xC5, 0x82, 0x69,
242 0xC4, 0xAF, 0x5F, 0x7F, 0x1E, 0x3F, 0xF8, 0xCD,
243 0xCB, 0xF1, 0xF5, 0xEF, 0xDF, 0x7F, 0xCC, 0xCC,
244 0x4C, 0x84, 0x6D, 0x98, 0x59, 0xD5, 0xEB, 0xCF,
245 0xA5, 0x16, 0xC4, 0xAB, 0x71, 0x72, 0xCB, 0x21,
246 0x4C, 0x59, 0x74, 0x03, 0x5E, 0x3F, 0x7F, 0xB3,
247 0x6B, 0xD6, 0x22, 0x46, 0xA6, 0x7F, 0x0C, 0x0C,
248 0x7F, 0xD7, 0x75, 0x4D, 0xFB, 0xF1, 0xFD, 0x27,
249 0x81, 0x78, 0xB8, 0x7D, 0xE9, 0x0A, 0xCB, 0xFF,
250 0xDF, 0x4C, 0x8C, 0x8C, 0x40, 0xF6, 0xAD, 0x4B,
251 0x67, 0x1F, 0xDE, 0xBD, 0x8B, 0x45, 0x03, 0x3C,
252 0x60, 0x8F, 0x9D, 0xD8, 0xB3, 0xEB, 0x74, 0xB5,
253 0x90, 0x26, 0x07, 0x03, 0x48, 0xE4, 0x3F, 0x8F,
254 0xF6, 0xFF, 0x1B, 0x0F, 0x9A, 0x1E, 0x3E, 0x3A,
255 0xFB, 0xF3, 0xDB, 0x8F, 0xB7, 0x0F, 0x9E, 0x43,
256 0x83, 0xF1, 0xCF, 0xDF, 0x3F, 0x8A, 0x29, 0xCE,
257 0x3F, 0x7F, 0xFD, 0xFC, 0xCF, 0xF0, 0xDF, 0x98,
258 0xE9, 0xB5, 0x8F, 0xBD, 0x8A, 0x3C, 0x6F, 0xEC,
259 0xB9, 0x2D, 0x47, 0xFE, 0xFC, 0xFF, 0x6F, 0x16,
260 0x6C, 0xF3, 0xEC, 0xD3, 0x1C, 0x2E, 0x96, 0xEF,
261 0xBF, 0xAB, 0x7E, 0x32, 0x7D, 0xE2, 0x10, 0xCE,
262 0x88, 0xF4, 0x69, 0x2B, 0x60, 0xFC, 0xF4, 0xF5,
263 0x97, 0x78, 0x8A, 0x36, 0xD8, 0x44, 0x86, 0x18,
264 0x0D, 0xD7, 0x29, 0x95, 0x13, 0xD8, 0xD9, 0x58,
265 0xE1, 0x0E, 0xF8, 0xF1, 0xF3, 0xDB, 0xC6, 0xD6,
266 0xEC, 0x5F, 0x53, 0x8E, 0xBF, 0xFE, 0xC3, 0x70,
267 0x93, 0x8D, 0x6D, 0xDA, 0xCB, 0x0B, 0x4C, 0x3F,
268 0xFF, 0xFC, 0xFA, 0xCF, 0x0C, 0xB4, 0x09, 0x84,
269 0x54, 0xD5, 0x74, 0x91, 0x55, 0x03, 0x01, 0x07,
270 0x3B, 0x97, 0x96, 0x6E, 0xC8, 0x17, 0xFE, 0x7F,
271 0x4F, 0xF8, 0xFE, 0xBC, 0x95, 0x16, 0x60, 0x62,
272 0x62, 0x64, 0xE1, 0xE6, 0x60, 0x73, 0xD1, 0xB2,
273 0x7A, 0xFA, 0xE2, 0xF1, 0xDF, 0x3F, 0xFF, 0xC4,
274 0x78, 0x44, 0x31, 0xA3, 0x45, 0x2B, 0xD0, 0xE3,
275 0xF6, 0xD9, 0xE3, 0x2F, 0x2E, 0x9D, 0x29, 0xA9,
276 0xAC, 0x07, 0xA6, 0x03, 0xF4, 0xB4, 0x44, 0x10,
277 0x00, 0x00, 0x75, 0x65, 0x12, 0xB0, 0x49, 0xFF,
278 0x3F, 0x68, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
279 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
283 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10,
284 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x28, 0x01,
285 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x28, 0x00,
286 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00,
287 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x0F,
291 0x0A, 0x00, 0x5C, 0x86, 0x4C, 0x00, 0x2F, 0x5E,
292 0x1A, 0x00, 0xBF, 0xD3, 0xD7, 0x00, 0x29, 0x17,
293 0x8D, 0x00, 0x50, 0xA7, 0xA4, 0x00, 0x59, 0x57,
294 0x7F, 0x00, 0xC6, 0xA3, 0xAC, 0x00, 0xFC, 0xFE,
295 0xFC, 0x00, 0x28, 0x12, 0x53, 0x00, 0x58, 0x7D,
296 0x72, 0x00, 0xC4, 0x3A, 0x34, 0x00, 0x3C, 0x3D,
297 0x69, 0x00, 0xC5, 0xB6, 0xB9, 0x00, 0x94, 0x92,
298 0x87, 0x00, 0x7E, 0x7A, 0xAA, 0x00, 0x88, 0x88,
299 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x81, 0x22,
300 0xD8, 0x88, 0x88, 0x88, 0xF6, 0xD8, 0x82, 0x22,
301 0xE8, 0x88, 0x88, 0x8D, 0x44, 0x98, 0x82, 0x22,
302 0xA8, 0x88, 0x88, 0x8F, 0x44, 0x48, 0x82, 0x22,
303 0x25, 0x76, 0x67, 0x55, 0x44, 0xF8, 0x88, 0x88,
304 0x3A, 0xC9, 0x9C, 0x53, 0x83, 0x88, 0x88, 0x88,
305 0x8D, 0x99, 0x99, 0x38, 0x88, 0x88, 0x88, 0x88,
306 0x88, 0x99, 0x9C, 0x88, 0x88, 0x88, 0x88, 0x88,
307 0x88, 0xF9, 0x9D, 0x88, 0x88, 0x88, 0x88, 0x88,
308 0x88, 0x8A, 0x58, 0x88, 0x88, 0x88, 0x88, 0x88,
309 0x88, 0x85, 0xD8, 0x88, 0x88, 0x88, 0x88, 0x88,
310 0x88, 0xEA, 0xAE, 0x88, 0x88, 0x88, 0x88, 0x88,
311 0x88, 0x00, 0x0B, 0x88, 0x88, 0x88, 0x88, 0x88,
312 0x88, 0x70, 0x0D, 0x88, 0x88, 0x88, 0x88, 0x88,
313 0x88, 0x87, 0xD8, 0x88, 0x88, 0x88, 0x88, 0x88,
314 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
331 int minor,
int major,
int text,
int label,
int grid,
double ymin,
double ymax,
334 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax);
336void show_header(
Return* r,
const char *title,
const char *method,
const char *path,
int refresh);
343 char c1, c2, *ps, *pp;
345 if (
str == NULL || pattern == NULL)
350 pp = (
char *) pattern;
353 if (toupper(c1) == toupper(c2)) {
358 if (toupper(c1) != toupper(c2))
380 return tv.tv_sec*1.0 +
tv.tv_usec/1000000.0;
426 printf(
"M %s ",
fMethod.c_str());
427 printf(
"URL %s ",
fUri.c_str());
428 if (
fRPC.length() > 0) {
429 printf(
"RPC %s ",
fRPC.c_str());
441 std::vector<RequestTrace*>
fBuf;
477 for (
unsigned i=0;
i<
fBuf.size();
i++) {
486 for (
unsigned i=0;
i<
fBuf.size();
i++) {
488 if (
fBuf[
k] != NULL) {
490 if (
fBuf[
k] == NULL) {
497 if (
fBuf[
k] == NULL) {
511#define WEB_BUFFER_SIZE (6*1024*1024)
560 for (
int i=0;
i<1000;
i++) {
572 assert(!
"Cannot happen!");
588void rread(
const char* filename,
int fh,
int len)
593 cm_msg(
MERROR,
"rread",
"Cannot read file \'%s\', read of %d returned %d, errno %d (%s)", filename, len, rd, errno, strerror(errno));
604 size_t len = strlen(
str);
623 size_t len = strlen(
str);
632 for (
size_t i = 0;
i < len;
i++) {
633 if (strncmp(
str +
i,
"http://", 7) == 0) {
636 char* p = (
char *) (
str +
i + 7);
639 for (
k = 0; *p && *p !=
' ' && *p !=
'\n';
k++,
i++)
643 sprintf(
return_buffer +
j,
"<a href=\"http://%s\">http://%s</a>", link, link);
698#define PARAM_LENGTH 256
699#define TEXT_SIZE 50000
732 printf(
"Error: parameter value too big\n");
746 int size = strlen(
value)+1;
747 _value[
i] = (
char*)malloc(size);
752 printf(
"Error: parameter array too small\n");
856 if (isxdigit(p[0]) && isxdigit(p[1])) {
862 sscanf(
str,
"%02X", &
i);
868 }
else if (*p ==
'+') {
898 if (isxdigit(p[0]) && isxdigit(p[1])) {
902 sscanf(
str,
"%02X", &
i);
908 }
else if (*p ==
'+') {
928 int len = strlen(ps);
929 char *
str = (
char*)malloc(len*3 + 10);
937 sprintf(pd,
"%%%02X", (*p)&0xFF);
945 printf(
"urlEncode [");
946 for (p=ps; *p!=0; p++)
947 printf(
"0x%02x ", (*p)&0xFF);
950 printf(
"urlEncode [%s] -> [%s]\n", ps,
str);
953 mstrlcpy(ps,
str, ps_size);
965 const char* p = text;
971 sprintf(buf,
"%%%02X", (*p)&0xFF);
978 printf(
"urlEncode [");
979 for (p=text; *p!=0; p++)
980 printf(
"0x%02x ", (*p)&0xFF);
983 printf(
"urlEncode [%s] -> [%s]\n", text, encoded.c_str());
998 std::vector<std::string> paths;
1004 paths.push_back(buf);
1012 paths.push_back(buf);
1016 paths.push_back(cwd +
"/");
1017 paths.push_back(cwd +
"/resources/");
1021 char *m = getenv(
"MIDASSYS");
1023 paths.push_back(std::string(m) +
"/resources/");
1037 if (strlen(filename) < 1) {
1038 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' is too short",
1044 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' starting with \'%c\' which is not allowed",
1049 if (strstr(filename,
"..") != NULL) {
1050 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' containing \'..\' which is not allowed",
1057 std::vector<std::string> paths_not_found;
1059 for (
unsigned i=0;
i<paths.size();
i++) {
1060 std::string path = paths[
i];
1061 if (path.length() < 1)
1079 FILE*
fp = fopen(xpath.c_str(),
"r");
1081 struct stat statbuf;
1082 int status = fstat(fileno(
fp), &statbuf);
1084 cm_msg(
MERROR,
"open_resource_file",
"Cannot fstat() file \'%s\', error %d (%s)", xpath.c_str(), errno, strerror(errno));
1089 if (statbuf.st_mode & S_IFREG) {
1095 }
else if (statbuf.st_mode & S_IFDIR) {
1096 cm_msg(
MERROR,
"open_resource_file",
"File \'%s\' for resource \'%s\' is a directory", xpath.c_str(), filename);
1100 cm_msg(
MERROR,
"open_resource_file",
"File \'%s\' for resource \'%s\' is not a regular file, st_mode is 0x%08x", xpath.c_str(), filename, statbuf.st_mode);
1119 paths_not_found.push_back(xpath);
1123 for (
unsigned i=0;
i<paths_not_found.size();
i++) {
1126 s += paths_not_found[
i];
1129 cm_msg(
MERROR,
"open_resource_file",
"Cannot find resource file \'%s\', tried %s", filename, s.c_str());
1137 std::string ext_upper;
1138 const char* p = filename;
1139 const char* last_dot = NULL;
1150 ext_upper += toupper(*p);
1156 if (
type.length() > 0)
1159 cm_msg(
MERROR,
"get_content_type",
"Unknown HTTP Content-Type for resource file \'%s\', file extension \'%s\'", filename, ext_upper.c_str());
1161 return "text/plain";
1172 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1174 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
1178 time_t now = time(NULL);
1179 now += (int) (3600 * 24);
1181 gmtime_r(&now, &gmt_tms);
1182 const char* format =
"%A, %d-%b-%y %H:%M:%S GMT";
1185 strftime(
str,
sizeof(
str), format, &gmt_tms);
1194 struct stat stat_buf;
1195 fstat(fileno(
fp), &stat_buf);
1196 int length = stat_buf.st_size;
1197 r->
rsprintf(
"Content-Length: %d\r\n", length);
1205 r->
rread(path.c_str(), fileno(
fp), length);
1214 FILE *
fp = fopen(path.c_str(),
"rb");
1219 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1223 r->
rsprintf(
"Error: Cannot read \"%s\", fopen() errno %d (%s)\n", path.c_str(), errno, strerror(errno));
1241 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1245 r->
rsprintf(
"Error: resource file \"%s\" not found, see messages\n",
name.c_str());
1255INT sendmail(
const char* from_host,
const char *smtp_host,
const char *from,
const char *to,
const char *subject,
const char *text)
1257 struct sockaddr_in bind_addr;
1258 struct hostent *phe;
1260 char *
str, buf[256];
1263 printf(
"\n\nEmail from %s to %s, SMTP host %s:\n", from, to, smtp_host);
1266 s =
socket(AF_INET, SOCK_STREAM, 0);
1271 memset(&bind_addr, 0,
sizeof(bind_addr));
1272 bind_addr.sin_family = AF_INET;
1273 bind_addr.sin_port = htons((
short) 25);
1275 phe = gethostbyname(smtp_host);
1278 memcpy((
char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
1280 if (connect(s, (
const sockaddr*)&bind_addr,
sizeof(bind_addr)) < 0) {
1286 str = (
char*)malloc(strsize);
1300 sprintf(
str,
"HELO %s\r\n", from_host);
1301 send(s,
str, strlen(
str), 0);
1308 if (strchr(from,
'<')) {
1309 mstrlcpy(buf, strchr(from,
'<') + 1,
sizeof(buf));
1310 if (strchr(buf,
'>'))
1311 *strchr(buf,
'>') = 0;
1313 mstrlcpy(buf, from,
sizeof(buf));
1315 sprintf(
str,
"MAIL FROM: %s\n", buf);
1316 send(s,
str, strlen(
str), 0);
1323 sprintf(
str,
"RCPT TO: <%s>\r\n", to);
1324 send(s,
str, strlen(
str), 0);
1331 sprintf(
str,
"DATA\r\n");
1332 send(s,
str, strlen(
str), 0);
1339 sprintf(
str,
"To: %s\r\nFrom: %s\r\nSubject: %s\r\n", to, from, subject);
1340 send(s,
str, strlen(
str), 0);
1345 send(s,
str, strlen(
str), 0);
1353 localtime_r(&now, &tms);
1354 strftime(buf,
sizeof(buf),
"%a, %d %b %Y %H:%M:%S", &tms);
1355 offset = (-(int) timezone);
1358 sprintf(
str,
"Date: %s %+03d%02d\r\n", buf, (
int) (
offset / 3600),
1359 (
int) ((abs((
int)
offset) / 60) % 60));
1360 send(s,
str, strlen(
str), 0);
1364 sprintf(
str,
"Content-Type: TEXT/PLAIN; charset=US-ASCII\r\n\r\n");
1365 send(s,
str, strlen(
str), 0);
1370 const char* p = text;
1372 while (strstr(p,
"\r\n.\r\n")) {
1374 mstrlcat(
str, p,
i);
1376 mstrlcat(
str,
"\r\n..\r\n", strsize);
1378 mstrlcat(
str, p, strsize);
1379 mstrlcat(
str,
"\r\n", strsize);
1380 send(s,
str, strlen(
str), 0);
1385 sprintf(
str,
".\r\n");
1386 send(s,
str, strlen(
str), 0);
1393 sprintf(
str,
"QUIT\n");
1394 send(s,
str, strlen(
str), 0);
1415 mstrlcpy(
str, path,
sizeof(
str));
1420 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
1424 if (strncmp(path,
"http:", 5) == 0)
1425 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1426 else if (strncmp(path,
"https:", 6) == 0)
1427 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1429 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1438 r->
rsprintf(
"HTTP/1.1 307 Temporary Redirect\r\n");
1441 r->
rsprintf(
"Location: %s\r\n", path);
1443 r->
rsprintf(
"<html>redirect to %s</html>\r\n", path);
1476 for (
i = 0; search_name[
i] ;
i++)
1477 str2[
i] = toupper(search_name[
i]);
1480 if (strstr(xstr1, str2) != NULL) {
1483 std::string path_encoded =
urlEncode(path.c_str());
1487 r->
rsprintf(
"<tr><td class=\"ODBkey\"><a href=\"?cmd=odb&odb_path=/%s\">/%s</a></tr>\n", path_encoded.c_str(), path.c_str());
1490 char* p =
const_cast<char *
>(path.data() + path.length() - 1);
1491 while (*p && *p !=
'/')
1498 size =
sizeof(
data);
1500 std::string data_str;
1502 data_str =
"<no read access>";
1506 r->
rsprintf(
"<tr><td class=\"ODBkey\">");
1507 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=/%s\">/%s/%s</a></td>", path_encoded.c_str(), path.c_str(),
key->
name);
1508 r->
rsprintf(
"<td class=\"ODBvalue\">%s</td></tr>\n", data_str.c_str());
1514 r->
rsprintf(
"<tr><td rowspan=%d class=\"ODBkey\">",
i);
1515 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=/%s\">/%s/%s\n", path_encoded.c_str(), path.c_str(),
key->
name);
1518 size =
sizeof(
data);
1526 r->
rsprintf(
"<td class=\"ODBvalue\">[%d] %s</td></tr>\n",
i, data_str.c_str());
1549 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
1550 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
1553 r->
rsprintf(
"<table class=\"mtable\" style=\"width: 95%%\">\n");
1555 r->
rsprintf(
" <td class=\"mtableheader\">MIDAS Help Page</td>\n");
1562 r->
rsprintf(
" <td style=\"text-align:right;\">Documentation:</td>\n");
1563 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://midas.triumf.ca\">https://midas.triumf.ca</a></td>\n");
1566 r->
rsprintf(
" <td style=\"text-align:right;\">Discussion Forum:</td>\n");
1567 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://midas.triumf.ca/forum/\">https://midas.triumf.ca/forum/</a></td>\n");
1570 r->
rsprintf(
" <td style=\"text-align:right;\">Code:</td>\n");
1571 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://bitbucket.org/tmidas/midas/\">https://bitbucket.org/tmidas/midas/</a></td>\n");
1574 r->
rsprintf(
" <td style=\"text-align:right;\">Report a bug:</td>\n");
1575 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://bitbucket.org/tmidas/midas/issues/\">https://bitbucket.org/tmidas/midas/issues/</a></td>\n");
1579 r->
rsprintf(
" <td style=\"text-align:right;\">Version:</td>\n");
1583 r->
rsprintf(
" <td style=\"text-align:right;\">Revision:</td>\n");
1585 std::string url =
"https://bitbucket.org/tmidas/midas/commits/";
1591 std::string::size_type pos = rev.find(
"-g");
1592 if (pos != std::string::npos) {
1593 std::string hash = rev.substr(pos+2);
1594 pos = hash.find(
"-dirty");
1595 if (pos != std::string::npos) {
1596 hash = hash.substr(0, pos);
1598 pos = hash.find(
" ");
1599 if (pos != std::string::npos) {
1600 hash = hash.substr(0, pos);
1603 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"%s\">%s</a></td>\n", url.c_str(), rev.c_str());
1605 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", rev.c_str());
1610 r->
rsprintf(
" <td style=\"text-align:right;\">MIDASSYS:</td>\n");
1611 s = getenv(
"MIDASSYS");
1612 if (!s) s =
"(unset)";
1613 mstrlcpy(
str, s,
sizeof(
str));
1614 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n",
str);
1618 r->
rsprintf(
" <td style=\"text-align:right;\">mhttpd current directory:</td>\n");
1620 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", cwd.c_str());
1624 r->
rsprintf(
" <td style=\"text-align:right;\">Exptab file:</td>\n");
1629 r->
rsprintf(
" <td style=\"text-align:right;\">Experiment:</td>\n");
1634 r->
rsprintf(
" <td style=\"text-align:right;\">Experiment directory:</td>\n");
1642 if (
list.size() == 1) {
1644 r->
rsprintf(
" <td style=\"text-align:right;\">System logfile:</td>\n");
1647 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", s.c_str());
1651 r->
rsprintf(
" <td style=\"text-align:right;\">Logfiles:</td>\n");
1652 r->
rsprintf(
" <td style=\"text-align:left;\">\n");
1653 for (
unsigned i=0 ;
i<
list.size() ;
i++) {
1666 r->
rsprintf(
" <td style=\"text-align:right;\">Image history:</td>\n");
1671 r->
rsprintf(
" <td style=\"text-align:right;\">Resource paths:</td>\n");
1672 r->
rsprintf(
" <td style=\"text-align:left;\">");
1674 for (
unsigned i=0;
i<resource_paths.size();
i++) {
1677 r->
rsputs(resource_paths[
i].c_str());
1680 if (exp != resource_paths[
i]) {
1692 r->
rsprintf(
" <td style=\"text-align:right;\">midas.css:</td>\n");
1694 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1696 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1700 r->
rsprintf(
" <td style=\"text-align:right;\">midas.js:</td>\n");
1702 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1704 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1708 r->
rsprintf(
" <td style=\"text-align:right;\">controls.js:</td>\n");
1710 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1712 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1716 r->
rsprintf(
" <td style=\"text-align:right;\">mhttpd.js:</td>\n");
1718 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1720 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1724 r->
rsprintf(
" <td style=\"text-align:right;\">obsolete.js:</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;\">Obsolete mhttpd.css:</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;\">JSON-RPC schema:</td>\n");
1741 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");
1745 r->
rsprintf(
" <td style=\"text-align:right;\">JavaScript examples:</td>\n");
1746 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=example\">example.html</a></td>\n");
1750 r->
rsprintf(
" <td style=\"text-align:right;\">Custom page example:</td>\n");
1751 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=custom_example\">custom_example.html</a></td>\n");
1755 r->
rsprintf(
" <td style=\"text-align:right;\">MPlot custom plot examples:</td>\n");
1756 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=plot_example\">plot_example.html</a></td>\n");
1764 r->
rsprintf(
"<table class=\"mtable\" style=\"width: 95%%\">\n");
1766 r->
rsprintf(
" <td class=\"mtableheader\">Contributions</td>\n");
1770 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");
1790 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1792 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
1793 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
1796 r->
rsprintf(
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n");
1800 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
1801 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
1802 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
1806 r->
rsprintf(
"<meta http-equiv=\"Refresh\" content=\"%02d\">\n", refresh);
1808 r->
rsprintf(
"<title>%s</title></head>\n", title);
1810 mstrlcpy(
str, path,
sizeof(
str));
1815 (
"<body><form name=\"form1\" method=\"POST\" action=\"%s\" enctype=\"multipart/form-data\">\n\n",
1818 r->
rsprintf(
"<body><form name=\"form1\" method=\"GET\" action=\"%s\">\n\n",
str);
1822 std::string exptname;
1831 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1833 r->
rsprintf(
"Access-Control-Allow-Origin: *\r\n");
1834 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
1835 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
1844 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1849 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
1850 r->
rsprintf(
"<title>MIDAS error</title></head>\n");
1851 r->
rsprintf(
"<body><H1>%s</H1></body></html>\n", error);
1859 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1861 r->
rsprintf(
"Content-Type: text/plain\r\n");
1864 r->
rsprintf(
"MIDAS error: %s\n", error);
1872 r->
rsprintf(
"window.addEventListener(\"load\", function(e) { mhttpd_init('%s', 1000); });\n", cur_page);
1875 r->
rsprintf(
"<!-- header and side navigation will be filled in mhttpd_init -->\n");
1876 r->
rsprintf(
"<div id=\"mheader\"></div>\n");
1877 r->
rsprintf(
"<div id=\"msidenav\"></div>\n");
1878 r->
rsprintf(
"<div id=\"mmain\">\n");
1888 cm_msg(
MERROR,
"check_obsolete_odb",
"ODB \"%s\" is obsolete, please delete it.", odb_path);
1897 int size =
sizeof(true_value);
1943 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/Base URL\" is obsolete, please delete it.");
1948 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/CSS File\" is obsolete, please delete it.");
1953 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/JS File\" is obsolete, please delete it.");
1958 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/Start-Stop Buttons\" is obsolete, please delete it.");
1961 bool xdefault =
true;
1962 odb->RB(
"Experiment/Pause-Resume Buttons", &xdefault,
true);
1964#ifdef HAVE_MONGOOSE616
1973 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.");
1989 std::string external_elog_url;
1991 size =
sizeof(external_elog);
1997 size =
sizeof(
BOOL);
2003 const char def_button[][
NAME_LENGTH] = {
"8h",
"24h",
"7d" };
2024 size_t len = strlen(text);
2025 for (
size_t i = 0;
i < len;
i++) {
2053 size_t len = strlen(text);
2054 for (
size_t i = 0;
i < len;
i++) {
2083 size_t len = strlen(text);
2084 for (
size_t i = 0;
i < len;
i++) {
2108 size_t len = strlen(text);
2109 for (
size_t i = 0;
i < len;
i++) {
2155 bout +=
"<table border=3 cellpadding=1 class=\"dialogTable\">\n";
2157 ctime_r(&now, ctimebuf);
2158 bout +=
msprintf(
"<tr><th colspan=2>%s</tr>\n", ctimebuf);
2159 bout +=
msprintf(
"<tr><th colspan=2>%s</tr>\n", path);
2180 size =
sizeof(
data);
2186 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2187 data_str =
"(empty)";
2191 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
2195 bout +=
"</td><td>";
2199 bout +=
")</td></tr>\n";
2203 bout +=
"</td></tr>\n";
2210 size =
sizeof(
data);
2215 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2216 data_str =
"(empty)";
2224 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
2232 bout +=
")<br></td></tr>\n";
2239 bout +=
"<br></td></tr>\n";
2246 bout +=
"</table>\n";
2253 char path[256], path1[256];
2254 char mail_to[256], mail_from[256], mail_list[256],
2255 smtp_host[256], tag[80], mail_param[1000];
2258 char att_file[3][256];
2259 int fh, size, n_mail;
2260 char mhttpd_full_url[256];
2263 mstrlcpy(att_file[0], pp->
getparam(
"attachment0"),
sizeof(att_file[0]));
2264 mstrlcpy(att_file[1], pp->
getparam(
"attachment1"),
sizeof(att_file[1]));
2265 mstrlcpy(att_file[2], pp->
getparam(
"attachment2"),
sizeof(att_file[2]));
2268 for (
int i = 0;
i < 3;
i++) {
2270 sprintf(
str,
"attachment%d",
i);
2275 mstrlcpy(path1, path,
sizeof(path1));
2276 while (strchr(path,
'\\'))
2277 *strchr(path,
'\\') =
'/';
2283 int bufsize = bout.length()+1;
2284 char* buf = (
char*)
M_MALLOC(bufsize);
2285 memcpy(buf, bout.c_str(), bufsize);
2286 mstrlcpy(att_file[
i], path,
sizeof(att_file[0]));
2287 mstrlcat(att_file[
i],
".html",
sizeof(att_file[0]));
2292 else if ((fh = open(path1, O_RDONLY |
O_BINARY)) >= 0) {
2293 size = lseek(fh, 0, SEEK_END);
2295 lseek(fh, 0, SEEK_SET);
2296 int rd =
read(fh, buf, size);
2300 mstrlcpy(att_file[
i], path,
sizeof(att_file[0]));
2303 }
else if (strncmp(path,
"/HS/", 4) == 0) {
2304 char* buf = (
char*)
M_MALLOC(100000);
2306 mstrlcpy(
str, path + 4,
sizeof(
str));
2307 if (strchr(
str,
'?')) {
2308 p = strchr(
str,
'?') + 1;
2320 p = strtok(NULL,
"&");
2323 *strchr(
str,
'?') = 0;
2326 mstrlcpy(att_file[
i],
str,
sizeof(att_file[0]));
2334 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
2339 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
2340 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
2341 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
2342 r->
rsprintf(
"<title>ELog Error</title></head>\n");
2343 r->
rsprintf(
"<i>Error: Attachment file <i>%s</i> not valid.</i><p>\n", pp->
getparam(
str));
2344 r->
rsprintf(
"Please go back and enter a proper filename (use the <b>Browse</b> button).\n");
2345 r->
rsprintf(
"<body></body></html>\n");
2351 int edit = atoi(pp->
getparam(
"edit"));
2356 mstrlcpy(tag, pp->
getparam(
"orig"),
sizeof(tag));
2366 *pp->
getparam(
"html") ?
"HTML" :
"plain",
2379 std::string elog_host_name;
2386 sprintf(mhttpd_full_url,
"http://%s/", elog_host_name.c_str());
2394 str +=
"/Elog/Email ";
2401 size =
sizeof(mail_list);
2405 show_error(r,
"No SMTP host defined under /Elog/SMTP host");
2408 size =
sizeof(smtp_host);
2411 p = strtok(mail_list,
",");
2413 mstrlcpy(mail_to, p,
sizeof(mail_to));
2415 std::string exptname;
2418 sprintf(mail_from,
"MIDAS %s <MIDAS@%s>", exptname.c_str(), elog_host_name.c_str());
2420 std::string mail_text;
2421 mail_text +=
"A new entry has been submitted by ";
2422 mail_text += pp->
getparam(
"author");
2426 mail_text +=
"Experiment : ";
2427 mail_text += exptname.c_str();
2430 mail_text +=
"Type : ";
2434 mail_text +=
"System : ";
2435 mail_text += pp->
getparam(
"system");
2438 mail_text +=
"Subject : ";
2439 mail_text += pp->
getparam(
"subject");
2442 mail_text +=
"Link : ";
2443 mail_text += mhttpd_full_url;
2444 mail_text +=
"/EL/";
2453 sendmail(elog_host_name.c_str(), smtp_host, mail_from, mail_to, pp->
getparam(
"type"), mail_text.c_str());
2455 if (mail_param[0] == 0)
2456 mstrlcpy(mail_param,
"?",
sizeof(mail_param));
2458 mstrlcat(mail_param,
"&",
sizeof(mail_param));
2459 sprintf(mail_param + strlen(mail_param),
"mail%d=%s", n_mail++, mail_to);
2461 p = strtok(NULL,
",");
2470 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
2479 r->
rsprintf(
"Location: ?cmd=Show+elog&tag=%s&%s\n\n<html>redir</html>\r\n", tag, mail_param + 1);
2481 r->
rsprintf(
"Location: ?cmd=Show+elog&tag=%s\n\n<html>redir</html>\r\n", tag);
2511 lseek(fh, 0, SEEK_END);
2512 int length =
TELL(fh);
2513 lseek(fh, 0, SEEK_SET);
2515 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
2517 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
2522 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
2542 sprintf(
str,
"/Equipment/%s/Settings/Editable", eq_name);
2564 int i,
j,
k, colspan, size, n_var, i_edit, i_set, line;
2565 char eq_name[32], group[32];
2575 i_edit = atoi(pp->
getparam(
"index"));
2580 i_set = atoi(pp->
getparam(
"index"));
2584 mstrlcpy(eq_name, pp->
getparam(
"eq"),
sizeof(eq_name));
2585 mstrlcpy(group,
"All",
sizeof(group));
2587 mstrlcpy(group, pp->
getparam(
"group"),
sizeof(group));
2592 sprintf(
str,
"/Equipment/%s/Settings", eq_name);
2595 HNDLE hkeynames = 0;
2606 if (strncmp(
key.
name,
"Names", 5) == 0)
2612 if (!hkeyset || !hkeynames) {
2614 sprintf(
str,
"?cmd=odb&odb_path=/Equipment/%s/Variables", eq_name);
2621 show_header(r,
"MIDAS slow control",
"", group, i_edit == -1 ? refresh : 0);
2622 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
2623 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
2624 r->
rsprintf(
"<script type=\"text/javascript\" src=\"obsolete.js\"></script>\n");
2629 r->
rsprintf(
"<tr><td colspan=15>\n");
2632 r->
rsprintf(
"<input type=submit name=cmd value=Set>\n");
2637 r->
rsprintf(
"<table class=\"ODBtable\" style=\"max-width:700px;\">");
2641 r->
rsprintf(
"<tr><td class=\"subStatusTitle\" colspan=15><i>Equipment:</i> \n");
2669 if (strncmp(
key.
name,
"Names", 5) == 0) {
2690 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names", eq_name);
2697 r->
rsprintf(
"<tr><td colspan=15><i>Groups:</i> ");
2701 r->
rsprintf(
"<b>All</b> ");
2703 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s\">All</a> ",
urlEncode(eq_name).c_str());
2707 memset(group_name, 0,
sizeof(group_name));
2711 for (
int level = 0; ; level++) {
2712 bool next_level =
false;
2715 size =
sizeof(name_str);
2718 char *s = strchr(name_str,
'%');
2719 for (
int k=0; s &&
k<level;
k++)
2720 s = strchr(s+1,
'%');
2724 if (strchr(s+1,
'%'))
2734 mstrlcpy(group_name[
j], name_str,
sizeof(group_name[0]));
2744 r->
rsprintf(
"<b>%s</b> ", group_name[
i]);
2746 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]);
2750 r->
rsprintf(
"<i>ODB:</i> ");
2751 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Common\">Common</a> ",
urlEncode(eq_name).c_str());
2752 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Settings\">Settings</a> ",
urlEncode(eq_name).c_str());
2753 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Variables\">Variables</a> ",
urlEncode(eq_name).c_str());
2757 std::string vars_path =
msprintf(
"/Equipment/%s/Variables", eq_name);
2771 if (
i == 0 ||
i > 15) {
2778 r->
rsprintf(
"<tr class=\"subStatusTitle\"><th colspan=%d>Names", colspan);
2781 for (
int i = 0;;
i++) {
2796 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names", eq_name);
2805 for (
int i = 0;
i < num_values;
i++) {
2806 char names_str[256];
2807 size =
sizeof(names_str);
2811 mstrlcpy(
name, names_str,
sizeof(
name));
2817 char *s = strstr(
name, group);
2820 if (
name[strlen(group)] !=
'%')
2824 if (strlen(
name) < 1)
2825 sprintf(
name,
"[%d]",
i);
2828 r->
rsprintf(
"<tr class=\"ODBtableEven\"><td colspan=%d><nobr>%s</nobr>", colspan,
name);
2830 r->
rsprintf(
"<tr class=\"ODBtableOdd\"><td colspan=%d><nobr>%s</nobr>", colspan,
name);
2832 for (
int j = 0;;
j++) {
2845 size =
sizeof(
data);
2850 if (n_var == i_set) {
2862 if (n_var == i_edit) {
2864 r->
rsprintf(
"<input type=text size=10 maxlenth=80 name=value value=\"%s\">\n", data_str.c_str());
2865 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set>\n");
2866 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", i_edit);
2869 sprintf(odb_path,
"Equipment/%s/Variables/%s[%d]", eq_name, varkey.
name,
i);
2871 r->
rsprintf(
"<a href=\"#\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\', 0);return false;\" >%s</a>", odb_path, data_str.c_str());
2875 r->
rsprintf(
"<td align=center>%s", data_str.c_str());
2882 r->
rsprintf(
"<tr><td colspan=15><i>Groups:</i> ");
2886 r->
rsprintf(
"<b>All</b> ");
2888 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s\">All</a> ", eq_name);
2892 std::string vars_path =
msprintf(
"/Equipment/%s/Variables", eq_name);
2897 for (
int i = 0;;
i++) {
2915 r->
rsprintf(
"<i>ODB:</i> ");
2916 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Common\">Common</a> ",
urlEncode(eq_name).c_str());
2917 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Settings\">Settings</a> ",
urlEncode(eq_name).c_str());
2918 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Variables\">Variables</a> ",
urlEncode(eq_name).c_str());
2928 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
2930 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
2942 r->
rsprintf(
"<tr class=\"subStatusTitle\"><th colspan=9>Names<th>%s</tr>\n", varkey.
name);
2945 HNDLE hkeyroot = hkey;
2958 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<br></tr>\n", style,
key.
name);
2962 size =
sizeof(
data);
2968 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2969 data_str =
"(empty)";
2973 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
2975 (
"<tr class=\"%s\" ><td colspan=9>%s<td align=center>%s (%s)<br></tr>\n",
2976 style,
key.
name, data_str.c_str(), hex_str.c_str());
2978 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<td align=center>%s<br></tr>\n",
2979 style,
key.
name, data_str.c_str());
2987 size =
sizeof(
data);
2992 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2993 data_str =
"(empty)";
3000 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
3001 r->
rsprintf(
"<td>[%d] %s (%s)<br></tr>\n",
k, data_str.c_str(), hex_str.c_str());
3003 r->
rsprintf(
"<td>[%d] %s<br></tr>\n",
k, data_str.c_str());
3011 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names %s", eq_name, varkey.
name);
3019 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<td align=center><i>... %d values ...</i>",
3025 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
3027 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
3031 size =
sizeof(
name);
3034 sprintf(
name,
"%s[%d]", varkey.
name,
j);
3037 if (strlen(
name) < 1) {
3038 sprintf(
name,
"%s[%d]", varkey.
name,
j);
3041 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s", style,
name);
3043 size =
sizeof(
data);
3048 if (n_var == i_set) {
3057 sprintf(
str,
"%s", group);
3061 if (n_var == i_edit) {
3062 r->
rsprintf(
"<td align=center><input type=text size=10 maxlenth=80 name=value value=\"%s\">\n", data_str.c_str());
3063 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set></tr>\n");
3064 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", i_edit);
3065 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
3068 sprintf(odb_path,
"Equipment/%s/Variables/%s[%d]", eq_name, varkey.
name,
j);
3071 r->
rsprintf(
"<a href=\"#\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\', 0);return false;\" >%s</a>", odb_path, data_str.c_str());
3076 r->
rsprintf(
"<td align=center>%s\n", data_str.c_str());
3098 char str[256], *ps, *pt;
3106 strcpy(
type,
"text");
3108 while (*p && *p !=
'<')
3116 while (*p && ((*p ==
' ') || iscntrl(*p)))
3134 while (*p && ((*p ==
' ') || iscntrl(*p)))
3144 while (*p && *p !=
'\"')
3150 while (*p && *p !=
' ' && *p !=
'>')
3163 while (*p && *p !=
'\"')
3169 while (*p && *p !=
' ' && *p !=
'>')
3190 while (*p && *p !=
' ' && *p !=
'>')
3202 while (*p && *p !=
'\"')
3208 while (*p && *p !=
' ' && *p !=
'>')
3219 while (*p && *p !=
'\"')
3225 while (*p && *p !=
' ' && *p !=
'>')
3230 if (strchr(p,
'=')) {
3231 mstrlcpy(
str, p,
sizeof(
str));
3232 pt = strchr(
str,
'=')+1;
3235 while (*pt && *pt !=
'\"')
3241 while (*pt && *pt !=
' ' && *pt !=
'>')
3246 mstrlcat(tail,
" ", 256);
3247 mstrlcat(tail,
str, 256);
3249 mstrlcat(tail,
str, 256);
3259 while (*p && ((*p ==
' ') || iscntrl(*p)))
3263 cm_msg(
MERROR,
"find_odb_tag",
"Invalid odb tag '%s'", ps);
3266 }
while (*p !=
'>');
3271 while (*p && *p !=
'>')
3282 int size,
index, i_edit, i_set;
3290 i_edit = atoi(pp->
getparam(
"index"));
3295 i_set = atoi(pp->
getparam(
"index"));
3298 mstrlcpy(full_keypath, keypath1,
sizeof(full_keypath));
3299 mstrlcpy(keypath, keypath1,
sizeof(keypath));
3302 if (strchr(keypath,
'[') && strchr(keypath,
']')) {
3303 for (p = strchr(keypath,
'[') + 1; *p && *p !=
']'; p++)
3307 if (*p && *p ==
']') {
3308 index = atoi(strchr(keypath,
'[') + 1);
3309 *strchr(keypath,
'[') = 0;
3316 r->
rsprintf(
"<b>Key \"%s\" not found in ODB</b>\n", keypath);
3319 size =
sizeof(
data);
3322 std::string data_str;
3323 if (format && strlen(format)>0)
3332 if (n_var == i_set) {
3335 if (data_str[0] ==
'y')
3340 if (atoi(data_str.c_str()) > 0)
3350 std::string options;
3351 if (data_str[0] ==
'y' || atoi(data_str.c_str()) > 0)
3352 options +=
"checked ";
3354 options +=
"disabled ";
3357 options +=
"onClick=\"o=document.createElement('input');o.type='hidden';o.name='cbi';o.value='";
3359 options +=
"';document.form1.appendChild(o);";
3360 options +=
"document.form1.submit();\" ";
3367 r->
rsprintf(
"<input type=\"checkbox\" %s>\n", options.c_str());
3372 if (n_var == i_set) {
3380 size =
sizeof(
data);
3385 if (n_var == i_edit) {
3386 r->
rsprintf(
"<input type=text size=10 maxlength=80 name=value value=\"%s\">\n", data_str.c_str());
3387 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set>\n");
3388 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", n_var);
3389 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
3393 r->
rsprintf(
"<a href=\"#\" %s>", tail);
3397 r->
rsprintf(
"<a onClick=\"promptpwd('%s?cmd=Edit&index=%d&pnam=%s')\" href=\"#\">", path, n_var,
pwd);
3399 r->
rsprintf(
"<a href=\"%s?cmd=Edit&index=%d\" %s>", path, n_var, tail);
3403 r->
rsputs(data_str.c_str());
3406 }
else if (edit == 2) {
3407 r->
rsprintf(
"<a href=\"#\" onclick=\"ODBEdit('%s')\">\n", full_keypath);
3408 r->
rsputs(data_str.c_str());
3412 r->
rsputs(data_str.c_str());
3434 "Src = STRING : [256] ",
3435 "Format = STRING : [32] %1.1f",
3436 "Font = STRING : [32] Medium",
3440 "FGColor = STRING : [8] 000000",
3441 "BGColor = STRING : [8] FFFFFF",
3474 "Src = STRING : [256] ",
3478 "Height = INT : 100",
3479 "Direction = INT : 0",
3481 "Logscale = BOOL : n",
3483 "Max = DOUBLE : 10",
3484 "FGColor = STRING : [8] 000000",
3485 "BGColor = STRING : [8] FFFFFF",
3486 "BDColor = STRING : [8] 808080",
3492 int x, y, width, height, direction,
axis;
3506 int i,
n, size, ivalue;
3512 for (
i=0 ;
i<(int)strlen(src) ;
i++)
3513 if (src[
i] ==
'>' || src[
i] ==
'&')
3515 strncpy(
str, src,
i);
3519 while (strlen(
str) > 0 &&
str[strlen(
str)-1] ==
' ')
3524 cm_msg(
MERROR,
"evaluate_src",
"Invalid Src key \"%s\" for Fill \"%s\"",
3530 size =
sizeof(
data);
3537 *fvalue = (
value[0] ==
'y');
3539 *fvalue = atof(
value.c_str());
3543 if (src[
i] ==
'>' && src[
i+1] ==
'>') {
3546 while (src[
i] ==
' ' || isdigit(src[
i]))
3548 ivalue = (int)*fvalue;
3553 if (src[
i] ==
'&') {
3555 while (src[
i] ==
' ')
3557 if (src[
i] ==
'0' && src[
i+1] ==
'x')
3558 sscanf(src+2+
i,
"%x", &
n);
3561 while (src[
i] ==
' ' || isxdigit(src[
i]) || src[
i] ==
'x')
3563 ivalue = (int)*fvalue;
3579 if (filename[0] ==
'/')
3587 std::string custom_path =
"";
3594 if (custom_path.length() < 1)
3598 cm_msg(
MERROR,
"add_custom_path",
"ODB /Custom/Path has a forbidden value \"%s\", please change it", custom_path.c_str());
3604 std::string full_filename = custom_path;
3605 if (full_filename[full_filename.length()-1] !=
DIR_SEPARATOR)
3607 full_filename += filename;
3609 return full_filename;
3617 std::string filename;
3623 sprintf(
str,
"/Custom/%s",
name);
3627 sprintf(
str,
"/Custom/%s&",
name);
3630 sprintf(
str,
"/Custom/%s!",
name);
3636 sprintf(
str,
"show_custom_file: Invalid custom page: \"/Custom/%s\" not found in ODB",
name);
3648 sprintf(errtext,
"show_custom_file: Error: db_get_key() for \"%s\" status %d",
str,
status);
3654 char* ctext = (
char*)malloc(size);
3660 sprintf(errtext,
"show_custom_file: Error: db_get_data() for \"%s\" status %d",
str,
status);
3679 char str[256],
data[256], src[256];
3680 int i,
index, length,
status, size, width, height, bgcol, fgcol, bdcol, r, g, b, x, y;
3681 HNDLE hDB, hkeygif, hkeyroot, hkey, hkeyval;
3682 double fvalue, ratio;
3694 sprintf(
str,
"/Custom/Images/%s",
name);
3705 std::string filename;
3710 f = fopen(full_filename.c_str(),
"rb");
3712 sprintf(
str,
"show_custom_gif: Cannot open file \"%s\"", full_filename.c_str());
3721 sprintf(
str,
"show_custom_gif: File \"%s\" is not a GIF image", filename.c_str());
3738 size =
sizeof(label);
3741 cm_msg(
MERROR,
"show_custom_gif",
"Cannot open data record for label \"%s\"",
3746 if (label.
src[0] == 0) {
3753 cm_msg(
MERROR,
"show_custom_gif",
"Invalid Src key \"%s\" for label \"%s\"",
3759 size =
sizeof(
data);
3772 if (strstr(label.
format,
"%c"))
3781 sscanf(label.
fgcolor,
"%02x%02x%02x", &r, &g, &b);
3786 sscanf(label.
bgcolor,
"%02x%02x%02x", &r, &g, &b);
3801 width =
value.length() * pfont->
w + 5 + 5;
3802 height = pfont->
h + 2 + 2;
3804 if (label.
align == 0) {
3807 label.
y + height, bgcol);
3811 }
else if (label.
align == 1) {
3814 label.
y + height, bgcol);
3816 label.
y + height, fgcol);
3821 label.
y + height, bgcol);
3842 cm_msg(
MERROR,
"show_custom_gif",
"Cannot open data record for bar \"%s\"",
3847 if (bar.
src[0] == 0) {
3854 cm_msg(
MERROR,
"show_custom_gif",
"Invalid Src key \"%s\" for bar \"%s\"",
3860 size =
sizeof(
data);
3866 fvalue = atof(
value.c_str());
3868 sscanf(bar.
fgcolor,
"%02x%02x%02x", &r, &g, &b);
3873 sscanf(bar.
bgcolor,
"%02x%02x%02x", &r, &g, &b);
3878 sscanf(bar.
bdcolor,
"%02x%02x%02x", &r, &g, &b);
3889 ratio = (log(fvalue) - log(bar.
min)) / (log(bar.
max) - log(bar.
min));
3891 ratio = (fvalue - bar.
min) / (bar.
max - bar.
min);
3900 r = (int) (ratio + 0.5);
3907 bar.
y + bar.
height - 1, fgcol);
3912 else if (bar.
axis == 2)
3918 ratio = ratio * (bar.
height - 2);
3919 r = (int) (ratio + 0.5);
3922 bar.
y + bar.
width, bgcol);
3926 bar.
y + bar.
width - 1, fgcol);
3929 haxis(im,
gdFontSmall, bdcol, 0, bar.
x, bar.
y, bar.
height, -3, -5, -7, -18,
3931 else if (bar.
axis == 2)
3933 5, 7, 8, 0, bar.
min, bar.
max);
3965 size =
sizeof(
data);
3968 cm_msg(
MERROR,
"show_custom_gif",
"No \"Limits\" entry for Fill \"%s\"",
3972 for (
i = 0;
i < size / (int)
sizeof(
double);
i++)
3973 if (*((
double *)
data +
i) > fvalue)
3980 cm_msg(
MERROR,
"show_custom_gif",
"No \"Fillcolors\" entry for Fill \"%s\"",
3985 size =
sizeof(
data);
3986 strcpy(
data,
"FFFFFF");
3989 sscanf(
data,
"%02x%02x%02x", &r, &g, &b);
4004 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
4007 rr->
rsprintf(
"Content-Type: image/gif\r\n");
4008 rr->
rsprintf(
"Content-Length: %d\r\n", length);
4009 rr->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
4010 rr->
rsprintf(
"Expires: Fri, 01-Jan-1983 00:00:00 GMT\r\n\r\n");
4022 { 9999,
"mhttpd_jrpc_rev0", {
4037 int count = 0, substring = 0, rpc;
4039 const char *xname = p->
getparam(
"name");
4040 const char *srpc = p->
getparam(
"rpc");
4042 if (!srpc || !xname) {
4044 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4049 mstrlcpy(sname, xname,
sizeof(sname));
4051 if (sname[strlen(sname)-1]==
'*') {
4052 sname[strlen(sname)-1] = 0;
4068 r->
rsprintf(
"calling rpc %d | ", rpc);
4073 HNDLE hDB, hrootkey, hsubkey, hkey;
4085 sprintf(
str,
"RPC/%d", rpc);
4092 size =
sizeof(client_name);
4097 if (strlen(sname) > 0) {
4099 if (strstr(client_name, sname) != client_name)
4102 if (strcmp(sname, client_name) != 0)
4109 r->
rsprintf(
"client %s", client_name);
4147 { 9998,
"mhttpd_jrpc_rev1", {
4164 int status, substring = 0, rpc;
4166 const char *xname = p->
getparam(
"name");
4167 const char *srpc = p->
getparam(
"rpc");
4169 if (!srpc || !xname) {
4171 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4176 mstrlcpy(sname, xname,
sizeof(sname));
4178 if (sname[strlen(sname)-1]==
'*') {
4179 sname[strlen(sname)-1] = 0;
4198 std::string reply_header;
4199 std::string reply_body;
4207 HNDLE hDB, hrootkey, hsubkey, hkey;
4211 int buf_length = 1024;
4213 int max_reply_length = atoi(p->
getparam(
"max_reply_length"));
4214 if (max_reply_length > buf_length)
4215 buf_length = max_reply_length;
4217 char* buf = (
char*)malloc(buf_length);
4219 assert(buf != NULL);
4224 for (
int i=0; ;
i++) {
4230 sprintf(
str,
"RPC/%d", rpc);
4237 size =
sizeof(client_name);
4242 if (strlen(sname) > 0) {
4244 if (strstr(client_name, sname) != client_name)
4247 if (strcmp(sname, client_name) != 0)
4255 int connect_status = -1;
4256 int call_status = -1;
4257 int call_length = 0;
4258 int disconnect_status = -1;
4289 call_length = strlen(buf);
4299 if (reply_header.length() > 0)
4300 reply_header +=
" | ";
4303 sprintf(tmp,
"%s %d %d %d %d", client_name, connect_status, call_status, disconnect_status, call_length);
4304 reply_header += tmp;
4315 if (reply_header.length() > 0) {
4316 r->
rsputs(reply_header.c_str());
4318 r->
rsputs(reply_body.c_str());
4330 const char *cmd = p->
getparam(
"rcmd");
4331 const char *args = p->
getparam(
"rarg");
4333 if (!
name || !cmd || !args) {
4335 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4341 int buf_length = 1024;
4343 int max_reply_length = atoi(p->
getparam(
"max_reply_length"));
4344 if (max_reply_length > buf_length)
4345 buf_length = max_reply_length;
4347 char* buf = (
char*)malloc(buf_length);
4348 assert(buf != NULL);
4357 r->
rsprintf(
"<RPC_CONNECT_ERROR>%d</RPC_CONNECT_ERROR>",
status);
4398 size =
sizeof(
data);
4408 std::string data_str;
4409 if (format && format[0])
4413 r->
rsputs(data_str.c_str());
4421 r->
rsputs(
"<DB_OUT_OF_RANGE>");
4423 std::string data_str;
4428 r->
rsputs(data_str.c_str());
4440 if (s1.length() < strlen(s2))
4442 return (strncasecmp(s1.c_str(), s2, strlen(s2)) == 0);
4459 char str[
TEXT_SIZE], format[256], facility[256], user[256];
4468 const int ENCODING_NONE = 0;
4469 const int ENCODING_ODB = 1;
4470 const int ENCODING_XML = 2;
4471 const int ENCODING_JSON = 3;
4473 std::string cmd_parameter;
4474 std::string encoding_parameter;
4475 int encoding = ENCODING_NONE;
4477 std::string jsonp_callback;
4478 bool single =
false;
4479 bool multiple =
false;
4480 std::vector<std::string> odb;
4485 cmd_parameter = p->
getparam(
"cmd");
4489 encoding_parameter = p->
getparam(
"encoding");
4492 if (encoding_parameter.length() > 0) {
4494 encoding = ENCODING_ODB;
4496 encoding = ENCODING_XML;
4498 encoding = ENCODING_JSON;
4501 if (encoding == ENCODING_JSON) {
4504 jsonp_callback = p->
getparam(
"callback");
4515 for (
int i=0 ; ;
i++) {
4517 sprintf(ppath,
"odb%d",
i);
4525 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());
4533 ppath +=
"/Custom/Pwd/";
4544 if (strchr(
str,
'[')) {
4545 if (*(strchr(
str,
'[')+1) ==
'*')
4549 *strchr(
str,
'[') = 0;
4558 const char* ptr = p->
getparam(
"value");
4559 for (
i=0 ; ptr != NULL ;
i++) {
4560 size =
sizeof(
data);
4562 if (strchr(
data,
','))
4563 *strchr(
data,
',') = 0;
4565 ptr = strchr(ptr,
',');
4570 size =
sizeof(
data);
4599 size =
sizeof(
data);
4620 if (strchr(
str,
'[')) {
4621 if (*(strchr(
str,
'[')+1) ==
'*')
4625 *strchr(
str,
'[') = 0;
4636 r->
rsputs(
"<DB_NO_KEY>");
4643 sprintf(ppath,
"odb%d",
i);
4644 sprintf(format,
"format%d",
i);
4647 if (strchr(
str,
'[')) {
4648 if (*(strchr(
str,
'[')+1) ==
'*')
4652 *strchr(
str,
'[') = 0;
4660 r->
rsputs(
"<DB_NO_KEY>");
4673 bool fmt_odb =
false;
4674 bool fmt_xml =
false;
4675 bool fmt_json =
true;
4676 bool fmt_jsonp =
false;
4677 int follow_links = 1;
4680 const char* fmt = NULL;
4681 const char* jsonp_callback =
"callback";
4685 }
else if (p->
isparam(
"format")) {
4692 fmt_json = (strstr(fmt,
"json") != NULL);
4695 fmt_xml = fmt_json =
false;
4697 fmt_odb = fmt_json =
false;
4699 fmt_odb = fmt_xml =
false;
4702 fmt_jsonp = (strstr(fmt,
"-p") != NULL);
4703 if (fmt_jsonp && p->
isparam(
"callback"))
4704 jsonp_callback = p->
getparam(
"callback");
4705 if (fmt_json && strstr(fmt,
"-nofollowlinks"))
4707 if (fmt_json && strstr(fmt,
"-nokeys"))
4709 if (fmt_json && strstr(fmt,
"-nolastwritten"))
4711 if (fmt_json && strstr(fmt,
"-norecurse"))
4727 r->
rsputs(jsonp_callback);
4733 char* buf = (
char *)malloc(bufsize);
4740 db_copy(
hDB, hkey, buf, &bufsize, (
char *)
"");
4749 r->
rsputs(
"<DB_NO_KEY>");
4755 r->
rsputs(jsonp_callback);
4762 }
else if (fmt_json)
4766 for (
int i=0 ; ;
i++) {
4768 sprintf(ppath,
"odb%d",
i);
4775 r->
rsputs(
"</data>\n<data>\n");
4788 r->
rsputs(
"<DB_NO_KEY/>\n");
4789 else if (fmt_json) {
4791 sprintf(tmp,
"{ \"/error\" : %d }\n",
status);
4794 r->
rsputs(
"<DB_NO_KEY>\n");
4800 char* buf = (
char *)malloc(bufsize);
4804 const char* s = strstr(buf,
"-->");
4810 }
else if (fmt_json) {
4814 db_copy(
hDB, hkey, buf, &bufsize, (
char *)
"");
4822 r->
rsputs(
"</data>\n</jcopy>\n");
4844 r->
rsputs(jsonp_callback.c_str());
4858 for (
unsigned i=0;
i<odb.size();
i++) {
4864 if (multiple &&
i>0)
4873 r->
rsputs(
"<DB_NO_KEY>\n");
4877 if (multiple &&
i>0)
4927 r->
rsputs(jsonp_callback.c_str());
4940 for (
unsigned i=0;
i<odb.size();
i++) {
4943 int arraylength = 0;
4948 arraylength = atoi(p->
getparam(
"arraylen"));
4949 strlength = atoi(p->
getparam(
"strlen"));
4951 else if (multiple) {
4953 sprintf(buf,
"type%d",
i);
4955 sprintf(buf,
"arraylen%d",
i);
4956 arraylength = atoi(p->
getparam(buf));
4957 sprintf(buf,
"strlen%d",
i);
4958 strlength = atoi(p->
getparam(buf));
4968 char* s = (
char*)calloc(strlength, 1);
4980 if (multiple &&
i>0)
5016 r->
rsputs(jsonp_callback.c_str());
5029 for (
unsigned i=0;
i<odb.size();
i++) {
5032 int arraylength = 0;
5036 arraylength = atoi(p->
getparam(
"arraylen"));
5037 strlength = atoi(p->
getparam(
"strlen"));
5039 else if (multiple) {
5041 sprintf(buf,
"arraylen%d",
i);
5042 arraylength = atoi(p->
getparam(buf));
5043 sprintf(buf,
"strlen%d",
i);
5044 strlength = atoi(p->
getparam(buf));
5055 char* olddata = (
char*)malloc(oldsize);
5061 char* s = (
char*)calloc(newsize, 1);
5080 if (multiple &&
i>0)
5113 r->
rsputs(jsonp_callback.c_str());
5126 for (
unsigned i=0;
i<odb.size();
i++) {
5127 const char*
name = NULL;
5130 else if (multiple) {
5132 sprintf(buf,
"name%d",
i);
5142 if (multiple &&
i>0)
5175 r->
rsputs(jsonp_callback.c_str());
5188 for (
unsigned i=0;
i<odb.size();
i++) {
5189 const char* dest = NULL;
5192 else if (multiple) {
5194 sprintf(buf,
"dest%d",
i);
5203 if (multiple &&
i>0)
5236 r->
rsputs(jsonp_callback.c_str());
5249 for (
unsigned i=0;
i<odb.size();
i++) {
5253 else if (multiple) {
5255 sprintf(buf,
"index%d",
i);
5267 if (multiple &&
i>0)
5300 r->
rsputs(jsonp_callback.c_str());
5313 for (
unsigned i=0;
i<odb.size();
i++) {
5318 if (multiple &&
i>0)
5345 mstrlcpy(facility, p->
getparam(
"f"),
sizeof(facility));
5347 mstrlcpy(facility,
"midas",
sizeof(facility));
5358 char* messages = NULL;
5359 int num_messages = 0;
5372 mstrlcpy(facility, p->
getparam(
"facility"),
sizeof(facility));
5374 mstrlcpy(facility,
"midas",
sizeof(facility));
5377 mstrlcpy(user, p->
getparam(
"user"),
sizeof(user));
5379 mstrlcpy(user,
"javascript_commands",
sizeof(user));
5391 r->
rsputs(
"Message successfully created\n");
5401 r->
rsputs(alarms.c_str());
5428 int size, n_var,
index, edit;
5429 char keypath[256],
type[32], *p, *ps;
5430 char pwd[256], tail[256];
5435 std::string path = pp->
getparam(
"page");
5438 show_error_404(r,
"show_custom_page: Invalid custom page: \"page\" parameter is empty");
5442 if (strstr(path.c_str(),
"..")) {
5444 str +=
"Invalid custom page name \'";
5446 str +=
"\' contains \'..\'";
5451 if (strstr(path.c_str(),
".gif")) {
5456 if (strchr(path.c_str(),
'.')) {
5463 std::string xpath = std::string(
"/Custom/") + path;
5466 xpath = std::string(
"/Custom/") + path +
"&";
5469 xpath = std::string(
"/Custom/") + path +
"!";
5481 ctext = (
char*)malloc(size);
5484 std::string errtext =
msprintf(
"show_custom_page: Error: db_get_data() for \"%s\" status %d", xpath.c_str(),
status);
5490 std::string content_type =
"text/html";
5493 if (std::string(ctext).substr(0, 5) ==
"?cmd=") {
5500 if (strchr(ctext,
'\n') == 0) {
5502 int fh = open(full_filename.c_str(), O_RDONLY |
O_BINARY);
5504 std::string
str =
msprintf(
"show_custom_page: Cannot open file \"%s\", open() errno %d (%s)", full_filename.c_str(), errno, strerror(errno));
5511 off_t off = lseek(fh, 0, SEEK_END);
5513 std::string
str =
msprintf(
"show_custom_page: Cannot open file \"%s\", lseek(SEEK_END) errno %d (%s)", full_filename.c_str(), errno, strerror(errno));
5520 lseek(fh, 0, SEEK_SET);
5521 ctext = (
char*)malloc(size+1);
5522 ssize_t rd =
read(fh, ctext, size);
5545 ps = strchr(p,
'>') + 1;
5547 if (
pwd[0] && n_var == atoi(pp->
getparam(
"index"))) {
5550 mstrlcpy(
str, path.c_str(),
sizeof(
str));
5551 if (strlen(
str)>0 &&
str[strlen(
str)-1] ==
'&')
5554 ppath +=
"/Custom/Pwd/";
5571 }
while (p != NULL);
5579 ppath +=
"/Custom/Pwd/";
5589 std::string podb = pp->
getparam(
"odb");
5590 std::string::size_type pos = podb.find(
'[');
5591 if (pos != std::string::npos) {
5592 index = atoi(podb.substr(pos+1).c_str());
5602 size =
sizeof(
data);
5605 if (atoi(data_str.c_str()) == 0)
5620 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
5636 ps = strchr(p + 1,
'>') + 1;
5641 }
while (p != NULL);
5652 std::string
str =
msprintf(
"Invalid custom page: Page \"%s\" not found in ODB", path.c_str());
5663 int c,
n, a, f,
d,
q, x, r, ia, id, w;
5665 HNDLE hDB, hrootkey, hsubkey, hkey;
5668 static HNDLE hconn = 0;
5685 size =
sizeof(client_name);
5692 if (client_name[0]) {
5700 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
5705 rr->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
5706 rr->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
5707 rr->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
5708 rr->
rsprintf(
"<title>MIDAS CAMAC interface</title></head>\n");
5709 rr->
rsprintf(
"<body><form method=\"GET\" action=\"CNAF\">\n\n");
5717 rr->
rsprintf(
"<table border=3 cellpadding=1>\n");
5718 rr->
rsprintf(
"<tr><th colspan=3>MIDAS experiment \"%s\"",
str);
5720 if (client_name[0] == 0)
5721 rr->
rsprintf(
"<th colspan=3 class=\"redLight\">No CAMAC server running</tr>\n");
5722 else if (hconn == 0)
5723 rr->
rsprintf(
"<th colspan=3 class=\"redLight\">Cannot connect to %s</tr>\n", client_name);
5725 rr->
rsprintf(
"<th colspan=3>CAMAC server: %s</tr>\n", client_name);
5729 a = f =
d =
q = x = 0;
5735 rr->
rsprintf(
"<tr><td colspan=3>\n");
5736 rr->
rsprintf(
"<input type=submit name=cmd value=Execute>\n");
5739 rr->
rsprintf(
"<input type=submit name=cmd value=ODB>\n");
5740 rr->
rsprintf(
"<input type=submit name=cmd value=Status>\n");
5741 rr->
rsprintf(
"<input type=submit name=cmd value=Help>\n");
5748 rr->
rsprintf(
"<th colspan=3>Data");
5753 const char* cmd = p->
getparam(
"cmd");
5755 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_CRATE_CLEAR, 0, 0, 0, 0, 0, &
d, &size, &x,
5758 rr->
rsprintf(
"<tr><td colspan=6 class=\"greenLight\">C cycle executed sucessfully</tr>\n");
5760 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_CRATE_ZINIT, 0, 0, 0, 0, 0, &
d, &size, &x,
5763 rr->
rsprintf(
"<tr><td colspan=6 class=\"greenLight\">Z cycle executed sucessfully</tr>\n");
5765 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_INHIBIT_CLEAR, 0, 0, 0, 0, 0, &
d, &size, &x,
5769 (
"<tr><td colspan=6 class=\"greenLight\">Clear inhibit executed sucessfully</tr>\n");
5771 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_INHIBIT_SET, 0, 0, 0, 0, 0, &
d, &size, &x,
5775 (
"<tr><td colspan=6 class=\"greenLight\">Set inhibit executed sucessfully</tr>\n");
5787 if (strncmp(pd,
"0x", 2) == 0)
5788 sscanf(pd + 2,
"%x", &
d);
5800 for (
i = 0;
i < r;
i++) {
5806 rpc_client_call(hconn,
RPC_CNAF24,
CNAF, 0,
c,
n, a, f, &
d, &size, &x,
5819 status =
rpc_client_call(hconn,
RPC_CNAF24,
CNAF, 0,
c,
n, a, f, &
d, &size, &x, &
q);
5826 (
"<tr><td colspan=6 class=\"redLight\">Error executing function, code = %d</tr>",
5829 rr->
rsprintf(
"<tr align=center><td>%d",
n);
5832 rr->
rsprintf(
"<td colspan=3>%d / 0x%04X Q%d X%d",
d,
d,
q, x);
5845 (
"<tr align=center><td><input type=text size=3 name=N value=%d>\n",
5847 rr->
rsprintf(
"<td><input type=text size=3 name=A value=%d>\n", a);
5848 rr->
rsprintf(
"<td><input type=text size=3 name=F value=%d>\n", f);
5850 (
"<td colspan=3><input type=text size=8 name=D value=%d></tr>\n",
5854 rr->
rsprintf(
"<tr><td colspan=2>Repeat");
5855 rr->
rsprintf(
"<td><input type=text size=3 name=R value=%d>\n", r);
5858 (
"<td align=center colspan=3><input type=submit name=cmd value=\"C cycle\">\n");
5859 rr->
rsprintf(
"<input type=submit name=cmd value=\"Z cycle\">\n");
5861 rr->
rsprintf(
"<tr><td colspan=2>Repeat delay [ms]");
5862 rr->
rsprintf(
"<td><input type=text size=3 name=W value=%d>\n", w);
5865 (
"<td align=center colspan=3><input type=submit name=cmd value=\"Set inhibit\">\n");
5866 rr->
rsprintf(
"<input type=submit name=cmd value=\"Clear inhibit\">\n");
5868 rr->
rsprintf(
"<tr><td colspan=2>Data increment");
5869 rr->
rsprintf(
"<td><input type=text size=3 name=ID value=%d>\n",
id);
5872 (
"<td colspan=3 align=center>Branch <input type=text size=3 name=B value=0>\n");
5874 rr->
rsprintf(
"<tr><td colspan=2>A increment");
5875 rr->
rsprintf(
"<td><input type=text size=3 name=IA value=%d>\n", ia);
5878 (
"<td colspan=3 align=center>Crate <input type=text size=3 name=C value=%d>\n",
5881 rr->
rsprintf(
"</table></body>\r\n");
5893static const NAME_TABLE prefix_table[] = {
5894 {PRFX_PICO,
"pico",},
5895 {PRFX_NANO,
"nano",},
5896 {PRFX_MICRO,
"micro",},
5897 {PRFX_MILLI,
"milli",},
5899 {PRFX_KILO,
"kilo",},
5900 {PRFX_MEGA,
"mega",},
5901 {PRFX_GIGA,
"giga",},
5902 {PRFX_TERA,
"tera",},
5906static const NAME_TABLE unit_table[] = {
5908 {UNIT_METER,
"meter",},
5909 {UNIT_GRAM,
"gram",},
5910 {UNIT_SECOND,
"second",},
5911 {UNIT_MINUTE,
"minute",},
5912 {UNIT_HOUR,
"hour",},
5913 {UNIT_AMPERE,
"ampere",},
5914 {UNIT_KELVIN,
"kelvin",},
5915 {UNIT_CELSIUS,
"deg. celsius",},
5916 {UNIT_FARENHEIT,
"deg. farenheit",},
5918 {UNIT_HERTZ,
"hertz",},
5919 {UNIT_PASCAL,
"pascal",},
5921 {UNIT_WATT,
"watt",},
5922 {UNIT_VOLT,
"volt",},
5924 {UNIT_TESLA,
"tesls",},
5925 {UNIT_LITERPERSEC,
"liter/sec",},
5927 {UNIT_FARAD,
"farad",},
5929 {UNIT_BOOLEAN,
"boolean",},
5930 {UNIT_BYTE,
"byte",},
5931 {UNIT_WORD,
"word",},
5932 {UNIT_DWORD,
"dword",},
5933 {UNIT_ASCII,
"ascii",},
5934 {UNIT_STRING,
"string",},
5935 {UNIT_BAUD,
"baud",},
5937 {UNIT_PERCENT,
"percent",},
5939 {UNIT_COUNT,
"counts",},
5940 {UNIT_FACTOR,
"factor",},
5946void print_mscb_var(
char *
value,
char *evalue,
char *unit, MSCB_INFO_VAR *info_chn,
void *pdata)
5950 unsigned short usdata;
5952 unsigned int uidata;
5959 if (info_chn->unit == UNIT_STRING) {
5960 memset(
str, 0,
sizeof(
str));
5961 strncpy(
str, (
char *)pdata, info_chn->width);
5962 for (
i = 0;
i < (int) strlen(
str);
i++)
5965 strcat(
value,
"\\001");
5968 strcat(
value,
"\\002");
5971 strcat(
value,
"\\t");
5974 strcat(
value,
"\\n");
5977 strcat(
value,
"\\r");
5984 mstrlcpy(evalue,
value, 256);
5986 switch (info_chn->width) {
5989 strcpy(evalue,
"0");
5993 if (info_chn->flags & MSCBF_SIGNED) {
5994 sprintf(
value,
"%d (0x%02X/", *((
signed char *)pdata), *((
signed char *)pdata));
5995 sprintf(evalue,
"%d", *((
signed char *)pdata));
5997 sprintf(
value,
"%u (0x%02X/", *((
unsigned char *)pdata), *((
unsigned char *)pdata));
5998 sprintf(evalue,
"%u", *((
unsigned char *)pdata));
6001 for (
i = 0;
i < 8;
i++)
6002 if (*((
unsigned char *)pdata) & (0x80 >>
i))
6010 if (info_chn->flags & MSCBF_SIGNED) {
6011 sdata = *((
signed short *)pdata);
6013 sprintf(
value,
"%d (0x%04X)", sdata, sdata);
6014 sprintf(evalue,
"%d", sdata);
6016 usdata = *((
unsigned short *)pdata);
6018 sprintf(
value,
"%u (0x%04X)", usdata, usdata);
6019 sprintf(evalue,
"%u", usdata);
6024 if (info_chn->flags & MSCBF_FLOAT) {
6025 fdata = *((
float *)pdata);
6027 sprintf(
value,
"%1.6lg", fdata);
6028 sprintf(evalue,
"%1.6lg", fdata);
6030 if (info_chn->flags & MSCBF_SIGNED) {
6031 idata = *((
signed int *)pdata);
6033 sprintf(
value,
"%d (0x%08X)", idata, idata);
6034 sprintf(evalue,
"%d", idata);
6036 uidata = *((
unsigned int *)pdata);
6038 sprintf(
value,
"%u (0x%08X)", uidata, uidata);
6039 sprintf(evalue,
"%u", uidata);
6048 if (info_chn->prefix) {
6049 for (
i = 0; prefix_table[
i].id != 99;
i++)
6050 if ((
unsigned char)prefix_table[
i].
id == info_chn->prefix)
6052 if (prefix_table[
i].
id)
6053 strcpy(unit, prefix_table[
i].
name);
6057 if (info_chn->unit && info_chn->unit != UNIT_STRING) {
6058 for (
i = 0; unit_table[
i].id;
i++)
6059 if ((
unsigned char)unit_table[
i].
id == info_chn->unit)
6061 if (unit_table[
i].
id)
6062 strcat(unit, unit_table[
i].
name);
6066static int cmp_int(
const void *a,
const void *b)
6068 return *((
int *)a) > *((
int *)b);
6073void create_mscb_tree()
6077 int i,
j,
k, l, size, address[1000], dev_badr[1000], dev_adr[1000], dev_chn[1000],
6078 n_address, n_dev_adr;
6079 char mscb_dev[256], mscb_pwd[32], eq_name[32];
6105 size =
sizeof(mscb_dev);
6108 size =
sizeof(mscb_pwd);
6112 size =
sizeof(dev_adr);
6114 n_dev_adr = size /
sizeof(int);
6117 size =
sizeof(mscb_dev);
6120 size =
sizeof(mscb_pwd);
6125 size =
sizeof(dev_badr);
6127 size =
sizeof(dev_chn);
6129 for (
k=0 ;
k<size/(int)
sizeof(
int) && n_dev_adr < (int)(
sizeof(dev_adr)/
sizeof(int)) ;
k++) {
6130 for (l=0 ; l<dev_chn[
k] ; l++)
6131 dev_adr[n_dev_adr++] = dev_badr[
k]+l;
6146 size =
sizeof(address);
6148 n_address = size /
sizeof(
int);
6153 for (
k=0 ;
k<n_dev_adr ;
k++) {
6154 for (l=0 ; l<n_address ; l++)
6155 if (address[l] == dev_adr[
k])
6159 address[n_address++] = dev_adr[
k];
6163 qsort(address, n_address,
sizeof(
int), cmp_int);
6177void show_mscb_page(
Param* p,
Return* r,
int refresh)
6179 int i,
j,
n, ind, fi, fd,
status, size, n_addr, cur_node, adr, show_hidden;
6180 unsigned int uptime;
6181 BOOL comment_created;
6184 char dbuf[256], evalue[256], unit[256], cur_subm_name[256];
6185 HNDLE hDB, hKeySubm, hKeyCurSubm,
hKey, hKeyAddr, hKeyComm;
6188 MSCB_INFO_VAR info_var;
6189 int ping_addr[0x10000];
6197 mstrlcpy(cur_subm_name, p->
getparam(
"subm"),
sizeof(cur_subm_name));
6198 if (cur_subm_name[0] == 0) {
6202 sprintf(errorstr,
"No submaster defined under /MSCB/Submaster");
6207 strcpy(cur_subm_name,
key.
name);
6212 cur_node = atoi(p->
getparam(
"node"));
6227 std::vector<int>
addr;
6228 std::vector<char> node_comment;
6233 addr.resize(n_addr);
6234 size =
sizeof(int)*n_addr;
6244 comment_created =
FALSE;
6256 node_comment.resize(32);
6257 comment_created =
TRUE;
6260 fd = mscb_init(cur_subm_name, 0,
"",
FALSE);
6263 for (
i=0 ;
i<0x10000 ;
i++)
6265 for (
i=0 ;
i<1000 ;
i++)
6267 for (
i=0 ;
i<0x10000 ;
i+=100)
6269 for (
i=0 ;
i<0x10000 ;
i+= 0x100)
6271 for (
i=0xFF00 ;
i<0x10000 ;
i++)
6274 for (ind =
n = 0; ind < 0x10000; ind++) {
6275 if (!ping_addr[ind])
6278 status = mscb_ping(fd, (
unsigned short) ind, 1, 0);
6279 if (
status == MSCB_SUCCESS) {
6282 for (
j=ind;
j<ind+100 &&
j<0x10000 ;
j++)
6286 status = mscb_info(fd, (
unsigned short) ind, &
info);
6288 if (
status == MSCB_SUCCESS) {
6290 for (
j=0 ;
j<n_addr ;
j++)
6294 addr.resize(n_addr+1);
6296 node_comment.resize(32*(n_addr+1));
6298 strncpy(node_comment.data()+n_addr*32,
info.node_name, 32);
6300 }
else if (comment_created) {
6301 node_comment.resize(32*n_addr);
6303 strncpy(node_comment.data()+
j*32,
info.node_name, 32);
6313 sprintf(redirstr,
"?cmd=mscb&subm=%s", cur_subm_name);
6319 sprintf(errorstr,
"Cannot talk to submaster \"%s\"", cur_subm_name);
6332 fd = mscb_init(cur_subm_name, 0,
"",
FALSE);
6334 status = mscb_info_variable(fd,
6335 (
unsigned short) cur_node, (
unsigned char)
i, &info_var);
6336 if (
status == MSCB_SUCCESS) {
6337 if (info_var.unit == UNIT_STRING) {
6339 mstrlcpy(valstr,
value,
sizeof(valstr));
6340 if (strlen(valstr) > 0 && valstr[strlen(valstr) - 1] ==
'\n')
6341 valstr[strlen(valstr) - 1] = 0;
6343 status = mscb_write(fd, (
unsigned short) cur_node,
6344 (
unsigned char)
i, valstr, strlen(valstr) + 1);
6346 if (info_var.flags & MSCBF_FLOAT) {
6347 fvalue = (float) atof(
value);
6348 memcpy(&dbuf, &fvalue,
sizeof(
float));
6350 if (
value[1] ==
'x')
6351 sscanf(
value + 2,
"%x", (
int *)&dbuf);
6353 *((
int *)dbuf) = atoi(
value);
6356 status = mscb_write(fd, (
unsigned short) cur_node,
6357 (
unsigned char)
i, dbuf, info_var.width);
6362 sprintf(redirstr,
"?cmd=mscb&subm=%s&node=%d", cur_subm_name, cur_node);
6368 show_hidden = atoi(p->
getparam(
"hidden"));
6370 show_hidden =
FALSE;
6373 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
6374 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
6378 r->
rsprintf(
"<style type=\"text/css\">\r\n");
6379 r->
rsprintf(
"select { width:150px; background-color:#FFFFE0; font-size:12px; }\r\n");
6381 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6383 r->
rsprintf(
" vertical-align:top;\r\n");
6384 r->
rsprintf(
" font-size:16px;\r\n");
6385 r->
rsprintf(
" border-right:1px solid #808080;\r\n");
6388 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6390 r->
rsprintf(
" vertical-align:top;\r\n");
6391 r->
rsprintf(
" font-size:16px;\r\n");
6392 r->
rsprintf(
" border-right:1px solid #808080;\r\n");
6395 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6397 r->
rsprintf(
" vertical-align:top;\r\n");
6398 r->
rsprintf(
" font-size:10px;\r\n");
6402 r->
rsprintf(
" font-weight:bold;\r\n");
6403 r->
rsprintf(
" font-size:12px;\r\n");
6406 r->
rsprintf(
" background-color:#F0F0F0;\r\n");
6408 r->
rsprintf(
" font-size:12px;\r\n");
6409 r->
rsprintf(
" border:1px solid #808080;\r\n");
6410 r->
rsprintf(
" border-right:1px solid #FFFFFF;\r\n");
6411 r->
rsprintf(
" border-bottom:1px solid #FFFFFF;\r\n");
6415 r->
rsprintf(
" font-size:12px;\r\n");
6420 r->
rsprintf(
"<script type=\"text/javascript\">\r\n");
6421 r->
rsprintf(
"function mscb_edit(index, value)\r\n");
6423 r->
rsprintf(
" var new_value = prompt('Please enter new value', value);\r\n");
6424 r->
rsprintf(
" if (new_value != undefined) {\r\n");
6425 r->
rsprintf(
" window.location.search = '?cmd=mscb&subm=%s&node=%d&idx='+index+'&value='+new_value;\n", cur_subm_name, cur_node);
6432 r->
rsprintf(
"<table class=\"mtable\">");
6433 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>MSCB</th><tr>");
6437 r->
rsprintf(
"<tr><td colspan=2>\n");
6438 r->
rsprintf(
"<table width=100%%><tr>\n");
6439 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());
6441 r->
rsprintf(
"<tr><td colspan=\"2\" cellpadding=\"0\" cellspacing=\"0\">\r\n");
6445 r->
rsprintf(
"<h1>No MSCB Submasters defined in ODB</h1>\r\n");
6456 r->
rsprintf(
"<table width=\"100%%\" cellpadding=\"0\" cellspacing=\"0\">");
6459 r->
rsprintf(
"<tr><td class=\"subm\">\r\n");
6471 r->
rsprintf(
"<select name=\"subm\" id=\"subm\" size=%d ",
i);
6472 r->
rsprintf(
"onChange=\"window.location.search='?cmd=mscb&subm='+document.getElementById('subm').value;\">\r\n");
6482 size =
sizeof(comment);
6484 mstrlcat(
str,
": ",
sizeof(
str));
6485 mstrlcat(
str, comment,
sizeof(
str));
6489 (cur_subm_name[0] == 0 &&
i == 0)) {
6498 r->
rsprintf(
"<td class=\"node\">\r\n");
6501 r->
rsprintf(
"<script type=\"text/javascript\">\n");
6503 r->
rsprintf(
"function rescan()\n");
6505 r->
rsprintf(
" flag = confirm('Rescan can take up to one minute.');\n");
6506 r->
rsprintf(
" if (flag == true)\n");
6507 r->
rsprintf(
" window.location.href = '?cmd=mscb&mcmd=Rescan&subm=%s';\n", cur_subm_name);
6512 r->
rsprintf(
"<input type=button name=cmd value=\"Rescan\" onClick=\"rescan();\">");
6516 r->
rsprintf(
"No submaster found in ODB\r\n");
6537 if (hKeyComm == 0) {
6551 r->
rsprintf(
"<select name=\"node\" id=\"node\" size=%d ",
i);
6552 r->
rsprintf(
"onChange=\"window.location.search='?cmd=mscb&subm=%s&node='+document.getElementById('node').value;\">\r\n", cur_subm_name);
6562 if (adr == cur_node)
6574 size =
sizeof(comment);
6576 sprintf(
str,
"%d: %s", adr, comment);
6578 sprintf(
str,
"%d", adr);
6580 if (cur_node == 0 &&
i == 0)
6582 if (adr == cur_node)
6583 r->
rsprintf(
"<option selected>%s</option>\r\n",
str);
6591 r->
rsprintf(
"<td class=\"vars\">\r\n");
6595 r->
rsprintf(
"<tr><td colspan=3 align=center><b>%s:%d</b>",
key.
name, cur_node);
6607 if (fd == EMSCB_WRONG_PASSWORD)
6608 r->
rsprintf(
"<tr><td colspan=3><b>Invalid password</b></td>");
6610 r->
rsprintf(
"<tr><td colspan=3><b>Submaster does not respond</b></td>");
6613 mscb_set_eth_max_retry(fd, 3);
6614 mscb_set_max_retry(1);
6616 status = mscb_ping(fd, cur_node, 0, 1);
6617 if (
status != MSCB_SUCCESS) {
6618 r->
rsprintf(
"<tr><td colspan=3><b>No response from node</b></td>");
6621 status = mscb_info(fd, (
unsigned short) cur_node, &
info);
6622 if (
status != MSCB_SUCCESS) {
6623 r->
rsprintf(
"<tr><td colspan=3><b>No response from node</b></td>");
6627 mstrlcpy(tr16,
info.node_name,
sizeof(tr16));
6628 r->
rsprintf(
"<tr><td class=\"v1\">Node name<td colspan=2 class=\"v2\">%s</tr>\n", tr16);
6629 r->
rsprintf(
"<tr><td class=\"v1\">GIT revision<td colspan=2 class=\"v2\">%d</tr>\n",
info.revision);
6631 if (
info.rtc[0] &&
info.rtc[0] != 0xFF) {
6632 for (
i=0 ;
i<6 ;
i++)
6634 r->
rsprintf(
"<tr><td class=\"v1\">Real Time Clock<td colspan=2 class=\"v2\">%02d-%02d-%02d %02d:%02d:%02d</td>\n",
6639 status = mscb_uptime(fd, (
unsigned short) cur_node, &uptime);
6640 if (
status == MSCB_SUCCESS)
6641 r->
rsprintf(
"<tr><td class=\"v1\">Uptime<td colspan=2 class=\"v2\">%dd %02dh %02dm %02ds</tr>\n",
6642 uptime / (3600 * 24),
6643 (uptime % (3600 * 24)) / 3600, (uptime % 3600) / 60,
6646 r->
rsprintf(
"<tr><td colspan=3><hr></td></tr>\r\n");
6649 for (
i=0 ;
i <
info.n_variables ;
i++) {
6650 mscb_info_variable(fd, cur_node,
i, &info_var);
6651 if (info_var.flags & MSCBF_HIDDEN)
6654 if (
i <
info.n_variables) {
6656 strcpy(
str, show_hidden ?
" checked" :
"");
6657 r->
rsprintf(
"<tr><td colspan=3><input type=checkbox%s name=\"hidden\" value=\"1\"",
str);
6658 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);
6662 for (fi=0 ; fi <
info.n_variables ; ) {
6663 for (
i=fi,size=0 ;
i <
info.n_variables && size < 100;
i++) {
6664 mscb_info_variable(fd, cur_node,
i, &info_var);
6665 size += info_var.width;
6668 size =
sizeof(dbuf);
6669 status = mscb_read_range(fd, cur_node, fi,
i-1, dbuf, &size);
6670 if (
status != MSCB_SUCCESS) {
6671 r->
rsprintf(
"<tr><td colspan=3><b>Error reading data from node</b></td>");
6676 for (
j=fi ;
j<
i ;
j++) {
6677 status = mscb_info_variable(fd, cur_node,
j, &info_var);
6678 if ((info_var.flags & MSCBF_HIDDEN) == 0 || show_hidden) {
6680 mstrlcpy(tr8, info_var.name,
sizeof(tr8));
6681 r->
rsprintf(
"<tr><td class=\"v1\">%s</td>\r\n", tr8);
6682 r->
rsprintf(
"<td class=\"v2\">\r\n");
6684 print_mscb_var(
value, evalue, unit, &info_var, pd);
6685 r->
rsprintf(
"<a href=\"#\" onClick=\"mscb_edit(%d,'%s')\">%s</a>",
6687 r->
rsprintf(
"</td><td class=\"v3\">%s</td>", unit);
6690 pd += info_var.width;
6698 r->
rsprintf(
"</td></tr></table>\r\n");
6699 r->
rsprintf(
"</td></tr></table>\r\n");
6700 r->
rsprintf(
"</td></tr></table>\r\n");
6701 r->
rsprintf(
"</div></body></html>\r\n");
6710 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
6715 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
6716 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
6717 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
6718 r->
rsprintf(
"<title>Enter password</title></head><body>\n\n");
6720 r->
rsprintf(
"<form method=\"GET\" action=\".\">\n\n");
6723 r->
rsprintf(
"<table class=\"headerTable\"><tr><td></td><tr></table>\n");
6725 r->
rsprintf(
"<table class=\"dialogTable\">\n");
6727 r->
rsprintf(
"<tr><th class=\"redLight\">Wrong password!</tr>\n");
6729 r->
rsprintf(
"<tr><th>Please enter password</tr>\n");
6730 r->
rsprintf(
"<tr><td align=center><input type=password name=pwd></tr>\n");
6731 r->
rsprintf(
"<tr><td align=center><input type=submit value=Submit></tr>");
6753 if (strcmp(password,
str) == 0)
6757 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
6762 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
6763 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
6764 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
6765 r->
rsprintf(
"<title>Enter password</title></head><body>\n\n");
6767 r->
rsprintf(
"<form method=\"GET\" action=\".\">\n\n");
6771 r->
rsprintf(
"<input type=hidden name=redir value=\"%s\">\n", redir);
6774 r->
rsprintf(
"<table class=\"headerTable\"><tr><td></td><tr></table>\n");
6776 r->
rsprintf(
"<table class=\"dialogTable\">\n");
6779 r->
rsprintf(
"<tr><th class=\"redLight\">Wrong password!</tr>\n");
6782 (
"<tr><th>Please enter password to obtain write access</tr>\n");
6783 r->
rsprintf(
"<tr><td align=center><input type=password name=wpwd></tr>\n");
6784 r->
rsprintf(
"<tr><td align=center><input type=submit value=Submit></tr>");
6801 int keyPresent, size,
status, line, link_index;
6812 if (strcmp(dec_path,
"root") == 0) {
6817 mstrlcpy(xdecpath, dec_path,
sizeof(xdecpath));
6818 if (strrchr(xdecpath,
'/'))
6819 mstrlcpy(xdecpath, strrchr(xdecpath,
'/')+1,
sizeof(xdecpath));
6820 if (xdecpath[0] == 0)
6821 mstrlcpy(xdecpath,
"root",
sizeof(xdecpath));
6822 show_header(r,
"MIDAS online database",
"", xdecpath, 0);
6825 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
6826 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
6827 r->
rsprintf(
"<script type=\"text/javascript\" src=\"obsolete.js\"></script>\n");
6828 r->
rsprintf(
"<script type=\"text/javascript\" src=\"controls.js\"></script>\n");
6833 r->
rsprintf(
"Error: cannot find key %s<P>\n", dec_path);
6843 mstrlcpy(xdec_path, dec_path,
sizeof(xdec_path));
6846 char* p = xdec_path + strlen(xdec_path) - 1;
6847 while (*p && *p !=
'/')
6854 r->
rsprintf(
"Error: cannot find key %s<P>\n", xdec_path);
6859 dec_path = xdec_path;
6872 r->
rsprintf(
"<table class=\"mtableheader\">\n");
6873 r->
rsprintf(
"<tr><td colspan=%d>\n", colspan);
6874 r->
rsprintf(
"<input type=button value=ELog onclick=\"self.location=\'?cmd=Alarms\';\">\n");
6875 r->
rsprintf(
"</td></tr></table>\n\n");
6881 r->
rsprintf(
"<table class=\"mtable\" style=\"border-spacing:0px;\">\n");
6882 r->
rsprintf(
"<tr><th colspan=%d class=\"mtableheader\">Online Database Browser</tr>\n", colspan);
6885 r->
rsprintf(
"<tr><td colspan=%d>\n", colspan);
6886 r->
rsprintf(
"<input type=button value=Find onclick=\"self.location=\'?cmd=Find\';\">\n");
6887 r->
rsprintf(
"<input type=button value=Create onclick=\"dlgShow('dlgCreate')\">\n");
6888 r->
rsprintf(
"<input type=button value=Link onclick=\"dlgShow('dlgLink')\">\n");
6889 r->
rsprintf(
"<input type=button value=Delete onclick=\"dlgShow('dlgDelete')\">\n");
6890 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());
6891 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());
6892 r->
rsprintf(
"<input type=button value=\"Show ODB clients\" onclick=\"self.location=\'?cmd=odb_scl\';\">\n");
6898 std::string dd =
"";
6900 dd +=
"<!-- Demo dialog -->\n";
6901 dd +=
"<div id=\"dlgDelete\" class=\"dlgFrame\">\n";
6902 dd +=
"<div class=\"dlgTitlebar\">Delete ODB entry</div>\n";
6903 dd +=
"<div class=\"dlgPanel\">\n";
6904 dd +=
"<div id=odbpath>";
6906 dd += MJsonNode::Encode(odbpath.c_str());
6909 dd +=
"<div><br></div>\n";
6911 dd +=
"<table class=\"dialogTable\">\n";
6912 dd +=
"<th colspan=2>Delete ODB entries:</th>\n";
6914 std::vector<std::string> delete_list;
6916 int count_delete = 0;
6921 r->
rsprintf(
"<tr><td colspan=%d class='ODBpath'><b>", colspan);
6922 r->
rsprintf(
"<a href=\"?cmd=oldodb\">/</a> \n");
6924 std::string enc_root_path;
6928 const char* p = dec_path;
6931 while (*p && *p !=
'/')
6936 if (pd.length() > 0)
6937 r->
rsprintf(
"<a href=\"?cmd=oldodb&odb_path=%s\">%s</a>\n / ", enc_root_path.c_str(), pd.c_str());
6939 enc_root_path +=
"/";
6949 for(
int scan=0; scan<2; scan++){
6950 if(scan==1 && keyPresent==1) {
6951 r->
rsprintf(
"<tr class=\"titleRow\">\n");
6952 r->
rsprintf(
"<th class=\"ODBkey\">Key</th>\n");
6953 r->
rsprintf(
"<th class=\"ODBvalue\">Value ");
6954 r->
rsprintf(
"<script type=\"text/javascript\">\n");
6955 r->
rsprintf(
"function expand()\n");
6957 r->
rsprintf(
" var n = document.getElementsByName('ext');\n");
6958 r->
rsprintf(
" for (i=0 ; i<n.length ; i++) {\n");
6959 r->
rsprintf(
" if (n[i].style.display == 'none')\n");
6960 r->
rsprintf(
" n[i].style.display = 'table-cell';\n");
6962 r->
rsprintf(
" n[i].style.display = 'none';\n");
6964 r->
rsprintf(
" if (document.getElementById('expp').expflag === true) {\n");
6965 r->
rsprintf(
" document.getElementById('expp').expflag = false;\n");
6966 r->
rsprintf(
" document.getElementById('expp').innerHTML = '⇥';\n");
6968 r->
rsprintf(
" document.getElementById('expp').expflag = true;\n");
6969 r->
rsprintf(
" document.getElementById('expp').innerHTML = '⇤';\n");
6973 r->
rsprintf(
"<div style=\"display:inline;float:right\"><a id=\"expp\"href=\"#\" onClick=\"expand();return false;\">⇥</div>");
6975 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Type</th>\n");
6976 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">#Val</th>\n");
6977 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Size</th>\n");
6978 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Written</th>\n");
6979 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Mode</th>\n");
6983 for (
int i = 0;;
i++) {
6990 delete_list.push_back(
key.
name);
6994 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
6996 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
6998 std::string keyname =
key.
name;
7001 std::string enc_full_path = enc_root_path + enc_keyname;
7003 std::string odb_path = dec_path;
7004 if (odb_path.length() > 0 && odb_path[odb_path.length() - 1] !=
'/')
7009 std::string enc_link_ref;
7014 size =
sizeof(link_name);
7023 enc_link_ref =
"?cmd=Set&odb_path=";
7024 enc_link_ref += enc_full_path;
7028 sprintf(link_name,
"%s",
"(empty)");
7032 std::string enc_ref;
7035 if (enc_root_path.back() ==
'/' && link_name[0] ==
'/') {
7038 enc_ref +=
"?cmd=Set&odb_path=";
7039 enc_ref += enc_root_path;
7044 enc_ref +=
"?cmd=Set&odb_path=";
7045 enc_ref += enc_root_path;
7051 enc_ref +=
"?cmd=Set&odb_path=";
7052 enc_ref += enc_full_path;
7057 r->
rsprintf(
"<tr><td class=\"yellowLight\">");
7058 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)");
7064 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());
7066 r->
rsprintf(
"<i>→ <a href=\"%s\">%s</a></i>", enc_link_ref.c_str(), link_name);
7070 if (strchr(link_name,
'['))
7071 link_index = atoi(strchr(link_name,
'[')+1);
7078 size =
sizeof(
data);
7081 std::string data_str;
7083 if (link_index != -1)
7089 if (size ==
sizeof(
data)) {
7090 data_str +=
"...(truncated)";
7094 std::string hex_str;
7097 if (link_index != -1)
7103 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
7104 data_str =
"(empty)";
7109 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
7111 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7112 r->
rsprintf(
"%s <i>→ ", keyname.c_str());
7113 r->
rsprintf(
"<a href=\"%s\">%s</a></i>\n", enc_link_ref.c_str(), link_name);
7114 r->
rsprintf(
"<td class=\"%s\">\n", style);
7116 r->
rsprintf(
"%s (%s)", data_str.c_str(), hex_str.c_str());
7118 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7119 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">%s (%s)</a>\n", odb_path.c_str(), data_str.c_str(), hex_str.c_str());
7122 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7123 r->
rsprintf(
"%s<td class=\"%s\">", keyname.c_str(), style);
7125 r->
rsprintf(
"%s (%s)", data_str.c_str(), hex_str.c_str());
7127 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7128 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">%s (%s)</a>\n", odb_path.c_str(), data_str.c_str(), hex_str.c_str());
7132 if (strchr(data_str.c_str(),
'\n')) {
7134 r->
rsprintf(
"<td class=\"ODBkey\">");
7135 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td class=\"ODBvalue\">", keyname.c_str(), enc_link_ref.c_str(), link_name);
7137 r->
rsprintf(
"<td class=\"ODBkey\">%s<td class=\"%s\">", keyname.c_str(), style);
7141 if (strlen(
data) > data_str.length())
7142 r->
rsprintf(
"<i>... (%d bytes total)<p>\n", (
int)strlen(
data));
7144 r->
rsprintf(
"<a href=\"%s\">Edit</a>\n", enc_ref.c_str());
7147 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7148 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td class=\"%s\">", keyname.c_str(), enc_link_ref.c_str(), link_name, style);
7152 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7153 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", odb_path.c_str());
7158 r->
rsprintf(
"<td class=\"ODBkey\">%s<td class=\"%s\">", keyname.c_str(), style);
7159 if (!write_access) {
7162 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7163 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", odb_path.c_str());
7172 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7176 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7180 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7184 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7188 else if (delta < 3600)
7189 r->
rsprintf(
"%1.0lfm", delta / 60.0);
7190 else if (delta < 86400)
7191 r->
rsprintf(
"%1.0lfh", delta / 3600.0);
7192 else if (delta < 86400 * 99)
7193 r->
rsprintf(
"%1.0lfd", delta / 86400.0);
7198 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7214 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);
7218 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);
7224 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
7226 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
7229 size =
sizeof(
data);
7233 std::string hex_str;
7241 if (size ==
sizeof(
data)) {
7242 data_str +=
"...(truncated)";
7246 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
7247 data_str =
"(empty)";
7253 enc_ref +=
"?cmd=Set&odb_path=";
7254 enc_ref += enc_full_path;
7255 enc_ref +=
"&index=";
7268 r->
rsprintf(
"<td class=\"%s\">[%d] ", style,
j);
7270 r->
rsprintf(
"<a href=\"%s\">", enc_ref.c_str());
7272 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), tmpstr.c_str());
7273 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", tmpstr.c_str());
7275 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
7276 r->
rsprintf(
"%s (%s)</a>\n", data_str.c_str(), hex_str.c_str());
7278 r->
rsprintf(
"%s</a>\n", data_str.c_str());
7282 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7286 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7290 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7294 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7298 else if (delta < 3600)
7299 r->
rsprintf(
"%1.0lfm", delta / 60.0);
7300 else if (delta < 86400)
7301 r->
rsprintf(
"%1.0lfh", delta / 3600.0);
7302 else if (delta < 86400 * 99)
7303 r->
rsprintf(
"%1.0lfh", delta / 86400.0);
7308 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7336 std::sort(delete_list.begin(), delete_list.end());
7338 for (
unsigned i=0;
i<delete_list.size();
i++) {
7339 std::string
name = delete_list[
i];
7341 dd +=
"<tr><td style=\"text-align:left;\" align=left><input align=left type=checkbox id=delete";
7345 dd += MJsonNode::Encode(
name.c_str());
7349 dd +=
"</input></td></tr>\n";
7353 dd +=
"<input type=button value=Delete onClick='mhttpd_delete_page_handle_delete(event);'>\n";
7354 dd +=
"<input type=button value=Cancel onClick='mhttpd_delete_page_handle_cancel(event);'>\n";
7362 std::string cd =
"";
7364 cd +=
"<!-- Demo dialog -->\n";
7365 cd +=
"<div id=\"dlgCreate\" class=\"dlgFrame\">\n";
7366 cd +=
"<div class=\"dlgTitlebar\">Create ODB entry</div>\n";
7367 cd +=
"<div class=\"dlgPanel\">\n";
7369 cd +=
"<div id=odbpath>";
7371 cd += MJsonNode::Encode(odbpath.c_str());
7374 cd +=
"<div><br></div>\n";
7376 cd +=
"<table class=\"dialogTable\">\n";
7377 cd +=
"<th colspan=2>Create ODB entry:</th>\n";
7381 cd +=
"<select type=text size=1 id=create_tid name=type>";
7382 cd +=
"<option value=7>Integer (32-bit)";
7383 cd +=
"<option value=9>Float (4 Bytes)";
7384 cd +=
"<option value=12>String";
7385 cd +=
"<option selected value=15>Subdirectory";
7386 cd +=
"<option value=1>Byte";
7387 cd +=
"<option value=2>Signed byte";
7388 cd +=
"<option value=3>Character (8-bit)";
7389 cd +=
"<option value=4>Word (16-bit)";
7390 cd +=
"<option value=5>Short integer (16-bit)";
7391 cd +=
"<option value=6>Double Word (32-bit)";
7392 cd +=
"<option value=8>Boolean";
7393 cd +=
"<option value=10>Double float (8 Bytes)";
7397 cd +=
"<tr><td>Name<td><input type=text size=31 maxlength=31 id=create_name name=value></tr>\n";
7398 cd +=
"<tr><td>Array size<td><input type=text size=31 maxlength=31 id=create_array_length name=index value=1></tr>\n";
7399 cd +=
"<tr><td>String length<td><input type=text size=31 maxlength=31 id=create_strlen name=strlen value=32></tr>\n";
7401 cd +=
"<input type=button value=Create onClick='mhttpd_create_page_handle_create(event);'>\n";
7402 cd +=
"<input type=button value=Cancel onClick='mhttpd_create_page_handle_cancel(event);'>\n";
7410 std::string ld =
"";
7412 ld +=
"<!-- Demo dialog -->\n";
7413 ld +=
"<div id=\"dlgLink\" class=\"dlgFrame\">\n";
7414 ld +=
"<div class=\"dlgTitlebar\">Create a link to an ODB entry</div>\n";
7415 ld +=
"<div class=\"dlgPanel\">\n";
7417 ld +=
"<div id=link_odbpath>";
7419 ld += MJsonNode::Encode(odbpath.c_str());
7422 ld +=
"<div><br></div>\n";
7424 ld +=
"<table class=\"dialogTable\">\n";
7425 ld +=
"<th colspan=2>Create a link to an ODB entry:</th>\n";
7426 ld +=
"<tr><td>Name<td><input type=text size=31 maxlength=31 id=link_name name=value></tr>\n";
7427 ld +=
"<tr><td>Link target<td><input type=text size=31 maxlength=256 id=link_target name=target></tr>\n";
7429 ld +=
"<input type=button value=Link onClick='mhttpd_link_page_handle_link(event);'>\n";
7430 ld +=
"<input type=button value=Cancel onClick='mhttpd_link_page_handle_cancel(event);'>\n";
7448 std::string odb_path = pp->
getparam(
"odb_path");
7458 r->
rsprintf(
"Error: cannot find key %s<P>\n", odb_path.c_str());
7468 r->
rsprintf(
"<table class=\"dialogTable\">");
7471 r->
rsprintf(
"<input type=hidden name=index value=\"%d\">\n",
index);
7476 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", group);
7478 r->
rsprintf(
"<input type=hidden name=odb_path value=\"%s\">\n", odb_path.c_str());
7486 str1 = odb_path.c_str();
7488 r->
rsprintf(
"<tr><th colspan=2>Set new value - type = %s</tr>\n", data_str1.c_str());
7489 r->
rsprintf(
"<tr><td>%s<td>\n", str1.c_str());
7492 size =
sizeof(
data);
7499 if (strchr(data_str.c_str(),
'\n') != NULL) {
7500 r->
rsprintf(
"<textarea rows=20 cols=80 name=\"text\">\n");
7505 if ((
int) data_str.length() > size)
7506 size = data_str.length() + 3;
7510 r->
rsprintf(
"<input type=\"text\" size=%d maxlength=256 name=\"value\" value=\"", size);
7517 r->
rsprintf(
"<tr><td align=center colspan=2>");
7518 r->
rsprintf(
"<input type=submit name=cmd value=Set>");
7519 r->
rsprintf(
"<input type=submit name=cmd value=Cancel>");
7523 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
7534 r->
rsprintf(
"Error: cannot find key %s<P>\n", odb_path.c_str());
7563 r->
rsprintf(
"<h2>Write access not allowed</h2>\n");
7579 if (
value[0] == 0) {
7587 r->
rsprintf(
"<table class=\"dialogTable\">");
7589 r->
rsprintf(
"<tr><th colspan=2>Find string in Online Database</tr>\n");
7590 r->
rsprintf(
"<tr><td>Enter substring (case insensitive)\n");
7592 r->
rsprintf(
"<td><input type=\"text\" size=\"20\" maxlength=\"80\" name=\"value\">\n");
7595 r->
rsprintf(
"<tr><td align=center colspan=2>");
7596 r->
rsprintf(
"<input type=submit name=cmd value=Find>");
7597 r->
rsprintf(
"<input type=submit name=cmd value=Cancel>");
7601 r->
rsprintf(
"<input type=hidden name=cmd value=Find>");
7609 r->
rsprintf(
"<table class=\"mtable\">\n");
7610 r->
rsprintf(
"<tr><th colspan=2 class=\"mtableheader\">");
7611 r->
rsprintf(
"Results of search for substring \"%s\"</tr>\n",
value);
7612 r->
rsprintf(
"<tr><th class=\"titlerow\">Key<th>Value</tr>\n");
7634#define LN10 2.302585094
7635#define LOG2 0.301029996
7636#define LOG5 0.698970005
7639 int x1,
int y1,
int width,
7640 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax)
7642 double dx, int_dx, frac_dx, x_act, label_dx, major_dx, x_screen, maxwidth;
7643 int tick_base, major_base, label_base, n_sig1, n_sig2, xs;
7645 double base[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
7647 if (xmax <= xmin || width <= 0)
7651 dx = (xmax - xmin) / (
double) (width / 5);
7653 frac_dx = modf(log(dx) /
LN10, &int_dx);
7659 tick_base = frac_dx <
LOG2 ? 1 : frac_dx <
LOG5 ? 2 : 3;
7660 major_base = label_base = tick_base + 1;
7663 dx = pow(10, int_dx) *
base[tick_base];
7664 major_dx = pow(10, int_dx) *
base[major_base];
7665 label_dx = major_dx;
7671 n_sig1 = (int) floor(log(fabs(xmin)) /
LN10) - (
int) floor(log(fabs(label_dx)) /
LN10) + 1;
7677 (int) floor(log(fabs(xmax)) /
LN10) - (
int) floor(log(fabs(label_dx)) /
LN10) + 1;
7679 n_sig1 =
MAX(n_sig1, n_sig2);
7680 n_sig1 =
MAX(n_sig1, 4);
7683 sprintf(
str,
"%1.*lG", n_sig1, floor(xmin / dx) * dx);
7684 maxwidth = font->
h / 2 * strlen(
str);
7685 sprintf(
str,
"%1.*lG", n_sig1, floor(xmax / dx) * dx);
7686 maxwidth =
MAX(maxwidth, font->
h / 2 * strlen(
str));
7687 sprintf(
str,
"%1.*lG", n_sig1, floor(xmax / dx) * dx + label_dx);
7688 maxwidth =
MAX(maxwidth, font->
h / 2 * strlen(
str));
7691 while (maxwidth > 0.7 * label_dx / (xmax - xmin) * width) {
7693 label_dx = pow(10, int_dx) *
base[label_base];
7694 if (label_base % 3 == 2 && major_base % 3 == 1) {
7696 major_dx = pow(10, int_dx) *
base[major_base];
7700 x_act = floor(xmin / dx) * dx;
7705 x_screen = (x_act - xmin) / (xmax - xmin) * width + x1;
7706 xs = (int) (x_screen + 0.5);
7708 if (x_screen > x1 + width + 0.001)
7711 if (x_screen >= x1) {
7712 if (fabs(floor(x_act / major_dx + 0.5) - x_act / major_dx) <
7713 dx / major_dx / 10.0) {
7715 if (fabs(floor(x_act / label_dx + 0.5) - x_act / label_dx) <
7716 dx / label_dx / 10.0) {
7721 if (grid != 0 && xs > x1 && xs < x1 + width)
7726 sprintf(
str,
"%1.*lG", n_sig1, x_act);
7728 y1 + label,
str, col);
7735 if (grid != 0 && xs > x1 && xs < x1 + width)
7748 if (fabs(x_act) < dx / 100)
7761 t_sec = (time_t) sec;
7764 localtime_r(&t_sec, &tms);
7765 strcpy(mon,
mname[tms.tm_mon]);
7770 sprintf(result,
"%02d %s %02d %02d:%02d:%02d",
7771 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min,
7773 else if (
base < 3600 * 24)
7774 sprintf(result,
"%02d %s %02d %02d:%02d",
7775 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min);
7777 sprintf(result,
"%02d %s %02d", tms.tm_mday, mon, tms.tm_year % 100);
7780 sprintf(result,
"%02d:%02d:%02d", tms.tm_hour, tms.tm_min, tms.tm_sec);
7781 else if (
base < 3600 * 3)
7782 sprintf(result,
"%02d:%02d", tms.tm_hour, tms.tm_min);
7783 else if (
base < 3600 * 24)
7784 sprintf(result,
"%02d %s %02d %02d:%02d",
7785 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min);
7787 sprintf(result,
"%02d %s %02d", tms.tm_mday, mon, tms.tm_year % 100);
7792 int x1,
int y1,
int width,
int xr,
7793 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax)
7795 int dx, x_act, label_dx, major_dx, x_screen, maxwidth;
7796 int tick_base, major_base, label_base, xs, xl;
7798 const int base[] = { 1, 5, 10, 60, 300, 600, 1800, 3600, 3600 * 6, 3600 * 12, 3600 * 24, 0 };
7800 int force_date, d1, d2;
7803 if (xmax <= xmin || width <= 0)
7808 localtime_r(<ime, &tms);
7810 ltime = (time_t) xmax;
7811 localtime_r(<ime, &tms);
7813 force_date = (d1 != d2);
7816 dx = (int) ((xmax - xmin) / (double) (width / 5) + 0.5);
7818 for (tick_base = 0;
base[tick_base]; tick_base++) {
7819 if (
base[tick_base] > dx)
7822 if (!
base[tick_base])
7824 dx =
base[tick_base];
7826 if (
base[tick_base + 1])
7827 major_base = tick_base + 1;
7829 major_base = tick_base;
7830 major_dx =
base[major_base];
7832 if (
base[major_base + 1])
7833 label_base = major_base + 1;
7835 label_base = major_base;
7836 label_dx =
base[label_base];
7840 maxwidth = font->
h / 2 * strlen(
str);
7843 if (maxwidth > 0.7 * label_dx / (xmax - xmin) * width) {
7844 if (
base[label_base + 1])
7845 label_dx =
base[++label_base];
7847 label_dx += 3600 * 24;
7858 x_screen = (int) ((x_act - xmin) / (xmax - xmin) * width + x1 + 0.5);
7859 xs = (int) (x_screen + 0.5);
7861 if (x_screen > x1 + width + 0.001)
7864 if (x_screen >= x1) {
7871 if (grid != 0 && xs > x1 && xs < x1 + width)
7879 xl = (int) xs - font->
w * strlen(
str) / 2;
7882 if (xl + font->
w * (
int) strlen(
str) > xr)
7883 xl = xr - font->
w * strlen(
str);
7891 if (grid != 0 && xs > x1 && xs < x1 + width)
7904 if (fabs((
double)x_act) < dx / 100)
7913 int x1,
int y1,
int width,
7914 int minor,
int major,
int text,
int label,
int grid,
double ymin,
double ymax,
7917 double dy, int_dy, frac_dy, y_act, label_dy, major_dy, y_screen, y_next;
7918 int tick_base, major_base, label_base, n_sig1, n_sig2, ys, max_width;
7921 const double base[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
7923 if (ymax <= ymin || width <= 0)
7927 if (fabs(ymax - ymin) <= 1
e-10)
7931 dy = pow(10, floor(log(ymin) /
LN10));
7936 dy = (ymax - ymin) / (
double) (width / 5);
7938 frac_dy = modf(log(dy) /
LN10, &int_dy);
7944 tick_base = frac_dy <
LOG2 ? 1 : frac_dy <
LOG5 ? 2 : 3;
7945 major_base = label_base = tick_base + 1;
7948 dy = pow(10, int_dy) *
base[tick_base];
7949 major_dy = pow(10, int_dy) *
base[major_base];
7950 label_dy = major_dy;
7957 (int) floor(log(fabs(ymin)) /
LN10) -
7958 (
int) floor(log(fabs(label_dy)) /
LN10) + 1;
7964 (int) floor(log(fabs(ymax)) /
LN10) -
7965 (
int) floor(log(fabs(label_dy)) /
LN10) + 1;
7967 n_sig1 =
MAX(n_sig1, n_sig2);
7968 n_sig1 =
MAX(n_sig1, 4);
7971 while (label_dy / (ymax - ymin) * width < 1.5 * font->h) {
7973 label_dy = pow(10, int_dy) *
base[label_base];
7974 if (label_base % 3 == 2 && major_base % 3 == 1) {
7976 major_dy = pow(10, int_dy) *
base[major_base];
7982 y_act = floor(ymin / dy) * dy;
7984 if (x1 != 0 || y1 != 0)
7987 last_label_y = y1 + 2 * font->
h;
7991 y_screen = y1 - (log(y_act) - log(ymin)) / (log(ymax) - log(ymin)) * width;
7993 y_screen = y1 - (y_act - ymin) / (ymax - ymin) * width;
7994 ys = (int) (y_screen + 0.5);
7996 if (y_screen < y1 - width - 0.001)
7999 if (y_screen <= y1 + 0.001) {
8000 if (fabs(floor(y_act / major_dy + 0.5) - y_act / major_dy) <
8001 dy / major_dy / 10.0) {
8002 if (fabs(floor(y_act / label_dy + 0.5) - y_act / label_dy) <
8003 dy / label_dy / 10.0) {
8004 if (x1 != 0 || y1 != 0) {
8009 if (grid != 0 && y_screen < y1 && y_screen > y1 - width) {
8018 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8021 ys - font->
h / 2,
str, col);
8025 last_label_y = ys - font->
h / 2;
8028 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8029 max_width =
MAX(max_width, (
int) (font->
w * strlen(
str)));
8032 if (x1 != 0 || y1 != 0) {
8037 if (grid != 0 && y_screen < y1 && y_screen > y1 - width)
8048 if (x1 != 0 || y1 != 0) {
8056 if (x1 != 0 || y1 != 0) {
8058 y_next = pow(10, floor(log(y_act) /
LN10) + 1);
8061 (log(y_next) - log(ymin)) / (log(ymax) -
8062 log(ymin)) * width + 0.5);
8064 if (ys + font->
h / 2 < last_label_y
8065 && ys - font->
h / 2 > y_screen + font->
h / 2) {
8066 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8069 ys - font->
h / 2,
str, col);
8075 last_label_y = ys - font->
h / 2;
8077 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8078 max_width =
MAX(max_width, (
int) (font->
w * strlen(
str)));
8088 if (fabs(y_act) < dy / 100)
8093 return max_width + abs(label);
8103 switch (
str[strlen(
str) - 1]) {
8126 for (; *
str != 0;
str++) {
8142 sprintf(buf,
"%.0f", (
double)t);
8155 cm_msg(
MINFO,
"history_watch_callback",
"History configuration may have changed, will reconnect");
8222 cm_msg(
MERROR,
"get_history",
"Cannot configure history, hs_get_history() status %d",
status);
8240#define ALLOC(t,n) (t*)calloc(sizeof(t),(n))
8241#define DELETE(x) if (x) { free(x); (x)=NULL; }
8242#define DELETEA(x, n) if (x) { for (int i=0; i<(n); i++) { free((x)[i]); (x)[i]=NULL; }; DELETE(x); }
8243#define STRDUP(x) strdup(x)
8299 printf(
"this %p, nvars %d. tstart %d, tend %d, scale %d\n",
this,
nvars, (
int)
tstart, (
int)
tend, (
int)
scale);
8326#define READ_HISTORY_DATA 0x1
8327#define READ_HISTORY_RUNMARKER 0x2
8328#define READ_HISTORY_LAST_WRITTEN 0x4
8388 cm_msg(
MERROR,
"read_history",
"Cannot find \'/History/Display\' in ODB, status %d",
status);
8395 cm_msg(
MERROR,
"read_history",
"Cannot find \'%s\' in ODB, status %d", path,
status);
8401 cm_msg(
MERROR,
"read_history",
"Cannot find \'%s/Variables\' in ODB, status %d", path,
status);
8411 data->tstart = tstart;
8413 data->scale = scale;
8415 for (
size_t i=0;
i<hp.
vars.size();
i++) {
8445 char *
q = strchr(
data->var_names[
data->nvars],
'[');
8447 data->var_index[
data->nvars] = atoi(
q+1);
8463 data->var_index[
data->nvars+0] = 0;
8464 data->var_index[
data->nvars+1] = 0;
8466 data->odb_index[
data->nvars+0] = -1;
8467 data->odb_index[
data->nvars+1] = -2;
8472 bool get_last_written =
false;
8486 printf(
"read_history: nvars %d, hs_read() status %d\n",
data->nvars,
status);
8487 for (
int i=0;
i<
data->nvars;
i++) {
8488 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]);
8493 cm_msg(
MERROR,
"read_history",
"Complete history failure, hs_read() status %d, see messages",
status);
8497 for (
int i=0;
i<
data->nvars;
i++) {
8499 get_last_written =
true;
8506 get_last_written =
true;
8508 if (get_last_written) {
8509 data->have_last_written =
true;
8517 data->last_written);
8520 data->have_last_written =
false;
8562 time_t tmin = endtime;
8565 for (
int k=0;
k<hsdata->
nvars;
k++) {
8596 *plastwritten = tmin;
8598 *plastwritten = tmax;
8605 printf(
"get_hist_last_written: elapsed time %f ms\n", tend-tstart);
8611 int width,
int height,
8615 int labels,
const char *bgcolor,
const char *fgcolor,
const char *gridcolor)
8623 int size,
status, r, g, b;
8626 int white, grey, red;
8628 int fgcol, bgcol, gridcol;
8648 time_t starttime, endtime;
8659 std::vector<int> var_index; var_index.resize(hp.
vars.size());
8661 for (
size_t i=0;
i<hp.
vars.size();
i++) {
8663 const char *vp = strchr(hp.
vars[
i].tag_name.c_str(),
'[');
8665 var_index[
i] = atoi(vp + 1);
8673 if ((minvalue == 0) && (maxvalue == 0)) {
8674 minvalue = -HUGE_VAL;
8675 maxvalue = +HUGE_VAL;
8690 sscanf(bgcolor,
"%02x%02x%02x", &r, &g, &b);
8692 sscanf(fgcolor,
"%02x%02x%02x", &r, &g, &b);
8694 sscanf(gridcolor,
"%02x%02x%02x", &r, &g, &b);
8731 sprintf(
str,
"History is not configured, see messages");
8755 if (hp.
vars.empty()) {
8756 sprintf(
str,
"No variables in panel %s/%s", hgroup, hpanel);
8762 sprintf(
str,
"Too many variables in panel %s/%s", hgroup, hpanel);
8770 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
8831 if (hp.
vars[
i].colour[0] ==
'#') {
8832 const char*
str = hp.
vars[
i].colour.c_str();
8839 r = strtoul(sss, NULL, 16);
8843 g = strtoul(sss, NULL, 16);
8847 b = strtoul(sss, NULL, 16);
8923 std::string odbpath;
8939 sprintf(
str,
"Variables/%s", hp.
vars[
i].tag_name.c_str());
8945 odbpath +=
"/Equipment/";
8946 odbpath += hp.
vars[
i].event_name;
8947 odbpath +=
"/Variables/";
8948 odbpath += hp.
vars[
i].tag_name;
8957 mstrlcpy(
str, hp.
vars[
i].tag_name.c_str(),
sizeof(
str));
8958 p =
str + strlen(
str) - 1;
8959 while (p >
str && *p !=
' ')
8961 std::string key_name = p + 1;
8964 std::string varname =
str;
8974 odbpath +=
"/Equipment/";
8975 odbpath += hp.
vars[
i].event_name;
8976 odbpath +=
"/Variables/";
8977 odbpath += key_name;
8999 std::string key_name =
key.
name;
9003 path +=
"Settings/Names ";
9016 odbpath +=
"/Equipment/";
9017 odbpath += hp.
vars[
i].event_name;
9018 odbpath +=
"/Variables/";
9019 odbpath += key_name;
9067 upper_limit[
i] = lower_limit[
i] = -12345;
9069 if (odbpath.length() > 0 && hkeyroot) {
9080 if (strstr(
str, odbpath.c_str())) {
9081 if (strchr(
str,
'<')) {
9082 p = strchr(
str,
'<') + 1;
9086 lower_limit[
i] = (hp.
vars[
i].factor * (atof(p) - hp.
vars[
i].voffset) + hp.
vars[
i].offset);
9088 lower_limit[
i] = atof(p);
9091 if (strchr(
str,
'>')) {
9092 p = strchr(
str,
'>') + 1;
9096 upper_limit[
i] = (hp.
vars[
i].factor * (atof(p) - hp.
vars[
i].voffset) + hp.
vars[
i].offset);
9098 upper_limit[
i] = atof(p);
9109 starttime = xendtime - scale;
9121 sprintf(
str,
"Complete history failure, read_history() status %d, see messages",
status);
9129 for (
int k=0;
k<hsdata->
nvars;
k++) {
9140 var_status[
i][0] = 0;
9142 sprintf(var_status[
i],
"not found in history");
9145 sprintf(var_status[
i],
"hs_read() error %d, see messages", hsdata->
status[
k]);
9151 int xx = (int)(hsdata->
t[
k][
j]);
9152 double yy = hsdata->
v[
k][
j];
9168 yy = hp.
vars[
i].factor * (yy - hp.
vars[
i].voffset) + hp.
vars[
i].offset;
9172 if ((
i == 0 ||
index != -1) && n_vp == 0)
9192 assert(x[
i].size() == y[
i].size());
9201 double yb1, yb2, yf1, yf2;
9210 if (ymin < minvalue)
9213 if (ymax > maxvalue)
9226 if (logaxis && ymin > 0 && ymax > 0) {
9227 yb1 = pow(10, floor(log(ymin) /
LN10));
9228 yf1 = floor(ymin / yb1);
9229 yb2 = pow(10, floor(log(ymax) /
LN10));
9230 yf2 = floor(ymax / yb2);
9232 if (yb1 == yb2 && yf1 == yf2)
9236 ybase = pow(10, floor(log(ymin) /
LN10));
9237 ymin = (floor(ymin / ybase) * ybase);
9238 ybase = pow(10, floor(log(ymax) /
LN10));
9239 ymax = ((floor(ymax / ybase) + 1) * ybase);
9252 if (ymin == 0 && ymax == 0) {
9257 ymax += (ymax - ymin) / 20.f;
9260 ymin -= (ymax - ymin) / 20.f;
9282 aoffset =
vaxis(im,
gdFontSmall, fgcol, gridcol, 0, 0, height, -3, -5, -7, -8, 0, ymin, ymax, logaxis);
9293 taxis(im,
gdFontSmall, fgcol, gridcol, x1, y1, x2 - x1, width, 3, 5, 9, 10, 0, (
double)starttime, (
double)endtime);
9295 vaxis(im,
gdFontSmall, fgcol, gridcol, x1, y1, y1 - y2, -3, -5, -7, -8, x2 - x1, ymin, ymax, logaxis);
9299 xs = ys = xold = yold = 0;
9306 const char* event_names[] = {
9311 const char* tag_names[] = {
9316 const int tag_indexes[] = {
9330 2, event_names, tag_names, tag_indexes,
9331 num_entries, tbuf, dbuf, st);
9335 int n_marker = num_entries[0];
9340 for (
j = 0;
j < (int) n_marker;
j++) {
9354 xs = (int) ((tbuf[1][
j] - starttime) / (scale/1.0) * (x2 - x1) + x1 + 0.5);
9367 if (dbuf[0][
j] == 1)
9369 else if (dbuf[0][
j] == 2)
9371 else if (dbuf[0][
j] == 3)
9394 if (num_entries[0]) {
9401 if (num_entries[1]) {
9412 int index_state = -1;
9413 int index_run_number = -1;
9415 for (
int k=0;
k<hsdata->
nvars;
k++) {
9420 index_run_number =
k;
9426 ok = (index_state >= 0) && (index_run_number >= 0);
9435 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]);
9442 if (ok && n_marker > 0 && n_marker < 100) {
9445 for (
j = 0;
j < (int) n_marker;
j++) {
9459 xs = (int) ((hsdata->
t[index_state][
j] - starttime) / (scale/1.0) * (x2 - x1) + x1 + 0.5);
9472 int state = (int)hsdata->
v[index_state][
j];
9476 else if (
state == 2)
9478 else if (
state == 3)
9502 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
9507 if (lower_limit[
i] != -12345) {
9509 if (lower_limit[
i] <= 0)
9512 ys = (int) (y1 - (log(lower_limit[
i]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9514 ys = (int) (y1 - (lower_limit[
i] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9526 if (ys > y2 && ys < y1) {
9539 if (upper_limit[
i] != -12345) {
9541 if (upper_limit[
i] <= 0)
9544 ys = (int) (y1 - (log(upper_limit[
i]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9546 ys = (int) (y1 - (upper_limit[
i] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9558 if (ys > y2 && ys < y1) {
9572 for (
j = 0;
j < (int) n_point[
i];
j++) {
9578 xs = (int) (((x[
i][
j] - starttime)/1.0) / (1.0*scale) * (x2 - x1) + x1 + 0.5);
9584 ys = (int) (y1 - (log(y[
i][
j]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9586 ys = (int) (y1 - (y[
i][
j] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9604 if (n_point[
i] > 0) {
9607 poly[1].
x = xs + 12;
9609 poly[2].
x = xs + 12;
9617 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
9628 std::string
str = hp.
vars[
i].label.c_str();
9634 if (hp.
vars[
i].voffset > 0)
9636 else if (hp.
vars[
i].voffset < 0)
9639 if (hp.
vars[
i].factor != 1) {
9640 if (hp.
vars[
i].voffset == 0)
9647 if (hp.
vars[
i].offset > 0)
9649 else if (hp.
vars[
i].offset < 0)
9658 for (
int j=0;
j<hsdata->
nvars;
j++)
9665 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]);
9670 if (n_point[
i] > 0) {
9671 sprintf(xstr,
" = %g", y[
i][n_point[
i]-1]);
9673 sprintf(xstr,
" = all data is NaN or INF");
9678 sprintf(xstr,
" = last data %s", ctimebuf);
9680 char*s = strchr(xstr,
'\n');
9684 var_status[
i][0] = 0;
9686 sprintf(xstr,
" = no data ever");
9689 sprintf(xstr,
" = no data");
9694 if (strlen(var_status[
i]) > 1) {
9698 row =
index == -1 ?
i : 0;
9728 if (buffer == NULL) {
9729 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
9732 rr->
rsprintf(
"Content-Type: image/gif\r\n");
9733 rr->
rsprintf(
"Content-Length: %d\r\n", length);
9734 rr->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
9735 rr->
rsprintf(
"Expires: Fri, 01-Jan-1983 00:00:00 GMT\r\n\r\n");
9739 if (length > *buffer_size) {
9740 printf(
"return buffer too small\n");
9744 memcpy(buffer, gb.
data, length);
9745 *buffer_size = length;
9770 struct tm tms = *ptms;
9773 localtime_r(&t1, &tms2);
9774 tms2.tm_year = ptms->tm_year;
9775 tms2.tm_mon = ptms->tm_mon;
9776 tms2.tm_mday = ptms->tm_mday;
9777 tms2.tm_hour = ptms->tm_hour;
9778 tms2.tm_min = ptms->tm_min;
9804 memset(&tms, 0,
sizeof(
struct tm));
9806 tms.tm_year = atoi(p->
getparam(
"y1")) % 100;
9808 std::string m1 = p->
getparam(
"m1");
9809 for (
i = 0;
i < 12;
i++)
9816 tms.tm_mday = atoi(p->
getparam(
"d1"));
9817 tms.tm_hour = atoi(p->
getparam(
"h1"));
9819 if (tms.tm_year < 90)
9824 memset(&tms, 0,
sizeof(
struct tm));
9825 tms.tm_year = atoi(p->
getparam(
"y2")) % 100;
9827 std::string m2 = p->
getparam(
"m2");
9828 for (
i = 0;
i < 12;
i++)
9835 tms.tm_mday = atoi(p->
getparam(
"d2"));
9836 tms.tm_hour = atoi(p->
getparam(
"h2"));
9838 if (tms.tm_year < 90)
9843 if (ltime_end == ltime_start)
9844 ltime_end += 3600 * 24;
9847 redir +=
"?cmd=oldhistory&";
9868 time_t now = time(NULL);
9870 time_t starttime = now - 3600 * 24;
9871 time_t endtime = now;
9872 bool full_day =
true;
9878 starttime = endtime - atoi(p->
getparam(
"hscale"));
9881 starttime = endtime - 3600 * 24;
9887 r->
rsprintf(
"<tr><td colspan=2>\n");
9888 r->
rsprintf(
"<input type=hidden name=cmd value=OldHistory>\n");
9889 r->
rsprintf(
"<input type=submit name=hcmd value=Query>\n");
9890 r->
rsprintf(
"<input type=submit name=hcmd value=Cancel>\n");
9892 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", p->
getparam(
"group"));
9894 r->
rsprintf(
"<input type=hidden name=panel value=\"%s\">\n", p->
getparam(
"panel"));
9896 r->
rsprintf(
"<input type=hidden name=htime value=\"%s\">\n", p->
getparam(
"htime"));
9898 r->
rsprintf(
"<input type=hidden name=hscale value=\"%s\">\n", p->
getparam(
"hscale"));
9900 r->
rsprintf(
"<input type=hidden name=hindex value=\"%s\">\n", p->
getparam(
"hindex"));
9904 r->
rsprintf(
"<table class=\"dialogTable\">");
9907 localtime_r(&starttime, &tms);
9908 tms.tm_year += 1900;
9910 r->
rsprintf(
"<tr><td nowrap>Start date:</td>");
9912 r->
rsprintf(
"<td>Month: <select name=\"m1\">\n");
9913 r->
rsprintf(
"<option value=\"\">\n");
9914 for (
i = 0;
i < 12;
i++)
9915 if (
i == tms.tm_mon)
9921 r->
rsprintf(
" Day: <select name=\"d1\">");
9922 r->
rsprintf(
"<option selected value=\"\">\n");
9923 for (
i = 0;
i < 31;
i++)
9924 if (
i + 1 == tms.tm_mday)
9925 r->
rsprintf(
"<option selected value=%d>%d\n",
i + 1,
i + 1);
9927 r->
rsprintf(
"<option value=%d>%d\n",
i + 1,
i + 1);
9930 int start_hour = tms.tm_hour;
9934 r->
rsprintf(
" Hour: <input type=\"text\" size=5 maxlength=5 name=\"h1\" value=\"%d\">", start_hour);
9936 r->
rsprintf(
" Year: <input type=\"text\" size=5 maxlength=5 name=\"y1\" value=\"%d\">", tms.tm_year);
9939 r->
rsprintf(
"<tr><td nowrap>End date:</td>");
9941 localtime_r(&endtime, &tms);
9942 tms.tm_year += 1900;
9944 r->
rsprintf(
"<td>Month: <select name=\"m2\">\n");
9945 r->
rsprintf(
"<option value=\"\">\n");
9946 for (
i = 0;
i < 12;
i++)
9947 if (
i == tms.tm_mon)
9953 r->
rsprintf(
" Day: <select name=\"d2\">");
9954 r->
rsprintf(
"<option selected value=\"\">\n");
9955 for (
i = 0;
i < 31;
i++)
9956 if (
i + 1 == tms.tm_mday)
9957 r->
rsprintf(
"<option selected value=%d>%d\n",
i + 1,
i + 1);
9959 r->
rsprintf(
"<option value=%d>%d\n",
i + 1,
i + 1);
9962 int end_hour = tms.tm_hour;
9966 r->
rsprintf(
" Hour: <input type=\"text\" size=5 maxlength=5 name=\"h2\" value=\"%d\">", end_hour);
9968 r->
rsprintf(
" Year: <input type=\"text\" size=5 maxlength=5 name=\"y2\" value=\"%d\">", tms.tm_year);
9984 const char*sa = (
const char*)a;
9985 const char*sb = (
const char*)b;
9994 printf(
"compare [%s] and [%s]\n", sa, sb);
9997 if (sa[
i]==0 && sb[
i]==0)
10002 if (isdigit(sa[
i]) && isdigit(sb[
i])) {
10003 int va = atoi(sa+
i);
10004 int vb = atoi(sb+
i);
10007 printf(
"index %d, values %d %d\n",
i, va, vb);
10018 if (sa[
i]==sb[
i]) {
10023 printf(
"index %d, char [%c] [%c]\n",
i, sa[
i], sb[
i]);
10027 else if (sb[
i] == 0)
10041 return cmp_names(a.c_str(), b.c_str()) < 0;
10055static int cmp_tags(
const void *a,
const void *b)
10057 const TAG*sa = (
const TAG*)a;
10058 const TAG*sb = (
const TAG*)b;
10062static void sort_tags(
int ntags,
TAG* tags)
10094 str =
"bad_xdb_find_key";
10114 printf(
"hist plot: %d variables\n", (
int)hp.
vars.size());
10115 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);
10117 for (
size_t i=0;
i<hp.
vars.size();
i++) {
10118 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);
10124 const char*
const colour[] =
10126 "#00AAFF",
"#FF9000",
"#FF00A0",
"#00C030",
10127 "#A0C0D0",
"#D0A060",
"#C04010",
"#807060",
10128 "#F0C000",
"#2090A0",
"#D040D0",
"#90B000",
10129 "#B0B040",
"#B0B0FF",
"#FFA0A0",
"#A0FFA0",
10132 for (
int i=0; colour[
i];
i++) {
10133 bool in_use =
false;
10135 for (
size_t j=0;
j<hp.
vars.size();
j++)
10136 if (hp.
vars[
j].colour == colour[
i]) {
10151 for (
size_t i=0;
i<hp.
vars.size();
i++)
10152 if (hp.
vars[
i].order > order)
10153 order = hp.
vars[
i].order;
10161 std::vector<size_t> colons;
10165 colons.push_back(
i);
10169 if (colons.size() == 0) {
10174 size_t slash_pos =
var_name.find(
"/");
10175 bool uses_per_variable_naming = (slash_pos != std::string::npos);
10177 if (uses_per_variable_naming && colons.size() % 2 == 1) {
10178 size_t middle_colon_pos = colons[colons.size() / 2];
10179 std::string slash_to_mid =
var_name.substr(slash_pos + 1, middle_colon_pos - slash_pos - 1);
10180 std::string mid_to_end =
var_name.substr(middle_colon_pos + 1);
10182 if (slash_to_mid == mid_to_end) {
10186 split_pos = middle_colon_pos;
10189 split_pos = colons[0];
10193 split_pos = colons[0];
10196 event_name =
var_name.substr(0, split_pos);
10197 tag_name =
var_name.substr(split_pos + 1);
10203 std::string path =
"History/Display/";
10208 MVOdb* o = odb->Chdir(path.c_str());
10214 o->RD(
"Minimum", &hp->
minimum);
10215 o->RD(
"Maximum", &hp->
maximum);
10225 std::vector<std::string> hist_vars;
10226 std::vector<std::string> hist_formula;
10227 std::vector<std::string> hist_colour;
10228 std::vector<std::string> hist_label;
10229 std::vector<bool> hist_show_raw_value;
10230 std::vector<double> hist_factor;
10231 std::vector<double> hist_offset;
10232 std::vector<double> hist_voffset;
10234 o->RSA(
"Variables", &hist_vars);
10235 o->RSA(
"Formula", &hist_formula);
10236 o->RSA(
"Colour", &hist_colour);
10237 o->RSA(
"Label", &hist_label);
10238 o->RBA(
"Show raw value", &hist_show_raw_value);
10239 o->RDA(
"Factor", &hist_factor);
10240 o->RDA(
"Offset", &hist_offset);
10241 o->RDA(
"VOffset", &hist_voffset);
10247 bool all_zero =
true;
10248 for (
size_t i=0;
i<hist_factor.size();
i++) {
10249 if (hist_factor[
i] != 0)
10253 for (
size_t i=0;
i<hist_factor.size();
i++) {
10254 hist_factor[
i] = 1.0;
10259 size_t num = std::max(hist_vars.size(), hist_formula.size());
10260 num = std::max(num, hist_colour.size());
10261 num = std::max(num, hist_label.size());
10262 num = std::max(num, hist_show_raw_value.size());
10263 num = std::max(num, hist_factor.size());
10264 num = std::max(num, hist_offset.size());
10265 num = std::max(num, hist_voffset.size());
10267 hist_vars.resize(num);
10268 hist_formula.resize(num);
10269 hist_colour.resize(num);
10270 hist_label.resize(num);
10271 hist_show_raw_value.resize(num);
10272 hist_factor.resize(num, 1.0);
10273 hist_offset.resize(num, 0.0);
10274 hist_voffset.resize(num, 0.0);
10276 for (
size_t i=0;
i<num;
i++) {
10283 v.
label = hist_label[
i];
10297 hp->
vars.push_back(v);
10370 hp->
vars.push_back(v);
10385 int seln = atoi(p->
getparam(
"seln"));
10386 for (
int i=0;
i<seln;
i++) {
10388 sprintf(
str,
"sel%d",
i);
10391 if (par.length() < 1)
10394 std::string event_name, tag_name;
10397 if (tag_name ==
"")
10407 hp.
vars.push_back(v);
10413 if (strlen(group) < 1) {
10414 cm_msg(
MERROR,
"SaveHistPlotToOdb",
"Error: Cannot write history plot to ODB, group \"%s\", panel \"%s\", invalid group name", group, panel);
10418 if (strlen(panel) < 1) {
10419 cm_msg(
MERROR,
"SaveHistPlotToOdb",
"Error: Cannot write history plot to ODB, group \"%s\", panel \"%s\", invalid panel name", group, panel);
10423 std::string path =
"History/Display/";
10431 MVOdb* o = odb->Chdir(path.c_str(),
true);
10433 o->WS(
"Timescale", hp.
timescale.c_str());
10434 o->WD(
"Minimum", hp.
minimum);
10435 o->WD(
"Maximum", hp.
maximum);
10444 std::vector<std::string> hist_vars;
10445 std::vector<std::string> hist_formula;
10446 std::vector<std::string> hist_colour;
10447 std::vector<std::string> hist_label;
10448 std::vector<bool> hist_show_raw_value;
10449 std::vector<double> hist_factor;
10450 std::vector<double> hist_offset;
10451 std::vector<double> hist_voffset;
10453 for (
size_t i=0;
i<hp.
vars.size();
i++) {
10454 hist_vars.push_back(hp.
vars[
i].event_name +
":" + hp.
vars[
i].tag_name);
10455 hist_formula.push_back(hp.
vars[
i].formula);
10456 hist_colour.push_back(hp.
vars[
i].colour);
10457 hist_label.push_back(hp.
vars[
i].label);
10458 hist_show_raw_value.push_back(hp.
vars[
i].show_raw_value);
10459 hist_factor.push_back(hp.
vars[
i].factor);
10460 hist_offset.push_back(hp.
vars[
i].offset);
10461 hist_voffset.push_back(hp.
vars[
i].voffset);
10464 if (hp.
vars.size() > 0) {
10465 o->WSA(
"Variables", hist_vars, 64);
10466 o->WSA(
"Formula", hist_formula, 64);
10469 o->WBA(
"Show raw value", hist_show_raw_value);
10470 o->WDA(
"Factor", hist_factor);
10471 o->WDA(
"Offset", hist_offset);
10472 o->WDA(
"VOffset", hist_voffset);
10474 o->Delete(
"Variables");
10475 o->Delete(
"Formula");
10476 o->Delete(
"Colour");
10477 o->Delete(
"Label");
10478 o->Delete(
"Show raw value");
10479 o->Delete(
"Factor");
10480 o->Delete(
"Offset");
10481 o->Delete(
"VOffset");
10492 bool something_deleted =
false;
10493 for (
unsigned i=0;
i<hp.
vars.size();
i++) {
10494 if (hp.
vars[
i].order <= 0) {
10496 something_deleted =
true;
10499 if (!something_deleted)
10508 bool need_sort =
false;
10509 for (
size_t i=1;
i<hp.
vars.size();
i++) {
10510 if (hp.
vars[
i-1].order >= hp.
vars[
i].order) {
10528 int max_display_events = 20;
10529 int max_display_tags = 200;
10530 char str[256], hcmd[256];
10532 odb->RI(
"History/MaxDisplayEvents", &max_display_events,
true);
10533 odb->RI(
"History/MaxDisplayTags", &max_display_tags,
true);
10535 mstrlcpy(hcmd, p->
getparam(
"hcmd"),
sizeof(hcmd));
10539 strcpy(hcmd,
"Refresh");
10559 if (strlen(p->
getparam(
"seln")) > 0)
10570 sprintf(
str,
"?cmd=oldhistory&group=%s&panel=%s", hgroup, hpanel);
10579 r->
rsprintf(
"<table class=\"mtable\">");
10581 r->
rsprintf(
"<tr><th colspan=11 class=\"subStatusTitle\">History Panel \"%s\" / \"%s\"</th></tr>\n", hgroup, hpanel);
10584 r->
rsprintf(
"<tr><td colspan=11>\n");
10586 r->
rsprintf(
"<input type=button value=Refresh ");
10587 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">\n");
10589 r->
rsprintf(
"<input type=button value=Save ");
10590 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Save';document.form1.submit()\">\n");
10593 r->
rsprintf(
"<input type=button value=Cancel ");
10594 std::string url =
"?cmd=oldhistory&group=";
10598 url +=
"&hcmd=Cancel";
10603 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10606 r->
rsprintf(
"<input type=button value=\"Edit in ODB\"");
10607 std::string url =
"?cmd=odb&odb_path=";
10608 url +=
"/History/Display/";
10612 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10615 r->
rsprintf(
"<input type=button value=\"Edit in new editor\"");
10616 std::string url =
"?cmd=hs_edit";
10625 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10627 r->
rsprintf(
"<input type=button value=\"Clear history cache\"");
10628 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Clear history cache';document.form1.submit()\">\n");
10629 r->
rsprintf(
"<input type=button value=\"Delete panel\"");
10630 r->
rsprintf(
"onclick=\"window.location.search='?cmd=oldhistory&group=%s&panel=%s&hcmd=Delete%%20panel'\">\n", hgroup, hpanel);
10633 r->
rsprintf(
"<tr><td colspan=11>\n");
10636 int sort_vars = *p->
getparam(
"sort_vars");
10637 r->
rsprintf(
"<input type=checkbox %s name=sort_vars value=1 onclick=\"this.form.submit();\">Sort variable names", sort_vars?
"checked":
"");
10640 int old_vars = *p->
getparam(
"old_vars");
10641 r->
rsprintf(
" <input type=checkbox %s name=old_vars value=1 onclick=\"this.form.submit();\">Show deleted and renamed variables", old_vars?
"checked":
"");
10644 r->
rsprintf(
" <input type=checkbox checked name=show_factor value=1 onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">");
10646 r->
rsprintf(
" <input type=checkbox name=show_factor value=1 onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">");
10647 r->
rsprintf(
"Show factor and offset\n");
10650 r->
rsprintf(
"<input type=hidden name=cmd value=Oldhistory>\n");
10651 r->
rsprintf(
"<input type=hidden name=hcmd value=Refresh>\n");
10652 r->
rsprintf(
"<input type=hidden name=panel value=\"%s\">\n", hpanel);
10653 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", hgroup);
10656 r->
rsprintf(
"<input type=hidden name=redir value=\"%s\">\n", p->
getparam(
"redir"));
10660 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Time scale (in units 'm', 'h', 'd'):</td>\n");
10661 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());
10663 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Minimum (set to '-inf' for autoscale):</td>\n");
10664 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=minimum value=%f></td><td colspan=4></td></tr>\n", hp.
minimum);
10666 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Maximum (set to 'inf' for autoscale):</td>\n");
10667 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=maximum value=%f></td><td colspan=4></td></tr>\n", hp.
maximum);
10669 r->
rsprintf(
"<tr><td colspan=11>");
10672 r->
rsprintf(
"<input type=checkbox checked name=zero_ylow value=1>");
10674 r->
rsprintf(
"<input type=checkbox name=zero_ylow value=1>");
10675 r->
rsprintf(
"Zero Y; axis\n");
10678 r->
rsprintf(
"<input type=checkbox checked name=log_axis value=1>");
10680 r->
rsprintf(
"<input type=checkbox name=log_axis value=1>");
10681 r->
rsprintf(
"Logarithmic Y axis\n");
10684 r->
rsprintf(
" <input type=checkbox checked name=run_markers value=1>");
10686 r->
rsprintf(
" <input type=checkbox name=run_markers value=1>");
10687 r->
rsprintf(
"Show run markers\n");
10690 r->
rsprintf(
" <input type=checkbox checked name=show_values value=1>");
10692 r->
rsprintf(
" <input type=checkbox name=show_values value=1>");
10693 r->
rsprintf(
"Show values of variables\n");
10696 r->
rsprintf(
" <input type=checkbox checked name=show_fill value=1>");
10698 r->
rsprintf(
" <input type=checkbox name=show_fill value=1>");
10699 r->
rsprintf(
"Show graph fill\n");
10713 time_t t = time(NULL);
10718 std::vector<std::string> events;
10723 if (events.size() == 0)
10727 for (
unsigned i=0;
i<events.size();
i++)
10728 printf(
"event %d: \"%s\"\n",
i, events[
i].c_str());
10733 std::sort(events.begin(), events.end(),
cmp_events1);
10735 if (strlen(p->
getparam(
"cmdx")) > 0) {
10736 r->
rsprintf(
"<tr><th colspan=8 class=\"subStatusTitle\">List of available history variables</th></tr>\n");
10737 r->
rsprintf(
"<tr><th colspan=1>Sel<th colspan=1>Equipment<th colspan=1>Event<th colspan=1>Variable</tr>\n");
10739 std::string cmdx = p->
xgetparam(
"cmdx");
10740 std::string xeqname;
10743 for (
unsigned e=0;
e<events.size();
e++) {
10744 std::string eqname;
10745 eqname = events[
e].substr(0, events[
e].find(
"/"));
10747 if (eqname.length() < 1)
10748 eqname = events[
e];
10751 if (eqname != xeqname)
10754 std::string qcmd =
"Expand " + eqname;
10758 bool collapsed =
true;
10763 if (strlen(p->
getparam(qcmd.c_str())) > 0)
10767 if (eqname == xeqname)
10772 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10773 r->
rsprintf(
"<td><input type=submit name=cmdx value=\"%s\"></td>\n", qcmd.c_str());
10781 r->
rsprintf(
"<tr><input type=hidden name=\"%s\" value=%d></tr>\n", qcmd.c_str(), 1);
10783 std::string rcmd =
"Expand " + events[
e];
10792 if (strlen(p->
getparam(rcmd.c_str())) > 0)
10798 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10799 r->
rsprintf(
"<td>%s</td>\n", events[
e].c_str());
10800 r->
rsprintf(
"<td><input type=submit name=cmdx value=\"%s\"></td>\n", rcmd.c_str());
10805 r->
rsprintf(
"<tr><input type=hidden name=\"%s\" value=%d></tr>\n", rcmd.c_str(), 1);
10809 std::vector<TAG> tags;
10816 std::sort(tags.begin(), tags.end(),
cmp_tags);
10818 for (
unsigned v=0; v<tags.size(); v++) {
10820 for (
unsigned j=0;
j<tags[v].n_data;
j++) {
10823 if (tags[v].n_data == 1)
10824 sprintf(tagname,
"%s", tags[v].
name);
10826 sprintf(tagname,
"%s[%d]", tags[v].
name,
j);
10828 bool checked =
false;
10839 r->
rsprintf(
"<td><input type=checkbox %s name=\"sel%d\" value=\"%s:%s\"></td>\n", checked?
"checked":
"",
i++, events[
e].c_str(), tagname);
10840 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10841 r->
rsprintf(
"<td>%s</td>\n", events[
e].c_str());
10842 r->
rsprintf(
"<td>%s</td>\n", tagname);
10852 r->
rsprintf(
"<input type=hidden name=seln value=%d>\n",
i);
10853 r->
rsprintf(
"<input type=submit value=\"Add Selected\">\n");
10858 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>New history: displayed_value = formula(history_value)</td></tr>\n");
10859 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>Old history: displayed_value = offset + factor*(history_value - voffset)</td></tr>\n");
10860 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");
10861 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");
10862 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");
10863 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");
10866 r->
rsprintf(
"<th>Col<th>Event<th>Variable<th>Formula<th>Colour<th>Label<th>Raw<th>Order");
10868 r->
rsprintf(
"<th>Factor<th>Offset<th>VOffset");
10874 size_t nvars = hp.
vars.size();
10879 if (
index < nvars) {
10882 r->
rsprintf(
"<td style=\"background-color:%s\"> <td>\n", hp.
vars[
index].colour.c_str());
10889 r->
rsprintf(
"<select name=\"event%d\" size=1 onChange=\"document.form1.submit()\">\n", (
int)
index);
10894 r->
rsprintf(
"<option value=\"/empty\"><empty>\n");
10896 if (
index==nvars) {
10897 for (
unsigned e=0;
e<events.size();
e++) {
10898 const char *p = events[
e].c_str();
10899 r->
rsprintf(
"<option value=\"%s\">%s\n", p, p);
10901 }
else if ((
int)events.size() > max_display_events) {
10903 r->
rsprintf(
"<option>(%d events omitted)\n", (
int)events.size());
10905 bool found =
false;
10906 for (
unsigned e=0;
e<events.size();
e++) {
10907 const char *s =
"";
10908 const char *p = events[
e].c_str();
10913 r->
rsprintf(
"<option %s value=\"%s\">%s\n", s, p, p);
10916 const char *p = hp.
vars[
index].event_name.c_str();
10917 r->
rsprintf(
"<option selected value=\"%s\">%s\n", p, p);
10926 if (
index < nvars) {
10927 bool found_tag =
false;
10928 std::string selected_tag = hp.
vars[
index].tag_name;
10932 std::vector<TAG> tags;
10939 printf(
"Compare %d\n",
cmp_names(
"AAA",
"BBB"));
10940 printf(
"Compare %d\n",
cmp_names(
"BBB",
"AAA"));
10941 printf(
"Compare %d\n",
cmp_names(
"AAA",
"AAA"));
10942 printf(
"Compare %d\n",
cmp_names(
"A",
"AAA"));
10943 printf(
"Compare %d\n",
cmp_names(
"A111",
"A1"));
10944 printf(
"Compare %d\n",
cmp_names(
"A111",
"A2"));
10945 printf(
"Compare %d\n",
cmp_names(
"A111",
"A222"));
10946 printf(
"Compare %d\n",
cmp_names(
"A111a",
"A111b"));
10950 std::sort(tags.begin(), tags.end(),
cmp_tags);
10953 printf(
"Event [%s] %d tags\n", hp.
vars[
index].event_name.c_str(), (
int)tags.size());
10955 for (
unsigned v=0; v<tags.size(); v++) {
10956 printf(
"tag[%d] [%s]\n", v, tags[v].
name);
10960 unsigned count_tags = 0;
10961 for (
unsigned v=0; v<tags.size(); v++)
10962 count_tags += tags[v].n_data;
10966 if ((
int)count_tags < max_display_tags) {
10967 for (
unsigned v=0; v<tags.size(); v++) {
10969 for (
unsigned j=0;
j<tags[v].n_data;
j++) {
10970 std::string tagname;
10972 if (tags[v].n_data == 1)
10973 tagname = tags[v].name;
10976 sprintf(buf,
"[%d]",
j);
10977 tagname = std::string(tags[v].
name) + buf;
10980 if (
equal_ustring(selected_tag.c_str(), tagname.c_str())) {
10981 r->
rsprintf(
"<option selected value=\"%s\">%s\n", tagname.c_str(), tagname.c_str());
10985 r->
rsprintf(
"<option value=\"%s\">%s\n", tagname.c_str(), tagname.c_str());
10994 if (hp.
vars[
index].tag_name.length() > 0)
10998 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());
10999 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());
11002 r->
rsprintf(
"<td><input type=checkbox checked name=\"raw%d\" value=1></td>", (
int)
index);
11004 r->
rsprintf(
"<td><input type=checkbox name=\"raw%d\" value=1></td>", (
int)
index);
11005 r->
rsprintf(
"<td><input type=text size=3 maxlength=32 name=\"ord%d\" value=\"%d\"></td>\n", (
int)
index, hp.
vars[
index].order);
11007 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"factor%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].factor);
11008 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"offset%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].offset);
11009 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"voffset%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].voffset);
11013 r->
rsprintf(
"<input type=hidden name=\"voffset%d\" value=\"%f\">\n", (
int)
index, hp.
vars[
index].voffset);
11016 r->
rsprintf(
"<td colspan=2><input type=submit name=cmdx value=\"List all variables\"></td>\n");
11026 r->
rsprintf(
"</body></html>\r\n");
11046 sprintf(
str,
"/History/Display/%s/%s", group, panel);
11049 sprintf(
str,
"Cannot find /History/Display/%s/%s in ODB\n", group, panel);
11055 BOOL runmarker = 1;
11056 size =
sizeof(runmarker);
11061 std::string
ts =
"1h";
11086 time_t starttime = endtime - scale;
11093 sprintf(
str,
"History error, status %d\n",
status);
11101 int *i_var = (
int *)malloc(
sizeof(
int)*hsdata->
nvars);
11103 assert(i_var != NULL);
11105 for (
int i = 0;
i < hsdata->
nvars;
i++)
11111 for (
int i = 0;
i < hsdata->
nvars;
i++)
11114 if ((t == 0) || (hsdata->
t[
i][0] > t))
11115 t = hsdata->
t[
i][0];
11117 if (t == 0 && hsdata->
nvars > 1) {
11118 show_error(r,
"No history available for choosen period");
11123 int run_index = -1;
11124 int state_index = -1;
11125 int n_run_number = 0;
11126 time_t* t_run_number = NULL;
11128 for (
int i = 0;
i < hsdata->
nvars;
i++) {
11131 t_run_number = hsdata->
t[
i];
11141 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
11143 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
11144 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
11145 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
11146 r->
rsprintf(
"Content-Type: text/plain\r\n");
11147 r->
rsprintf(
"Content-disposition: attachment; filename=\"export.csv\"\r\n");
11152 r->
rsprintf(
"Time, Timestamp, Run, Run State, ");
11156 for (
int i = 0, first = 1;
i < hsdata->
nvars;
i++) {
11173 printf(
"hsdata %p, t %d, irun %d\n", hsdata, (
int)t, i_run);
11177 while (i_run < n_run_number-1 && t_run_number[i_run+1] <= t)
11183 for (
int i = 0;
i < hsdata->
nvars;
i++)
11189 for (
int i = 0 ;
i < hsdata->
nvars ;
i++)
11196 printf(
"step to time %d: ", (
int)t);
11197 for (
int i = 0;
i < hsdata->
nvars;
i++) {
11200 printf(
" done: %d\n",
done);
11207 localtime_r(&t, &tms);
11211 strcpy(fmt,
"%Y.%m.%d %H:%M:%S");
11213 strftime(
str,
sizeof(
str), fmt, &tms);
11215 if (t_run_number && run_index>=0 && state_index>=0) {
11216 if (t_run_number[i_run] <= t)
11217 r->
rsprintf(
"%s, %d, %.0f, %.0f, ",
str, (
int)t, hsdata->
v[run_index][i_run], hsdata->
v[state_index][i_run]);
11224 for (
int i= 0 ;
i < hsdata->
nvars ;
i++)
11225 printf(
" %d (%g)", i_var[
i], hsdata->
v[
i][i_var[
i]]);
11229 for (
int i=0, first=1 ;
i<hsdata->
nvars ;
i++) {
11244 for (
int i = 0 ;
i < hsdata->
nvars ;
i++)
11246 int xdt = hsdata->
t[
i][i_var[
i]+1] - t;
11248 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);
11249 if (dt <= 0 || xdt < dt)
11254 printf(
"dt %d\n", dt);
11270 HNDLE hDB, hkey, hikeyp, hkeyp, hkeybutton;
11273 char hgroup[256], hpanel[256], hcmd[256];
11274 const char def_button[][
NAME_LENGTH] = {
"10m",
"1h",
"3h",
"12h",
"24h",
"3d",
"7d" };
11278 hcmd[0] = hgroup[0] = hpanel[0] = 0;
11281 mstrlcpy(hgroup, p->
getparam(
"group"),
sizeof(hgroup));
11283 mstrlcpy(hpanel, p->
getparam(
"panel"),
sizeof(hpanel));
11285 mstrlcpy(hcmd, p->
getparam(
"hcmd"),
sizeof(hcmd));
11290 redir +=
"?cmd=oldhistory&group=";
11292 redir +=
"&panel=";
11309 redir +=
"?cmd=oldhistory&group=";
11311 redir +=
"&panel=";
11330 r->
rsprintf(
"<table class=\"dialogTable\">");
11331 r->
rsprintf(
"<tr><th class=\"subStatusTitle\" colspan=2>New History Item</th><tr>");
11332 r->
rsprintf(
"<tr><td align=center colspan=2>\n");
11333 r->
rsprintf(
"Select group: ");
11334 r->
rsprintf(
"<select id=\"group\" name=\"group\">\n");
11340 for (
i = 0;;
i++) {
11353 if (!hkey ||
i == 0)
11354 r->
rsprintf(
"<option>Default</option>\n");
11357 r->
rsprintf(
"Or enter new group name: ");
11358 r->
rsprintf(
"<input type=text size=15 maxlength=31 id=new_group name=new_group>\n");
11360 r->
rsprintf(
"<tr><td align=center colspan=2>\n");
11361 r->
rsprintf(
"<br>Panel name: ");
11362 r->
rsprintf(
"<input type=text size=15 maxlength=31 id=panel name=panel><br><br>\n");
11365 r->
rsprintf(
"<tr><td align=center colspan=2>");
11366 std::string
str =
"?cmd=oldhistory&hcmd=createnew";
11367 str +=
"&new_group='+document.getElementById('new_group').value+'";
11368 str +=
"&group='+document.getElementById('group').value+'";
11369 str +=
"&panel='+document.getElementById('panel').value+'";
11370 r->
rsprintf(
"<input type=button value=Submit onclick=\"window.location.search='%s'\">\n",
str.c_str());
11376 r->
rsprintf(
"</body></html>\r\n");
11383 path +=
"/History/Display/";
11395 while (hpanel[0] ==
' ') {
11397 mstrlcpy(
str, hpanel+1,
sizeof(
str));
11398 mstrlcpy(hpanel,
str,
sizeof(hpanel));
11400 while (strlen(hpanel)> 1 && hpanel[strlen(hpanel)-1] ==
' ')
11401 hpanel[strlen(hpanel)-1] = 0;
11405 mstrlcpy(hgroup, p->
getparam(
"new_group"),
sizeof(hgroup));
11412 const char* pscale = p->
getparam(
"scale");
11413 if (pscale == NULL || *pscale == 0)
11415 const char* pwidth = p->
getparam(
"width");
11416 if (pwidth == NULL || *pwidth == 0)
11418 const char* pheight = p->
getparam(
"height");
11419 if (pheight == NULL || *pheight == 0)
11421 const char* pindex = p->
getparam(
"index");
11422 if (pindex == NULL || *pindex == 0)
11429 std::string bgcolor =
"FFFFFF";
11433 std::string fgcolor =
"000000";
11437 std::string gridcolor =
"A0A0A0";
11443 time_t endtime = 0;
11446 else if (p->
isparam(
"htime"))
11449 if (pscale && *pscale)
11455 if (pindex && *pindex)
11456 index = atoi(pindex);
11468 char* fbuffer = (
char*)
M_MALLOC(fsize);
11469 assert(fbuffer != NULL);
11480 }
else if (atoi(pmag) > 0) {
11481 width = atoi(pmag);
11486 generate_hist_graph(odb, r, hgroup, hpanel, fbuffer, &fsize, width, height, endtime, scale,
index, labels, bgcolor.c_str(), fgcolor.c_str(), gridcolor.c_str());
11491 if (dir.length() > 0 && dir[dir.length()-1] !=
DIR_SEPARATOR)
11494 time_t now = time(NULL);
11495 localtime_r(&now, &tms);
11498 tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday,
11499 tms.tm_hour, tms.tm_min, tms.tm_sec, hpanel);
11503 fh = open(fname.c_str(), O_CREAT | O_RDWR |
O_BINARY, 0644);
11505 cm_msg(
MERROR,
"show_hist_page",
"Cannot write attachment file \"%s\", open() errno %d (%s)", fname.c_str(), errno, strerror(errno));
11507 int wr =
write(fh, fbuffer, fsize);
11509 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));
11515 if (strlen(url) > 1 && url[strlen(url)-1] !=
'/')
11516 mstrlcat(url,
"/",
sizeof(url));
11517 mstrlcat(url,
"?cmd=New&fa=",
sizeof(url));
11526 std::string
str =
msprintf(
"\\HS\\%s.gif", hpanel);
11530 if (strchr(
str.c_str(),
'?'))
11544 if (strchr(
str.c_str(),
'?'))
11551 if (strchr(
str.c_str(),
'?'))
11558 show_elog_new(r, hpanel, NULL,
FALSE,
str.c_str(),
"../../EL/");
11569 if (strstr(dec_path,
".gif")) {
11578 }
else if (atoi(pwidth) > 0) {
11579 width = atoi(pwidth);
11580 if (atoi(pheight) > 0)
11581 height = atoi(pheight);
11583 height = (int)(0.625 * width);
11588 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());
11596 time_t now = time(NULL);
11602 time_t last_written = 0;
11605 endtime = last_written + scale/2;
11611 time_t last_written = 0;
11614 if (last_written != endtime)
11615 endtime = last_written + scale/2;
11621 endtime -= scale/2;
11628 endtime += scale/2;
11640 endtime -= scale / 4;
11647 endtime += scale / 2;
11653 int xrefresh = refresh;
11658 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
11659 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
11662 r->
rsprintf(
"<table class=\"mtable\">");
11663 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>History</th></tr>");
11669 path +=
"/History/Display/";
11675 r->
rsprintf(
"<h1>Error: History panel \"%s\" in group \"%s\" does not exist</h1>\n", hpanel, hgroup);
11679 r->
rsprintf(
"</body></html>\r\n");
11685 if (pscale && *pscale)
11686 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%d>\n", scale);
11689 if (hpanel[0] && !
equal_ustring(hpanel,
"All") && hgroup[0]) {
11691 path +=
"/History/Display/";
11695 path +=
"/Timescale";
11697 std::string scalestr =
"1h";
11706 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%s>\n", scalestr.c_str());
11713 if (pwidth && *pwidth)
11714 r->
rsprintf(
"<input type=hidden name=hwidth id=hwidth value=%s>\n", pwidth);
11715 if (pheight && *pheight)
11716 r->
rsprintf(
"<input type=hidden name=hheight id=hheight value=%s>\n", pheight);
11717 if (pindex && *pindex)
11718 r->
rsprintf(
"<input type=hidden name=hindex id=hindex value=%s>\n", pindex);
11722 if (hgroup[0] == 0) {
11724 r->
rsprintf(
"<tr><td colspan=2><input type=\"button\" name=\"New\" value=\"New\" ");
11725 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New'\"></td></tr>\n");
11728 r->
rsprintf(
"<tr><td colspan=2 style=\"text-align:left;\">\n");
11730 r->
rsprintf(
"<b>Please select panel:</b><br>\n");
11733 r->
rsprintf(
"<table class=\"historyTable\">");
11736 r->
rsprintf(
"<tr><td colspan=2 class=\"titleCell\">\n");
11740 r->
rsprintf(
"<a href=\"?cmd=oldhistory&group=All\">ALL</a>\n");
11748 strcpy(
str,
"System:Trigger per sec.");
11768 for (
i = 0;;
i++) {
11777 char enc_name[256];
11778 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11784 r->
rsprintf(
"<tr><td class=\"titleCell\"><a href=\"?cmd=oldhistory&group=%s\">%s</a></td>\n<td>", enc_name,
key.
name);
11786 for (
j = 0;;
j++) {
11797 char enc_iname[256];
11798 mstrlcpy(enc_iname, ikey.
name,
sizeof(enc_iname));
11799 urlEncode(enc_iname,
sizeof(enc_iname));
11802 r->
rsprintf(
"<small><b>%s</b></small> ", ikey.
name);
11804 r->
rsprintf(
"<small><a href=\"?cmd=oldhistory&group=%s&panel=%s\">%s</a></small> \n", enc_name, enc_iname, ikey.
name);
11815 r->
rsprintf(
"<tr><td colspan=2>\n");
11819 r->
rsprintf(
"<select title=\"Select group\" id=\"fgroup\" onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value;\">\n");
11824 for (
i = 0;;
i++) {
11844 r->
rsprintf(
"<option selected value=\"%s\">%s\n",
"ALL",
"ALL");
11846 r->
rsprintf(
"<option value=\"%s\">%s\n",
"ALL",
"ALL");
11850 r->
rsprintf(
" Panel:\n");
11851 r->
rsprintf(
"<select title=\"Select panel\" id=\"fpanel\" ");
11852 r->
rsprintf(
"onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value+");
11853 r->
rsprintf(
"'&panel='+document.getElementById('fpanel').value;\">\n");
11857 for (
i = 0;;
i++) {
11876 r->
rsprintf(
"<option value=\"\">- all -\n");
11878 r->
rsprintf(
"<option selected value=\"\">- all -\n");
11884 r->
rsprintf(
"<input type=submit value=\"Go\">\n");
11887 r->
rsprintf(
" <input type=\"button\" name=\"New\" value=\"New\" ");
11888 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New&group=%s'\">\n", hgroup);
11890 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Reset\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Reset&group=%s&panel=%s'\">\n", hgroup, hpanel);
11892 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Query\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Query&group=%s&panel=%s'\">\n", hgroup, hpanel);
11894 double xendtime = endtime;
11897 double xstarttime = xendtime - scale;
11899 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);
11907 if (hgroup[0] && !
equal_ustring(hgroup,
"ALL") && hpanel[0] == 0) {
11908 std::string strwidth =
"Small";
11912 path +=
"/History/Display/";
11916 for (
i = 0 ;;
i++) {
11924 char enc_name[256];
11925 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11929 ref +=
"graph.gif?width=";
11931 ref +=
"&cmd=oldhistory&group=";
11937 ref2 +=
"?cmd=oldhistory&group=";
11942 if (endtime != 0) {
11944 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
11952 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
11954 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
11958 r->
rsprintf(
"Group \"%s\" not found", hgroup);
11968 path +=
"/History/Display/";
11972 path +=
"/Buttons";
11974 if (hkeybutton == 0) {
11979 cm_msg(
MERROR,
"show_hist_page",
"Cannot create history panel with invalid ODB path \"%s\"", path.c_str());
11986 r->
rsprintf(
"function histDisp(p) {\n");
11987 r->
rsprintf(
" var params = '?cmd=oldhistory&group=%s&panel=%s';\n", hgroup, hpanel);
11988 r->
rsprintf(
" params += '&'+p;\n");
11989 r->
rsprintf(
" if (document.getElementById(\'hscale\') !== null)\n");
11990 r->
rsprintf(
" params += '&hscale='+document.getElementById(\'hscale\').value;\n");
11991 r->
rsprintf(
" if (document.getElementById(\'htime\') !== null)\n");
11992 r->
rsprintf(
" params += '&htime='+document.getElementById(\'htime\').value;\n");
11993 r->
rsprintf(
" if (document.getElementById(\'hwdith\') !== null)\n");
11994 r->
rsprintf(
" params += '&hwidth='+document.getElementById(\'hwidth\').value;\n");
11995 r->
rsprintf(
" if (document.getElementById(\'hindex\') !== null)\n");
11996 r->
rsprintf(
" params += '&hindex='+document.getElementById(\'hindex\').value;\n");
11997 r->
rsprintf(
" window.location.search = params;\n");
12005 size =
sizeof(
str);
12007 r->
rsprintf(
"<input type=\"button\" title=\"display last %s\" value=%s onclick=\"histDisp('scale=%s')\">\n",
str,
str,
str);
12010 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')\">");
12011 r->
rsprintf(
"<input type=\"button\" value=\"<<\" title=\"go back in time to last available data\" onclick=\"histDisp('shift=leftmax')\">");
12012 r->
rsprintf(
"<input type=\"button\" value=\"<\" title=\"go back in time\" onclick=\"histDisp('shift=left')\">");
12014 r->
rsprintf(
"<input type=\"button\" value=\" + \" title=\"zoom in\" onclick=\"histDisp('shift=zoomin')\">");
12015 r->
rsprintf(
"<input type=\"button\" value=\" - \" title=\"zoom out\" onclick=\"histDisp('shift=zoomout')\">");
12017 if (endtime != 0) {
12018 r->
rsprintf(
"<input type=\"button\" value=\">\" title=\"go forward in time\" onclick=\"histDisp('shift=right')\">");
12019 r->
rsprintf(
"<input type=\"button\" value=\">>\" title=\"go to currently updated fresh data\" onclick=\"histDisp('shift=rightmax')\">");
12023 r->
rsprintf(
"<input type=\"button\" value=\"Large\" title=\"large display\" onclick=\"histDisp('width=Large')\">\n");
12024 r->
rsprintf(
"<input type=\"button\" value=\"Small\" title=\"large display\" onclick=\"histDisp('width=Small')\">\n");
12025 r->
rsprintf(
"<input type=\"button\" value=\"Create Elog\" title=\"large display\" onclick=\"histDisp('hcmd=Create Elog')\">\n");
12026 r->
rsprintf(
"<input type=\"button\" value=\"Config\" title=\"large display\" onclick=\"histDisp('hcmd=Config')\">\n");
12027 r->
rsprintf(
"<input type=\"button\" value=\"Export\" title=\"large display\" onclick=\"histDisp('hcmd=Export')\">\n");
12030 char paramstr[256];
12033 sprintf(paramstr + strlen(paramstr),
"&scale=%d", scale);
12035 sprintf(paramstr + strlen(paramstr),
"&time=%s",
time_to_string(endtime).c_str());
12036 if (pwidth && *pwidth)
12037 sprintf(paramstr + strlen(paramstr),
"&width=%s", pwidth);
12039 std::string wi =
"640";
12041 sprintf(paramstr + strlen(paramstr),
"&width=%s", wi.c_str());
12043 if (pheight && *pheight)
12044 sprintf(paramstr + strlen(paramstr),
"&height=%s", pheight);
12047 r->
rsprintf(
"<map name=\"%s\">\r\n", hpanel);
12049 if (!(pindex && *pindex)) {
12051 path +=
"/History/Display/";
12055 path +=
"/Variables";
12068 ref +=
"?cmd=oldhistory&group=";
12079 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());
12083 std::string ref =
"?cmd=oldhistory&group=";
12097 else if (atoi(pwidth) > 0)
12098 width = atoi(pwidth);
12102 r->
rsprintf(
" <area shape=rect coords=\"%d,%d,%d,%d\" href=\"%s\">\r\n", 0, 0, width, 20, ref.c_str());
12108 if (pindex && *pindex)
12109 sprintf(paramstr + strlen(paramstr),
"&index=%s", pindex);
12113 ref +=
"graph.gif?cmd=oldhistory&group=";
12120 r->
rsprintf(
"<tr><td colspan=2><img src=\"%s\" usemap=\"#%s\"></tr>\n", ref.c_str(), hpanel);
12127 for (
i = 0,
k = 0;;
i++) {
12135 char enc_group_name[256];
12136 mstrlcpy(enc_group_name,
key.
name,
sizeof(enc_group_name));
12137 urlEncode(enc_group_name,
sizeof(enc_group_name));
12139 for (
j = 0;;
j++,
k++) {
12148 char enc_panel_name[256];
12149 mstrlcpy(enc_panel_name, ikey.
name,
sizeof(enc_panel_name));
12150 urlEncode(enc_panel_name,
sizeof(enc_panel_name));
12153 ref +=
"graph.gif?width=Small";
12154 ref +=
"&cmd=oldhistory&group=";
12155 ref += enc_group_name;
12157 ref += enc_panel_name;
12160 ref2 +=
"?cmd=oldhistory&group=";
12161 ref2 += enc_group_name;
12163 ref2 += enc_panel_name;
12165 if (endtime != 0) {
12167 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
12175 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
12177 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
12184 r->
rsprintf(
"</body></html>\r\n");
12193 const unsigned char *picon;
12194 char str[256], format[256];
12197 if (strstr(icon,
"favicon.ico") != 0) {
12200 }
else if (strstr(icon,
"favicon.png") != 0) {
12206 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
12208 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
12212 now += (int) (3600 * 24);
12214 gmtime_r(&now, &gmt_tms);
12215 strcpy(format,
"%A, %d-%b-%y %H:%M:%S GMT");
12216 strftime(
str,
sizeof(
str), format, &gmt_tms);
12220 r->
rsprintf(
"Content-Type: image/x-icon\r\n");
12222 r->
rsprintf(
"Content-Type: image/png\r\n");
12224 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
12270 if (strstr(dec_path,
"favicon.ico") != 0 ||
12271 strstr(dec_path,
"favicon.png")) {
12276 const char* password = p->
getparam(
"pwd");
12277 const char* wpassword = p->
getparam(
"wpwd");
12278 const char* command = p->
getparam(
"cmd");
12301 if (!password[0] && hkey) {
12303 int size =
sizeof(
str);
12307 db_find_key(
hDB, 0,
"/Experiment/Security/Allowed programs/mhttpd", &hkey);
12308 if (hkey == 0 && strcmp(
c->cookie_pwd.c_str(),
str) != 0) {
12319 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12328 gmtime_r(&now, &gmt_tms);
12331 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12333 r->
rsprintf(
"Set-Cookie: midas_pwd=%s; path=/; expires=%s\r\n",
12336 r->
rsprintf(
"Location: ./\n\n<html>redir</html>\r\n");
12340 if (wpassword[0]) {
12345 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12354 gmtime_r(&now, &gmt_tms);
12357 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:%M:%S GMT", &gmt_tms);
12359 r->
rsprintf(
"Set-Cookie: midas_wpwd=%s; path=/; expires=%s\r\n",
ss_crypt(wpassword,
"mi"),
str);
12362 r->
rsprintf(
"Location: %s\n\n<html>redir</html>\r\n",
str);
12368 if (strlen(dec_path) > 3 &&
12369 dec_path[strlen(dec_path)-3] ==
'm' &&
12370 dec_path[strlen(dec_path)-2] ==
'p' &&
12371 dec_path[strlen(dec_path)-1] ==
'3') {
12372 if (strrchr(dec_path,
'/'))
12381 if (strstr(dec_path,
"midas.js")) {
12386 if (strstr(dec_path,
"midas.css")) {
12393 if (strstr(dec_path,
"mhttpd.js")) {
12400 if (strstr(dec_path,
"obsolete.js")) {
12407 if (strstr(dec_path,
"mhttpd.css")) {
12414 if (strstr(dec_path,
"controls.js")) {
12447 path +=
"/Script/";
12473 path +=
"/CustomScript/";
12474 path += p->
getparam(
"customscript");
12501 std::string filename = custom[
"Status"];
12545 !(dec_path[0] ==
'H' && dec_path[1] ==
'S' && dec_path[2] ==
'/')) {
12661 show_mscb_page(p, r,
c->refresh);
12663 show_error(r,
"MSCB support not compiled into this version of mhttpd");
12681 if (strncmp(command,
"Trigger", 7) == 0) {
12694 mstrlcpy(eq_name, command + 8,
sizeof(eq_name));
12695 if (strchr(eq_name,
' '))
12696 *strchr(eq_name,
' ') = 0;
12700 path +=
"/Equipment/";
12702 path +=
"/Common/Frontend name";
12709 path +=
"/Equipment/";
12711 path +=
"/Common/Event ID";
12718 str +=
"Frontend \"";
12720 str +=
"\" not running!";
12727 str +=
"Cannot connect to frontend \"";
12749 if (strncmp(command,
"Next Subrun", 11) == 0) {
12770 mstrlcpy(
str,
"?cmd=set",
sizeof(
str));
12774 const char* group = p->
getparam(
"group");
12796 if (
equal_ustring(command,
"CNAF") || strncmp(dec_path,
"CNAF", 4) == 0) {
12812 std::string external_elog_url;
12813 int size =
sizeof(external_elog);
12816 if (external_elog && (external_elog_url.length() > 0)) {
12817 redirect(r, external_elog_url.c_str());
12827 mstrlcpy(cmdx, command,
sizeof(cmdx));
12836 if (
equal_ustring(command,
"Create ELog from this page")) {
12838 redir +=
"?cmd=New+elog";
12839 redir +=
"&odb_path=";
12862 int refresh = atoi(p->
getparam(
"refr"));
12865 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12872 now += 3600 * 24 * 365;
12875 gmtime_r(&now, &gmt_tms);
12878 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12880 r->
rsprintf(
"Set-Cookie: midas_refr=%d; path=/; expires=%s\r\n", refresh,
str);
12881 r->
rsprintf(
"Location: ./\r\n\r\n<html>redir</html>\r\n");
12928 int write_access =
TRUE;
12929 db_find_key(
hDB, 0,
"/Experiment/Security/Web Password", &hkey);
12932 int size =
sizeof(
str);
12934 if (strcmp(
c->cookie_wpwd.c_str(),
str) == 0)
12935 write_access =
TRUE;
12937 write_access =
FALSE;
12940 std::string odb_path;
12942 odb_path = p->
getparam(
"odb_path");
12973 if ((command[0]==0) && dec_path[0]) {
12975 std::string new_url =
"./?cmd=odb";
12982 if ((command[0]==0) && dec_path[0]) {
12988 for (
const char* s = dec_path; *s; s++) {
12992 std::string new_url;
12997 for (
int i=0;
i<level;
i++) {
13003 new_url +=
"?cmd=odb";
13004 new_url +=
"&odb_path=";
13031 std::string odb_path;
13036 odb_path +=
"/Custom/Images/";
13037 odb_path += dec_path;
13038 odb_path +=
"/Background";
13045 if (strstr(dec_path,
"..")) {
13047 str +=
"Invalid custom gif name \'";
13049 str +=
"\' contains \'..\'";
13060 bool found_custom =
false;
13063 odb_path +=
"/Custom/";
13064 odb_path += dec_path;
13071 found_custom =
true;
13074 odb_path +=
"/Custom/";
13075 odb_path += dec_path;
13083 found_custom =
true;
13086 odb_path +=
"/Custom/";
13087 odb_path += dec_path;
13095 found_custom =
true;
13100 if (found_custom) {
13102 if (strstr(dec_path,
"..")) {
13104 str +=
"Invalid custom page name \'";
13106 str +=
"\' contains \'..\'";
13121 std::string custom_path;
13124 if (strstr(dec_path,
"..")) {
13126 str +=
"Invalid custom file name \'";
13128 str +=
"\' contains \'..\'";
13152 if (strlen(p->
getparam(
"path")) > 0) {
13166 r->
rsprintf(
"HTTP/1.1 400 Bad Request\r\n");
13170 r->
rsprintf(
"Error: Invalid URL \"%s\" or query \"%s\" or command \"%s\"\n", p->
getparam(
"path"), p->
getparam(
"query"), command);
13177 int len = strlen(query_string);
13178 char *buf = (
char *)malloc(len+1);
13179 assert(buf != NULL);
13180 memcpy(buf, query_string, len+1);
13182 p = strtok(p,
"&");
13183 while (p != NULL) {
13185 p = strchr(p,
'=');
13194 p = strtok(NULL,
"&");
13208 param->initparam();
13211 mstrlcpy(path, url + 1,
sizeof(path));
13213 mstrlcpy(path,
string + 1,
sizeof(path));
13215 if (strchr(path,
'?'))
13216 *strchr(path,
'?') = 0;
13219 param->setparam(
"path", path);
13221 assert(query_string != NULL);
13225 param->setparam(
"query", query_string);
13227 char dec_path[256];
13228 mstrlcpy(dec_path, path,
sizeof(dec_path));
13232 param->freeparam();
13240 bool debug_decode_post =
false;
13249 mstrlcpy(path, url + 1,
sizeof(path));
13251 mstrlcpy(path, header + 1,
sizeof(path));
13252 if (strchr(path,
'?'))
13253 *strchr(path,
'?') = 0;
13254 if (strchr(path,
' '))
13255 *strchr(path,
' ') = 0;
13257 param->setparam(
"path", path);
13261 const char* pinit = string;
13267 if (strstr(
string, boundary))
13268 string = strstr(
string, boundary) + strlen(boundary);
13270 if (debug_decode_post)
13271 printf(
"decode_post: -->[%s]<--\n",
string);
13275 if (strstr(
string,
"name=")) {
13276 const char* pitem = strstr(
string,
"name=") + 5;
13277 if (*pitem ==
'\"')
13282 if (strncmp(pitem,
"attfile", 7) == 0) {
13283 int n = pitem[7] -
'1';
13289 if (strstr(pitem,
"filename=")) {
13290 const char* p = strstr(pitem,
"filename=") + 9;
13293 if (strstr(p,
"\r\n\r\n"))
13294 string = strstr(p,
"\r\n\r\n") + 4;
13295 else if (strstr(p,
"\r\r\n\r\r\n"))
13296 string = strstr(p,
"\r\r\n\r\r\n") + 6;
13301 if (strchr(pp,
'\"'))
13302 *strchr(pp,
'\"') = 0;
13306 sprintf(
str,
"attachment%d",
n);
13307 if (debug_decode_post)
13313 const char* ptmp = string;
13314 const char* p = NULL;
13316 while (*ptmp !=
'-')
13319 p = strstr(ptmp, boundary);
13330 ptmp += strlen(ptmp);
13337 char* buf = (
char*)malloc(size+1);
13341 memcpy(buf,
string, size);
13345 if (debug_decode_post)
13349 string = strstr(p, boundary) + strlen(boundary);
13351 const char* p = pitem;
13352 if (strstr(p,
"\r\n\r\n"))
13353 p = strstr(p,
"\r\n\r\n") + 4;
13354 else if (strstr(p,
"\r\r\n\r\r\n"))
13355 p = strstr(p,
"\r\r\n\r\r\n") + 6;
13357 char* ppitem = (
char*)strchr(pitem,
'\"');
13361 char* pb = (
char*)(strstr(p, boundary));
13363 string = pb + strlen(boundary);
13365 char* ptmp = (
char*)(p + (strlen(p) - 1));
13366 while (*ptmp ==
'-' || *ptmp ==
'\n' || *ptmp ==
'\r')
13372 if (debug_decode_post)
13373 printf(
"decode_post: [%s] = [%s]\n", pitem, p);
13374 param->setparam(pitem, p);
13377 while (*
string ==
'-' || *
string ==
'\n' || *
string ==
'\r')
13383 char dec_path[256];
13384 mstrlcpy(dec_path, path,
sizeof(dec_path));
13409 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo corrected successfully");
13411 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13415 cm_msg(
MERROR,
"check_odb_records",
"ODB subtree /Runinfo does not exist");
13418 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo created successfully");
13420 cm_msg(
MERROR,
"check_odb_records",
"Cannot create ODB subtree /Runinfo, db_create_record() status %d",
status);
13424 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13430 for (
i = 0 ;;
i++) {
13440 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Equipment/%s/Common corrected successfully",
key.
name);
13442 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13445 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13465#ifdef HAVE_MONGOOSE6
13466static std::vector<std::string> gUserAllowedHosts;
13469#ifdef HAVE_MONGOOSE6
13470static const std::string gOdbAllowedHosts =
"/Experiment/Security/mhttpd hosts/Allowed hosts";
13473#ifdef HAVE_MONGOOSE6
13477 cm_msg(
MINFO,
"load_allowed_hosts",
"Reloading mhttpd hosts access control list via hotlink callback");
13482 for (
unsigned int i=0;
i<gUserAllowedHosts.size();
i++)
13487 for (
int i=0; ;
i++) {
13496 if (s.length() < 1)
13509 if (
total - last < 5) {
13510 int new_size = last + 10;
13514 cm_msg(
MERROR,
"load_allowed_hosts",
"Cannot resize the allowed hosts access control list, db_resize_string(%d) status %d", new_size,
status);
13519static int init_allowed_hosts()
13533 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot create the mhttpd hosts access control list, db_get_value_string() status %d",
status);
13540 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot find the mhttpd hosts access control list, db_find_key() status %d",
status);
13544 load_allowed_hosts(
hDB, 0, 0, NULL);
13549 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot watch the mhttpd hosts access control list, db_watch() status %d",
status);
13556 int check_midas_acl(
const struct sockaddr *sa,
int len) {
13561 char hname[NI_MAXHOST];
13565 const char* status_string =
"success";
13567 status = getnameinfo(sa, len, hname,
sizeof(hname), NULL, 0, 0);
13570 status_string = gai_strerror(
status);
13575 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
status, status_string);
13580 if (strcmp(hname,
"localhost.localdomain") == 0)
13582 if (strcmp(hname,
"localhost") == 0)
13590 printf(
"Rejecting connection from \'%s\'\n", hname);
13594int open_listening_socket(
int port)
13597 struct sockaddr_in bind_addr;
13600 int lsock =
socket(AF_INET, SOCK_STREAM, 0);
13603 printf(
"Cannot create socket, socket() errno %d (%s)\n", errno, strerror(errno));
13608 memset(&bind_addr, 0,
sizeof(bind_addr));
13609 bind_addr.sin_family = AF_INET;
13610 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
13611 bind_addr.sin_port = htons((
short) port);
13615 status = setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (
char *) &flag,
sizeof(
INT));
13618 printf(
"Cannot setsockopt(SOL_SOCKET, SO_REUSEADDR), errno %d (%s)\n", errno, strerror(errno));
13622 status = bind(lsock, (
struct sockaddr *) &bind_addr,
sizeof(bind_addr));
13625 printf(
"Cannot bind() to port %d, bind() errno %d (%s)\n", port, errno, strerror(errno));
13632 printf(
"Cannot listen() on port %d, errno %d (%s), bye!\n", port, errno, strerror(errno));
13636 printf(
"mhttpd is listening on port %d\n", port);
13644int try_file_mg(
const char* try_dir,
const char* filename, std::string& path, FILE** fpp,
bool trace)
13650 if (strlen(try_dir) < 1)
13658 FILE*
fp = fopen(path.c_str(),
"r");
13662 printf(
"file \"%s\": OK!\n", path.c_str());
13664 printf(
"file \"%s\": not found.\n", path.c_str());
13677int find_file_mg(
const char* filename, std::string& path, FILE** fpp,
bool trace)
13694 try_file_mg(exptdir.c_str(), filename, path, NULL,
false);
13698#ifdef HAVE_MONGOOSE6
13702#ifdef HAVE_MONGOOSE616
13706extern void cs_md5(
char buf[33], ...);
13714#ifdef HAVE_MONGOOSE616
13715static bool multithread_mg =
true;
13718#ifdef HAVE_MONGOOSE6
13719static struct mg_mgr mgr_mg;
13743 if (!exptname.empty())
13761 size_t uri_len,
const char *ha1,
size_t ha1_len,
13762 const char *nonce,
size_t nonce_len,
const char *nc,
13763 size_t nc_len,
const char *cnonce,
size_t cnonce_len,
13764 const char *qop,
size_t qop_len,
char *resp) {
13765 static const char colon[] =
":";
13766 static const size_t one = 1;
13769 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
13770 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
13771 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
13772 colon, one, ha2,
sizeof(ha2) - 1, NULL);
13782 unsigned long now = (
unsigned long) time(NULL);
13783 unsigned long val = (
unsigned long) strtoul(nonce, NULL, 16);
13784 return now < val || now - val < 3600;
13793 const char *domain) {
13795 "HTTP/1.1 401 Unauthorized\r\n"
13796 "WWW-Authenticate: Digest qop=\"auth\", "
13797 "realm=\"%s\", nonce=\"%lu\"\r\n"
13798 "Content-Length: 0\r\n\r\n",
13799 domain, (
unsigned long) time(NULL));
13812 cm_msg(
MERROR,
"mongoose",
"mongoose web server cannot find password file \"%s\"", path.c_str());
13813 cm_msg(
MERROR,
"mongoose",
"please create password file: touch %s", path.c_str());
13817 bool have_realm =
false;
13825 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
13827 char f_domain[256];
13830 if (sscanf(buf,
"%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3) {
13833 e.username = f_user;
13834 e.password = f_ha1;
13836 if (
e.realm == auth->
realm) {
13848#ifdef HAVE_MONGOOSE6
13849std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13851 assert(!
"this code is untested!");
13857 if (buf_size == 0) {
13859 buf = (
char*)malloc(buf_size);
13860 assert(buf != NULL);
13870 if (size < buf_size) {
13871 std::string s = buf;
13876 buf_size = buf_size*2 + 16;
13877 buf = (
char*)realloc(buf, buf_size);
13878 assert(buf != NULL);
13883#ifdef HAVE_MONGOOSE616
13884std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13891 assert(buf != NULL);
13892 std::string s = buf;
13900 char expected_response[33];
13912 std::string user = find_var_mg(hdr,
"username");
13913 std::string cnonce = find_var_mg(hdr,
"cnonce");
13914 std::string
response = find_var_mg(hdr,
"response");
13915 std::string uri = find_var_mg(hdr,
"uri");
13916 std::string qop = find_var_mg(hdr,
"qop");
13917 std::string nc = find_var_mg(hdr,
"nc");
13918 std::string nonce = find_var_mg(hdr,
"nonce");
13920 if (user.length()<1)
return "";
13921 if (cnonce.length()<1)
return "";
13922 if (
response.length()<1)
return "";
13923 if (uri.length()<1)
return "";
13924 if (qop.length()<1)
return "";
13925 if (nc.length()<1)
return "";
13926 if (nonce.length()<1)
return "";
13933 const char* uri_end = strchr(hm->
uri.
p,
' ');
13934 if (!uri_end)
return "";
13936 size_t uri_length = uri_end - hm->
uri.
p;
13938 if (uri_length != uri.length())
13941 int cmp = strncmp(hm->
uri.
p, uri.c_str(), uri_length);
13950 if (
e->username != user)
13952 if (
e->realm != auth->
realm)
13954 const char* f_ha1 =
e->password.c_str();
13955 int uri_len = hm->
uri.
len;
13956 if (hm->
uri.
p[uri_len] ==
'?')
13959 hm->
uri.
p, uri_len,
13960 f_ha1, strlen(f_ha1),
13961 nonce.c_str(), nonce.length(),
13962 nc.c_str(), nc.length(),
13963 cnonce.c_str(), cnonce.length(),
13964 qop.c_str(), qop.length(),
13965 expected_response);
13966 int cmp = strcasecmp(
response.c_str(), expected_response);
13969 return e->username;
13976#ifdef HAVE_MONGOOSE616
13978struct HostlistCacheEntry
13980 time_t time_created = 0;
13981 time_t time_last_used = 0;
13982 int count_used = 0;
13985 uint32_t ipv4addr = 0;
13986 struct in6_addr ipv6addr;
13987 std::string hostname;
13988 int gai_status = 0;
13989 std::string gai_strerror;
13993static std::vector<HostlistCacheEntry*> gHostlistCache;
13995static void print_hostlist_cache()
13997 time_t now = time(NULL);
13999 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14000 HostlistCacheEntry*
e = gHostlistCache[
i];
14006 printf(
"%3d: %s \"%s\", ok %d, count_used %d, age created: %d, last_used %d",
14008 e->ipv4?
"IPv4":(
e->ipv6?
"IPv6":
"????"),
14009 e->hostname.c_str(),
14012 (int)(now -
e->time_created),
14013 (int)(now -
e->time_last_used));
14015 if (
e->gai_status) {
14016 printf(
", getnameinfo() status %d (%s)",
e->gai_status,
e->gai_strerror.c_str());
14023static bool mongoose_check_hostlist(
const union socket_address *sa)
14025 time_t now = time(NULL);
14028 uint32_t ipv4addr = 0;
14029 struct in6_addr ipv6addr;
14031 if (sa->
sa.sa_family == AF_INET) {
14033 ipv4addr = sa->
sin.sin_addr.s_addr;
14034 }
else if (sa->
sa.sa_family == AF_INET6) {
14036 memcpy(&ipv6addr, &sa->
sin6.sin6_addr,
sizeof(ipv6addr));
14038 printf(
"Rejecting connection from unknown address family %d (AF_xxx)\n", sa->
sa.sa_family);
14042 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14043 HostlistCacheEntry*
e = gHostlistCache[
i];
14049 if ((ipv4 ==
e->ipv4) && (ipv4addr ==
e->ipv4addr)) {
14051 e->time_last_used = now;
14056 if ((ipv6 ==
e->ipv6) && (memcmp(&ipv6addr, &
e->ipv6addr,
sizeof(ipv6addr)) == 0)) {
14058 e->time_last_used = now;
14065 if (
e->time_last_used < now - 24*60*60) {
14066 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);
14067 gHostlistCache[
i] = NULL;
14074 assert(ipv4 || ipv6);
14076 HostlistCacheEntry*
e =
new HostlistCacheEntry;
14078 bool found =
false;
14079 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14080 if (gHostlistCache[
i] == NULL) {
14081 gHostlistCache[
i] =
e;
14086 gHostlistCache.push_back(
e);
14089 e->time_created = now;
14090 e->time_last_used = now;
14095 e->ipv4addr = ipv4addr;
14097 memcpy(&
e->ipv6addr, &ipv6addr,
sizeof(ipv6addr));
14100 char hname[NI_MAXHOST];
14103 e->gai_status = getnameinfo(&sa->
sa,
sizeof(*sa), hname,
sizeof(hname), NULL, 0, 0);
14105 if (
e->gai_status) {
14106 e->gai_strerror = gai_strerror(
e->gai_status);
14108 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
e->gai_status,
e->gai_strerror.c_str());
14114 printf(
"connection from \"%s\"\n", hname);
14116 e->hostname = hname;
14119 if (
e->hostname ==
"localhost.localdomain")
14121 else if (
e->hostname ==
"localhost")
14132 printf(
"Rejecting connection from \'%s\'\n", hname);
14135 print_hostlist_cache();
14144 return std::string(s->
p, s->
len);
14149 size_t nlen = strlen(
name);
14163 if (cookies.length() < 1)
14165 const char* p = strstr(cookies.c_str(), cookie_name);
14168 const char* v = p+strlen(cookie_name);
14186 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> accept\n", nc, ev, ev_data);
14190 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);
14199 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> send %d bytes\n", nc, ev, ev_data, *(
int*)ev_data);
14203 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> close\n", nc, ev, ev_data);
14207 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
14216 char cookie_pwd[256];
14217 char cookie_wpwd[256];
14218 char cookie_cpwd[256];
14221 cookie_wpwd[0] = 0;
14222 cookie_cpwd[0] = 0;
14225 if (s.length() > 0) {
14226 mstrlcpy(cookie_pwd, s.c_str(),
sizeof(cookie_pwd));
14227 cookie_pwd[strcspn(cookie_pwd,
" ;\r\n")] = 0;
14232 mstrlcpy(cookie_wpwd, s.c_str(),
sizeof(cookie_pwd));
14233 cookie_wpwd[strcspn(cookie_wpwd,
" ;\r\n")] = 0;
14238 mstrlcpy(cookie_cpwd, s.c_str(),
sizeof(cookie_pwd));
14239 cookie_cpwd[strcspn(cookie_cpwd,
" ;\r\n")] = 0;
14245 if (s.length() > 0)
14246 c->refresh = atoi(s.c_str());
14254 c->cookie_pwd = cookie_pwd;
14255 c->cookie_wpwd = cookie_wpwd;
14256 c->cookie_cpwd = cookie_cpwd;
14259#define RESPONSE_SENT 1
14260#define RESPONSE_QUEUED 2
14261#define RESPONSE_501 3
14271#ifdef HAVE_MONGOOSE6
14286 decode_get(rr, NULL, &cookies, uri, query_string, t);
14295#ifdef HAVE_MONGOOSE6
14307#ifdef HAVE_MONGOOSE6
14327#ifdef HAVE_MONGOOSE616
14329static uint32_t s_ncseqno = 1;
14331struct MongooseNcUserData
14333 uint32_t ncseqno = 0;
14335 MongooseNcUserData()
14337 ncseqno = s_ncseqno++;
14341 ~MongooseNcUserData()
14353 const MongooseNcUserData* ncud = (
const MongooseNcUserData*)nc->
user_data;
14354 return ncud->ncseqno;
14357static uint32_t s_wseqno = 1;
14359struct MongooseWorkObject
14361 uint32_t wseqno = 0;
14363 uint32_t wncseqno = 0;
14364 bool http_get =
false;
14365 bool http_post =
false;
14366 bool mjsonrpc =
false;
14368 std::string origin;
14370 std::string query_string;
14371 std::string post_body;
14372 std::string post_boundary;
14374 bool send_done =
false;
14378 wseqno = s_wseqno++;
14380 wncseqno = GetNcSeqno(nc);
14385 ~MongooseWorkObject()
14395struct MongooseThreadObject
14397 std::atomic_bool fIsRunning{
false};
14398 std::thread* fThread = NULL;
14401 std::deque<MongooseWorkObject*> fQueue;
14402 std::condition_variable fNotify;
14415static std::vector<MongooseThreadObject*> gMongooseThreads;
14417static void mongoose_thread(MongooseThreadObject*);
14419MongooseThreadObject* FindThread(
void* nc)
14423 MongooseThreadObject* last_not_connected = NULL;
14425 for (
auto it : gMongooseThreads) {
14426 MongooseThreadObject* to = it;
14427 if (to->fNc == nc) {
14431 if (to->fNc == NULL) {
14432 last_not_connected = to;
14436 if (last_not_connected) {
14437 MongooseThreadObject* to = last_not_connected;
14443 MongooseThreadObject* to =
new MongooseThreadObject();
14449 gMongooseThreads.push_back(to);
14451 printf(
"Mongoose web server is using %d threads \r", (
int)gMongooseThreads.size());
14454 to->fThread =
new std::thread(mongoose_thread, to);
14459void FreeThread(
void* nc)
14463 for (
auto it : gMongooseThreads) {
14464 MongooseThreadObject* to = it;
14465 if (to->fNc == nc) {
14475static void mongoose_queue(
mg_connection* nc, MongooseWorkObject* w)
14478 MongooseThreadObject* to = FindThread(nc);
14479 assert(to->fNc == nc);
14481 to->fQueue.push_back(w);
14482 to->fMutex.unlock();
14483 to->fNotify.notify_one();
14486static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag =
false);
14490 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14491 w->http_get =
true;
14494 w->query_string = query_string;
14497 mongoose_queue(nc, w);
14504 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14505 w->http_post =
true;
14508 w->query_string = query_string;
14510 w->post_boundary = boundary;
14513 mongoose_queue(nc, w);
14518static int queue_mjsonrpc(
struct mg_connection *nc,
const std::string& origin,
const std::string& post_body,
RequestTrace* t)
14520 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14521 w->mjsonrpc =
true;
14522 w->origin = origin;
14523 w->post_body = post_body;
14526 mongoose_queue(nc, w);
14531static int thread_http_get(
mg_connection *nc, MongooseWorkObject *w)
14548 decode_get(rr, NULL, &w->cookies, w->uri.c_str(), w->query_string.c_str(), w->t);
14569 bool close_flag =
false;
14587static int thread_http_post(
mg_connection *nc, MongooseWorkObject *w)
14589 const char* post_data = w->post_body.c_str();
14590 int post_data_len = w->post_body.length();
14605 decode_post(rr, NULL, (
char*)post_data, w->post_boundary.c_str(), post_data_len, &w->cookies, w->uri.c_str(), w->t);
14608 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14621 bool close_flag =
false;
14637static int thread_mjsonrpc(
mg_connection *nc, MongooseWorkObject *w)
14639 w->t->fRPC = w->post_body;
14654 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14657 reply->GetArrayBuffer(&ptr, &size);
14659 std::string headers;
14660 headers +=
"HTTP/1.1 200 OK\n";
14661 if (w->origin.length() > 0)
14662 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14664 headers +=
"Access-Control-Allow-Origin: *\n";
14665 headers +=
"Access-Control-Allow-Credentials: true\n";
14666 headers +=
"Content-Length: " +
toString(size) +
"\n";
14667 headers +=
"Content-Type: application/octet-stream\n";
14673 std::string send = headers +
"\n";
14677 mongoose_send(nc, w, send.c_str(), send.length(), ptr, size);
14686 std::string reply_string = reply->Stringify();
14687 int reply_length = reply_string.length();
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(reply_length) +
"\n";
14697 headers +=
"Content-Type: application/json\n";
14701 printf(
"-----------------------\nSending headers: %s", headers.c_str());
14702 std::string r = reply_string.substr(0, 128);
14703 printf(
"-----------------------\nSending reply (%d bytes): %s\n\n\n", (
int)reply_string.size(), r.c_str());
14706 std::string send = headers +
"\n" + reply_string;
14710 mongoose_send(nc, w, send.c_str(), send.length(), NULL, 0);
14719static int thread_work_function(
mg_connection *nc, MongooseWorkObject *w)
14722 return thread_http_get(nc, w);
14723 else if (w->http_post)
14724 return thread_http_post(nc, w);
14725 else if (w->mjsonrpc)
14726 return thread_mjsonrpc(nc, w);
14736 char boundary[256];
14739 if (ct.length() > 0) {
14740 const char* s = strstr(ct.c_str(),
"boundary=");
14742 mstrlcpy(boundary, s+9,
sizeof(boundary));
14745#ifdef HAVE_MONGOOSE616
14746 if (multithread_mg)
14747 return queue_decode_post(nc, msg, boundary, uri, query_string, t);
14754 const char* post_data = msg->
body.
p;
14755 int post_data_len = msg->
body.
len;
14759#ifdef HAVE_MONGOOSE6
14772 decode_post(rr, NULL, (
char*)post_data, boundary, post_data_len, &cookies, uri, t);
14775 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14778#ifdef HAVE_MONGOOSE6
14788#ifdef HAVE_MONGOOSE6
14811 printf(
"handle_http_get: uri [%s], query [%s]\n", uri, query_string.c_str());
14813 if (query_string ==
"mjsonrpc_schema") {
14815 std::string reply = s->Stringify();
14818 int reply_length = reply.length();
14820 const std::string origin_header =
find_header_mg(msg,
"Origin");
14822 std::string headers;
14823 headers +=
"HTTP/1.1 200 OK\n";
14824 if (origin_header.length() > 0)
14825 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14827 headers +=
"Access-Control-Allow-Origin: *\n";
14828 headers +=
"Access-Control-Allow-Credentials: true\n";
14829 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14830 headers +=
"Content-Type: application/json\n";
14836 std::string send = headers +
"\n" + reply;
14840 mg_send(nc, send.c_str(), send.length());
14847 if (query_string ==
"mjsonrpc_schema_text") {
14852 int reply_length = reply.length();
14854 const std::string origin_header =
find_header_mg(msg,
"Origin");
14856 std::string headers;
14857 headers +=
"HTTP/1.1 200 OK\n";
14858 if (origin_header.length() > 0)
14859 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14861 headers +=
"Access-Control-Allow-Origin: *\n";
14862 headers +=
"Access-Control-Allow-Credentials: true\n";
14863 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14864 headers +=
"Content-Type: text/plain\n";
14870 std::string send = headers +
"\n" + reply;
14874 mg_send(nc, send.c_str(), send.length());
14881#ifdef HAVE_MONGOOSE616
14882 if (multithread_mg)
14883 return queue_decode_get(nc, msg, uri, query_string.c_str(), t);
14892 std::string post_data =
mgstr(&msg->
body);
14895 printf(
"handle_http_post: uri [%s], query [%s], post data %d bytes\n", uri, query_string.c_str(), (
int)post_data.length());
14897 printf(
"handle_http_post: post data = \n%s\n", post_data.c_str());
14899 if (query_string.substr(0, 8) ==
"mjsonrpc") {
14900 const std::string origin_header =
find_header_mg(msg,
"Origin");
14901 const std::string ctype_header =
find_header_mg(msg,
"Content-Type");
14903 if (strstr(ctype_header.c_str(),
"application/json") == NULL) {
14904 std::string headers;
14905 headers +=
"HTTP/1.1 415 Unsupported Media Type\n";
14912 printf(
"handle_http_post: unsupported media type \"%s\"\n", ctype_header.c_str());
14914 std::string send = headers +
"\n";
14918 mg_send(nc, send.c_str(), send.length());
14925#ifdef HAVE_MONGOOSE616
14926 if (multithread_mg)
14927 return queue_mjsonrpc(nc, origin_header, post_data, t);
14932 t->
fRPC = post_data;
14934#ifdef HAVE_MONGOOSE6
14945#ifdef HAVE_MONGOOSE6
14949 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14952 reply->GetArrayBuffer(&ptr, &size);
14954 std::string headers;
14955 headers +=
"HTTP/1.1 200 OK\n";
14956 if (origin_header.length() > 0)
14957 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14959 headers +=
"Access-Control-Allow-Origin: *\n";
14960 headers +=
"Access-Control-Allow-Credentials: true\n";
14961 headers +=
"Content-Length: " +
toString(size) +
"\n";
14962 headers +=
"Content-Type: application/octet-stream\n";
14968 std::string send = headers +
"\n";
14972 mg_send(nc, send.c_str(), send.length());
14982 std::string reply_string = reply->Stringify();
14983 int reply_length = reply_string.length();
14985 std::string headers;
14986 headers +=
"HTTP/1.1 200 OK\n";
14987 if (origin_header.length() > 0)
14988 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14990 headers +=
"Access-Control-Allow-Origin: *\n";
14991 headers +=
"Access-Control-Allow-Credentials: true\n";
14992 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14993 headers +=
"Content-Type: application/json\n";
14999 std::string send = headers +
"\n" + reply_string;
15003 mg_send(nc, send.c_str(), send.length());
15048 const std::string origin_header =
find_header_mg(msg,
"Origin");
15051 printf(
"handle_http_options_cors: origin [%s]\n", origin_header.c_str());
15053 std::string headers;
15054 headers +=
"HTTP/1.1 200 OK\n";
15056 if (origin_header.length() > 0)
15057 headers +=
"Access-Control-Allow-Origin: " + origin_header +
"\n";
15059 headers +=
"Access-Control-Allow-Origin: *\n";
15060 headers +=
"Access-Control-Allow-Headers: Content-Type\n";
15061 headers +=
"Access-Control-Allow-Credentials: true\n";
15062 headers +=
"Access-Control-Max-Age: 120\n";
15063 headers +=
"Content-Length: 0\n";
15064 headers +=
"Content-Type: text/plain\n";
15068 std::string send = headers +
"\n";
15072 mg_send(nc, send.c_str(), send.length());
15081#ifdef HAVE_MONGOOSE616
15082static MVOdb* gProxyOdb = NULL;
15089 std::string uri_encoded =
mgstr(&msg->
uri);
15090 std::string uri =
UrlDecode(uri_encoded.c_str());
15093 printf(
"handle_http_message: method [%s] uri [%s] proto [%s]\n", method.c_str(), uri.c_str(),
mgstr(&msg->
proto).c_str());
15099 t->
fQuery = query_string;
15103 if (method ==
"OPTIONS" && query_string ==
"mjsonrpc" &&
mg_get_http_header(msg,
"Access-Control-Request-Method") != NULL) {
15126 printf(
"handle_http_message: auth user: \"%s\"\n", username.c_str());
15128 if (username.length() == 0) {
15130 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());
15142#ifdef HAVE_MONGOOSE616
15144 std::string::size_type p1 = uri.find(
"/", 1);
15145 if (p1 == uri.length()-1) {
15146 std::string
response =
"404 Not Found (Proxy name is missing)";
15152 std::string::size_type p2 = uri.find(
"/", p1+1);
15153 if (p2 == std::string::npos) {
15154 std::string
response =
"404 Not Found (Proxy URL should end with a slash)";
15160 std::string p = uri.substr(p1+1, p2-p1-1);
15162 if (p.length() < 1) {
15163 std::string
response =
"404 Not Found (Double-slash or Proxy name is too short)";
15169 std::string destination;
15170 gProxyOdb->RS(p.c_str(), &destination);
15171 if (destination.length() < 1) {
15172 std::string
response =
"404 Not Found (Proxy not found in ODB)";
15177 }
else if (destination[0] ==
'#') {
15178 std::string
response =
"404 Not Found (Proxy commented-out in ODB)";
15184 std::string
response =
"404 Not Found (Proxy address should not end with a slash)";
15190 std::string
response =
"404 Not Found (Proxy address does not start with http";
15203 printf(
"proxy: uri [%s] mount [%s] upstream [%s]\n", uri.c_str(),
mgstr(&mount).c_str(),
mgstr(&upstream).c_str());
15205 mg_http_reverse_proxy(nc, msg, mount, upstream);
15214 if (method ==
"GET")
15216 else if (method ==
"POST")
15221 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15223 std::string
response =
"501 Not Implemented";
15234#ifdef HAVE_MONGOOSE6
15236static void handle_http_event_mg(
struct mg_connection *nc,
int ev,
void *ev_data)
15241 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15246 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15251static void handle_http_redirect(
struct mg_connection *nc,
int ev,
void *ev_data)
15258 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15260 mg_printf(nc,
"HTTP/1.1 302 Found\r\nLocation: https://%s%s\r\n\r\n",
15261 ((std::string*)(nc->
user_data))->c_str(),
15268 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15274#ifdef HAVE_MONGOOSE616
15279static std::atomic_bool s_shutdown{
false};
15280static struct mg_mgr s_mgr;
15281static std::atomic_int s_rseqno{1};
15282static std::mutex s_mg_broadcast_mutex;
15286struct work_request {
15288 MongooseWorkObject* w;
15293struct work_result {
15295 uint32_t check = 0x12345678;
15297 MongooseWorkObject* w = NULL;
15298 const char* p1 = NULL;
15300 const char* p2 = NULL;
15302 bool close_flag =
false;
15303 bool send_501 =
false;
15307static void mongoose_queue(
void *nc, MongooseWorkObject *w)
15309 struct work_request req = {nc, w};
15313 if (
write(s_sock[0], &req,
sizeof(req)) < 0) {
15314 fprintf(stderr,
"mongoose_queue: Error: write(s_sock(0)) error %d (%s)\n", errno, strerror(errno));
15320static void on_work_complete(
struct mg_connection *nc,
int ev,
void *ev_data)
15323 struct work_result *res = (
struct work_result *)ev_data;
15325 assert(res != NULL);
15326 assert(res->w != NULL);
15337 if (GetNcSeqno(nc) != res->w->wncseqno)
15342 if (res->send_501) {
15343 std::string
response =
"501 Not Implemented";
15349 mg_send(nc, res->p1, res->s1);
15352 mg_send(nc, res->p2, res->s2);
15354 if (res->close_flag) {
15361 res->w->send_done =
true;
15364static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag)
15367 struct work_result res;
15370 res.rseqno = s_rseqno++;
15375 res.close_flag = close_flag;
15376 res.send_501 =
false;
15418 s_mg_broadcast_mutex.lock();
15419 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15420 s_mg_broadcast_mutex.unlock();
15423static void mongoose_send_501(
mg_connection* nc, MongooseWorkObject* w)
15425 struct work_result res;
15428 res.rseqno = s_rseqno++;
15433 res.close_flag =
false;
15434 res.send_501 =
true;
15437 s_mg_broadcast_mutex.lock();
15438 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15439 s_mg_broadcast_mutex.unlock();
15443void *worker_thread_proc(
void *
param)
15446 struct work_request req = {0};
15448 while ((!
_abort) && (! s_shutdown)) {
15449 int rd =
read(s_sock[1], &req,
sizeof(req));
15455 if (
_abort || s_shutdown) {
15458 fprintf(stderr,
"worker_thread_proc: Error: read(s_sock(1)) returned %d, error %d (%s)\n", rd, errno, strerror(errno));
15465 int response = thread_work_function(req.nc, req.w);
15469 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15470 mongoose_send_501(req.nc, req.w);
15473 req.w->t->fCompleted =
true;
15485static void mongoose_thread(MongooseThreadObject* to)
15489 std::unique_lock<std::mutex> ulm(to->fMutex, std::defer_lock);
15491 to->fIsRunning =
true;
15493 while ((!
_abort) && (! s_shutdown)) {
15494 MongooseWorkObject *w = NULL;
15497 while (to->fQueue.empty()) {
15499 to->fNotify.wait(ulm);
15500 if (
_abort || s_shutdown) {
15505 if (
_abort || s_shutdown) {
15509 w = to->fQueue.front();
15510 to->fQueue.pop_front();
15515 int response = thread_work_function(w->nc, w);
15519 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15520 mongoose_send_501(w->nc, w);
15525 if (!w->send_done) {
15531 w->t->fCompleted =
true;
15539 to->fIsRunning =
false;
15544static bool mongoose_hostlist_enabled(
const struct mg_connection *nc);
15546static void ev_handler(
struct mg_connection *nc,
int ev,
void *ev_data)
15560 printf(
"ev_handler: connection %p, event %d\n", nc, ev);
15566 nc->
user_data =
new MongooseNcUserData();
15569 printf(
"ev_handler: connection %p, MG_EV_ACCEPT, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15574 }
else if (mongoose_hostlist_enabled(nc)) {
15575 if (!mongoose_check_hostlist(&nc->
sa)) {
15582 printf(
"ev_handler: connection %p, MG_EV_RECV, %d bytes\n", nc, *(
int*)ev_data);
15591 printf(
"ev_handler: connection %p, MG_EV_SEND, %d bytes\n", nc, *(
int*)ev_data);
15596 printf(
"ev_handler: connection %p, MG_EV_HTTP_CHUNK\n", nc);
15607 printf(
"ev_handler: connection %p, MG_EV_HTTP_REQUEST \"%s\" \"%s\"\n", nc,
mgstr(&msg->
method).c_str(),
mgstr(&msg->
uri).c_str());
15619 printf(
"ev_handler: connection %p, MG_EV_CLOSE, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15624 MongooseNcUserData* ncud = (MongooseNcUserData*)nc->
user_data;
15633#define FLAG_HTTPS MG_F_USER_1
15634#define FLAG_PASSWORDS MG_F_USER_2
15635#define FLAG_HOSTLIST MG_F_USER_3
15644 return flags & FLAG_PASSWORDS;
15647static bool mongoose_hostlist_enabled(
const struct mg_connection *nc)
15654 return flags & FLAG_HOSTLIST;
15657static int mongoose_listen(
const char* address,
int flags)
15661 if (flags & FLAG_HTTPS) {
15662 cm_msg(
MERROR,
"mongoose_listen",
"https port \"%s\" requested, but mhttpd compiled without MG_ENABLE_SSL", address);
15669 cm_msg(
MERROR,
"mongoose_listen",
"Cannot mg_bind address \"%s\"", address);
15673 if (
flags & FLAG_HTTPS) {
15675 std::string cert_file;
15680 cm_msg(
MERROR,
"mongoose_listen",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
15681 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");
15682 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");
15686 printf(
"Mongoose web server will use https certificate file \"%s\"\n", cert_file.c_str());
15688 const char* errmsg =
mg_set_ssl(nc, cert_file.c_str(), NULL);
15690 cm_msg(
MERROR,
"mongoose_listen",
"Cannot enable https with certificate file \"%s\", error: %s", cert_file.c_str(), errmsg);
15704 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");
15709static int mongoose_init(MVOdb* odb,
bool no_passwords,
bool no_hostlist,
const std::vector<std::string>& user_hostlist)
15711 bool enable_localhost_port =
true;
15712 int localhost_port = 8080;
15713 bool localhost_port_passwords =
false;
15715 bool enable_insecure_port =
false;
15716 int insecure_port = 8081;
15717 bool insecure_port_passwords =
true;
15718 bool insecure_port_hostlist =
true;
15720 bool enable_https_port =
false;
15721 int https_port = 8443;
15722 bool https_port_passwords =
true;
15723 bool https_port_hostlist =
false;
15725 std::vector<std::string> hostlist;
15726 hostlist.push_back(
"localhost");
15728 bool enable_ipv6 =
true;
15730 odb->RB(
"Enable localhost port", &enable_localhost_port,
true);
15731 odb->RI(
"localhost port", &localhost_port,
true);
15732 odb->RB(
"localhost port passwords", &localhost_port_passwords,
true);
15733 odb->RB(
"Enable insecure port", &enable_insecure_port,
true);
15734 odb->RI(
"insecure port", &insecure_port,
true);
15735 odb->RB(
"insecure port passwords", &insecure_port_passwords,
true);
15736 odb->RB(
"insecure port host list", &insecure_port_hostlist,
true);
15737 odb->RB(
"Enable https port", &enable_https_port,
true);
15738 odb->RI(
"https port", &https_port,
true);
15739 odb->RB(
"https port passwords", &https_port_passwords,
true);
15740 odb->RB(
"https port host list", &https_port_hostlist,
true);
15741 odb->RSA(
"Host list", &hostlist,
true, 10, 256);
15742 odb->RB(
"Enable IPv6", &enable_ipv6,
true);
15745 gProxyOdb = odb->Chdir(
"Proxy",
true);
15746 std::string proxy_example =
"#http://localhost:8080";
15747 gProxyOdb->RS(
"example", &proxy_example,
true);
15753 && ((enable_localhost_port && localhost_port_passwords)
15754 || (enable_insecure_port && insecure_port_passwords)
15755 || (enable_https_port && https_port_passwords))) {
15759 printf(
"mongoose_init: Error: Cannot initialize authorization object!\n");
15764 printf(
"Password protection is off\n");
15768 && ((enable_insecure_port && insecure_port_hostlist)
15769 || (enable_https_port && https_port_hostlist))) {
15773 for (
unsigned int i=0;
i<user_hostlist.size();
i++)
15776 for (
unsigned i=0;
i<hostlist.size();
i++) {
15777 std::string s = hostlist[
i];
15778 if (s.length() < 1)
15788 printf(
"Hostlist active, connections will be accepted only from: ");
15796 printf(
"Hostlist off, connections from anywhere will be accepted\n");
15801 bool listen_failed =
false;
15803 if (enable_localhost_port) {
15805 sprintf(
str,
"localhost:%d", localhost_port);
15808 listen_failed =
true;
15810 sprintf(
str,
"[::1]:%d", localhost_port);
15813 listen_failed =
true;
15817 if (enable_insecure_port) {
15820 if (insecure_port_passwords)
15821 flags |= FLAG_PASSWORDS;
15822 if (insecure_port_hostlist)
15823 flags |= FLAG_HOSTLIST;
15825 sprintf(
str,
"[::]:%d", insecure_port);
15828 listen_failed =
true;
15830 sprintf(
str,
"%d", insecure_port);
15833 listen_failed =
true;
15837 if (enable_https_port) {
15840 if (https_port_passwords)
15841 flags |= FLAG_PASSWORDS;
15842 if (https_port_hostlist)
15843 flags |= FLAG_HOSTLIST;
15844 flags |= FLAG_HTTPS;
15846 sprintf(
str,
"[::]:%d", https_port);
15849 listen_failed =
true;
15851 sprintf(
str,
"%d", https_port);
15854 listen_failed =
true;
15858 if (listen_failed) {
15859 cm_msg(
MERROR,
"mongoose_init",
"Failed to listen on a TCP port enabled in ODB /WebServer");
15866static void mongoose_poll(
int msec = 200)
15871static void mongoose_cleanup()
15873 printf(
"Mongoose web server shutting down\n");
15878 if (s_mgr.active_connections) {
15890 for (
auto it : gMongooseThreads) {
15891 MongooseThreadObject* to = it;
15892 to->fNotify.notify_one();
15896 for (
int i=0;
i<10;
i++) {
15897 int count_running = 0;
15898 for (
auto it : gMongooseThreads) {
15899 MongooseThreadObject* to = it;
15901 if (to->fIsRunning) {
15905 printf(
"Mongoose web server shutting down, %d threads still running\n", count_running);
15906 if (count_running == 0)
15908 mongoose_poll(1000);
15912 for (
auto it : gMongooseThreads) {
15913 MongooseThreadObject* to = it;
15915 if (to->fIsRunning) {
15916 cm_msg(
MERROR,
"mongoose",
"thread failed to shut down");
15919 to->fThread->join();
15920 delete to->fThread;
15923 gMongooseThreads.clear();
15931 for (
auto e : gHostlistCache) {
15934 gHostlistCache.clear();
15944 printf(
"Mongoose web server shut down\n");
15949#ifdef HAVE_MONGOOSE6
15956int start_mg(
int user_http_port,
int user_https_port,
int socket_priviledged_port,
int verbose)
15971 int http_port = 8080;
15972 int https_port = 8443;
15973 int http_redirect_to_https = 1;
15975 size =
sizeof(http_port);
15978 size =
sizeof(https_port);
15981 size =
sizeof(http_redirect_to_https);
15984 bool need_cert_file =
false;
15985 bool need_password_file =
false;
15987 if (user_http_port)
15988 http_port = user_http_port;
15990 if (user_https_port)
15991 https_port = user_https_port;
15994 need_cert_file =
true;
15995 need_password_file =
true;
15999 http_redirect_to_https = 0;
16001 if (http_port && !http_redirect_to_https) {
16004 need_password_file =
false;
16007 if (socket_priviledged_port >= 0) {
16009 need_password_file =
false;
16010 printf(
"Mongoose web server password portection is disabled: serving unencrypted http on port 80\n");
16013 bool have_at_least_one_port =
false;
16015 std::string cert_file;
16017 if (need_cert_file) {
16021 cm_msg(
MERROR,
"mongoose",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
16022 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");
16026 printf(
"Mongoose web server will use SSL certificate file \"%s\"\n", cert_file.c_str());
16029 if (need_password_file) {
16033 printf(
"Error: Cannot initialize authorization object!\n");
16038 printf(
"Mongoose web server will not use password protection\n");
16042 printf(
"start_mg!\n");
16045 signal(SIGPIPE, SIG_IGN);
16052 if (!request_mutex) {
16060 if (socket_priviledged_port >= 0) {
16063 cm_msg(
MERROR,
"mongoose",
"Cannot create mg_connection for set-uid-root privileged port");
16068#ifdef MG_ENABLE_THREADS
16074 have_at_least_one_port =
true;
16075 printf(
"mongoose web server is listening on the set-uid-root privileged port\n");
16078 if (http_port != 80) {
16080 sprintf(
str,
"%d", http_port);
16083 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", http_port);
16087#ifdef MG_ENABLE_THREADS
16092 if (http_redirect_to_https) {
16095 sprintf(
str,
"%d", https_port);
16096 std::string s = hostname +
":" + std::string(
str);
16099 printf(
"mongoose web server is redirecting HTTP port %d to https://%s\n", http_port, s.c_str());
16104 have_at_least_one_port =
true;
16105 printf(
"mongoose web server is listening on the HTTP port %d\n", http_port);
16109#ifdef MG_ENABLE_SSL
16111 sprintf(
str,
"%d", https_port);
16114 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", https_port);
16119#ifdef MG_ENABLE_THREADS
16125 have_at_least_one_port =
true;
16126 printf(
"mongoose web server is listening on the HTTPS port %d\n", https_port);
16128 cm_msg(
MERROR,
"mongoose",
"https port %d requested, but mhttpd compiled without MG_ENABLE_SSL", https_port);
16133 if (!have_at_least_one_port) {
16134 cm_msg(
MERROR,
"mongoose",
"cannot start: no ports defined");
16144 printf(
"stop_mg!\n");
16150 printf(
"stop_mg done!\n");
16165#ifdef HAVE_MONGOOSE6
16176#ifdef HAVE_MONGOOSE6
16193 doc->
D(
"get current value of mhttpd http_trace");
16194 doc->
P(NULL, 0,
"there are no input parameters");
16195 doc->
R(NULL, MJSON_INT,
"current value of http_trace");
16206 doc->
D(
"set new value of mhttpd http_trace");
16207 doc->
P(NULL, MJSON_INT,
"new value of http_trace");
16208 doc->
R(NULL, MJSON_INT,
"new value of http_trace");
16228#ifdef HAVE_MONGOOSE6
16229 int user_http_port = 0;
16230 int user_https_port = 0;
16232#ifdef HAVE_MONGOOSE616
16233 bool no_passwords =
false;
16234 bool no_hostlist =
false;
16236 const char *myname =
"mhttpd";
16238 setbuf(stdout, NULL);
16239 setbuf(stderr, NULL);
16242 signal(SIGPIPE, SIG_IGN);
16245#ifdef HAVE_MONGOOSE6
16250 int socket_priviledged_port = -1;
16254 if (getuid() != geteuid()) {
16257 printf(
"mhttpd is running in setuid-root mode.\n");
16259 socket_priviledged_port = open_listening_socket(port80);
16260 if (socket_priviledged_port < 0) {
16261 printf(
"Cannot open listening socket on TCP port %d, aborting.\n", port80);
16266 status = setuid(getuid());
16268 printf(
"Cannot give up root privelege, aborting.\n");
16271 status = setuid(getuid());
16273 printf(
"Cannot give up root privelege, aborting.\n");
16280 char midas_hostname[256];
16281 char midas_expt[256];
16284 cm_get_environment(midas_hostname,
sizeof(midas_hostname), midas_expt,
sizeof(midas_expt));
16287#ifdef HAVE_MONGOOSE6
16288 gUserAllowedHosts.clear();
16290 std::vector<std::string> user_hostlist;
16292 for (
int i = 1;
i < argc;
i++) {
16293 if (argv[
i][0] ==
'-' && argv[
i][1] ==
'D')
16295 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'v')
16297 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'E')
16299 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'H') {
16301#ifdef HAVE_MONGOOSE6
16302 }
else if (strcmp(argv[
i],
"--http") == 0) {
16304 user_http_port = atoi(argv[
i+1]);
16306 }
else if (strcmp(argv[
i],
"--https") == 0) {
16308 user_https_port = atoi(argv[
i+1]);
16311 }
else if (strcmp(argv[
i],
"--trace-mg") == 0) {
16315 }
else if (strcmp(argv[
i],
"--trace-mg-verbose") == 0) {
16317 }
else if (strcmp(argv[
i],
"--no-trace-mg-recv") == 0) {
16319 }
else if (strcmp(argv[
i],
"--no-trace-mg-send") == 0) {
16321 }
else if (strcmp(argv[
i],
"--verbose-mg") == 0) {
16323#ifdef HAVE_MONGOOSE616
16324 }
else if (strcmp(argv[
i],
"--no-multithread") == 0) {
16325 multithread_mg =
false;
16326 }
else if (strcmp(argv[
i],
"--no-passwords") == 0) {
16327 no_passwords =
true;
16328 }
else if (strcmp(argv[
i],
"--no-hostlist") == 0) {
16329 no_hostlist =
true;
16331 }
else if (argv[
i][0] ==
'-') {
16332 if (
i + 1 >= argc || argv[
i + 1][0] ==
'-')
16334 if (argv[
i][1] ==
'h')
16335 mstrlcpy(midas_hostname, argv[++
i],
sizeof(midas_hostname));
16336 else if (argv[
i][1] ==
'e')
16337 mstrlcpy(midas_expt, argv[++
i],
sizeof(midas_hostname));
16338 else if (argv[
i][1] ==
'a') {
16339#ifdef HAVE_MONGOOSE6
16340 gUserAllowedHosts.push_back(argv[++
i]);
16342 user_hostlist.push_back(argv[++
i]);
16344 }
else if (argv[
i][1] ==
'p') {
16345 printf(
"Option \"-p port_number\" for the old web server is obsolete.\n");
16346 printf(
"mongoose web server is the new default, port number is set in ODB or with \"--http port_number\".\n");
16347 printf(
"To run the obsolete old web server, please use \"--oldserver\" switch.\n");
16351 printf(
"usage: %s [-h Hostname[:port]] [-e Experiment] [-v] [-D] [-a Hostname]\n\n", argv[0]);
16352 printf(
" -a add hostname to the hostlist of hosts allowed to connect to mhttpd\n");
16353 printf(
" -e experiment to connect to\n");
16354 printf(
" -h connect to midas server (mserver) on given host\n");
16355 printf(
" -v display verbose HTTP communication\n");
16356 printf(
" -D become a daemon\n");
16357 printf(
" -E only display ELog system\n");
16358 printf(
" -H only display history plots\n");
16359#ifdef HAVE_MONGOOSE6
16360 printf(
" --http port - bind to specified HTTP port (default is ODB \"/Experiment/midas http port\")\n");
16361 printf(
" --https port - bind to specified HTTP port (default is ODB \"/Experiment/midas https port\")\n");
16363 printf(
" --verbose-mg - trace mongoose web requests\n");
16364 printf(
" --trace-mg - trace mongoose events\n");
16365 printf(
" --no-trace-mg-recv - do not trace mongoose recv events\n");
16366 printf(
" --no-trace-mg-send - dop not trace mongoose send events\n");
16367#ifdef HAVE_MONGOOSE616
16368 printf(
" --no-multithread - disable mongoose multithreading\n");
16369 printf(
" --no-passwords - disable password protection\n");
16370 printf(
" --no-hostlist - disable access control host list\n");
16378 printf(
"Becoming a daemon...\n");
16384 FILE *
f = fopen(
"/var/run/mhttpd.pid",
"w");
16392 myname =
"mhttpd_history";
16420 MVOdb *odb = MakeMidasOdb(
hDB);
16428 printf(
"check_odb_records() failed, see messages and midas.log, bye!\n");
16433#ifdef HAVE_MONGOOSE6
16434 if (init_allowed_hosts() !=
SUCCESS) {
16435 printf(
"init_allowed_hosts() failed, see messages and midas.log, bye!\n");
16442 printf(
"mhttpd allowed hosts list: ");
16450 printf(
"mhttpd allowed hosts list is empty\n");
16473#ifdef HAVE_MONGOOSE6
16474 status = start_mg(user_http_port, user_https_port, socket_priviledged_port,
verbose);
16477 printf(
"could not start the mongoose web server, see messages and midas.log, bye!\n");
16483#ifdef HAVE_MONGOOSE616
16487 signal(SIGPIPE, SIG_IGN);
16503 MVOdb* o = odb->Chdir(
"WebServer",
true);
16504 status = mongoose_init(o, no_passwords, no_hostlist, user_hostlist);
16507 printf(
"Error: Could not start the mongoose web server, see messages and midas.log, bye!\n");
16515#ifdef HAVE_MONGOOSE6
16520#ifdef HAVE_MONGOOSE616
16541 mongoose_cleanup();
char * attachment_buffer[3]
size_t attachment_size[3]
std::vector< AuthEntry > passwords
std::string passwd_filename
virtual int hs_read(time_t start_time, time_t end_time, time_t interval, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], int num_entries[], time_t *time_buffer[], double *data_buffer[], int status[])=0
see hs_read(), returns HS_SUCCESS
virtual int hs_disconnect()=0
disconnect from history, returns HS_SUCCESS
virtual int hs_get_events(time_t time_from, std::vector< std::string > *pevents)=0
get list of events that exist(ed) at given time and later (value 0 means "return all events from begi...
virtual int hs_get_tags(const char *event_name, time_t time_from, std::vector< TAG > *ptags)=0
get list of history variables for given event (use event names returned by hs_get_events()) that exis...
virtual int hs_get_last_written(time_t start_time, int num_var, const char *const event_name[], const char *const tag_name[], const int var_index[], time_t last_written[])=0
virtual int hs_clear_cache()=0
clear internal cache, returns HS_SUCCESS
void unsetparam(const char *param)
const char * getparam(const char *param)
char _param[MAX_PARAM][PARAM_LENGTH]
void setparam(const char *param, const char *value)
BOOL isparam(const char *param)
std::string xgetparam(const char *param)
void AddTrace(RequestTrace *t)
void AddTraceMTS(RequestTrace *t)
std::vector< RequestTrace * > fBuf
else strcpy(return_buffer+strlen_retbuf, str)
int return_grow(size_t len)
vsprintf(str,(char *) format, argptr)
void rread(const char *filename, int fh, int len)
void rsprintf(const char *format,...) MATTRPRINTF(2
void rmemcpy(const void *buf, int len)
void rsputs2(const char *str)
void rsputs(const char *str)
assert(strlen(str)< sizeof(str))
static bool exists(const std::string &name)
INT al_get_alarms(std::string *presult)
INT cm_yield(INT millisec)
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
INT cm_connect_client(const char *client_name, HNDLE *hConn)
INT cm_start_watchdog_thread()
INT cm_connect_experiment1(const char *host_name, const char *default_exp_name, const char *client_name, void(*func)(char *), INT odb_size, DWORD watchdog_timeout)
std::string cm_expand_env(const char *str)
int cm_exec_script(const char *odb_path_to_script)
INT cm_disconnect_experiment(void)
std::string cm_get_exptab_filename()
std::string cm_get_path()
std::string cm_get_history_path(const char *history_channel)
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
const char * cm_get_version()
std::string cm_get_experiment_name()
const char * cm_get_revision()
INT cm_exist(const char *name, BOOL bUnique)
INT el_submit(int run, const char *author, const char *type, const char *syst, const char *subject, const char *text, const char *reply_to, const char *encoding, const char *afilename1, const char *buffer1, INT buffer_size1, const char *afilename2, const char *buffer2, INT buffer_size2, const char *afilename3, const char *buffer3, INT buffer_size3, char *tag, INT tag_size)
#define CM_WRONG_PASSWORD
#define DB_STRUCT_MISMATCH
#define DB_INVALID_HANDLE
#define DB_NO_MORE_SUBKEYS
void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c)
void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
gdImagePtr gdImageCreate(int sx, int sy)
void gdImageString(gdImagePtr im, gdFontPtr f, int x, int y, const char *s, int color)
void gdImageFilledRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
void gdImageLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
gdImagePtr gdImageCreateFromGif(FILE *fd)
void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, const char *s, int color)
void gdImageDestroy(gdImagePtr im)
gdFontPtr gdFontMediumBold
int gdImageColorClosest(gdImagePtr im, int r, int g, int b)
void gdImageGif(gdImagePtr im, gdGifBuffer *buffer)
void gdImageDashedLine(gdImagePtr im, int x1, int y1, int x2, int y2, int color)
int gdImageColorAllocate(gdImagePtr im, int r, int g, int b)
void gdImageInterlace(gdImagePtr im, int interlaceArg)
void gdImageFill(gdImagePtr im, int x, int y, int color)
void gdImageColorTransparent(gdImagePtr im, int color)
void D(const char *description)
MJsonNode * mjsonrpc_decode_post_data(const char *post_data)
void P(const char *name, int mjson_type, const char *description)
MJsonNode * mjsonrpc_make_result(MJsonNode *node)
MJsonNode * mjsonrpc_get_schema()
void mjsonrpc_set_std_mutex(void *mutex)
std::string mjsonrpc_schema_to_text(const MJsonNode *schema)
void mjsonrpc_add_handler(const char *method, mjsonrpc_handler_t *handler, bool needs_locking)
void R(const char *name, int mjson_type, const char *description)
int mg_printf(struct mg_connection *, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
time_t mg_mgr_poll(struct mg_mgr *, int milli)
void mg_mgr_free(struct mg_mgr *)
char * cs_md5(char buf[33],...)
struct mg_str header_names[MG_MAX_HTTP_HEADERS]
#define MG_MAX_HTTP_HEADERS
#define MG_F_CLOSE_IMMEDIATELY
void mbuf_remove(struct mbuf *, size_t data_size)
void mg_mgr_init(struct mg_mgr *mgr, void *user_data)
void mg_send_head(struct mg_connection *n, int status_code, int64_t content_length, const char *extra_headers)
const char * mg_set_ssl(struct mg_connection *nc, const char *cert, const char *ca_cert)
void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t)
struct mg_str header_values[MG_MAX_HTTP_HEADERS]
void mg_send(struct mg_connection *, const void *buf, int len)
struct mg_connection * next
void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path, mg_event_handler_t handler)
struct mg_str query_string
void mg_set_protocol_http_websocket(struct mg_connection *nc)
struct mg_connection * listener
struct mg_connection * mg_bind(struct mg_mgr *, const char *, mg_event_handler_t)
int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf, size_t buf_size)
struct mg_str mg_mk_str(const char *s)
void mg_enable_multithreading(struct mg_connection *nc)
struct mg_str * mg_get_http_header(struct http_message *hm, const char *name)
struct mg_connection * mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t)
#define MG_F_SEND_AND_CLOSE
#define MG_EV_HTTP_REQUEST
std::string ss_gethostname()
INT ss_mutex_release(MUTEX_T *mutex)
time_t ss_mktime(struct tm *tms)
int ss_file_exist(const char *path)
INT ss_mutex_create(MUTEX_T **mutex, BOOL recursive)
INT recv_string(int sock, char *buffer, DWORD buffer_size, INT millisec)
std::string ss_replace_env_variables(const std::string &inputPath)
INT ss_daemon_init(BOOL keep_stdout)
INT ss_sleep(INT millisec)
char * ss_crypt(const char *buf, const char *salt)
void * ss_ctrlc_handler(void(*func)(int))
INT ss_mutex_wait_for(MUTEX_T *mutex, INT timeout)
INT cm_msg1(INT message_type, const char *filename, INT line, const char *facility, const char *routine, const char *format,...)
INT EXPRT cm_msg_facilities(STRING_LIST *list)
std::string cm_get_error(INT code)
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
INT cm_msg_retrieve2(const char *facility, time_t t, INT n_message, char **messages, int *num_messages)
void cm_msg_get_logfile(const char *fac, time_t t, std::string *filename, std::string *linkname, std::string *linktarget)
BOOL equal_ustring(const char *str1, const char *str2)
INT db_sprintfh(char *string, const void *data, INT data_size, INT idx, DWORD type)
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
INT db_find_link(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
INT db_reorder_key(HNDLE hDB, HNDLE hKey, INT idx)
std::string strcomb1(const char **list)
INT db_set_link_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
INT db_get_path(HNDLE hDB, HNDLE hKey, char *path, INT buf_size)
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
INT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, const char *path)
INT db_set_link_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
INT db_copy_xml(HNDLE hDB, HNDLE hKey, char *buffer, int *buffer_size, bool header)
INT db_scan_tree(HNDLE hDB, HNDLE hKey, INT level, INT(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
INT db_get_link(HNDLE hDB, HNDLE hKey, KEY *key)
INT EXPRT db_get_value_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int index, std::string *s, BOOL create, int create_string_length)
INT db_sprintff(char *string, const char *format, const void *data, INT data_size, INT idx, DWORD type)
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
INT db_watch(HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT db_delete(HNDLE hDB, HNDLE hKeyRoot, const char *odb_path)
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
INT db_copy_json_obsolete(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int save_keys, int follow_links, int recurse)
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_get_link_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
INT db_rename_key(HNDLE hDB, HNDLE hKey, const char *name)
INT db_get_key_time(HNDLE hDB, HNDLE hKey, DWORD *delta)
INT db_set_value_index(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT idx, DWORD type, BOOL trunc)
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT EXPRT db_resize_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int num_values, int max_string_length)
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
INT db_sscanf(const char *data_str, void *data, INT *data_size, INT i, DWORD tid)
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
INT db_create_link(HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
INT rpc_client_call(HNDLE hConn, DWORD routine_id,...)
INT rpc_register_functions(const RPC_LIST *new_list, RPC_HANDLER func)
static std::vector< RPC_LIST > rpc_list
const char * rpc_tid_name(INT id)
static std::string q(const char *s)
int hs_read_event_list(std::vector< std::string > *pevents)
int hs_find_reader_channel(HNDLE hDB, HNDLE *hKeyOut, int debug_flag)
int hs_get_history(HNDLE hDB, HNDLE hKey, int flags, int debug_flag, MidasHistoryInterface **mh)
BOOL debug
debug printouts
static void handle_event_mg(struct mg_connection *nc, int ev, void *ev_data)
static void SaveHistPlotToOdb(MVOdb *odb, const HistPlot &hp, const char *group, const char *panel)
static bool trace_mg_send
BOOL is_editable(char *eq_name, char *var_name)
const unsigned char favicon_png[]
void haxis(gdImagePtr im, gdFont *font, int col, int gcol, int x1, int y1, int width, int minor, int major, int text, int label, int grid, double xmin, double xmax)
static bool cmp_vars(const HistVar &a, const HistVar &b)
void output_key(Param *p, Return *r, HNDLE hkey, int index, const char *format)
void get_elog_url(char *url, int len)
static void DeleteHistPlotDeleted(HistPlot &hp)
static void LoadHistPlotFromParam(HistPlot *hp, Param *p)
static void add_rpc_functions()
INT check_odb_records(MVOdb *odb)
static int handle_http_post(struct mg_connection *nc, const http_message *msg, const char *uri, RequestTrace *t)
std::string get_content_type(const char *filename)
static const std::string find_header_mg(const struct http_message *msg, const char *name)
static void xmg_mkmd5resp(const char *method, size_t method_len, const char *uri, size_t uri_len, const char *ha1, size_t ha1_len, const char *nonce, size_t nonce_len, const char *nc, size_t nc_len, const char *cnonce, size_t cnonce_len, const char *qop, size_t qop_len, char *resp)
void strencode(Return *r, const char *text)
static MVOdb * gMimeTypesOdb
static const char default_type_list[20][NAME_LENGTH]
void show_eqtable_page(Param *pp, Return *r, int refresh)
static void history_watch_callback(HNDLE hDB, HNDLE hKey, int index, void *info)
void show_custom_file(Return *r, const char *name)
void show_find_page(Return *r, const char *value)
BOOL check_web_password(Return *r, HNDLE hDB, const char *dec_path, const char *password, const char *redir)
bool send_fp(Return *r, const std::string &path, FILE *fp)
std::vector< std::string > get_resource_paths()
static void SplitEventAndTagNames(std::string var_name, std::string &event_name, std::string &tag_name)
void decode_cookies(Cookies *c, const http_message *msg)
char * stristr(const char *str, const char *pattern)
void submit_elog(MVOdb *odb, Param *pp, Return *r, Attachment *a)
void show_query_page(Param *p, Return *r)
static void urlEncode(char *ps, int ps_size)
static std::string NextHistPlotColour(const HistPlot &hp)
std::string strencode2(const char *text)
void decode_get(Return *rr, char *string, const Cookies *c, const char *url, const char *query_string, RequestTrace *t)
static MJsonNode * get_http_trace(const MJsonNode *params)
void show_error(Return *r, const char *error)
static bool read_passwords(Auth *auth)
void redirect2(Return *r, const char *path)
static void show_cnaf_page(Param *p, Return *rr)
static void SaveMimetypes(MVOdb *odb)
void show_navigation_bar(Return *r, const char *cur_page)
void ctrlc_handler(int sig)
static void PrintHistPlot(const HistPlot &hp)
void javascript_commands(Param *p, Return *r, const char *cookie_cpwd)
static int handle_decode_post(struct mg_connection *nc, const http_message *msg, const char *uri, const char *query_string, RequestTrace *t)
std::string time_to_string(time_t t)
static std::string mgstr(const mg_str *s)
int vaxis(gdImagePtr im, gdFont *font, int col, int gcol, int x1, int y1, int width, int minor, int major, int text, int label, int grid, double ymin, double ymax, BOOL logaxis)
static bool mongoose_passwords_enabled(const struct mg_connection *nc)
static int cmp_names(const void *a, const void *b)
INT sendmail(const char *from_host, const char *smtp_host, const char *from, const char *to, const char *subject, const char *text)
int find_file_mg(const char *filename, std::string &path, FILE **fpp, bool trace)
void decode_query(Param *pp, const char *query_string)
static bool gDoReloadHistory
static std::string check_digest_auth(struct http_message *hm, Auth *auth)
static MidasHistoryInterface * gMh
static bool trace_mg_verbose
static bool gDoSetupHistoryWatch
int get_hist_last_written(MVOdb *odb, const char *group, const char *panel, time_t endtime, int index, int want_all, time_t *plastwritten)
void taxis(gdImagePtr im, gdFont *font, int col, int gcol, int x1, int y1, int width, int xr, int minor, int major, int text, int label, int grid, double xmin, double xmax)
void show_password_page(Return *r, const char *dec_path, const char *password)
time_t string_to_time(const char *str)
void show_header(Return *r, const char *title, const char *method, const char *path, int refresh)
bool send_resource(Return *r, const std::string &name, bool generate_404=true)
void strencode3(Return *r, const char *text)
static std::vector< std::string > gAllowedHosts
bool send_file(Return *r, const std::string &path, bool generate_404=true)
static int xmg_check_nonce(const char *nonce)
void show_text_header(Return *r)
char * find_odb_tag(char *p, char *path, char *format, int *edit, char *type, char *pwd, char *tail)
static std::string UrlDecode(const char *p)
void strencode4(Return *r, const char *text)
void show_elog_attachment(Param *p, Return *r, const char *path)
void Unlock(RequestTrace *t)
int evaluate_src(char *key, char *src, double *fvalue)
void redirect(Return *r, const char *path)
static void urlDecode(char *p)
static std::string add_param_to_url(const char *name, const char *value)
#define READ_HISTORY_DATA
bool starts_with(const std::string &s1, const char *s2)
static const char * cgif_bar_str[]
static MidasHistoryInterface * get_history(bool reset=false)
void show_odb_tag(Param *pp, Return *r, const char *path, const char *keypath1, const char *format, int n_var, int edit, char *type, char *pwd, char *tail)
static int handle_http_get(struct mg_connection *nc, const http_message *msg, const char *uri, RequestTrace *t)
#define READ_HISTORY_RUNMARKER
std::string add_custom_path(const std::string &filename)
void sec_to_label(char *result, int sec, int base, int force_date)
void show_odb_page(Param *pp, Return *r, const char *dec_path, int write_access)
void send_icon(Return *r, const char *icon)
void Lock(RequestTrace *t)
void show_set_page(Param *pp, Return *r, const char *group, int index, const char *value)
void decode_post(Return *rr, const char *header, const char *string, const char *boundary, int length, const Cookies *c, const char *url, RequestTrace *t)
void show_hist_config_page(MVOdb *odb, Param *p, Return *r, const char *hgroup, const char *hpanel)
static const std::string find_cookie_mg(const struct http_message *msg, const char *cookie_name)
void do_jrpc(Param *p, Return *r)
const unsigned char favicon_ico[]
void init_mhttpd_odb(MVOdb *odb)
void check_obsolete_odb(HNDLE hDB, const char *odb_path)
void do_jrpc_rev1(Param *p, Return *r)
static RequestTraceBuf * gTraceBuf
const char * mhttpd_revision(void)
void show_hist_page(MVOdb *odb, Param *p, Return *r, const char *dec_path, char *buffer, int *buffer_size, int refresh)
static int handle_decode_get(struct mg_connection *nc, const http_message *msg, const char *uri, const char *query_string, RequestTrace *t)
void gen_odb_attachment(Return *r, const char *path, std::string &bout)
bool open_resource_file(const char *filename, std::string *ppath, FILE **pfp)
void redirect_307(Return *r, const char *path)
static std::string GetMimetype(const std::string &ext)
static double GetTimeSec()
void show_custom_page(Param *pp, Return *r, const char *cookie_cpwd)
static MJsonNode * set_http_trace(const MJsonNode *params)
const bool cmp_tags(const TAG &a, const TAG &b)
const bool cmp_events1(const std::string &a, const std::string &b)
#define READ_HISTORY_LAST_WRITTEN
int read_history(const HistPlot &hp, int index, int flags, time_t tstart, time_t tend, time_t scale, HistoryData *data)
static std::string toString(int i)
const MimetypeTableEntry gMimetypeTable[]
int time_to_sec(const char *str)
void show_help_page(Return *r, const char *dec_path)
void do_jrpc_rev0(Param *p, Return *r)
INT search_callback(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *info)
void init_menu_buttons(MVOdb *odb)
void generate_hist_graph(MVOdb *odb, Return *rr, const char *hgroup, const char *hpanel, char *buffer, int *buffer_size, int width, int height, time_t xendtime, int scale, int index, int labels, const char *bgcolor, const char *fgcolor, const char *gridcolor)
static const char * cgif_label_str[]
time_t mktime_with_dst(const struct tm *ptms)
int try_file_mg(const char *try_dir, const char *filename, std::string &path, FILE **fpp, bool trace)
void export_hist(MVOdb *odb, Return *r, const char *group, const char *panel, time_t endtime, int scale, int index, int labels)
static void xmg_http_send_digest_auth_request(struct mg_connection *c, const char *domain)
void interprete(Param *p, Return *r, Attachment *a, const Cookies *c, const char *dec_path, RequestTrace *t)
static const char default_system_list[20][NAME_LENGTH]
static void handle_http_options_cors(struct mg_connection *nc, const http_message *msg, RequestTrace *t)
static void SortHistPlotVars(HistPlot &hp)
const bool cmp_events(const std::string &a, const std::string &b)
int xdb_get_data_index(HNDLE hDB, const char *str, void *value, int size, int index, int tid)
void show_error_404(Return *r, const char *error)
static void handle_http_message(struct mg_connection *nc, http_message *msg)
static int xdb_find_key(HNDLE hDB, HNDLE dir, const char *str, HNDLE *hKey, int tid, int size)
static void AddHistPlotSelectedParam(HistPlot &hp, Param *p)
void show_custom_gif(Return *rr, const char *name)
static void LoadHistPlotFromOdb(MVOdb *odb, HistPlot *hp, const char *group, const char *panel)
static bool trace_mg_recv
static int NextHistPlotOrder(const HistPlot &hp)
bool ends_with_char(const std::string &s, char c)
std::string msprintf(const char *format,...)
#define DIR_SEPARATOR_STR
#define DEFAULT_WATCHDOG_TIMEOUT
#define MATTRPRINTF(a, b)
#define EQUIPMENT_COMMON_STR
std::vector< std::string > STRING_LIST
#define RUNINFO_STR(_name)
#define CNAF_INHIBIT_CLEAR
MidasHistoryInterface * mh
#define write(n, a, f, d)
int mg_http_parse_header2(struct mg_str *hdr, const char *var_name, char **buf, size_t buf_size)
int gettimeofday(struct timeval *tp, void *tzp)
std::vector< HistVar > vars
void Allocate(int xnvars)
static te_expr * base(state *s)
static te_expr * list(state *s)