19#include <condition_variable>
39#define DEFAULT_REFRESH 60
42static MUTEX_T* request_mutex = NULL;
60 sprintf(buf,
"%d",
i);
74 for (
int i=0;
i<3;
i++) {
81 for (
int i=0;
i<3;
i++) {
99extern const char *
mname[];
131 {
".ASC",
"text/plain" },
132 {
".CSS",
"text/css" },
133 {
".CSV",
"text/csv" },
134 {
".HTM",
"text/html" },
135 {
".HTML",
"text/html" },
136 {
".TXT",
"text/plain" },
138 {
".BMP",
"image/bmp" },
139 {
".GIF",
"image/gif" },
140 {
".ICO",
"image/x-icon" },
141 {
".JPEG",
"image/jpeg" },
142 {
".JPG",
"image/jpeg" },
143 {
".PNG",
"image/png" },
144 {
".SVG",
"image/svg+xml" },
145 {
".TIF",
"image/tiff" },
146 {
".TIFF",
"image/tiff" },
148 {
".MID",
"audio/midi" },
149 {
".MP3",
"audio/mpeg" },
150 {
".OGA",
"audio/ogg" },
151 {
".OGG",
"audio/ogg" },
152 {
".WAV",
"audio/wav" },
154 {
".BIN",
"application/octet-stream" },
155 {
".BZ",
"application/x-bzip" },
156 {
".BZ2",
"application/x-bzip2" },
157 {
".DOC",
"application/msword" },
158 {
".EPS",
"application/postscript" },
159 {
".GZ",
"application/gzip" },
160 {
".JS",
"application/javascript" },
161 {
".JSON",
"application/json" },
162 {
".MJS",
"application/javascript" },
163 {
".PDF",
"application/pdf" },
164 {
".PHP",
"application/x-httpd-php" },
165 {
".RTF",
"application/rtf" },
166 {
".PS",
"application/postscript" },
167 {
".ROOT",
"application/octet-stream" },
168 {
".XLS",
"application/x-msexcel" },
169 {
".XML",
"application/xml" },
170 {
".ZIP",
"application/zip" },
172 {
".ODP",
"application/vnd.oasis.opendocument.presentation" },
173 {
".ODS",
"application/vnd.oasis.opendocument.spreadsheet" },
174 {
".ODT",
"application/vnd.oasis.opendocument.text" },
184 std::string mimetype;
186 if (mimetype.length() > 0) {
213#define HTTP_ENCODING "UTF-8"
218 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
219 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
220 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
221 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x91, 0x68,
222 0x36, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4D,
223 0x45, 0x07, 0xD4, 0x0B, 0x1A, 0x08, 0x37, 0x07,
224 0x0D, 0x7F, 0x16, 0x5C, 0x00, 0x00, 0x00, 0x09,
225 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x2E, 0x23,
226 0x00, 0x00, 0x2E, 0x23, 0x01, 0x78, 0xA5, 0x3F,
227 0x76, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4D,
228 0x41, 0x00, 0x00, 0xB1, 0x8F, 0x0B, 0xFC, 0x61,
229 0x05, 0x00, 0x00, 0x01, 0x7D, 0x49, 0x44, 0x41,
230 0x54, 0x78, 0xDA, 0x63, 0xFC, 0xFF, 0xFF, 0x3F,
231 0x03, 0x29, 0x80, 0x09, 0xAB, 0xE8, 0xD2, 0x65,
232 0x77, 0x36, 0x6F, 0x7E, 0x8A, 0x5D, 0xC7, 0x7F,
233 0x0C, 0x30, 0x67, 0xEE, 0x0D, 0x56, 0xCE, 0xCD,
234 0x5C, 0xBC, 0x3B, 0xB6, 0x6D, 0x7F, 0x81, 0x29,
235 0xCB, 0x88, 0xE6, 0x24, 0x20, 0x57, 0x50, 0x7C,
236 0xDD, 0xCF, 0x1F, 0x6C, 0x40, 0xCB, 0xB5, 0xB5,
237 0x05, 0xCF, 0x1C, 0xB7, 0x42, 0xB3, 0x80, 0x05,
238 0x8D, 0xCF, 0xC8, 0xC8, 0x58, 0x5A, 0x2A, 0xFB,
239 0xF6, 0x4D, 0x37, 0x1B, 0xAB, 0xA0, 0xB4, 0x4C,
240 0x0A, 0x51, 0x4E, 0x02, 0x82, 0x85, 0xCB, 0x12,
241 0x0E, 0x1D, 0xAB, 0xC7, 0x2A, 0xC5, 0x82, 0x69,
242 0xC4, 0xAF, 0x5F, 0x7F, 0x1E, 0x3F, 0xF8, 0xCD,
243 0xCB, 0xF1, 0xF5, 0xEF, 0xDF, 0x7F, 0xCC, 0xCC,
244 0x4C, 0x84, 0x6D, 0x98, 0x59, 0xD5, 0xEB, 0xCF,
245 0xA5, 0x16, 0xC4, 0xAB, 0x71, 0x72, 0xCB, 0x21,
246 0x4C, 0x59, 0x74, 0x03, 0x5E, 0x3F, 0x7F, 0xB3,
247 0x6B, 0xD6, 0x22, 0x46, 0xA6, 0x7F, 0x0C, 0x0C,
248 0x7F, 0xD7, 0x75, 0x4D, 0xFB, 0xF1, 0xFD, 0x27,
249 0x81, 0x78, 0xB8, 0x7D, 0xE9, 0x0A, 0xCB, 0xFF,
250 0xDF, 0x4C, 0x8C, 0x8C, 0x40, 0xF6, 0xAD, 0x4B,
251 0x67, 0x1F, 0xDE, 0xBD, 0x8B, 0x45, 0x03, 0x3C,
252 0x60, 0x8F, 0x9D, 0xD8, 0xB3, 0xEB, 0x74, 0xB5,
253 0x90, 0x26, 0x07, 0x03, 0x48, 0xE4, 0x3F, 0x8F,
254 0xF6, 0xFF, 0x1B, 0x0F, 0x9A, 0x1E, 0x3E, 0x3A,
255 0xFB, 0xF3, 0xDB, 0x8F, 0xB7, 0x0F, 0x9E, 0x43,
256 0x83, 0xF1, 0xCF, 0xDF, 0x3F, 0x8A, 0x29, 0xCE,
257 0x3F, 0x7F, 0xFD, 0xFC, 0xCF, 0xF0, 0xDF, 0x98,
258 0xE9, 0xB5, 0x8F, 0xBD, 0x8A, 0x3C, 0x6F, 0xEC,
259 0xB9, 0x2D, 0x47, 0xFE, 0xFC, 0xFF, 0x6F, 0x16,
260 0x6C, 0xF3, 0xEC, 0xD3, 0x1C, 0x2E, 0x96, 0xEF,
261 0xBF, 0xAB, 0x7E, 0x32, 0x7D, 0xE2, 0x10, 0xCE,
262 0x88, 0xF4, 0x69, 0x2B, 0x60, 0xFC, 0xF4, 0xF5,
263 0x97, 0x78, 0x8A, 0x36, 0xD8, 0x44, 0x86, 0x18,
264 0x0D, 0xD7, 0x29, 0x95, 0x13, 0xD8, 0xD9, 0x58,
265 0xE1, 0x0E, 0xF8, 0xF1, 0xF3, 0xDB, 0xC6, 0xD6,
266 0xEC, 0x5F, 0x53, 0x8E, 0xBF, 0xFE, 0xC3, 0x70,
267 0x93, 0x8D, 0x6D, 0xDA, 0xCB, 0x0B, 0x4C, 0x3F,
268 0xFF, 0xFC, 0xFA, 0xCF, 0x0C, 0xB4, 0x09, 0x84,
269 0x54, 0xD5, 0x74, 0x91, 0x55, 0x03, 0x01, 0x07,
270 0x3B, 0x97, 0x96, 0x6E, 0xC8, 0x17, 0xFE, 0x7F,
271 0x4F, 0xF8, 0xFE, 0xBC, 0x95, 0x16, 0x60, 0x62,
272 0x62, 0x64, 0xE1, 0xE6, 0x60, 0x73, 0xD1, 0xB2,
273 0x7A, 0xFA, 0xE2, 0xF1, 0xDF, 0x3F, 0xFF, 0xC4,
274 0x78, 0x44, 0x31, 0xA3, 0x45, 0x2B, 0xD0, 0xE3,
275 0xF6, 0xD9, 0xE3, 0x2F, 0x2E, 0x9D, 0x29, 0xA9,
276 0xAC, 0x07, 0xA6, 0x03, 0xF4, 0xB4, 0x44, 0x10,
277 0x00, 0x00, 0x75, 0x65, 0x12, 0xB0, 0x49, 0xFF,
278 0x3F, 0x68, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45,
279 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82
283 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10,
284 0x10, 0x00, 0x01, 0x00, 0x04, 0x00, 0x28, 0x01,
285 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x28, 0x00,
286 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00,
287 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x0F,
291 0x0A, 0x00, 0x5C, 0x86, 0x4C, 0x00, 0x2F, 0x5E,
292 0x1A, 0x00, 0xBF, 0xD3, 0xD7, 0x00, 0x29, 0x17,
293 0x8D, 0x00, 0x50, 0xA7, 0xA4, 0x00, 0x59, 0x57,
294 0x7F, 0x00, 0xC6, 0xA3, 0xAC, 0x00, 0xFC, 0xFE,
295 0xFC, 0x00, 0x28, 0x12, 0x53, 0x00, 0x58, 0x7D,
296 0x72, 0x00, 0xC4, 0x3A, 0x34, 0x00, 0x3C, 0x3D,
297 0x69, 0x00, 0xC5, 0xB6, 0xB9, 0x00, 0x94, 0x92,
298 0x87, 0x00, 0x7E, 0x7A, 0xAA, 0x00, 0x88, 0x88,
299 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x81, 0x22,
300 0xD8, 0x88, 0x88, 0x88, 0xF6, 0xD8, 0x82, 0x22,
301 0xE8, 0x88, 0x88, 0x8D, 0x44, 0x98, 0x82, 0x22,
302 0xA8, 0x88, 0x88, 0x8F, 0x44, 0x48, 0x82, 0x22,
303 0x25, 0x76, 0x67, 0x55, 0x44, 0xF8, 0x88, 0x88,
304 0x3A, 0xC9, 0x9C, 0x53, 0x83, 0x88, 0x88, 0x88,
305 0x8D, 0x99, 0x99, 0x38, 0x88, 0x88, 0x88, 0x88,
306 0x88, 0x99, 0x9C, 0x88, 0x88, 0x88, 0x88, 0x88,
307 0x88, 0xF9, 0x9D, 0x88, 0x88, 0x88, 0x88, 0x88,
308 0x88, 0x8A, 0x58, 0x88, 0x88, 0x88, 0x88, 0x88,
309 0x88, 0x85, 0xD8, 0x88, 0x88, 0x88, 0x88, 0x88,
310 0x88, 0xEA, 0xAE, 0x88, 0x88, 0x88, 0x88, 0x88,
311 0x88, 0x00, 0x0B, 0x88, 0x88, 0x88, 0x88, 0x88,
312 0x88, 0x70, 0x0D, 0x88, 0x88, 0x88, 0x88, 0x88,
313 0x88, 0x87, 0xD8, 0x88, 0x88, 0x88, 0x88, 0x88,
314 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
331 int minor,
int major,
int text,
int label,
int grid,
double ymin,
double ymax,
334 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax);
336void show_header(
Return* r,
const char *title,
const char *method,
const char *path,
int refresh);
343 char c1, c2, *ps, *pp;
345 if (
str == NULL || pattern == NULL)
350 pp = (
char *) pattern;
353 if (toupper(c1) == toupper(c2)) {
358 if (toupper(c1) != toupper(c2))
380 return tv.tv_sec*1.0 +
tv.tv_usec/1000000.0;
426 printf(
"M %s ",
fMethod.c_str());
427 printf(
"URL %s ",
fUri.c_str());
428 if (
fRPC.length() > 0) {
429 printf(
"RPC %s ",
fRPC.c_str());
441 std::vector<RequestTrace*>
fBuf;
477 for (
unsigned i=0;
i<
fBuf.size();
i++) {
486 for (
unsigned i=0;
i<
fBuf.size();
i++) {
488 if (
fBuf[
k] != NULL) {
490 if (
fBuf[
k] == NULL) {
497 if (
fBuf[
k] == NULL) {
511#define WEB_BUFFER_SIZE (6*1024*1024)
560 for (
int i=0;
i<1000;
i++) {
572 assert(!
"Cannot happen!");
588void rread(
const char* filename,
int fh,
int len)
593 cm_msg(
MERROR,
"rread",
"Cannot read file \'%s\', read of %d returned %d, errno %d (%s)", filename, len, rd, errno, strerror(errno));
604 size_t len = strlen(
str);
623 size_t len = strlen(
str);
632 for (
size_t i = 0;
i < len;
i++) {
633 if (strncmp(
str +
i,
"http://", 7) == 0) {
636 char* p = (
char *) (
str +
i + 7);
639 for (
k = 0; *p && *p !=
' ' && *p !=
'\n';
k++,
i++)
643 sprintf(
return_buffer +
j,
"<a href=\"http://%s\">http://%s</a>", link, link);
698#define PARAM_LENGTH 256
699#define TEXT_SIZE 50000
732 printf(
"Error: parameter value too big\n");
746 int size = strlen(
value)+1;
747 _value[
i] = (
char*)malloc(size);
752 printf(
"Error: parameter array too small\n");
856 if (isxdigit(p[0]) && isxdigit(p[1])) {
862 sscanf(
str,
"%02X", &
i);
868 }
else if (*p ==
'+') {
898 if (isxdigit(p[0]) && isxdigit(p[1])) {
902 sscanf(
str,
"%02X", &
i);
908 }
else if (*p ==
'+') {
928 int len = strlen(ps);
929 char *
str = (
char*)malloc(len*3 + 10);
937 sprintf(pd,
"%%%02X", (*p)&0xFF);
945 printf(
"urlEncode [");
946 for (p=ps; *p!=0; p++)
947 printf(
"0x%02x ", (*p)&0xFF);
950 printf(
"urlEncode [%s] -> [%s]\n", ps,
str);
953 mstrlcpy(ps,
str, ps_size);
965 const char* p = text;
971 sprintf(buf,
"%%%02X", (*p)&0xFF);
978 printf(
"urlEncode [");
979 for (p=text; *p!=0; p++)
980 printf(
"0x%02x ", (*p)&0xFF);
983 printf(
"urlEncode [%s] -> [%s]\n", text, encoded.c_str());
998 std::vector<std::string> paths;
1004 paths.push_back(buf);
1012 paths.push_back(buf);
1016 paths.push_back(cwd +
"/");
1017 paths.push_back(cwd +
"/resources/");
1021 char *m = getenv(
"MIDASSYS");
1023 paths.push_back(std::string(m) +
"/resources/");
1037 if (strlen(filename) < 1) {
1038 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' is too short",
1044 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' starting with \'%c\' which is not allowed",
1049 if (strstr(filename,
"..") != NULL) {
1050 cm_msg(
MERROR,
"open_resource_file",
"Invalid resource file name \'%s\' containing \'..\' which is not allowed",
1057 std::vector<std::string> paths_not_found;
1059 for (
unsigned i=0;
i<paths.size();
i++) {
1060 std::string path = paths[
i];
1061 if (path.length() < 1)
1079 FILE*
fp = fopen(xpath.c_str(),
"r");
1081 struct stat statbuf;
1082 int status = fstat(fileno(
fp), &statbuf);
1084 cm_msg(
MERROR,
"open_resource_file",
"Cannot fstat() file \'%s\', error %d (%s)", xpath.c_str(), errno, strerror(errno));
1089 if (statbuf.st_mode & S_IFREG) {
1095 }
else if (statbuf.st_mode & S_IFDIR) {
1096 cm_msg(
MERROR,
"open_resource_file",
"File \'%s\' for resource \'%s\' is a directory", xpath.c_str(), filename);
1100 cm_msg(
MERROR,
"open_resource_file",
"File \'%s\' for resource \'%s\' is not a regular file, st_mode is 0x%08x", xpath.c_str(), filename, statbuf.st_mode);
1119 paths_not_found.push_back(xpath);
1123 for (
unsigned i=0;
i<paths_not_found.size();
i++) {
1126 s += paths_not_found[
i];
1129 cm_msg(
MERROR,
"open_resource_file",
"Cannot find resource file \'%s\', tried %s", filename, s.c_str());
1137 std::string ext_upper;
1138 const char* p = filename;
1139 const char* last_dot = NULL;
1150 ext_upper += toupper(*p);
1156 if (
type.length() > 0)
1159 cm_msg(
MERROR,
"get_content_type",
"Unknown HTTP Content-Type for resource file \'%s\', file extension \'%s\'", filename, ext_upper.c_str());
1161 return "text/plain";
1172 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1174 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
1178 time_t now = time(NULL);
1179 now += (int) (3600 * 24);
1181 gmtime_r(&now, &gmt_tms);
1182 const char* format =
"%A, %d-%b-%y %H:%M:%S GMT";
1185 strftime(
str,
sizeof(
str), format, &gmt_tms);
1194 struct stat stat_buf;
1195 fstat(fileno(
fp), &stat_buf);
1196 int length = stat_buf.st_size;
1197 r->
rsprintf(
"Content-Length: %d\r\n", length);
1205 r->
rread(path.c_str(), fileno(
fp), length);
1214 FILE *
fp = fopen(path.c_str(),
"rb");
1219 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1223 r->
rsprintf(
"Error: Cannot read \"%s\", fopen() errno %d (%s)\n", path.c_str(), errno, strerror(errno));
1241 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1245 r->
rsprintf(
"Error: resource file \"%s\" not found, see messages\n",
name.c_str());
1255INT sendmail(
const char* from_host,
const char *smtp_host,
const char *from,
const char *to,
const char *subject,
const char *text)
1257 struct sockaddr_in bind_addr;
1258 struct hostent *phe;
1260 char *
str, buf[256];
1263 printf(
"\n\nEmail from %s to %s, SMTP host %s:\n", from, to, smtp_host);
1266 s =
socket(AF_INET, SOCK_STREAM, 0);
1271 memset(&bind_addr, 0,
sizeof(bind_addr));
1272 bind_addr.sin_family = AF_INET;
1273 bind_addr.sin_port = htons((
short) 25);
1275 phe = gethostbyname(smtp_host);
1278 memcpy((
char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
1280 if (connect(s, (
const sockaddr*)&bind_addr,
sizeof(bind_addr)) < 0) {
1286 str = (
char*)malloc(strsize);
1288 assert(
str != NULL);
1302 sprintf(
str,
"HELO %s\r\n", from_host);
1303 send(s,
str, strlen(
str), 0);
1310 if (strchr(from,
'<')) {
1311 mstrlcpy(buf, strchr(from,
'<') + 1,
sizeof(buf));
1312 if (strchr(buf,
'>'))
1313 *strchr(buf,
'>') = 0;
1315 mstrlcpy(buf, from,
sizeof(buf));
1317 sprintf(
str,
"MAIL FROM: %s\n", buf);
1318 send(s,
str, strlen(
str), 0);
1325 sprintf(
str,
"RCPT TO: <%s>\r\n", to);
1326 send(s,
str, strlen(
str), 0);
1333 sprintf(
str,
"DATA\r\n");
1334 send(s,
str, strlen(
str), 0);
1341 sprintf(
str,
"To: %s\r\nFrom: %s\r\nSubject: %s\r\n", to, from, subject);
1342 send(s,
str, strlen(
str), 0);
1347 send(s,
str, strlen(
str), 0);
1355 localtime_r(&now, &tms);
1356 strftime(buf,
sizeof(buf),
"%a, %d %b %Y %H:%M:%S", &tms);
1357 offset = (-(int) timezone);
1360 sprintf(
str,
"Date: %s %+03d%02d\r\n", buf, (
int) (
offset / 3600),
1361 (
int) ((abs((
int)
offset) / 60) % 60));
1362 send(s,
str, strlen(
str), 0);
1366 sprintf(
str,
"Content-Type: TEXT/PLAIN; charset=US-ASCII\r\n\r\n");
1367 send(s,
str, strlen(
str), 0);
1372 const char* p = text;
1374 while (strstr(p,
"\r\n.\r\n")) {
1376 mstrlcat(
str, p,
i);
1378 mstrlcat(
str,
"\r\n..\r\n", strsize);
1380 mstrlcat(
str, p, strsize);
1381 mstrlcat(
str,
"\r\n", strsize);
1382 send(s,
str, strlen(
str), 0);
1387 sprintf(
str,
".\r\n");
1388 send(s,
str, strlen(
str), 0);
1395 sprintf(
str,
"QUIT\n");
1396 send(s,
str, strlen(
str), 0);
1417 mstrlcpy(
str, path,
sizeof(
str));
1422 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
1426 if (strncmp(path,
"http:", 5) == 0)
1427 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1428 else if (strncmp(path,
"https:", 6) == 0)
1429 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1431 r->
rsprintf(
"Location: %s\r\n\r\n<html>redir</html>\r\n",
str);
1440 r->
rsprintf(
"HTTP/1.1 307 Temporary Redirect\r\n");
1443 r->
rsprintf(
"Location: %s\r\n", path);
1445 r->
rsprintf(
"<html>redirect to %s</html>\r\n", path);
1478 for (
i = 0; search_name[
i] ;
i++)
1479 str2[
i] = toupper(search_name[
i]);
1482 if (strstr(xstr1, str2) != NULL) {
1485 std::string path_encoded =
urlEncode(path.c_str());
1489 r->
rsprintf(
"<tr><td class=\"ODBkey\"><a href=\"?cmd=odb&odb_path=/%s\">/%s</a></tr>\n", path_encoded.c_str(), path.c_str());
1492 char* p =
const_cast<char *
>(path.data() + path.length() - 1);
1493 while (*p && *p !=
'/')
1500 size =
sizeof(
data);
1502 std::string data_str;
1504 data_str =
"<no read access>";
1508 r->
rsprintf(
"<tr><td class=\"ODBkey\">");
1509 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=/%s\">/%s/%s</a></td>", path_encoded.c_str(), path.c_str(),
key->
name);
1510 r->
rsprintf(
"<td class=\"ODBvalue\">%s</td></tr>\n", data_str.c_str());
1516 r->
rsprintf(
"<tr><td rowspan=%d class=\"ODBkey\">",
i);
1517 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=/%s\">/%s/%s\n", path_encoded.c_str(), path.c_str(),
key->
name);
1520 size =
sizeof(
data);
1528 r->
rsprintf(
"<td class=\"ODBvalue\">[%d] %s</td></tr>\n",
i, data_str.c_str());
1551 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
1552 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
1555 r->
rsprintf(
"<table class=\"mtable\" style=\"width: 95%%\">\n");
1557 r->
rsprintf(
" <td class=\"mtableheader\">MIDAS Help Page</td>\n");
1564 r->
rsprintf(
" <td style=\"text-align:right;\">Documentation:</td>\n");
1565 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://midas.triumf.ca\">https://midas.triumf.ca</a></td>\n");
1568 r->
rsprintf(
" <td style=\"text-align:right;\">Discussion Forum:</td>\n");
1569 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://midas.triumf.ca/forum/\">https://midas.triumf.ca/forum/</a></td>\n");
1572 r->
rsprintf(
" <td style=\"text-align:right;\">Code:</td>\n");
1573 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://bitbucket.org/tmidas/midas/\">https://bitbucket.org/tmidas/midas/</a></td>\n");
1576 r->
rsprintf(
" <td style=\"text-align:right;\">Report a bug:</td>\n");
1577 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"https://bitbucket.org/tmidas/midas/issues/\">https://bitbucket.org/tmidas/midas/issues/</a></td>\n");
1581 r->
rsprintf(
" <td style=\"text-align:right;\">Version:</td>\n");
1585 r->
rsprintf(
" <td style=\"text-align:right;\">Revision:</td>\n");
1587 std::string url =
"https://bitbucket.org/tmidas/midas/commits/";
1593 std::string::size_type pos = rev.find(
"-g");
1594 if (pos != std::string::npos) {
1595 std::string hash = rev.substr(pos+2);
1596 pos = hash.find(
"-dirty");
1597 if (pos != std::string::npos) {
1598 hash = hash.substr(0, pos);
1600 pos = hash.find(
" ");
1601 if (pos != std::string::npos) {
1602 hash = hash.substr(0, pos);
1605 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"%s\">%s</a></td>\n", url.c_str(), rev.c_str());
1607 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", rev.c_str());
1612 r->
rsprintf(
" <td style=\"text-align:right;\">MIDASSYS:</td>\n");
1613 s = getenv(
"MIDASSYS");
1614 if (!s) s =
"(unset)";
1615 mstrlcpy(
str, s,
sizeof(
str));
1616 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n",
str);
1620 r->
rsprintf(
" <td style=\"text-align:right;\">mhttpd current directory:</td>\n");
1622 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", cwd.c_str());
1626 r->
rsprintf(
" <td style=\"text-align:right;\">Exptab file:</td>\n");
1631 r->
rsprintf(
" <td style=\"text-align:right;\">Experiment:</td>\n");
1636 r->
rsprintf(
" <td style=\"text-align:right;\">Experiment directory:</td>\n");
1644 if (
list.size() == 1) {
1646 r->
rsprintf(
" <td style=\"text-align:right;\">System logfile:</td>\n");
1649 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", s.c_str());
1653 r->
rsprintf(
" <td style=\"text-align:right;\">Logfiles:</td>\n");
1654 r->
rsprintf(
" <td style=\"text-align:left;\">\n");
1655 for (
unsigned i=0 ;
i<
list.size() ;
i++) {
1668 r->
rsprintf(
" <td style=\"text-align:right;\">Image history:</td>\n");
1673 r->
rsprintf(
" <td style=\"text-align:right;\">Resource paths:</td>\n");
1674 r->
rsprintf(
" <td style=\"text-align:left;\">");
1676 for (
unsigned i=0;
i<resource_paths.size();
i++) {
1679 r->
rsputs(resource_paths[
i].c_str());
1682 if (exp != resource_paths[
i]) {
1694 r->
rsprintf(
" <td style=\"text-align:right;\">midas.css:</td>\n");
1696 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1698 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1702 r->
rsprintf(
" <td style=\"text-align:right;\">midas.js:</td>\n");
1704 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1706 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1710 r->
rsprintf(
" <td style=\"text-align:right;\">controls.js:</td>\n");
1712 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1714 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1718 r->
rsprintf(
" <td style=\"text-align:right;\">mhttpd.js:</td>\n");
1720 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1722 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1726 r->
rsprintf(
" <td style=\"text-align:right;\">obsolete.js:</td>\n");
1728 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1730 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1734 r->
rsprintf(
" <td style=\"text-align:right;\">Obsolete mhttpd.css:</td>\n");
1736 r->
rsprintf(
" <td style=\"text-align:left;\">%s</td>\n", path.c_str());
1738 r->
rsprintf(
" <td style=\"text-align:left;\">NOT FOUND</td>\n");
1742 r->
rsprintf(
" <td style=\"text-align:right;\">JSON-RPC schema:</td>\n");
1743 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?mjsonrpc_schema\">json format</a> or <a href=\"?mjsonrpc_schema_text\">text table format</a></td>\n");
1747 r->
rsprintf(
" <td style=\"text-align:right;\">JavaScript examples:</td>\n");
1748 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=example\">example.html</a></td>\n");
1752 r->
rsprintf(
" <td style=\"text-align:right;\">Custom page example:</td>\n");
1753 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=custom_example\">custom_example.html</a></td>\n");
1757 r->
rsprintf(
" <td style=\"text-align:right;\">MPlot custom plot examples:</td>\n");
1758 r->
rsprintf(
" <td style=\"text-align:left;\"><a href=\"?cmd=plot_example\">plot_example.html</a></td>\n");
1766 r->
rsprintf(
"<table class=\"mtable\" style=\"width: 95%%\">\n");
1768 r->
rsprintf(
" <td class=\"mtableheader\">Contributions</td>\n");
1772 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");
1792 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1794 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
1795 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
1798 r->
rsprintf(
"<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n");
1802 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
1803 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
1804 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
1808 r->
rsprintf(
"<meta http-equiv=\"Refresh\" content=\"%02d\">\n", refresh);
1810 r->
rsprintf(
"<title>%s</title></head>\n", title);
1812 mstrlcpy(
str, path,
sizeof(
str));
1817 (
"<body><form name=\"form1\" method=\"POST\" action=\"%s\" enctype=\"multipart/form-data\">\n\n",
1820 r->
rsprintf(
"<body><form name=\"form1\" method=\"GET\" action=\"%s\">\n\n",
str);
1824 std::string exptname;
1833 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1835 r->
rsprintf(
"Access-Control-Allow-Origin: *\r\n");
1836 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
1837 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
1846 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
1851 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
1852 r->
rsprintf(
"<title>MIDAS error</title></head>\n");
1853 r->
rsprintf(
"<body><H1>%s</H1></body></html>\n", error);
1861 r->
rsprintf(
"HTTP/1.1 404 Not Found\r\n");
1863 r->
rsprintf(
"Content-Type: text/plain\r\n");
1866 r->
rsprintf(
"MIDAS error: %s\n", error);
1874 r->
rsprintf(
"window.addEventListener(\"load\", function(e) { mhttpd_init('%s', 1000); });\n", cur_page);
1877 r->
rsprintf(
"<!-- header and side navigation will be filled in mhttpd_init -->\n");
1878 r->
rsprintf(
"<div id=\"mheader\"></div>\n");
1879 r->
rsprintf(
"<div id=\"msidenav\"></div>\n");
1880 r->
rsprintf(
"<div id=\"mmain\">\n");
1890 cm_msg(
MERROR,
"check_obsolete_odb",
"ODB \"%s\" is obsolete, please delete it.", odb_path);
1899 int size =
sizeof(true_value);
1945 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/Base URL\" is obsolete, please delete it.");
1950 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/CSS File\" is obsolete, please delete it.");
1955 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/JS File\" is obsolete, please delete it.");
1960 cm_msg(
MERROR,
"init_mhttpd_odb",
"ODB \"/Experiment/Start-Stop Buttons\" is obsolete, please delete it.");
1963 bool xdefault =
true;
1964 odb->RB(
"Experiment/Pause-Resume Buttons", &xdefault,
true);
1966#ifdef HAVE_MONGOOSE616
1975 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.");
1991 std::string external_elog_url;
1993 size =
sizeof(external_elog);
1999 size =
sizeof(
BOOL);
2005 const char def_button[][
NAME_LENGTH] = {
"8h",
"24h",
"7d" };
2026 size_t len = strlen(text);
2027 for (
size_t i = 0;
i < len;
i++) {
2055 size_t len = strlen(text);
2056 for (
size_t i = 0;
i < len;
i++) {
2085 size_t len = strlen(text);
2086 for (
size_t i = 0;
i < len;
i++) {
2110 size_t len = strlen(text);
2111 for (
size_t i = 0;
i < len;
i++) {
2157 bout +=
"<table border=3 cellpadding=1 class=\"dialogTable\">\n";
2159 ctime_r(&now, ctimebuf);
2160 bout +=
msprintf(
"<tr><th colspan=2>%s</tr>\n", ctimebuf);
2161 bout +=
msprintf(
"<tr><th colspan=2>%s</tr>\n", path);
2182 size =
sizeof(
data);
2188 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2189 data_str =
"(empty)";
2193 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
2197 bout +=
"</td><td>";
2201 bout +=
")</td></tr>\n";
2205 bout +=
"</td></tr>\n";
2212 size =
sizeof(
data);
2217 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2218 data_str =
"(empty)";
2226 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
2234 bout +=
")<br></td></tr>\n";
2241 bout +=
"<br></td></tr>\n";
2248 bout +=
"</table>\n";
2255 char path[256], path1[256];
2256 char mail_to[256], mail_from[256], mail_list[256],
2257 smtp_host[256], tag[80], mail_param[1000];
2260 char att_file[3][256];
2261 int fh, size, n_mail;
2262 char mhttpd_full_url[256];
2265 mstrlcpy(att_file[0], pp->
getparam(
"attachment0"),
sizeof(att_file[0]));
2266 mstrlcpy(att_file[1], pp->
getparam(
"attachment1"),
sizeof(att_file[1]));
2267 mstrlcpy(att_file[2], pp->
getparam(
"attachment2"),
sizeof(att_file[2]));
2270 for (
int i = 0;
i < 3;
i++) {
2272 sprintf(
str,
"attachment%d",
i);
2277 mstrlcpy(path1, path,
sizeof(path1));
2278 while (strchr(path,
'\\'))
2279 *strchr(path,
'\\') =
'/';
2285 int bufsize = bout.length()+1;
2286 char* buf = (
char*)
M_MALLOC(bufsize);
2287 memcpy(buf, bout.c_str(), bufsize);
2288 mstrlcpy(att_file[
i], path,
sizeof(att_file[0]));
2289 mstrlcat(att_file[
i],
".html",
sizeof(att_file[0]));
2294 else if ((fh = open(path1, O_RDONLY |
O_BINARY)) >= 0) {
2295 size = lseek(fh, 0, SEEK_END);
2297 lseek(fh, 0, SEEK_SET);
2298 int rd =
read(fh, buf, size);
2302 mstrlcpy(att_file[
i], path,
sizeof(att_file[0]));
2305 }
else if (strncmp(path,
"/HS/", 4) == 0) {
2306 char* buf = (
char*)
M_MALLOC(100000);
2308 mstrlcpy(
str, path + 4,
sizeof(
str));
2309 if (strchr(
str,
'?')) {
2310 p = strchr(
str,
'?') + 1;
2322 p = strtok(NULL,
"&");
2325 *strchr(
str,
'?') = 0;
2328 mstrlcpy(att_file[
i],
str,
sizeof(att_file[0]));
2336 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
2341 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
2342 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
2343 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
2344 r->
rsprintf(
"<title>ELog Error</title></head>\n");
2345 r->
rsprintf(
"<i>Error: Attachment file <i>%s</i> not valid.</i><p>\n", pp->
getparam(
str));
2346 r->
rsprintf(
"Please go back and enter a proper filename (use the <b>Browse</b> button).\n");
2347 r->
rsprintf(
"<body></body></html>\n");
2353 int edit = atoi(pp->
getparam(
"edit"));
2358 mstrlcpy(tag, pp->
getparam(
"orig"),
sizeof(tag));
2368 *pp->
getparam(
"html") ?
"HTML" :
"plain",
2381 std::string elog_host_name;
2388 sprintf(mhttpd_full_url,
"http://%s/", elog_host_name.c_str());
2396 str +=
"/Elog/Email ";
2403 size =
sizeof(mail_list);
2407 show_error(r,
"No SMTP host defined under /Elog/SMTP host");
2410 size =
sizeof(smtp_host);
2413 p = strtok(mail_list,
",");
2415 mstrlcpy(mail_to, p,
sizeof(mail_to));
2417 std::string exptname;
2420 sprintf(mail_from,
"MIDAS %s <MIDAS@%s>", exptname.c_str(), elog_host_name.c_str());
2422 std::string mail_text;
2423 mail_text +=
"A new entry has been submitted by ";
2424 mail_text += pp->
getparam(
"author");
2428 mail_text +=
"Experiment : ";
2429 mail_text += exptname.c_str();
2432 mail_text +=
"Type : ";
2436 mail_text +=
"System : ";
2437 mail_text += pp->
getparam(
"system");
2440 mail_text +=
"Subject : ";
2441 mail_text += pp->
getparam(
"subject");
2444 mail_text +=
"Link : ";
2445 mail_text += mhttpd_full_url;
2446 mail_text +=
"/EL/";
2455 sendmail(elog_host_name.c_str(), smtp_host, mail_from, mail_to, pp->
getparam(
"type"), mail_text.c_str());
2457 if (mail_param[0] == 0)
2458 mstrlcpy(mail_param,
"?",
sizeof(mail_param));
2460 mstrlcat(mail_param,
"&",
sizeof(mail_param));
2461 sprintf(mail_param + strlen(mail_param),
"mail%d=%s", n_mail++, mail_to);
2463 p = strtok(NULL,
",");
2472 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
2481 r->
rsprintf(
"Location: ?cmd=Show+elog&tag=%s&%s\n\n<html>redir</html>\r\n", tag, mail_param + 1);
2483 r->
rsprintf(
"Location: ?cmd=Show+elog&tag=%s\n\n<html>redir</html>\r\n", tag);
2513 lseek(fh, 0, SEEK_END);
2514 int length =
TELL(fh);
2515 lseek(fh, 0, SEEK_SET);
2517 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
2519 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
2524 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
2544 sprintf(
str,
"/Equipment/%s/Settings/Editable", eq_name);
2566 int i,
j,
k, colspan, size, n_var, i_edit, i_set, line;
2567 char eq_name[32], group[32];
2577 i_edit = atoi(pp->
getparam(
"index"));
2582 i_set = atoi(pp->
getparam(
"index"));
2586 mstrlcpy(eq_name, pp->
getparam(
"eq"),
sizeof(eq_name));
2587 mstrlcpy(group,
"All",
sizeof(group));
2589 mstrlcpy(group, pp->
getparam(
"group"),
sizeof(group));
2594 sprintf(
str,
"/Equipment/%s/Settings", eq_name);
2597 HNDLE hkeynames = 0;
2608 if (strncmp(
key.
name,
"Names", 5) == 0)
2614 if (!hkeyset || !hkeynames) {
2616 sprintf(
str,
"?cmd=odb&odb_path=/Equipment/%s/Variables", eq_name);
2623 show_header(r,
"MIDAS slow control",
"", group, i_edit == -1 ? refresh : 0);
2624 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
2625 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
2626 r->
rsprintf(
"<script type=\"text/javascript\" src=\"obsolete.js\"></script>\n");
2631 r->
rsprintf(
"<tr><td colspan=15>\n");
2634 r->
rsprintf(
"<input type=submit name=cmd value=Set>\n");
2639 r->
rsprintf(
"<table class=\"ODBtable\" style=\"max-width:700px;\">");
2643 r->
rsprintf(
"<tr><td class=\"subStatusTitle\" colspan=15><i>Equipment:</i> \n");
2671 if (strncmp(
key.
name,
"Names", 5) == 0) {
2692 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names", eq_name);
2699 r->
rsprintf(
"<tr><td colspan=15><i>Groups:</i> ");
2703 r->
rsprintf(
"<b>All</b> ");
2705 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s\">All</a> ",
urlEncode(eq_name).c_str());
2709 memset(group_name, 0,
sizeof(group_name));
2713 for (
int level = 0; ; level++) {
2714 bool next_level =
false;
2717 size =
sizeof(name_str);
2720 char *s = strchr(name_str,
'%');
2721 for (
int k=0; s &&
k<level;
k++)
2722 s = strchr(s+1,
'%');
2726 if (strchr(s+1,
'%'))
2736 mstrlcpy(group_name[
j], name_str,
sizeof(group_name[0]));
2746 r->
rsprintf(
"<b>%s</b> ", group_name[
i]);
2748 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]);
2752 r->
rsprintf(
"<i>ODB:</i> ");
2753 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Common\">Common</a> ",
urlEncode(eq_name).c_str());
2754 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Settings\">Settings</a> ",
urlEncode(eq_name).c_str());
2755 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Variables\">Variables</a> ",
urlEncode(eq_name).c_str());
2759 std::string vars_path =
msprintf(
"/Equipment/%s/Variables", eq_name);
2773 if (
i == 0 ||
i > 15) {
2780 r->
rsprintf(
"<tr class=\"subStatusTitle\"><th colspan=%d>Names", colspan);
2783 for (
int i = 0;;
i++) {
2798 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names", eq_name);
2807 for (
int i = 0;
i < num_values;
i++) {
2808 char names_str[256];
2809 size =
sizeof(names_str);
2813 mstrlcpy(
name, names_str,
sizeof(
name));
2819 char *s = strstr(
name, group);
2822 if (
name[strlen(group)] !=
'%')
2826 if (strlen(
name) < 1)
2827 sprintf(
name,
"[%d]",
i);
2830 r->
rsprintf(
"<tr class=\"ODBtableEven\"><td colspan=%d><nobr>%s</nobr>", colspan,
name);
2832 r->
rsprintf(
"<tr class=\"ODBtableOdd\"><td colspan=%d><nobr>%s</nobr>", colspan,
name);
2834 for (
int j = 0;;
j++) {
2847 size =
sizeof(
data);
2852 if (n_var == i_set) {
2864 if (n_var == i_edit) {
2866 r->
rsprintf(
"<input type=text size=10 maxlenth=80 name=value value=\"%s\">\n", data_str.c_str());
2867 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set>\n");
2868 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", i_edit);
2871 sprintf(odb_path,
"Equipment/%s/Variables/%s[%d]", eq_name, varkey.
name,
i);
2873 r->
rsprintf(
"<a href=\"#\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\', 0);return false;\" >%s</a>", odb_path, data_str.c_str());
2877 r->
rsprintf(
"<td align=center>%s", data_str.c_str());
2884 r->
rsprintf(
"<tr><td colspan=15><i>Groups:</i> ");
2888 r->
rsprintf(
"<b>All</b> ");
2890 r->
rsprintf(
"<a href=\"?cmd=eqtable&eq=%s\">All</a> ", eq_name);
2894 std::string vars_path =
msprintf(
"/Equipment/%s/Variables", eq_name);
2899 for (
int i = 0;;
i++) {
2917 r->
rsprintf(
"<i>ODB:</i> ");
2918 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Common\">Common</a> ",
urlEncode(eq_name).c_str());
2919 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Settings\">Settings</a> ",
urlEncode(eq_name).c_str());
2920 r->
rsprintf(
"<a href=\"?cmd=odb&odb_path=Equipment/%s/Variables\">Variables</a> ",
urlEncode(eq_name).c_str());
2930 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
2932 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
2944 r->
rsprintf(
"<tr class=\"subStatusTitle\"><th colspan=9>Names<th>%s</tr>\n", varkey.
name);
2947 HNDLE hkeyroot = hkey;
2960 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<br></tr>\n", style,
key.
name);
2964 size =
sizeof(
data);
2970 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2971 data_str =
"(empty)";
2975 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
2977 (
"<tr class=\"%s\" ><td colspan=9>%s<td align=center>%s (%s)<br></tr>\n",
2978 style,
key.
name, data_str.c_str(), hex_str.c_str());
2980 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<td align=center>%s<br></tr>\n",
2981 style,
key.
name, data_str.c_str());
2989 size =
sizeof(
data);
2994 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
2995 data_str =
"(empty)";
3002 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
3003 r->
rsprintf(
"<td>[%d] %s (%s)<br></tr>\n",
k, data_str.c_str(), hex_str.c_str());
3005 r->
rsprintf(
"<td>[%d] %s<br></tr>\n",
k, data_str.c_str());
3013 std::string names_path =
msprintf(
"/Equipment/%s/Settings/Names %s", eq_name, varkey.
name);
3021 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s<td align=center><i>... %d values ...</i>",
3027 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
3029 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
3033 size =
sizeof(
name);
3036 sprintf(
name,
"%s[%d]", varkey.
name,
j);
3039 if (strlen(
name) < 1) {
3040 sprintf(
name,
"%s[%d]", varkey.
name,
j);
3043 r->
rsprintf(
"<tr class=\"%s\"><td colspan=9>%s", style,
name);
3045 size =
sizeof(
data);
3050 if (n_var == i_set) {
3059 sprintf(
str,
"%s", group);
3063 if (n_var == i_edit) {
3064 r->
rsprintf(
"<td align=center><input type=text size=10 maxlenth=80 name=value value=\"%s\">\n", data_str.c_str());
3065 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set></tr>\n");
3066 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", i_edit);
3067 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
3070 sprintf(odb_path,
"Equipment/%s/Variables/%s[%d]", eq_name, varkey.
name,
j);
3073 r->
rsprintf(
"<a href=\"#\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\', 0);return false;\" >%s</a>", odb_path, data_str.c_str());
3078 r->
rsprintf(
"<td align=center>%s\n", data_str.c_str());
3100 char str[256], *ps, *pt;
3108 strcpy(
type,
"text");
3110 while (*p && *p !=
'<')
3118 while (*p && ((*p ==
' ') || iscntrl(*p)))
3136 while (*p && ((*p ==
' ') || iscntrl(*p)))
3146 while (*p && *p !=
'\"')
3152 while (*p && *p !=
' ' && *p !=
'>')
3165 while (*p && *p !=
'\"')
3171 while (*p && *p !=
' ' && *p !=
'>')
3192 while (*p && *p !=
' ' && *p !=
'>')
3204 while (*p && *p !=
'\"')
3210 while (*p && *p !=
' ' && *p !=
'>')
3221 while (*p && *p !=
'\"')
3227 while (*p && *p !=
' ' && *p !=
'>')
3232 if (strchr(p,
'=')) {
3233 mstrlcpy(
str, p,
sizeof(
str));
3234 pt = strchr(
str,
'=')+1;
3237 while (*pt && *pt !=
'\"')
3243 while (*pt && *pt !=
' ' && *pt !=
'>')
3248 mstrlcat(tail,
" ", 256);
3249 mstrlcat(tail,
str, 256);
3251 mstrlcat(tail,
str, 256);
3261 while (*p && ((*p ==
' ') || iscntrl(*p)))
3265 cm_msg(
MERROR,
"find_odb_tag",
"Invalid odb tag '%s'", ps);
3268 }
while (*p !=
'>');
3273 while (*p && *p !=
'>')
3284 int size,
index, i_edit, i_set;
3292 i_edit = atoi(pp->
getparam(
"index"));
3297 i_set = atoi(pp->
getparam(
"index"));
3300 mstrlcpy(full_keypath, keypath1,
sizeof(full_keypath));
3301 mstrlcpy(keypath, keypath1,
sizeof(keypath));
3304 if (strchr(keypath,
'[') && strchr(keypath,
']')) {
3305 for (p = strchr(keypath,
'[') + 1; *p && *p !=
']'; p++)
3309 if (*p && *p ==
']') {
3310 index = atoi(strchr(keypath,
'[') + 1);
3311 *strchr(keypath,
'[') = 0;
3318 r->
rsprintf(
"<b>Key \"%s\" not found in ODB</b>\n", keypath);
3321 size =
sizeof(
data);
3324 std::string data_str;
3325 if (format && strlen(format)>0)
3334 if (n_var == i_set) {
3337 if (data_str[0] ==
'y')
3342 if (atoi(data_str.c_str()) > 0)
3352 std::string options;
3353 if (data_str[0] ==
'y' || atoi(data_str.c_str()) > 0)
3354 options +=
"checked ";
3356 options +=
"disabled ";
3359 options +=
"onClick=\"o=document.createElement('input');o.type='hidden';o.name='cbi';o.value='";
3361 options +=
"';document.form1.appendChild(o);";
3362 options +=
"document.form1.submit();\" ";
3369 r->
rsprintf(
"<input type=\"checkbox\" %s>\n", options.c_str());
3374 if (n_var == i_set) {
3382 size =
sizeof(
data);
3387 if (n_var == i_edit) {
3388 r->
rsprintf(
"<input type=text size=10 maxlength=80 name=value value=\"%s\">\n", data_str.c_str());
3389 r->
rsprintf(
"<input type=submit size=20 name=cmd value=Set>\n");
3390 r->
rsprintf(
"<input type=hidden name=index value=%d>\n", n_var);
3391 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
3395 r->
rsprintf(
"<a href=\"#\" %s>", tail);
3399 r->
rsprintf(
"<a onClick=\"promptpwd('%s?cmd=Edit&index=%d&pnam=%s')\" href=\"#\">", path, n_var,
pwd);
3401 r->
rsprintf(
"<a href=\"%s?cmd=Edit&index=%d\" %s>", path, n_var, tail);
3405 r->
rsputs(data_str.c_str());
3408 }
else if (edit == 2) {
3409 r->
rsprintf(
"<a href=\"#\" onclick=\"ODBEdit('%s')\">\n", full_keypath);
3410 r->
rsputs(data_str.c_str());
3414 r->
rsputs(data_str.c_str());
3436 "Src = STRING : [256] ",
3437 "Format = STRING : [32] %1.1f",
3438 "Font = STRING : [32] Medium",
3442 "FGColor = STRING : [8] 000000",
3443 "BGColor = STRING : [8] FFFFFF",
3476 "Src = STRING : [256] ",
3480 "Height = INT : 100",
3481 "Direction = INT : 0",
3483 "Logscale = BOOL : n",
3485 "Max = DOUBLE : 10",
3486 "FGColor = STRING : [8] 000000",
3487 "BGColor = STRING : [8] FFFFFF",
3488 "BDColor = STRING : [8] 808080",
3494 int x, y, width, height, direction,
axis;
3508 int i,
n, size, ivalue;
3514 for (
i=0 ;
i<(int)strlen(src) ;
i++)
3515 if (src[
i] ==
'>' || src[
i] ==
'&')
3517 strncpy(
str, src,
i);
3521 while (strlen(
str) > 0 &&
str[strlen(
str)-1] ==
' ')
3526 cm_msg(
MERROR,
"evaluate_src",
"Invalid Src key \"%s\" for Fill \"%s\"",
3532 size =
sizeof(
data);
3539 *fvalue = (
value[0] ==
'y');
3541 *fvalue = atof(
value.c_str());
3545 if (src[
i] ==
'>' && src[
i+1] ==
'>') {
3548 while (src[
i] ==
' ' || isdigit(src[
i]))
3550 ivalue = (int)*fvalue;
3555 if (src[
i] ==
'&') {
3557 while (src[
i] ==
' ')
3559 if (src[
i] ==
'0' && src[
i+1] ==
'x')
3560 sscanf(src+2+
i,
"%x", &
n);
3563 while (src[
i] ==
' ' || isxdigit(src[
i]) || src[
i] ==
'x')
3565 ivalue = (int)*fvalue;
3581 if (filename[0] ==
'/')
3589 std::string custom_path =
"";
3596 if (custom_path.length() < 1)
3600 cm_msg(
MERROR,
"add_custom_path",
"ODB /Custom/Path has a forbidden value \"%s\", please change it", custom_path.c_str());
3606 std::string full_filename = custom_path;
3607 if (full_filename[full_filename.length()-1] !=
DIR_SEPARATOR)
3609 full_filename += filename;
3611 return full_filename;
3619 std::string filename;
3625 sprintf(
str,
"/Custom/%s",
name);
3629 sprintf(
str,
"/Custom/%s&",
name);
3632 sprintf(
str,
"/Custom/%s!",
name);
3638 sprintf(
str,
"show_custom_file: Invalid custom page: \"/Custom/%s\" not found in ODB",
name);
3650 sprintf(errtext,
"show_custom_file: Error: db_get_key() for \"%s\" status %d",
str,
status);
3656 char* ctext = (
char*)malloc(size);
3662 sprintf(errtext,
"show_custom_file: Error: db_get_data() for \"%s\" status %d",
str,
status);
3681 char str[256],
data[256], src[256];
3682 int i,
index, length,
status, size, width, height, bgcol, fgcol, bdcol, r, g, b, x, y;
3683 HNDLE hDB, hkeygif, hkeyroot, hkey, hkeyval;
3684 double fvalue, ratio;
3696 sprintf(
str,
"/Custom/Images/%s",
name);
3707 std::string filename;
3712 f = fopen(full_filename.c_str(),
"rb");
3714 sprintf(
str,
"show_custom_gif: Cannot open file \"%s\"", full_filename.c_str());
3723 sprintf(
str,
"show_custom_gif: File \"%s\" is not a GIF image", filename.c_str());
3740 size =
sizeof(label);
3743 cm_msg(
MERROR,
"show_custom_gif",
"Cannot open data record for label \"%s\"",
3748 if (label.
src[0] == 0) {
3755 cm_msg(
MERROR,
"show_custom_gif",
"Invalid Src key \"%s\" for label \"%s\"",
3761 size =
sizeof(
data);
3774 if (strstr(label.
format,
"%c"))
3783 sscanf(label.
fgcolor,
"%02x%02x%02x", &r, &g, &b);
3788 sscanf(label.
bgcolor,
"%02x%02x%02x", &r, &g, &b);
3803 width =
value.length() * pfont->
w + 5 + 5;
3804 height = pfont->
h + 2 + 2;
3806 if (label.
align == 0) {
3809 label.
y + height, bgcol);
3813 }
else if (label.
align == 1) {
3816 label.
y + height, bgcol);
3818 label.
y + height, fgcol);
3823 label.
y + height, bgcol);
3844 cm_msg(
MERROR,
"show_custom_gif",
"Cannot open data record for bar \"%s\"",
3849 if (bar.
src[0] == 0) {
3856 cm_msg(
MERROR,
"show_custom_gif",
"Invalid Src key \"%s\" for bar \"%s\"",
3862 size =
sizeof(
data);
3868 fvalue = atof(
value.c_str());
3870 sscanf(bar.
fgcolor,
"%02x%02x%02x", &r, &g, &b);
3875 sscanf(bar.
bgcolor,
"%02x%02x%02x", &r, &g, &b);
3880 sscanf(bar.
bdcolor,
"%02x%02x%02x", &r, &g, &b);
3891 ratio = (log(fvalue) - log(bar.
min)) / (log(bar.
max) - log(bar.
min));
3893 ratio = (fvalue - bar.
min) / (bar.
max - bar.
min);
3902 r = (int) (ratio + 0.5);
3909 bar.
y + bar.
height - 1, fgcol);
3914 else if (bar.
axis == 2)
3920 ratio = ratio * (bar.
height - 2);
3921 r = (int) (ratio + 0.5);
3924 bar.
y + bar.
width, bgcol);
3928 bar.
y + bar.
width - 1, fgcol);
3931 haxis(im,
gdFontSmall, bdcol, 0, bar.
x, bar.
y, bar.
height, -3, -5, -7, -18,
3933 else if (bar.
axis == 2)
3935 5, 7, 8, 0, bar.
min, bar.
max);
3967 size =
sizeof(
data);
3970 cm_msg(
MERROR,
"show_custom_gif",
"No \"Limits\" entry for Fill \"%s\"",
3974 for (
i = 0;
i < size / (int)
sizeof(
double);
i++)
3975 if (*((
double *)
data +
i) > fvalue)
3982 cm_msg(
MERROR,
"show_custom_gif",
"No \"Fillcolors\" entry for Fill \"%s\"",
3987 size =
sizeof(
data);
3988 strcpy(
data,
"FFFFFF");
3991 sscanf(
data,
"%02x%02x%02x", &r, &g, &b);
4006 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
4009 rr->
rsprintf(
"Content-Type: image/gif\r\n");
4010 rr->
rsprintf(
"Content-Length: %d\r\n", length);
4011 rr->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
4012 rr->
rsprintf(
"Expires: Fri, 01-Jan-1983 00:00:00 GMT\r\n\r\n");
4024 { 9999,
"mhttpd_jrpc_rev0", {
4039 int count = 0, substring = 0, rpc;
4041 const char *xname = p->
getparam(
"name");
4042 const char *srpc = p->
getparam(
"rpc");
4044 if (!srpc || !xname) {
4046 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4051 mstrlcpy(sname, xname,
sizeof(sname));
4053 if (sname[strlen(sname)-1]==
'*') {
4054 sname[strlen(sname)-1] = 0;
4070 r->
rsprintf(
"calling rpc %d | ", rpc);
4075 HNDLE hDB, hrootkey, hsubkey, hkey;
4087 sprintf(
str,
"RPC/%d", rpc);
4094 size =
sizeof(client_name);
4099 if (strlen(sname) > 0) {
4101 if (strstr(client_name, sname) != client_name)
4104 if (strcmp(sname, client_name) != 0)
4111 r->
rsprintf(
"client %s", client_name);
4149 { 9998,
"mhttpd_jrpc_rev1", {
4166 int status, substring = 0, rpc;
4168 const char *xname = p->
getparam(
"name");
4169 const char *srpc = p->
getparam(
"rpc");
4171 if (!srpc || !xname) {
4173 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4178 mstrlcpy(sname, xname,
sizeof(sname));
4180 if (sname[strlen(sname)-1]==
'*') {
4181 sname[strlen(sname)-1] = 0;
4200 std::string reply_header;
4201 std::string reply_body;
4209 HNDLE hDB, hrootkey, hsubkey, hkey;
4213 int buf_length = 1024;
4215 int max_reply_length = atoi(p->
getparam(
"max_reply_length"));
4216 if (max_reply_length > buf_length)
4217 buf_length = max_reply_length;
4219 char* buf = (
char*)malloc(buf_length);
4221 assert(buf != NULL);
4226 for (
int i=0; ;
i++) {
4232 sprintf(
str,
"RPC/%d", rpc);
4239 size =
sizeof(client_name);
4244 if (strlen(sname) > 0) {
4246 if (strstr(client_name, sname) != client_name)
4249 if (strcmp(sname, client_name) != 0)
4257 int connect_status = -1;
4258 int call_status = -1;
4259 int call_length = 0;
4260 int disconnect_status = -1;
4291 call_length = strlen(buf);
4301 if (reply_header.length() > 0)
4302 reply_header +=
" | ";
4305 sprintf(tmp,
"%s %d %d %d %d", client_name, connect_status, call_status, disconnect_status, call_length);
4306 reply_header += tmp;
4317 if (reply_header.length() > 0) {
4318 r->
rsputs(reply_header.c_str());
4320 r->
rsputs(reply_body.c_str());
4332 const char *cmd = p->
getparam(
"rcmd");
4333 const char *args = p->
getparam(
"rarg");
4335 if (!
name || !cmd || !args) {
4337 r->
rsprintf(
"<INVALID_ARGUMENTS>");
4343 int buf_length = 1024;
4345 int max_reply_length = atoi(p->
getparam(
"max_reply_length"));
4346 if (max_reply_length > buf_length)
4347 buf_length = max_reply_length;
4349 char* buf = (
char*)malloc(buf_length);
4350 assert(buf != NULL);
4359 r->
rsprintf(
"<RPC_CONNECT_ERROR>%d</RPC_CONNECT_ERROR>",
status);
4400 size =
sizeof(
data);
4410 std::string data_str;
4411 if (format && format[0])
4415 r->
rsputs(data_str.c_str());
4423 r->
rsputs(
"<DB_OUT_OF_RANGE>");
4425 std::string data_str;
4430 r->
rsputs(data_str.c_str());
4442 if (s1.length() < strlen(s2))
4444 return (strncasecmp(s1.c_str(), s2, strlen(s2)) == 0);
4461 char str[
TEXT_SIZE], format[256], facility[256], user[256];
4470 const int ENCODING_NONE = 0;
4471 const int ENCODING_ODB = 1;
4472 const int ENCODING_XML = 2;
4473 const int ENCODING_JSON = 3;
4475 std::string cmd_parameter;
4476 std::string encoding_parameter;
4477 int encoding = ENCODING_NONE;
4479 std::string jsonp_callback;
4480 bool single =
false;
4481 bool multiple =
false;
4482 std::vector<std::string> odb;
4487 cmd_parameter = p->
getparam(
"cmd");
4491 encoding_parameter = p->
getparam(
"encoding");
4494 if (encoding_parameter.length() > 0) {
4496 encoding = ENCODING_ODB;
4498 encoding = ENCODING_XML;
4500 encoding = ENCODING_JSON;
4503 if (encoding == ENCODING_JSON) {
4506 jsonp_callback = p->
getparam(
"callback");
4517 for (
int i=0 ; ;
i++) {
4519 sprintf(ppath,
"odb%d",
i);
4527 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());
4535 ppath +=
"/Custom/Pwd/";
4546 if (strchr(
str,
'[')) {
4547 if (*(strchr(
str,
'[')+1) ==
'*')
4551 *strchr(
str,
'[') = 0;
4560 const char* ptr = p->
getparam(
"value");
4561 for (
i=0 ; ptr != NULL ;
i++) {
4562 size =
sizeof(
data);
4564 if (strchr(
data,
','))
4565 *strchr(
data,
',') = 0;
4567 ptr = strchr(ptr,
',');
4572 size =
sizeof(
data);
4601 size =
sizeof(
data);
4622 if (strchr(
str,
'[')) {
4623 if (*(strchr(
str,
'[')+1) ==
'*')
4627 *strchr(
str,
'[') = 0;
4638 r->
rsputs(
"<DB_NO_KEY>");
4645 sprintf(ppath,
"odb%d",
i);
4646 sprintf(format,
"format%d",
i);
4649 if (strchr(
str,
'[')) {
4650 if (*(strchr(
str,
'[')+1) ==
'*')
4654 *strchr(
str,
'[') = 0;
4662 r->
rsputs(
"<DB_NO_KEY>");
4675 bool fmt_odb =
false;
4676 bool fmt_xml =
false;
4677 bool fmt_json =
true;
4678 bool fmt_jsonp =
false;
4679 int follow_links = 1;
4682 const char* fmt = NULL;
4683 const char* jsonp_callback =
"callback";
4687 }
else if (p->
isparam(
"format")) {
4694 fmt_json = (strstr(fmt,
"json") != NULL);
4697 fmt_xml = fmt_json =
false;
4699 fmt_odb = fmt_json =
false;
4701 fmt_odb = fmt_xml =
false;
4704 fmt_jsonp = (strstr(fmt,
"-p") != NULL);
4705 if (fmt_jsonp && p->
isparam(
"callback"))
4706 jsonp_callback = p->
getparam(
"callback");
4707 if (fmt_json && strstr(fmt,
"-nofollowlinks"))
4709 if (fmt_json && strstr(fmt,
"-nokeys"))
4711 if (fmt_json && strstr(fmt,
"-nolastwritten"))
4713 if (fmt_json && strstr(fmt,
"-norecurse"))
4729 r->
rsputs(jsonp_callback);
4735 char* buf = (
char *)malloc(bufsize);
4742 db_copy(
hDB, hkey, buf, &bufsize, (
char *)
"");
4751 r->
rsputs(
"<DB_NO_KEY>");
4757 r->
rsputs(jsonp_callback);
4764 }
else if (fmt_json)
4768 for (
int i=0 ; ;
i++) {
4770 sprintf(ppath,
"odb%d",
i);
4777 r->
rsputs(
"</data>\n<data>\n");
4790 r->
rsputs(
"<DB_NO_KEY/>\n");
4791 else if (fmt_json) {
4793 sprintf(tmp,
"{ \"/error\" : %d }\n",
status);
4796 r->
rsputs(
"<DB_NO_KEY>\n");
4802 char* buf = (
char *)malloc(bufsize);
4806 const char* s = strstr(buf,
"-->");
4812 }
else if (fmt_json) {
4816 db_copy(
hDB, hkey, buf, &bufsize, (
char *)
"");
4824 r->
rsputs(
"</data>\n</jcopy>\n");
4846 r->
rsputs(jsonp_callback.c_str());
4860 for (
unsigned i=0;
i<odb.size();
i++) {
4866 if (multiple &&
i>0)
4875 r->
rsputs(
"<DB_NO_KEY>\n");
4879 if (multiple &&
i>0)
4929 r->
rsputs(jsonp_callback.c_str());
4942 for (
unsigned i=0;
i<odb.size();
i++) {
4945 int arraylength = 0;
4950 arraylength = atoi(p->
getparam(
"arraylen"));
4951 strlength = atoi(p->
getparam(
"strlen"));
4953 else if (multiple) {
4955 sprintf(buf,
"type%d",
i);
4957 sprintf(buf,
"arraylen%d",
i);
4958 arraylength = atoi(p->
getparam(buf));
4959 sprintf(buf,
"strlen%d",
i);
4960 strlength = atoi(p->
getparam(buf));
4970 char* s = (
char*)calloc(strlength, 1);
4982 if (multiple &&
i>0)
5018 r->
rsputs(jsonp_callback.c_str());
5031 for (
unsigned i=0;
i<odb.size();
i++) {
5034 int arraylength = 0;
5038 arraylength = atoi(p->
getparam(
"arraylen"));
5039 strlength = atoi(p->
getparam(
"strlen"));
5041 else if (multiple) {
5043 sprintf(buf,
"arraylen%d",
i);
5044 arraylength = atoi(p->
getparam(buf));
5045 sprintf(buf,
"strlen%d",
i);
5046 strlength = atoi(p->
getparam(buf));
5057 char* olddata = (
char*)malloc(oldsize);
5063 char* s = (
char*)calloc(newsize, 1);
5082 if (multiple &&
i>0)
5115 r->
rsputs(jsonp_callback.c_str());
5128 for (
unsigned i=0;
i<odb.size();
i++) {
5129 const char*
name = NULL;
5132 else if (multiple) {
5134 sprintf(buf,
"name%d",
i);
5144 if (multiple &&
i>0)
5177 r->
rsputs(jsonp_callback.c_str());
5190 for (
unsigned i=0;
i<odb.size();
i++) {
5191 const char* dest = NULL;
5194 else if (multiple) {
5196 sprintf(buf,
"dest%d",
i);
5205 if (multiple &&
i>0)
5238 r->
rsputs(jsonp_callback.c_str());
5251 for (
unsigned i=0;
i<odb.size();
i++) {
5255 else if (multiple) {
5257 sprintf(buf,
"index%d",
i);
5269 if (multiple &&
i>0)
5302 r->
rsputs(jsonp_callback.c_str());
5315 for (
unsigned i=0;
i<odb.size();
i++) {
5320 if (multiple &&
i>0)
5347 mstrlcpy(facility, p->
getparam(
"f"),
sizeof(facility));
5349 mstrlcpy(facility,
"midas",
sizeof(facility));
5360 char* messages = NULL;
5361 int num_messages = 0;
5374 mstrlcpy(facility, p->
getparam(
"facility"),
sizeof(facility));
5376 mstrlcpy(facility,
"midas",
sizeof(facility));
5379 mstrlcpy(user, p->
getparam(
"user"),
sizeof(user));
5381 mstrlcpy(user,
"javascript_commands",
sizeof(user));
5393 r->
rsputs(
"Message successfully created\n");
5403 r->
rsputs(alarms.c_str());
5430 int size, n_var,
index, edit;
5431 char keypath[256],
type[32], *p, *ps;
5432 char pwd[256], tail[256];
5437 std::string path = pp->
getparam(
"page");
5440 show_error_404(r,
"show_custom_page: Invalid custom page: \"page\" parameter is empty");
5444 if (strstr(path.c_str(),
"..")) {
5446 str +=
"Invalid custom page name \'";
5448 str +=
"\' contains \'..\'";
5453 if (strstr(path.c_str(),
".gif")) {
5458 if (strchr(path.c_str(),
'.')) {
5465 std::string xpath = std::string(
"/Custom/") + path;
5468 xpath = std::string(
"/Custom/") + path +
"&";
5471 xpath = std::string(
"/Custom/") + path +
"!";
5483 ctext = (
char*)malloc(size);
5486 std::string errtext =
msprintf(
"show_custom_page: Error: db_get_data() for \"%s\" status %d", xpath.c_str(),
status);
5492 std::string content_type =
"text/html";
5495 if (std::string(ctext).substr(0, 5) ==
"?cmd=") {
5502 if (strchr(ctext,
'\n') == 0) {
5504 int fh = open(full_filename.c_str(), O_RDONLY |
O_BINARY);
5506 std::string
str =
msprintf(
"show_custom_page: Cannot open file \"%s\", open() errno %d (%s)", full_filename.c_str(), errno, strerror(errno));
5513 off_t off = lseek(fh, 0, SEEK_END);
5515 std::string
str =
msprintf(
"show_custom_page: Cannot open file \"%s\", lseek(SEEK_END) errno %d (%s)", full_filename.c_str(), errno, strerror(errno));
5522 lseek(fh, 0, SEEK_SET);
5523 ctext = (
char*)malloc(size+1);
5524 ssize_t rd =
read(fh, ctext, size);
5547 ps = strchr(p,
'>') + 1;
5549 if (
pwd[0] && n_var == atoi(pp->
getparam(
"index"))) {
5552 mstrlcpy(
str, path.c_str(),
sizeof(
str));
5553 if (strlen(
str)>0 &&
str[strlen(
str)-1] ==
'&')
5556 ppath +=
"/Custom/Pwd/";
5573 }
while (p != NULL);
5581 ppath +=
"/Custom/Pwd/";
5591 std::string podb = pp->
getparam(
"odb");
5592 std::string::size_type pos = podb.find(
'[');
5593 if (pos != std::string::npos) {
5594 index = atoi(podb.substr(pos+1).c_str());
5604 size =
sizeof(
data);
5607 if (atoi(data_str.c_str()) == 0)
5622 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
5638 ps = strchr(p + 1,
'>') + 1;
5643 }
while (p != NULL);
5654 std::string
str =
msprintf(
"Invalid custom page: Page \"%s\" not found in ODB", path.c_str());
5665 int c,
n, a, f,
d,
q, x, r, ia, id, w;
5667 HNDLE hDB, hrootkey, hsubkey, hkey;
5670 static HNDLE hconn = 0;
5687 size =
sizeof(client_name);
5694 if (client_name[0]) {
5702 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
5707 rr->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
5708 rr->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
5709 rr->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
5710 rr->
rsprintf(
"<title>MIDAS CAMAC interface</title></head>\n");
5711 rr->
rsprintf(
"<body><form method=\"GET\" action=\"CNAF\">\n\n");
5719 rr->
rsprintf(
"<table border=3 cellpadding=1>\n");
5720 rr->
rsprintf(
"<tr><th colspan=3>MIDAS experiment \"%s\"",
str);
5722 if (client_name[0] == 0)
5723 rr->
rsprintf(
"<th colspan=3 class=\"redLight\">No CAMAC server running</tr>\n");
5724 else if (hconn == 0)
5725 rr->
rsprintf(
"<th colspan=3 class=\"redLight\">Cannot connect to %s</tr>\n", client_name);
5727 rr->
rsprintf(
"<th colspan=3>CAMAC server: %s</tr>\n", client_name);
5731 a = f =
d =
q = x = 0;
5737 rr->
rsprintf(
"<tr><td colspan=3>\n");
5738 rr->
rsprintf(
"<input type=submit name=cmd value=Execute>\n");
5741 rr->
rsprintf(
"<input type=submit name=cmd value=ODB>\n");
5742 rr->
rsprintf(
"<input type=submit name=cmd value=Status>\n");
5743 rr->
rsprintf(
"<input type=submit name=cmd value=Help>\n");
5750 rr->
rsprintf(
"<th colspan=3>Data");
5755 const char* cmd = p->
getparam(
"cmd");
5757 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_CRATE_CLEAR, 0, 0, 0, 0, 0, &
d, &size, &x,
5760 rr->
rsprintf(
"<tr><td colspan=6 class=\"greenLight\">C cycle executed sucessfully</tr>\n");
5762 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_CRATE_ZINIT, 0, 0, 0, 0, 0, &
d, &size, &x,
5765 rr->
rsprintf(
"<tr><td colspan=6 class=\"greenLight\">Z cycle executed sucessfully</tr>\n");
5767 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_INHIBIT_CLEAR, 0, 0, 0, 0, 0, &
d, &size, &x,
5771 (
"<tr><td colspan=6 class=\"greenLight\">Clear inhibit executed sucessfully</tr>\n");
5773 rpc_client_call(hconn,
RPC_CNAF16,
CNAF_INHIBIT_SET, 0, 0, 0, 0, 0, &
d, &size, &x,
5777 (
"<tr><td colspan=6 class=\"greenLight\">Set inhibit executed sucessfully</tr>\n");
5789 if (strncmp(pd,
"0x", 2) == 0)
5790 sscanf(pd + 2,
"%x", &
d);
5802 for (
i = 0;
i < r;
i++) {
5808 rpc_client_call(hconn,
RPC_CNAF24,
CNAF, 0,
c,
n, a, f, &
d, &size, &x,
5821 status =
rpc_client_call(hconn,
RPC_CNAF24,
CNAF, 0,
c,
n, a, f, &
d, &size, &x, &
q);
5828 (
"<tr><td colspan=6 class=\"redLight\">Error executing function, code = %d</tr>",
5831 rr->
rsprintf(
"<tr align=center><td>%d",
n);
5834 rr->
rsprintf(
"<td colspan=3>%d / 0x%04X Q%d X%d",
d,
d,
q, x);
5847 (
"<tr align=center><td><input type=text size=3 name=N value=%d>\n",
5849 rr->
rsprintf(
"<td><input type=text size=3 name=A value=%d>\n", a);
5850 rr->
rsprintf(
"<td><input type=text size=3 name=F value=%d>\n", f);
5852 (
"<td colspan=3><input type=text size=8 name=D value=%d></tr>\n",
5856 rr->
rsprintf(
"<tr><td colspan=2>Repeat");
5857 rr->
rsprintf(
"<td><input type=text size=3 name=R value=%d>\n", r);
5860 (
"<td align=center colspan=3><input type=submit name=cmd value=\"C cycle\">\n");
5861 rr->
rsprintf(
"<input type=submit name=cmd value=\"Z cycle\">\n");
5863 rr->
rsprintf(
"<tr><td colspan=2>Repeat delay [ms]");
5864 rr->
rsprintf(
"<td><input type=text size=3 name=W value=%d>\n", w);
5867 (
"<td align=center colspan=3><input type=submit name=cmd value=\"Set inhibit\">\n");
5868 rr->
rsprintf(
"<input type=submit name=cmd value=\"Clear inhibit\">\n");
5870 rr->
rsprintf(
"<tr><td colspan=2>Data increment");
5871 rr->
rsprintf(
"<td><input type=text size=3 name=ID value=%d>\n",
id);
5874 (
"<td colspan=3 align=center>Branch <input type=text size=3 name=B value=0>\n");
5876 rr->
rsprintf(
"<tr><td colspan=2>A increment");
5877 rr->
rsprintf(
"<td><input type=text size=3 name=IA value=%d>\n", ia);
5880 (
"<td colspan=3 align=center>Crate <input type=text size=3 name=C value=%d>\n",
5883 rr->
rsprintf(
"</table></body>\r\n");
5895static const NAME_TABLE prefix_table[] = {
5896 {PRFX_PICO,
"pico",},
5897 {PRFX_NANO,
"nano",},
5898 {PRFX_MICRO,
"micro",},
5899 {PRFX_MILLI,
"milli",},
5901 {PRFX_KILO,
"kilo",},
5902 {PRFX_MEGA,
"mega",},
5903 {PRFX_GIGA,
"giga",},
5904 {PRFX_TERA,
"tera",},
5908static const NAME_TABLE unit_table[] = {
5910 {UNIT_METER,
"meter",},
5911 {UNIT_GRAM,
"gram",},
5912 {UNIT_SECOND,
"second",},
5913 {UNIT_MINUTE,
"minute",},
5914 {UNIT_HOUR,
"hour",},
5915 {UNIT_AMPERE,
"ampere",},
5916 {UNIT_KELVIN,
"kelvin",},
5917 {UNIT_CELSIUS,
"deg. celsius",},
5918 {UNIT_FARENHEIT,
"deg. farenheit",},
5920 {UNIT_HERTZ,
"hertz",},
5921 {UNIT_PASCAL,
"pascal",},
5923 {UNIT_WATT,
"watt",},
5924 {UNIT_VOLT,
"volt",},
5926 {UNIT_TESLA,
"tesls",},
5927 {UNIT_LITERPERSEC,
"liter/sec",},
5929 {UNIT_FARAD,
"farad",},
5931 {UNIT_BOOLEAN,
"boolean",},
5932 {UNIT_BYTE,
"byte",},
5933 {UNIT_WORD,
"word",},
5934 {UNIT_DWORD,
"dword",},
5935 {UNIT_ASCII,
"ascii",},
5936 {UNIT_STRING,
"string",},
5937 {UNIT_BAUD,
"baud",},
5939 {UNIT_PERCENT,
"percent",},
5941 {UNIT_COUNT,
"counts",},
5942 {UNIT_FACTOR,
"factor",},
5948void print_mscb_var(
char *
value,
char *evalue,
char *unit, MSCB_INFO_VAR *info_chn,
void *pdata)
5952 unsigned short usdata;
5954 unsigned int uidata;
5961 if (info_chn->unit == UNIT_STRING) {
5962 memset(
str, 0,
sizeof(
str));
5963 strncpy(
str, (
char *)pdata, info_chn->width);
5964 for (
i = 0;
i < (int) strlen(
str);
i++)
5967 strcat(
value,
"\\001");
5970 strcat(
value,
"\\002");
5973 strcat(
value,
"\\t");
5976 strcat(
value,
"\\n");
5979 strcat(
value,
"\\r");
5986 mstrlcpy(evalue,
value, 256);
5988 switch (info_chn->width) {
5991 strcpy(evalue,
"0");
5995 if (info_chn->flags & MSCBF_SIGNED) {
5996 sprintf(
value,
"%d (0x%02X/", *((
signed char *)pdata), *((
signed char *)pdata));
5997 sprintf(evalue,
"%d", *((
signed char *)pdata));
5999 sprintf(
value,
"%u (0x%02X/", *((
unsigned char *)pdata), *((
unsigned char *)pdata));
6000 sprintf(evalue,
"%u", *((
unsigned char *)pdata));
6003 for (
i = 0;
i < 8;
i++)
6004 if (*((
unsigned char *)pdata) & (0x80 >>
i))
6012 if (info_chn->flags & MSCBF_SIGNED) {
6013 sdata = *((
signed short *)pdata);
6015 sprintf(
value,
"%d (0x%04X)", sdata, sdata);
6016 sprintf(evalue,
"%d", sdata);
6018 usdata = *((
unsigned short *)pdata);
6020 sprintf(
value,
"%u (0x%04X)", usdata, usdata);
6021 sprintf(evalue,
"%u", usdata);
6026 if (info_chn->flags & MSCBF_FLOAT) {
6027 fdata = *((
float *)pdata);
6029 sprintf(
value,
"%1.6lg", fdata);
6030 sprintf(evalue,
"%1.6lg", fdata);
6032 if (info_chn->flags & MSCBF_SIGNED) {
6033 idata = *((
signed int *)pdata);
6035 sprintf(
value,
"%d (0x%08X)", idata, idata);
6036 sprintf(evalue,
"%d", idata);
6038 uidata = *((
unsigned int *)pdata);
6040 sprintf(
value,
"%u (0x%08X)", uidata, uidata);
6041 sprintf(evalue,
"%u", uidata);
6050 if (info_chn->prefix) {
6051 for (
i = 0; prefix_table[
i].id != 99;
i++)
6052 if ((
unsigned char)prefix_table[
i].
id == info_chn->prefix)
6054 if (prefix_table[
i].
id)
6055 strcpy(unit, prefix_table[
i].
name);
6059 if (info_chn->unit && info_chn->unit != UNIT_STRING) {
6060 for (
i = 0; unit_table[
i].id;
i++)
6061 if ((
unsigned char)unit_table[
i].
id == info_chn->unit)
6063 if (unit_table[
i].
id)
6064 strcat(unit, unit_table[
i].
name);
6068static int cmp_int(
const void *a,
const void *b)
6070 return *((
int *)a) > *((
int *)b);
6075void create_mscb_tree()
6079 int i,
j,
k, l, size, address[1000], dev_badr[1000], dev_adr[1000], dev_chn[1000],
6080 n_address, n_dev_adr;
6081 char mscb_dev[256], mscb_pwd[32], eq_name[32];
6107 size =
sizeof(mscb_dev);
6110 size =
sizeof(mscb_pwd);
6114 size =
sizeof(dev_adr);
6116 n_dev_adr = size /
sizeof(int);
6119 size =
sizeof(mscb_dev);
6122 size =
sizeof(mscb_pwd);
6127 size =
sizeof(dev_badr);
6129 size =
sizeof(dev_chn);
6131 for (
k=0 ;
k<size/(int)
sizeof(
int) && n_dev_adr < (int)(
sizeof(dev_adr)/
sizeof(int)) ;
k++) {
6132 for (l=0 ; l<dev_chn[
k] ; l++)
6133 dev_adr[n_dev_adr++] = dev_badr[
k]+l;
6148 size =
sizeof(address);
6150 n_address = size /
sizeof(
int);
6155 for (
k=0 ;
k<n_dev_adr ;
k++) {
6156 for (l=0 ; l<n_address ; l++)
6157 if (address[l] == dev_adr[
k])
6161 address[n_address++] = dev_adr[
k];
6165 qsort(address, n_address,
sizeof(
int), cmp_int);
6179void show_mscb_page(
Param* p,
Return* r,
int refresh)
6181 int i,
j,
n, ind, fi, fd,
status, size, n_addr, cur_node, adr, show_hidden;
6182 unsigned int uptime;
6183 BOOL comment_created;
6186 char dbuf[256], evalue[256], unit[256], cur_subm_name[256];
6187 HNDLE hDB, hKeySubm, hKeyCurSubm,
hKey, hKeyAddr, hKeyComm;
6190 MSCB_INFO_VAR info_var;
6191 int ping_addr[0x10000];
6199 mstrlcpy(cur_subm_name, p->
getparam(
"subm"),
sizeof(cur_subm_name));
6200 if (cur_subm_name[0] == 0) {
6204 sprintf(errorstr,
"No submaster defined under /MSCB/Submaster");
6209 strcpy(cur_subm_name,
key.
name);
6214 cur_node = atoi(p->
getparam(
"node"));
6229 std::vector<int>
addr;
6230 std::vector<char> node_comment;
6235 addr.resize(n_addr);
6236 size =
sizeof(int)*n_addr;
6246 comment_created =
FALSE;
6258 node_comment.resize(32);
6259 comment_created =
TRUE;
6262 fd = mscb_init(cur_subm_name, 0,
"",
FALSE);
6265 for (
i=0 ;
i<0x10000 ;
i++)
6267 for (
i=0 ;
i<1000 ;
i++)
6269 for (
i=0 ;
i<0x10000 ;
i+=100)
6271 for (
i=0 ;
i<0x10000 ;
i+= 0x100)
6273 for (
i=0xFF00 ;
i<0x10000 ;
i++)
6276 for (ind =
n = 0; ind < 0x10000; ind++) {
6277 if (!ping_addr[ind])
6280 status = mscb_ping(fd, (
unsigned short) ind, 1, 0);
6281 if (
status == MSCB_SUCCESS) {
6284 for (
j=ind;
j<ind+100 &&
j<0x10000 ;
j++)
6288 status = mscb_info(fd, (
unsigned short) ind, &
info);
6290 if (
status == MSCB_SUCCESS) {
6292 for (
j=0 ;
j<n_addr ;
j++)
6296 addr.resize(n_addr+1);
6298 node_comment.resize(32*(n_addr+1));
6300 strncpy(node_comment.data()+n_addr*32,
info.node_name, 32);
6302 }
else if (comment_created) {
6303 node_comment.resize(32*n_addr);
6305 strncpy(node_comment.data()+
j*32,
info.node_name, 32);
6315 sprintf(redirstr,
"?cmd=mscb&subm=%s", cur_subm_name);
6321 sprintf(errorstr,
"Cannot talk to submaster \"%s\"", cur_subm_name);
6334 fd = mscb_init(cur_subm_name, 0,
"",
FALSE);
6336 status = mscb_info_variable(fd,
6337 (
unsigned short) cur_node, (
unsigned char)
i, &info_var);
6338 if (
status == MSCB_SUCCESS) {
6339 if (info_var.unit == UNIT_STRING) {
6341 mstrlcpy(valstr,
value,
sizeof(valstr));
6342 if (strlen(valstr) > 0 && valstr[strlen(valstr) - 1] ==
'\n')
6343 valstr[strlen(valstr) - 1] = 0;
6345 status = mscb_write(fd, (
unsigned short) cur_node,
6346 (
unsigned char)
i, valstr, strlen(valstr) + 1);
6348 if (info_var.flags & MSCBF_FLOAT) {
6349 fvalue = (float) atof(
value);
6350 memcpy(&dbuf, &fvalue,
sizeof(
float));
6352 if (
value[1] ==
'x')
6353 sscanf(
value + 2,
"%x", (
int *)&dbuf);
6355 *((
int *)dbuf) = atoi(
value);
6358 status = mscb_write(fd, (
unsigned short) cur_node,
6359 (
unsigned char)
i, dbuf, info_var.width);
6364 sprintf(redirstr,
"?cmd=mscb&subm=%s&node=%d", cur_subm_name, cur_node);
6370 show_hidden = atoi(p->
getparam(
"hidden"));
6372 show_hidden =
FALSE;
6375 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
6376 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
6380 r->
rsprintf(
"<style type=\"text/css\">\r\n");
6381 r->
rsprintf(
"select { width:150px; background-color:#FFFFE0; font-size:12px; }\r\n");
6383 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6385 r->
rsprintf(
" vertical-align:top;\r\n");
6386 r->
rsprintf(
" font-size:16px;\r\n");
6387 r->
rsprintf(
" border-right:1px solid #808080;\r\n");
6390 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6392 r->
rsprintf(
" vertical-align:top;\r\n");
6393 r->
rsprintf(
" font-size:16px;\r\n");
6394 r->
rsprintf(
" border-right:1px solid #808080;\r\n");
6397 r->
rsprintf(
" background-color:#E0E0E0; text-align:center; font-weight:bold;\r\n");
6399 r->
rsprintf(
" vertical-align:top;\r\n");
6400 r->
rsprintf(
" font-size:10px;\r\n");
6404 r->
rsprintf(
" font-weight:bold;\r\n");
6405 r->
rsprintf(
" font-size:12px;\r\n");
6408 r->
rsprintf(
" background-color:#F0F0F0;\r\n");
6410 r->
rsprintf(
" font-size:12px;\r\n");
6411 r->
rsprintf(
" border:1px solid #808080;\r\n");
6412 r->
rsprintf(
" border-right:1px solid #FFFFFF;\r\n");
6413 r->
rsprintf(
" border-bottom:1px solid #FFFFFF;\r\n");
6417 r->
rsprintf(
" font-size:12px;\r\n");
6422 r->
rsprintf(
"<script type=\"text/javascript\">\r\n");
6423 r->
rsprintf(
"function mscb_edit(index, value)\r\n");
6425 r->
rsprintf(
" var new_value = prompt('Please enter new value', value);\r\n");
6426 r->
rsprintf(
" if (new_value != undefined) {\r\n");
6427 r->
rsprintf(
" window.location.search = '?cmd=mscb&subm=%s&node=%d&idx='+index+'&value='+new_value;\n", cur_subm_name, cur_node);
6434 r->
rsprintf(
"<table class=\"mtable\">");
6435 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>MSCB</th><tr>");
6439 r->
rsprintf(
"<tr><td colspan=2>\n");
6440 r->
rsprintf(
"<table width=100%%><tr>\n");
6441 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());
6443 r->
rsprintf(
"<tr><td colspan=\"2\" cellpadding=\"0\" cellspacing=\"0\">\r\n");
6447 r->
rsprintf(
"<h1>No MSCB Submasters defined in ODB</h1>\r\n");
6458 r->
rsprintf(
"<table width=\"100%%\" cellpadding=\"0\" cellspacing=\"0\">");
6461 r->
rsprintf(
"<tr><td class=\"subm\">\r\n");
6473 r->
rsprintf(
"<select name=\"subm\" id=\"subm\" size=%d ",
i);
6474 r->
rsprintf(
"onChange=\"window.location.search='?cmd=mscb&subm='+document.getElementById('subm').value;\">\r\n");
6484 size =
sizeof(comment);
6486 mstrlcat(
str,
": ",
sizeof(
str));
6487 mstrlcat(
str, comment,
sizeof(
str));
6491 (cur_subm_name[0] == 0 &&
i == 0)) {
6500 r->
rsprintf(
"<td class=\"node\">\r\n");
6503 r->
rsprintf(
"<script type=\"text/javascript\">\n");
6505 r->
rsprintf(
"function rescan()\n");
6507 r->
rsprintf(
" flag = confirm('Rescan can take up to one minute.');\n");
6508 r->
rsprintf(
" if (flag == true)\n");
6509 r->
rsprintf(
" window.location.href = '?cmd=mscb&mcmd=Rescan&subm=%s';\n", cur_subm_name);
6514 r->
rsprintf(
"<input type=button name=cmd value=\"Rescan\" onClick=\"rescan();\">");
6518 r->
rsprintf(
"No submaster found in ODB\r\n");
6539 if (hKeyComm == 0) {
6553 r->
rsprintf(
"<select name=\"node\" id=\"node\" size=%d ",
i);
6554 r->
rsprintf(
"onChange=\"window.location.search='?cmd=mscb&subm=%s&node='+document.getElementById('node').value;\">\r\n", cur_subm_name);
6564 if (adr == cur_node)
6576 size =
sizeof(comment);
6578 sprintf(
str,
"%d: %s", adr, comment);
6580 sprintf(
str,
"%d", adr);
6582 if (cur_node == 0 &&
i == 0)
6584 if (adr == cur_node)
6585 r->
rsprintf(
"<option selected>%s</option>\r\n",
str);
6593 r->
rsprintf(
"<td class=\"vars\">\r\n");
6597 r->
rsprintf(
"<tr><td colspan=3 align=center><b>%s:%d</b>",
key.
name, cur_node);
6609 if (fd == EMSCB_WRONG_PASSWORD)
6610 r->
rsprintf(
"<tr><td colspan=3><b>Invalid password</b></td>");
6612 r->
rsprintf(
"<tr><td colspan=3><b>Submaster does not respond</b></td>");
6615 mscb_set_eth_max_retry(fd, 3);
6616 mscb_set_max_retry(1);
6618 status = mscb_ping(fd, cur_node, 0, 1);
6619 if (
status != MSCB_SUCCESS) {
6620 r->
rsprintf(
"<tr><td colspan=3><b>No response from node</b></td>");
6623 status = mscb_info(fd, (
unsigned short) cur_node, &
info);
6624 if (
status != MSCB_SUCCESS) {
6625 r->
rsprintf(
"<tr><td colspan=3><b>No response from node</b></td>");
6629 mstrlcpy(tr16,
info.node_name,
sizeof(tr16));
6630 r->
rsprintf(
"<tr><td class=\"v1\">Node name<td colspan=2 class=\"v2\">%s</tr>\n", tr16);
6631 r->
rsprintf(
"<tr><td class=\"v1\">GIT revision<td colspan=2 class=\"v2\">%d</tr>\n",
info.revision);
6633 if (
info.rtc[0] &&
info.rtc[0] != 0xFF) {
6634 for (
i=0 ;
i<6 ;
i++)
6636 r->
rsprintf(
"<tr><td class=\"v1\">Real Time Clock<td colspan=2 class=\"v2\">%02d-%02d-%02d %02d:%02d:%02d</td>\n",
6641 status = mscb_uptime(fd, (
unsigned short) cur_node, &uptime);
6642 if (
status == MSCB_SUCCESS)
6643 r->
rsprintf(
"<tr><td class=\"v1\">Uptime<td colspan=2 class=\"v2\">%dd %02dh %02dm %02ds</tr>\n",
6644 uptime / (3600 * 24),
6645 (uptime % (3600 * 24)) / 3600, (uptime % 3600) / 60,
6648 r->
rsprintf(
"<tr><td colspan=3><hr></td></tr>\r\n");
6651 for (
i=0 ;
i <
info.n_variables ;
i++) {
6652 mscb_info_variable(fd, cur_node,
i, &info_var);
6653 if (info_var.flags & MSCBF_HIDDEN)
6656 if (
i <
info.n_variables) {
6658 strcpy(
str, show_hidden ?
" checked" :
"");
6659 r->
rsprintf(
"<tr><td colspan=3><input type=checkbox%s name=\"hidden\" value=\"1\"",
str);
6660 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);
6664 for (fi=0 ; fi <
info.n_variables ; ) {
6665 for (
i=fi,size=0 ;
i <
info.n_variables && size < 100;
i++) {
6666 mscb_info_variable(fd, cur_node,
i, &info_var);
6667 size += info_var.width;
6670 size =
sizeof(dbuf);
6671 status = mscb_read_range(fd, cur_node, fi,
i-1, dbuf, &size);
6672 if (
status != MSCB_SUCCESS) {
6673 r->
rsprintf(
"<tr><td colspan=3><b>Error reading data from node</b></td>");
6678 for (
j=fi ;
j<
i ;
j++) {
6679 status = mscb_info_variable(fd, cur_node,
j, &info_var);
6680 if ((info_var.flags & MSCBF_HIDDEN) == 0 || show_hidden) {
6682 mstrlcpy(tr8, info_var.name,
sizeof(tr8));
6683 r->
rsprintf(
"<tr><td class=\"v1\">%s</td>\r\n", tr8);
6684 r->
rsprintf(
"<td class=\"v2\">\r\n");
6686 print_mscb_var(
value, evalue, unit, &info_var, pd);
6687 r->
rsprintf(
"<a href=\"#\" onClick=\"mscb_edit(%d,'%s')\">%s</a>",
6689 r->
rsprintf(
"</td><td class=\"v3\">%s</td>", unit);
6692 pd += info_var.width;
6700 r->
rsprintf(
"</td></tr></table>\r\n");
6701 r->
rsprintf(
"</td></tr></table>\r\n");
6702 r->
rsprintf(
"</td></tr></table>\r\n");
6703 r->
rsprintf(
"</div></body></html>\r\n");
6712 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
6717 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
6718 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
6719 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
6720 r->
rsprintf(
"<title>Enter password</title></head><body>\n\n");
6722 r->
rsprintf(
"<form method=\"GET\" action=\".\">\n\n");
6725 r->
rsprintf(
"<table class=\"headerTable\"><tr><td></td><tr></table>\n");
6727 r->
rsprintf(
"<table class=\"dialogTable\">\n");
6729 r->
rsprintf(
"<tr><th class=\"redLight\">Wrong password!</tr>\n");
6731 r->
rsprintf(
"<tr><th>Please enter password</tr>\n");
6732 r->
rsprintf(
"<tr><td align=center><input type=password name=pwd></tr>\n");
6733 r->
rsprintf(
"<tr><td align=center><input type=submit value=Submit></tr>");
6755 if (strcmp(password,
str) == 0)
6759 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
6764 r->
rsprintf(
"<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\" />\n");
6765 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"midas.css\" type=\"text/css\" />\n");
6766 r->
rsprintf(
"<link rel=\"stylesheet\" href=\"mhttpd.css\" type=\"text/css\" />\n");
6767 r->
rsprintf(
"<title>Enter password</title></head><body>\n\n");
6769 r->
rsprintf(
"<form method=\"GET\" action=\".\">\n\n");
6773 r->
rsprintf(
"<input type=hidden name=redir value=\"%s\">\n", redir);
6776 r->
rsprintf(
"<table class=\"headerTable\"><tr><td></td><tr></table>\n");
6778 r->
rsprintf(
"<table class=\"dialogTable\">\n");
6781 r->
rsprintf(
"<tr><th class=\"redLight\">Wrong password!</tr>\n");
6784 (
"<tr><th>Please enter password to obtain write access</tr>\n");
6785 r->
rsprintf(
"<tr><td align=center><input type=password name=wpwd></tr>\n");
6786 r->
rsprintf(
"<tr><td align=center><input type=submit value=Submit></tr>");
6803 int keyPresent, size,
status, line, link_index;
6814 if (strcmp(dec_path,
"root") == 0) {
6819 mstrlcpy(xdecpath, dec_path,
sizeof(xdecpath));
6820 if (strrchr(xdecpath,
'/'))
6821 mstrlcpy(xdecpath, strrchr(xdecpath,
'/')+1,
sizeof(xdecpath));
6822 if (xdecpath[0] == 0)
6823 mstrlcpy(xdecpath,
"root",
sizeof(xdecpath));
6824 show_header(r,
"MIDAS online database",
"", xdecpath, 0);
6827 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
6828 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
6829 r->
rsprintf(
"<script type=\"text/javascript\" src=\"obsolete.js\"></script>\n");
6830 r->
rsprintf(
"<script type=\"text/javascript\" src=\"controls.js\"></script>\n");
6835 r->
rsprintf(
"Error: cannot find key %s<P>\n", dec_path);
6845 mstrlcpy(xdec_path, dec_path,
sizeof(xdec_path));
6848 char* p = xdec_path + strlen(xdec_path) - 1;
6849 while (*p && *p !=
'/')
6856 r->
rsprintf(
"Error: cannot find key %s<P>\n", xdec_path);
6861 dec_path = xdec_path;
6874 r->
rsprintf(
"<table class=\"mtableheader\">\n");
6875 r->
rsprintf(
"<tr><td colspan=%d>\n", colspan);
6876 r->
rsprintf(
"<input type=button value=ELog onclick=\"self.location=\'?cmd=Alarms\';\">\n");
6877 r->
rsprintf(
"</td></tr></table>\n\n");
6883 r->
rsprintf(
"<table class=\"mtable\" style=\"border-spacing:0px;\">\n");
6884 r->
rsprintf(
"<tr><th colspan=%d class=\"mtableheader\">Online Database Browser</tr>\n", colspan);
6887 r->
rsprintf(
"<tr><td colspan=%d>\n", colspan);
6888 r->
rsprintf(
"<input type=button value=Find onclick=\"self.location=\'?cmd=Find\';\">\n");
6889 r->
rsprintf(
"<input type=button value=Create onclick=\"dlgShow('dlgCreate')\">\n");
6890 r->
rsprintf(
"<input type=button value=Link onclick=\"dlgShow('dlgLink')\">\n");
6891 r->
rsprintf(
"<input type=button value=Delete onclick=\"dlgShow('dlgDelete')\">\n");
6892 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());
6893 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());
6894 r->
rsprintf(
"<input type=button value=\"Show ODB clients\" onclick=\"self.location=\'?cmd=odb_scl\';\">\n");
6900 std::string dd =
"";
6902 dd +=
"<!-- Demo dialog -->\n";
6903 dd +=
"<div id=\"dlgDelete\" class=\"dlgFrame\">\n";
6904 dd +=
"<div class=\"dlgTitlebar\">Delete ODB entry</div>\n";
6905 dd +=
"<div class=\"dlgPanel\">\n";
6906 dd +=
"<div id=odbpath>";
6908 dd += MJsonNode::Encode(odbpath.c_str());
6911 dd +=
"<div><br></div>\n";
6913 dd +=
"<table class=\"dialogTable\">\n";
6914 dd +=
"<th colspan=2>Delete ODB entries:</th>\n";
6916 std::vector<std::string> delete_list;
6918 int count_delete = 0;
6923 r->
rsprintf(
"<tr><td colspan=%d class='ODBpath'><b>", colspan);
6924 r->
rsprintf(
"<a href=\"?cmd=oldodb\">/</a> \n");
6926 std::string enc_root_path;
6930 const char* p = dec_path;
6933 while (*p && *p !=
'/')
6938 if (pd.length() > 0)
6939 r->
rsprintf(
"<a href=\"?cmd=oldodb&odb_path=%s\">%s</a>\n / ", enc_root_path.c_str(), pd.c_str());
6941 enc_root_path +=
"/";
6951 for(
int scan=0; scan<2; scan++){
6952 if(scan==1 && keyPresent==1) {
6953 r->
rsprintf(
"<tr class=\"titleRow\">\n");
6954 r->
rsprintf(
"<th class=\"ODBkey\">Key</th>\n");
6955 r->
rsprintf(
"<th class=\"ODBvalue\">Value ");
6956 r->
rsprintf(
"<script type=\"text/javascript\">\n");
6957 r->
rsprintf(
"function expand()\n");
6959 r->
rsprintf(
" var n = document.getElementsByName('ext');\n");
6960 r->
rsprintf(
" for (i=0 ; i<n.length ; i++) {\n");
6961 r->
rsprintf(
" if (n[i].style.display == 'none')\n");
6962 r->
rsprintf(
" n[i].style.display = 'table-cell';\n");
6964 r->
rsprintf(
" n[i].style.display = 'none';\n");
6966 r->
rsprintf(
" if (document.getElementById('expp').expflag === true) {\n");
6967 r->
rsprintf(
" document.getElementById('expp').expflag = false;\n");
6968 r->
rsprintf(
" document.getElementById('expp').innerHTML = '⇥';\n");
6970 r->
rsprintf(
" document.getElementById('expp').expflag = true;\n");
6971 r->
rsprintf(
" document.getElementById('expp').innerHTML = '⇤';\n");
6975 r->
rsprintf(
"<div style=\"display:inline;float:right\"><a id=\"expp\"href=\"#\" onClick=\"expand();return false;\">⇥</div>");
6977 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Type</th>\n");
6978 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">#Val</th>\n");
6979 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Size</th>\n");
6980 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Written</th>\n");
6981 r->
rsprintf(
"<th class=\"ODBvalue\" name=\"ext\" style=\"display:none\">Mode</th>\n");
6985 for (
int i = 0;;
i++) {
6992 delete_list.push_back(
key.
name);
6996 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
6998 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
7000 std::string keyname =
key.
name;
7003 std::string enc_full_path = enc_root_path + enc_keyname;
7005 std::string odb_path = dec_path;
7006 if (odb_path.length() > 0 && odb_path[odb_path.length() - 1] !=
'/')
7011 std::string enc_link_ref;
7016 size =
sizeof(link_name);
7025 enc_link_ref =
"?cmd=Set&odb_path=";
7026 enc_link_ref += enc_full_path;
7030 sprintf(link_name,
"%s",
"(empty)");
7034 std::string enc_ref;
7037 if (enc_root_path.back() ==
'/' && link_name[0] ==
'/') {
7040 enc_ref +=
"?cmd=Set&odb_path=";
7041 enc_ref += enc_root_path;
7046 enc_ref +=
"?cmd=Set&odb_path=";
7047 enc_ref += enc_root_path;
7053 enc_ref +=
"?cmd=Set&odb_path=";
7054 enc_ref += enc_full_path;
7059 r->
rsprintf(
"<tr><td class=\"yellowLight\">");
7060 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)");
7066 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());
7068 r->
rsprintf(
"<i>→ <a href=\"%s\">%s</a></i>", enc_link_ref.c_str(), link_name);
7072 if (strchr(link_name,
'['))
7073 link_index = atoi(strchr(link_name,
'[')+1);
7080 size =
sizeof(
data);
7083 std::string data_str;
7085 if (link_index != -1)
7091 if (size ==
sizeof(
data)) {
7092 data_str +=
"...(truncated)";
7096 std::string hex_str;
7099 if (link_index != -1)
7105 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
7106 data_str =
"(empty)";
7111 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0]) {
7113 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7114 r->
rsprintf(
"%s <i>→ ", keyname.c_str());
7115 r->
rsprintf(
"<a href=\"%s\">%s</a></i>\n", enc_link_ref.c_str(), link_name);
7116 r->
rsprintf(
"<td class=\"%s\">\n", style);
7118 r->
rsprintf(
"%s (%s)", data_str.c_str(), hex_str.c_str());
7120 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7121 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">%s (%s)</a>\n", odb_path.c_str(), data_str.c_str(), hex_str.c_str());
7124 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7125 r->
rsprintf(
"%s<td class=\"%s\">", keyname.c_str(), style);
7127 r->
rsprintf(
"%s (%s)", data_str.c_str(), hex_str.c_str());
7129 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7130 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">%s (%s)</a>\n", odb_path.c_str(), data_str.c_str(), hex_str.c_str());
7134 if (strchr(data_str.c_str(),
'\n')) {
7136 r->
rsprintf(
"<td class=\"ODBkey\">");
7137 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td class=\"ODBvalue\">", keyname.c_str(), enc_link_ref.c_str(), link_name);
7139 r->
rsprintf(
"<td class=\"ODBkey\">%s<td class=\"%s\">", keyname.c_str(), style);
7143 if (strlen(
data) > data_str.length())
7144 r->
rsprintf(
"<i>... (%d bytes total)<p>\n", (
int)strlen(
data));
7146 r->
rsprintf(
"<a href=\"%s\">Edit</a>\n", enc_ref.c_str());
7149 r->
rsprintf(
"<td class=\"ODBkey\">\n");
7150 r->
rsprintf(
"%s <i>→ <a href=\"%s\">%s</a></i><td class=\"%s\">", keyname.c_str(), enc_link_ref.c_str(), link_name, style);
7154 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7155 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", odb_path.c_str());
7160 r->
rsprintf(
"<td class=\"ODBkey\">%s<td class=\"%s\">", keyname.c_str(), style);
7161 if (!write_access) {
7164 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), odb_path.c_str());
7165 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", odb_path.c_str());
7174 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7178 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7182 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7186 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7190 else if (delta < 3600)
7191 r->
rsprintf(
"%1.0lfm", delta / 60.0);
7192 else if (delta < 86400)
7193 r->
rsprintf(
"%1.0lfh", delta / 3600.0);
7194 else if (delta < 86400 * 99)
7195 r->
rsprintf(
"%1.0lfd", delta / 86400.0);
7200 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\">");
7216 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);
7220 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);
7226 mstrlcpy(style,
"ODBtableEven",
sizeof(style));
7228 mstrlcpy(style,
"ODBtableOdd",
sizeof(style));
7231 size =
sizeof(
data);
7235 std::string hex_str;
7243 if (size ==
sizeof(
data)) {
7244 data_str +=
"...(truncated)";
7248 if (data_str.empty() ||
equal_ustring(data_str.c_str(),
"<NULL>")) {
7249 data_str =
"(empty)";
7255 enc_ref +=
"?cmd=Set&odb_path=";
7256 enc_ref += enc_full_path;
7257 enc_ref +=
"&index=";
7270 r->
rsprintf(
"<td class=\"%s\">[%d] ", style,
j);
7272 r->
rsprintf(
"<a href=\"%s\">", enc_ref.c_str());
7274 r->
rsprintf(
"<a href=\"%s\" onClick=\"ODBInlineEdit(this.parentNode,\'%s\');return false;\" ", enc_ref.c_str(), tmpstr.c_str());
7275 r->
rsprintf(
"onFocus=\"ODBInlineEdit(this.parentNode,\'%s\');\">", tmpstr.c_str());
7277 if (strcmp(data_str.c_str(), hex_str.c_str()) != 0 && hex_str[0])
7278 r->
rsprintf(
"%s (%s)</a>\n", data_str.c_str(), hex_str.c_str());
7280 r->
rsprintf(
"%s</a>\n", data_str.c_str());
7284 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7288 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7292 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7296 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7300 else if (delta < 3600)
7301 r->
rsprintf(
"%1.0lfm", delta / 60.0);
7302 else if (delta < 86400)
7303 r->
rsprintf(
"%1.0lfh", delta / 3600.0);
7304 else if (delta < 86400 * 99)
7305 r->
rsprintf(
"%1.0lfh", delta / 86400.0);
7310 r->
rsprintf(
"<td class=\"ODBkey\" name=\"ext\" style=\"display:none\" rowspan=%d>",
key.
num_values);
7338 std::sort(delete_list.begin(), delete_list.end());
7340 for (
unsigned i=0;
i<delete_list.size();
i++) {
7341 std::string
name = delete_list[
i];
7343 dd +=
"<tr><td style=\"text-align:left;\" align=left><input align=left type=checkbox id=delete";
7347 dd += MJsonNode::Encode(
name.c_str());
7351 dd +=
"</input></td></tr>\n";
7355 dd +=
"<input type=button value=Delete onClick='mhttpd_delete_page_handle_delete(event);'>\n";
7356 dd +=
"<input type=button value=Cancel onClick='mhttpd_delete_page_handle_cancel(event);'>\n";
7364 std::string cd =
"";
7366 cd +=
"<!-- Demo dialog -->\n";
7367 cd +=
"<div id=\"dlgCreate\" class=\"dlgFrame\">\n";
7368 cd +=
"<div class=\"dlgTitlebar\">Create ODB entry</div>\n";
7369 cd +=
"<div class=\"dlgPanel\">\n";
7371 cd +=
"<div id=odbpath>";
7373 cd += MJsonNode::Encode(odbpath.c_str());
7376 cd +=
"<div><br></div>\n";
7378 cd +=
"<table class=\"dialogTable\">\n";
7379 cd +=
"<th colspan=2>Create ODB entry:</th>\n";
7383 cd +=
"<select type=text size=1 id=create_tid name=type>";
7384 cd +=
"<option value=7>Integer (32-bit)";
7385 cd +=
"<option value=9>Float (4 Bytes)";
7386 cd +=
"<option value=12>String";
7387 cd +=
"<option selected value=15>Subdirectory";
7388 cd +=
"<option value=1>Byte";
7389 cd +=
"<option value=2>Signed byte";
7390 cd +=
"<option value=3>Character (8-bit)";
7391 cd +=
"<option value=4>Word (16-bit)";
7392 cd +=
"<option value=5>Short integer (16-bit)";
7393 cd +=
"<option value=6>Double Word (32-bit)";
7394 cd +=
"<option value=8>Boolean";
7395 cd +=
"<option value=10>Double float (8 Bytes)";
7399 cd +=
"<tr><td>Name<td><input type=text size=31 maxlength=31 id=create_name name=value></tr>\n";
7400 cd +=
"<tr><td>Array size<td><input type=text size=31 maxlength=31 id=create_array_length name=index value=1></tr>\n";
7401 cd +=
"<tr><td>String length<td><input type=text size=31 maxlength=31 id=create_strlen name=strlen value=32></tr>\n";
7403 cd +=
"<input type=button value=Create onClick='mhttpd_create_page_handle_create(event);'>\n";
7404 cd +=
"<input type=button value=Cancel onClick='mhttpd_create_page_handle_cancel(event);'>\n";
7412 std::string ld =
"";
7414 ld +=
"<!-- Demo dialog -->\n";
7415 ld +=
"<div id=\"dlgLink\" class=\"dlgFrame\">\n";
7416 ld +=
"<div class=\"dlgTitlebar\">Create a link to an ODB entry</div>\n";
7417 ld +=
"<div class=\"dlgPanel\">\n";
7419 ld +=
"<div id=link_odbpath>";
7421 ld += MJsonNode::Encode(odbpath.c_str());
7424 ld +=
"<div><br></div>\n";
7426 ld +=
"<table class=\"dialogTable\">\n";
7427 ld +=
"<th colspan=2>Create a link to an ODB entry:</th>\n";
7428 ld +=
"<tr><td>Name<td><input type=text size=31 maxlength=31 id=link_name name=value></tr>\n";
7429 ld +=
"<tr><td>Link target<td><input type=text size=31 maxlength=256 id=link_target name=target></tr>\n";
7431 ld +=
"<input type=button value=Link onClick='mhttpd_link_page_handle_link(event);'>\n";
7432 ld +=
"<input type=button value=Cancel onClick='mhttpd_link_page_handle_cancel(event);'>\n";
7450 std::string odb_path = pp->
getparam(
"odb_path");
7460 r->
rsprintf(
"Error: cannot find key %s<P>\n", odb_path.c_str());
7470 r->
rsprintf(
"<table class=\"dialogTable\">");
7473 r->
rsprintf(
"<input type=hidden name=index value=\"%d\">\n",
index);
7478 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", group);
7480 r->
rsprintf(
"<input type=hidden name=odb_path value=\"%s\">\n", odb_path.c_str());
7488 str1 = odb_path.c_str();
7490 r->
rsprintf(
"<tr><th colspan=2>Set new value - type = %s</tr>\n", data_str1.c_str());
7491 r->
rsprintf(
"<tr><td>%s<td>\n", str1.c_str());
7494 size =
sizeof(
data);
7501 if (strchr(data_str.c_str(),
'\n') != NULL) {
7502 r->
rsprintf(
"<textarea rows=20 cols=80 name=\"text\">\n");
7507 if ((
int) data_str.length() > size)
7508 size = data_str.length() + 3;
7512 r->
rsprintf(
"<input type=\"text\" size=%d maxlength=256 name=\"value\" value=\"", size);
7519 r->
rsprintf(
"<tr><td align=center colspan=2>");
7520 r->
rsprintf(
"<input type=submit name=cmd value=Set>");
7521 r->
rsprintf(
"<input type=submit name=cmd value=Cancel>");
7525 r->
rsprintf(
"<input type=hidden name=cmd value=Set>\n");
7536 r->
rsprintf(
"Error: cannot find key %s<P>\n", odb_path.c_str());
7565 r->
rsprintf(
"<h2>Write access not allowed</h2>\n");
7581 if (
value[0] == 0) {
7589 r->
rsprintf(
"<table class=\"dialogTable\">");
7591 r->
rsprintf(
"<tr><th colspan=2>Find string in Online Database</tr>\n");
7592 r->
rsprintf(
"<tr><td>Enter substring (case insensitive)\n");
7594 r->
rsprintf(
"<td><input type=\"text\" size=\"20\" maxlength=\"80\" name=\"value\">\n");
7597 r->
rsprintf(
"<tr><td align=center colspan=2>");
7598 r->
rsprintf(
"<input type=submit name=cmd value=Find>");
7599 r->
rsprintf(
"<input type=submit name=cmd value=Cancel>");
7603 r->
rsprintf(
"<input type=hidden name=cmd value=Find>");
7611 r->
rsprintf(
"<table class=\"mtable\">\n");
7612 r->
rsprintf(
"<tr><th colspan=2 class=\"mtableheader\">");
7613 r->
rsprintf(
"Results of search for substring \"%s\"</tr>\n",
value);
7614 r->
rsprintf(
"<tr><th class=\"titlerow\">Key<th>Value</tr>\n");
7636#define LN10 2.302585094
7637#define LOG2 0.301029996
7638#define LOG5 0.698970005
7641 int x1,
int y1,
int width,
7642 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax)
7644 double dx, int_dx, frac_dx, x_act, label_dx, major_dx, x_screen, maxwidth;
7645 int tick_base, major_base, label_base, n_sig1, n_sig2, xs;
7647 double base[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
7649 if (xmax <= xmin || width <= 0)
7653 dx = (xmax - xmin) / (
double) (width / 5);
7655 frac_dx = modf(log(dx) /
LN10, &int_dx);
7661 tick_base = frac_dx <
LOG2 ? 1 : frac_dx <
LOG5 ? 2 : 3;
7662 major_base = label_base = tick_base + 1;
7665 dx = pow(10, int_dx) *
base[tick_base];
7666 major_dx = pow(10, int_dx) *
base[major_base];
7667 label_dx = major_dx;
7673 n_sig1 = (int) floor(log(fabs(xmin)) /
LN10) - (
int) floor(log(fabs(label_dx)) /
LN10) + 1;
7679 (int) floor(log(fabs(xmax)) /
LN10) - (
int) floor(log(fabs(label_dx)) /
LN10) + 1;
7681 n_sig1 =
MAX(n_sig1, n_sig2);
7682 n_sig1 =
MAX(n_sig1, 4);
7685 sprintf(
str,
"%1.*lG", n_sig1, floor(xmin / dx) * dx);
7686 maxwidth = font->
h / 2 * strlen(
str);
7687 sprintf(
str,
"%1.*lG", n_sig1, floor(xmax / dx) * dx);
7688 maxwidth =
MAX(maxwidth, font->
h / 2 * strlen(
str));
7689 sprintf(
str,
"%1.*lG", n_sig1, floor(xmax / dx) * dx + label_dx);
7690 maxwidth =
MAX(maxwidth, font->
h / 2 * strlen(
str));
7693 while (maxwidth > 0.7 * label_dx / (xmax - xmin) * width) {
7695 label_dx = pow(10, int_dx) *
base[label_base];
7696 if (label_base % 3 == 2 && major_base % 3 == 1) {
7698 major_dx = pow(10, int_dx) *
base[major_base];
7702 x_act = floor(xmin / dx) * dx;
7707 x_screen = (x_act - xmin) / (xmax - xmin) * width + x1;
7708 xs = (int) (x_screen + 0.5);
7710 if (x_screen > x1 + width + 0.001)
7713 if (x_screen >= x1) {
7714 if (fabs(floor(x_act / major_dx + 0.5) - x_act / major_dx) <
7715 dx / major_dx / 10.0) {
7717 if (fabs(floor(x_act / label_dx + 0.5) - x_act / label_dx) <
7718 dx / label_dx / 10.0) {
7723 if (grid != 0 && xs > x1 && xs < x1 + width)
7728 sprintf(
str,
"%1.*lG", n_sig1, x_act);
7730 y1 + label,
str, col);
7737 if (grid != 0 && xs > x1 && xs < x1 + width)
7750 if (fabs(x_act) < dx / 100)
7763 t_sec = (time_t) sec;
7766 localtime_r(&t_sec, &tms);
7767 strcpy(mon,
mname[tms.tm_mon]);
7772 sprintf(result,
"%02d %s %02d %02d:%02d:%02d",
7773 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min,
7775 else if (
base < 3600 * 24)
7776 sprintf(result,
"%02d %s %02d %02d:%02d",
7777 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min);
7779 sprintf(result,
"%02d %s %02d", tms.tm_mday, mon, tms.tm_year % 100);
7782 sprintf(result,
"%02d:%02d:%02d", tms.tm_hour, tms.tm_min, tms.tm_sec);
7783 else if (
base < 3600 * 3)
7784 sprintf(result,
"%02d:%02d", tms.tm_hour, tms.tm_min);
7785 else if (
base < 3600 * 24)
7786 sprintf(result,
"%02d %s %02d %02d:%02d",
7787 tms.tm_mday, mon, tms.tm_year % 100, tms.tm_hour, tms.tm_min);
7789 sprintf(result,
"%02d %s %02d", tms.tm_mday, mon, tms.tm_year % 100);
7794 int x1,
int y1,
int width,
int xr,
7795 int minor,
int major,
int text,
int label,
int grid,
double xmin,
double xmax)
7797 int dx, x_act, label_dx, major_dx, x_screen, maxwidth;
7798 int tick_base, major_base, label_base, xs, xl;
7800 const int base[] = { 1, 5, 10, 60, 300, 600, 1800, 3600, 3600 * 6, 3600 * 12, 3600 * 24, 0 };
7802 int force_date, d1, d2;
7805 if (xmax <= xmin || width <= 0)
7810 localtime_r(<ime, &tms);
7812 ltime = (time_t) xmax;
7813 localtime_r(<ime, &tms);
7815 force_date = (d1 != d2);
7818 dx = (int) ((xmax - xmin) / (double) (width / 5) + 0.5);
7820 for (tick_base = 0;
base[tick_base]; tick_base++) {
7821 if (
base[tick_base] > dx)
7824 if (!
base[tick_base])
7826 dx =
base[tick_base];
7828 if (
base[tick_base + 1])
7829 major_base = tick_base + 1;
7831 major_base = tick_base;
7832 major_dx =
base[major_base];
7834 if (
base[major_base + 1])
7835 label_base = major_base + 1;
7837 label_base = major_base;
7838 label_dx =
base[label_base];
7842 maxwidth = font->
h / 2 * strlen(
str);
7845 if (maxwidth > 0.7 * label_dx / (xmax - xmin) * width) {
7846 if (
base[label_base + 1])
7847 label_dx =
base[++label_base];
7849 label_dx += 3600 * 24;
7860 x_screen = (int) ((x_act - xmin) / (xmax - xmin) * width + x1 + 0.5);
7861 xs = (int) (x_screen + 0.5);
7863 if (x_screen > x1 + width + 0.001)
7866 if (x_screen >= x1) {
7873 if (grid != 0 && xs > x1 && xs < x1 + width)
7881 xl = (int) xs - font->
w * strlen(
str) / 2;
7884 if (xl + font->
w * (
int) strlen(
str) > xr)
7885 xl = xr - font->
w * strlen(
str);
7893 if (grid != 0 && xs > x1 && xs < x1 + width)
7906 if (fabs((
double)x_act) < dx / 100)
7915 int x1,
int y1,
int width,
7916 int minor,
int major,
int text,
int label,
int grid,
double ymin,
double ymax,
7919 double dy, int_dy, frac_dy, y_act, label_dy, major_dy, y_screen, y_next;
7920 int tick_base, major_base, label_base, n_sig1, n_sig2, ys, max_width;
7923 const double base[] = { 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 };
7925 if (ymax <= ymin || width <= 0)
7929 if (fabs(ymax - ymin) <= 1
e-10)
7933 dy = pow(10, floor(log(ymin) /
LN10));
7938 dy = (ymax - ymin) / (
double) (width / 5);
7940 frac_dy = modf(log(dy) /
LN10, &int_dy);
7946 tick_base = frac_dy <
LOG2 ? 1 : frac_dy <
LOG5 ? 2 : 3;
7947 major_base = label_base = tick_base + 1;
7950 dy = pow(10, int_dy) *
base[tick_base];
7951 major_dy = pow(10, int_dy) *
base[major_base];
7952 label_dy = major_dy;
7959 (int) floor(log(fabs(ymin)) /
LN10) -
7960 (
int) floor(log(fabs(label_dy)) /
LN10) + 1;
7966 (int) floor(log(fabs(ymax)) /
LN10) -
7967 (
int) floor(log(fabs(label_dy)) /
LN10) + 1;
7969 n_sig1 =
MAX(n_sig1, n_sig2);
7970 n_sig1 =
MAX(n_sig1, 4);
7973 while (label_dy / (ymax - ymin) * width < 1.5 * font->h) {
7975 label_dy = pow(10, int_dy) *
base[label_base];
7976 if (label_base % 3 == 2 && major_base % 3 == 1) {
7978 major_dy = pow(10, int_dy) *
base[major_base];
7984 y_act = floor(ymin / dy) * dy;
7986 if (x1 != 0 || y1 != 0)
7989 last_label_y = y1 + 2 * font->
h;
7993 y_screen = y1 - (log(y_act) - log(ymin)) / (log(ymax) - log(ymin)) * width;
7995 y_screen = y1 - (y_act - ymin) / (ymax - ymin) * width;
7996 ys = (int) (y_screen + 0.5);
7998 if (y_screen < y1 - width - 0.001)
8001 if (y_screen <= y1 + 0.001) {
8002 if (fabs(floor(y_act / major_dy + 0.5) - y_act / major_dy) <
8003 dy / major_dy / 10.0) {
8004 if (fabs(floor(y_act / label_dy + 0.5) - y_act / label_dy) <
8005 dy / label_dy / 10.0) {
8006 if (x1 != 0 || y1 != 0) {
8011 if (grid != 0 && y_screen < y1 && y_screen > y1 - width) {
8020 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8023 ys - font->
h / 2,
str, col);
8027 last_label_y = ys - font->
h / 2;
8030 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8031 max_width =
MAX(max_width, (
int) (font->
w * strlen(
str)));
8034 if (x1 != 0 || y1 != 0) {
8039 if (grid != 0 && y_screen < y1 && y_screen > y1 - width)
8050 if (x1 != 0 || y1 != 0) {
8058 if (x1 != 0 || y1 != 0) {
8060 y_next = pow(10, floor(log(y_act) /
LN10) + 1);
8063 (log(y_next) - log(ymin)) / (log(ymax) -
8064 log(ymin)) * width + 0.5);
8066 if (ys + font->
h / 2 < last_label_y
8067 && ys - font->
h / 2 > y_screen + font->
h / 2) {
8068 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8071 ys - font->
h / 2,
str, col);
8077 last_label_y = ys - font->
h / 2;
8079 sprintf(
str,
"%1.*lG", n_sig1, y_act);
8080 max_width =
MAX(max_width, (
int) (font->
w * strlen(
str)));
8090 if (fabs(y_act) < dy / 100)
8095 return max_width + abs(label);
8105 switch (
str[strlen(
str) - 1]) {
8128 for (; *
str != 0;
str++) {
8144 sprintf(buf,
"%.0f", (
double)t);
8157 cm_msg(
MINFO,
"history_watch_callback",
"History configuration may have changed, will reconnect");
8224 cm_msg(
MERROR,
"get_history",
"Cannot configure history, hs_get_history() status %d",
status);
8242#define ALLOC(t,n) (t*)calloc(sizeof(t),(n))
8243#define DELETE(x) if (x) { free(x); (x)=NULL; }
8244#define DELETEA(x, n) if (x) { for (int i=0; i<(n); i++) { free((x)[i]); (x)[i]=NULL; }; DELETE(x); }
8245#define STRDUP(x) strdup(x)
8301 printf(
"this %p, nvars %d. tstart %d, tend %d, scale %d\n",
this,
nvars, (
int)
tstart, (
int)
tend, (
int)
scale);
8328#define READ_HISTORY_DATA 0x1
8329#define READ_HISTORY_RUNMARKER 0x2
8330#define READ_HISTORY_LAST_WRITTEN 0x4
8390 cm_msg(
MERROR,
"read_history",
"Cannot find \'/History/Display\' in ODB, status %d",
status);
8397 cm_msg(
MERROR,
"read_history",
"Cannot find \'%s\' in ODB, status %d", path,
status);
8403 cm_msg(
MERROR,
"read_history",
"Cannot find \'%s/Variables\' in ODB, status %d", path,
status);
8413 data->tstart = tstart;
8415 data->scale = scale;
8417 for (
size_t i=0;
i<hp.
vars.size();
i++) {
8447 char *
q = strchr(
data->var_names[
data->nvars],
'[');
8449 data->var_index[
data->nvars] = atoi(
q+1);
8465 data->var_index[
data->nvars+0] = 0;
8466 data->var_index[
data->nvars+1] = 0;
8468 data->odb_index[
data->nvars+0] = -1;
8469 data->odb_index[
data->nvars+1] = -2;
8474 bool get_last_written =
false;
8488 printf(
"read_history: nvars %d, hs_read() status %d\n",
data->nvars,
status);
8489 for (
int i=0;
i<
data->nvars;
i++) {
8490 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]);
8495 cm_msg(
MERROR,
"read_history",
"Complete history failure, hs_read() status %d, see messages",
status);
8499 for (
int i=0;
i<
data->nvars;
i++) {
8501 get_last_written =
true;
8508 get_last_written =
true;
8510 if (get_last_written) {
8511 data->have_last_written =
true;
8519 data->last_written);
8522 data->have_last_written =
false;
8564 time_t tmin = endtime;
8567 for (
int k=0;
k<hsdata->
nvars;
k++) {
8598 *plastwritten = tmin;
8600 *plastwritten = tmax;
8607 printf(
"get_hist_last_written: elapsed time %f ms\n", tend-tstart);
8613 int width,
int height,
8617 int labels,
const char *bgcolor,
const char *fgcolor,
const char *gridcolor)
8625 int size,
status, r, g, b;
8628 int white, grey, red;
8630 int fgcol, bgcol, gridcol;
8650 time_t starttime, endtime;
8661 std::vector<int> var_index; var_index.resize(hp.
vars.size());
8663 for (
size_t i=0;
i<hp.
vars.size();
i++) {
8665 const char *vp = strchr(hp.
vars[
i].tag_name.c_str(),
'[');
8667 var_index[
i] = atoi(vp + 1);
8675 if ((minvalue == 0) && (maxvalue == 0)) {
8676 minvalue = -HUGE_VAL;
8677 maxvalue = +HUGE_VAL;
8692 sscanf(bgcolor,
"%02x%02x%02x", &r, &g, &b);
8694 sscanf(fgcolor,
"%02x%02x%02x", &r, &g, &b);
8696 sscanf(gridcolor,
"%02x%02x%02x", &r, &g, &b);
8733 sprintf(
str,
"History is not configured, see messages");
8757 if (hp.
vars.empty()) {
8758 sprintf(
str,
"No variables in panel %s/%s", hgroup, hpanel);
8764 sprintf(
str,
"Too many variables in panel %s/%s", hgroup, hpanel);
8772 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
8833 if (hp.
vars[
i].colour[0] ==
'#') {
8834 const char*
str = hp.
vars[
i].colour.c_str();
8841 r = strtoul(sss, NULL, 16);
8845 g = strtoul(sss, NULL, 16);
8849 b = strtoul(sss, NULL, 16);
8925 std::string odbpath;
8941 sprintf(
str,
"Variables/%s", hp.
vars[
i].tag_name.c_str());
8947 odbpath +=
"/Equipment/";
8948 odbpath += hp.
vars[
i].event_name;
8949 odbpath +=
"/Variables/";
8950 odbpath += hp.
vars[
i].tag_name;
8959 mstrlcpy(
str, hp.
vars[
i].tag_name.c_str(),
sizeof(
str));
8960 p =
str + strlen(
str) - 1;
8961 while (p >
str && *p !=
' ')
8963 std::string key_name = p + 1;
8966 std::string varname =
str;
8976 odbpath +=
"/Equipment/";
8977 odbpath += hp.
vars[
i].event_name;
8978 odbpath +=
"/Variables/";
8979 odbpath += key_name;
9001 std::string key_name =
key.
name;
9005 path +=
"Settings/Names ";
9018 odbpath +=
"/Equipment/";
9019 odbpath += hp.
vars[
i].event_name;
9020 odbpath +=
"/Variables/";
9021 odbpath += key_name;
9069 upper_limit[
i] = lower_limit[
i] = -12345;
9071 if (odbpath.length() > 0 && hkeyroot) {
9082 if (strstr(
str, odbpath.c_str())) {
9083 if (strchr(
str,
'<')) {
9084 p = strchr(
str,
'<') + 1;
9088 lower_limit[
i] = (hp.
vars[
i].factor * (atof(p) - hp.
vars[
i].voffset) + hp.
vars[
i].offset);
9090 lower_limit[
i] = atof(p);
9093 if (strchr(
str,
'>')) {
9094 p = strchr(
str,
'>') + 1;
9098 upper_limit[
i] = (hp.
vars[
i].factor * (atof(p) - hp.
vars[
i].voffset) + hp.
vars[
i].offset);
9100 upper_limit[
i] = atof(p);
9111 starttime = xendtime - scale;
9123 sprintf(
str,
"Complete history failure, read_history() status %d, see messages",
status);
9131 for (
int k=0;
k<hsdata->
nvars;
k++) {
9142 var_status[
i][0] = 0;
9144 sprintf(var_status[
i],
"not found in history");
9147 sprintf(var_status[
i],
"hs_read() error %d, see messages", hsdata->
status[
k]);
9153 int xx = (int)(hsdata->
t[
k][
j]);
9154 double yy = hsdata->
v[
k][
j];
9170 yy = hp.
vars[
i].factor * (yy - hp.
vars[
i].voffset) + hp.
vars[
i].offset;
9174 if ((
i == 0 ||
index != -1) && n_vp == 0)
9194 assert(x[
i].size() == y[
i].size());
9203 double yb1, yb2, yf1, yf2;
9212 if (ymin < minvalue)
9215 if (ymax > maxvalue)
9228 if (logaxis && ymin > 0 && ymax > 0) {
9229 yb1 = pow(10, floor(log(ymin) /
LN10));
9230 yf1 = floor(ymin / yb1);
9231 yb2 = pow(10, floor(log(ymax) /
LN10));
9232 yf2 = floor(ymax / yb2);
9234 if (yb1 == yb2 && yf1 == yf2)
9238 ybase = pow(10, floor(log(ymin) /
LN10));
9239 ymin = (floor(ymin / ybase) * ybase);
9240 ybase = pow(10, floor(log(ymax) /
LN10));
9241 ymax = ((floor(ymax / ybase) + 1) * ybase);
9254 if (ymin == 0 && ymax == 0) {
9259 ymax += (ymax - ymin) / 20.f;
9262 ymin -= (ymax - ymin) / 20.f;
9284 aoffset =
vaxis(im,
gdFontSmall, fgcol, gridcol, 0, 0, height, -3, -5, -7, -8, 0, ymin, ymax, logaxis);
9295 taxis(im,
gdFontSmall, fgcol, gridcol, x1, y1, x2 - x1, width, 3, 5, 9, 10, 0, (
double)starttime, (
double)endtime);
9297 vaxis(im,
gdFontSmall, fgcol, gridcol, x1, y1, y1 - y2, -3, -5, -7, -8, x2 - x1, ymin, ymax, logaxis);
9301 xs = ys = xold = yold = 0;
9308 const char* event_names[] = {
9313 const char* tag_names[] = {
9318 const int tag_indexes[] = {
9332 2, event_names, tag_names, tag_indexes,
9333 num_entries, tbuf, dbuf, st);
9337 int n_marker = num_entries[0];
9342 for (
j = 0;
j < (int) n_marker;
j++) {
9356 xs = (int) ((tbuf[1][
j] - starttime) / (scale/1.0) * (x2 - x1) + x1 + 0.5);
9369 if (dbuf[0][
j] == 1)
9371 else if (dbuf[0][
j] == 2)
9373 else if (dbuf[0][
j] == 3)
9396 if (num_entries[0]) {
9403 if (num_entries[1]) {
9414 int index_state = -1;
9415 int index_run_number = -1;
9417 for (
int k=0;
k<hsdata->
nvars;
k++) {
9422 index_run_number =
k;
9428 ok = (index_state >= 0) && (index_run_number >= 0);
9437 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]);
9444 if (ok && n_marker > 0 && n_marker < 100) {
9447 for (
j = 0;
j < (int) n_marker;
j++) {
9461 xs = (int) ((hsdata->
t[index_state][
j] - starttime) / (scale/1.0) * (x2 - x1) + x1 + 0.5);
9474 int state = (int)hsdata->
v[index_state][
j];
9478 else if (
state == 2)
9480 else if (
state == 3)
9504 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
9509 if (lower_limit[
i] != -12345) {
9511 if (lower_limit[
i] <= 0)
9514 ys = (int) (y1 - (log(lower_limit[
i]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9516 ys = (int) (y1 - (lower_limit[
i] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9528 if (ys > y2 && ys < y1) {
9541 if (upper_limit[
i] != -12345) {
9543 if (upper_limit[
i] <= 0)
9546 ys = (int) (y1 - (log(upper_limit[
i]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9548 ys = (int) (y1 - (upper_limit[
i] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9560 if (ys > y2 && ys < y1) {
9574 for (
j = 0;
j < (int) n_point[
i];
j++) {
9580 xs = (int) (((x[
i][
j] - starttime)/1.0) / (1.0*scale) * (x2 - x1) + x1 + 0.5);
9586 ys = (int) (y1 - (log(y[
i][
j]) - log(ymin)) / (log(ymax) - log(ymin)) * (y1 - y2) + 0.5);
9588 ys = (int) (y1 - (y[
i][
j] - ymin) / (ymax - ymin) * (y1 - y2) + 0.5);
9606 if (n_point[
i] > 0) {
9609 poly[1].
x = xs + 12;
9611 poly[2].
x = xs + 12;
9619 for (
i = 0;
i < (int)hp.
vars.size();
i++) {
9630 std::string
str = hp.
vars[
i].label.c_str();
9636 if (hp.
vars[
i].voffset > 0)
9638 else if (hp.
vars[
i].voffset < 0)
9641 if (hp.
vars[
i].factor != 1) {
9642 if (hp.
vars[
i].voffset == 0)
9649 if (hp.
vars[
i].offset > 0)
9651 else if (hp.
vars[
i].offset < 0)
9660 for (
int j=0;
j<hsdata->
nvars;
j++)
9667 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]);
9672 if (n_point[
i] > 0) {
9673 sprintf(xstr,
" = %g", y[
i][n_point[
i]-1]);
9675 sprintf(xstr,
" = all data is NaN or INF");
9680 sprintf(xstr,
" = last data %s", ctimebuf);
9682 char*s = strchr(xstr,
'\n');
9686 var_status[
i][0] = 0;
9688 sprintf(xstr,
" = no data ever");
9691 sprintf(xstr,
" = no data");
9696 if (strlen(var_status[
i]) > 1) {
9700 row =
index == -1 ?
i : 0;
9730 if (buffer == NULL) {
9731 rr->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
9734 rr->
rsprintf(
"Content-Type: image/gif\r\n");
9735 rr->
rsprintf(
"Content-Length: %d\r\n", length);
9736 rr->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
9737 rr->
rsprintf(
"Expires: Fri, 01-Jan-1983 00:00:00 GMT\r\n\r\n");
9741 if (length > *buffer_size) {
9742 printf(
"return buffer too small\n");
9746 memcpy(buffer, gb.
data, length);
9747 *buffer_size = length;
9772 struct tm tms = *ptms;
9775 localtime_r(&t1, &tms2);
9776 tms2.tm_year = ptms->tm_year;
9777 tms2.tm_mon = ptms->tm_mon;
9778 tms2.tm_mday = ptms->tm_mday;
9779 tms2.tm_hour = ptms->tm_hour;
9780 tms2.tm_min = ptms->tm_min;
9806 memset(&tms, 0,
sizeof(
struct tm));
9808 tms.tm_year = atoi(p->
getparam(
"y1")) % 100;
9810 std::string m1 = p->
getparam(
"m1");
9811 for (
i = 0;
i < 12;
i++)
9818 tms.tm_mday = atoi(p->
getparam(
"d1"));
9819 tms.tm_hour = atoi(p->
getparam(
"h1"));
9821 if (tms.tm_year < 90)
9826 memset(&tms, 0,
sizeof(
struct tm));
9827 tms.tm_year = atoi(p->
getparam(
"y2")) % 100;
9829 std::string m2 = p->
getparam(
"m2");
9830 for (
i = 0;
i < 12;
i++)
9837 tms.tm_mday = atoi(p->
getparam(
"d2"));
9838 tms.tm_hour = atoi(p->
getparam(
"h2"));
9840 if (tms.tm_year < 90)
9845 if (ltime_end == ltime_start)
9846 ltime_end += 3600 * 24;
9849 redir +=
"?cmd=oldhistory&";
9870 time_t now = time(NULL);
9872 time_t starttime = now - 3600 * 24;
9873 time_t endtime = now;
9874 bool full_day =
true;
9880 starttime = endtime - atoi(p->
getparam(
"hscale"));
9883 starttime = endtime - 3600 * 24;
9889 r->
rsprintf(
"<tr><td colspan=2>\n");
9890 r->
rsprintf(
"<input type=hidden name=cmd value=OldHistory>\n");
9891 r->
rsprintf(
"<input type=submit name=hcmd value=Query>\n");
9892 r->
rsprintf(
"<input type=submit name=hcmd value=Cancel>\n");
9894 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", p->
getparam(
"group"));
9896 r->
rsprintf(
"<input type=hidden name=panel value=\"%s\">\n", p->
getparam(
"panel"));
9898 r->
rsprintf(
"<input type=hidden name=htime value=\"%s\">\n", p->
getparam(
"htime"));
9900 r->
rsprintf(
"<input type=hidden name=hscale value=\"%s\">\n", p->
getparam(
"hscale"));
9902 r->
rsprintf(
"<input type=hidden name=hindex value=\"%s\">\n", p->
getparam(
"hindex"));
9906 r->
rsprintf(
"<table class=\"dialogTable\">");
9909 localtime_r(&starttime, &tms);
9910 tms.tm_year += 1900;
9912 r->
rsprintf(
"<tr><td nowrap>Start date:</td>");
9914 r->
rsprintf(
"<td>Month: <select name=\"m1\">\n");
9915 r->
rsprintf(
"<option value=\"\">\n");
9916 for (
i = 0;
i < 12;
i++)
9917 if (
i == tms.tm_mon)
9923 r->
rsprintf(
" Day: <select name=\"d1\">");
9924 r->
rsprintf(
"<option selected value=\"\">\n");
9925 for (
i = 0;
i < 31;
i++)
9926 if (
i + 1 == tms.tm_mday)
9927 r->
rsprintf(
"<option selected value=%d>%d\n",
i + 1,
i + 1);
9929 r->
rsprintf(
"<option value=%d>%d\n",
i + 1,
i + 1);
9932 int start_hour = tms.tm_hour;
9936 r->
rsprintf(
" Hour: <input type=\"text\" size=5 maxlength=5 name=\"h1\" value=\"%d\">", start_hour);
9938 r->
rsprintf(
" Year: <input type=\"text\" size=5 maxlength=5 name=\"y1\" value=\"%d\">", tms.tm_year);
9941 r->
rsprintf(
"<tr><td nowrap>End date:</td>");
9943 localtime_r(&endtime, &tms);
9944 tms.tm_year += 1900;
9946 r->
rsprintf(
"<td>Month: <select name=\"m2\">\n");
9947 r->
rsprintf(
"<option value=\"\">\n");
9948 for (
i = 0;
i < 12;
i++)
9949 if (
i == tms.tm_mon)
9955 r->
rsprintf(
" Day: <select name=\"d2\">");
9956 r->
rsprintf(
"<option selected value=\"\">\n");
9957 for (
i = 0;
i < 31;
i++)
9958 if (
i + 1 == tms.tm_mday)
9959 r->
rsprintf(
"<option selected value=%d>%d\n",
i + 1,
i + 1);
9961 r->
rsprintf(
"<option value=%d>%d\n",
i + 1,
i + 1);
9964 int end_hour = tms.tm_hour;
9968 r->
rsprintf(
" Hour: <input type=\"text\" size=5 maxlength=5 name=\"h2\" value=\"%d\">", end_hour);
9970 r->
rsprintf(
" Year: <input type=\"text\" size=5 maxlength=5 name=\"y2\" value=\"%d\">", tms.tm_year);
9986 const char*sa = (
const char*)a;
9987 const char*sb = (
const char*)b;
9996 printf(
"compare [%s] and [%s]\n", sa, sb);
9999 if (sa[
i]==0 && sb[
i]==0)
10004 if (isdigit(sa[
i]) && isdigit(sb[
i])) {
10005 int va = atoi(sa+
i);
10006 int vb = atoi(sb+
i);
10009 printf(
"index %d, values %d %d\n",
i, va, vb);
10020 if (sa[
i]==sb[
i]) {
10025 printf(
"index %d, char [%c] [%c]\n",
i, sa[
i], sb[
i]);
10029 else if (sb[
i] == 0)
10043 return cmp_names(a.c_str(), b.c_str()) < 0;
10057static int cmp_tags(
const void *a,
const void *b)
10059 const TAG*sa = (
const TAG*)a;
10060 const TAG*sb = (
const TAG*)b;
10064static void sort_tags(
int ntags,
TAG* tags)
10096 str =
"bad_xdb_find_key";
10116 printf(
"hist plot: %d variables\n", (
int)hp.
vars.size());
10117 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);
10119 for (
size_t i=0;
i<hp.
vars.size();
i++) {
10120 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);
10126 const char*
const colour[] =
10128 "#00AAFF",
"#FF9000",
"#FF00A0",
"#00C030",
10129 "#A0C0D0",
"#D0A060",
"#C04010",
"#807060",
10130 "#F0C000",
"#2090A0",
"#D040D0",
"#90B000",
10131 "#B0B040",
"#B0B0FF",
"#FFA0A0",
"#A0FFA0",
10134 for (
int i=0; colour[
i];
i++) {
10135 bool in_use =
false;
10137 for (
size_t j=0;
j<hp.
vars.size();
j++)
10138 if (hp.
vars[
j].colour == colour[
i]) {
10153 for (
size_t i=0;
i<hp.
vars.size();
i++)
10154 if (hp.
vars[
i].order > order)
10155 order = hp.
vars[
i].order;
10163 std::vector<size_t> colons;
10167 colons.push_back(
i);
10171 if (colons.size() == 0) {
10176 size_t slash_pos =
var_name.find(
"/");
10177 bool uses_per_variable_naming = (slash_pos != std::string::npos);
10179 if (uses_per_variable_naming && colons.size() % 2 == 1) {
10180 size_t middle_colon_pos = colons[colons.size() / 2];
10181 std::string slash_to_mid =
var_name.substr(slash_pos + 1, middle_colon_pos - slash_pos - 1);
10182 std::string mid_to_end =
var_name.substr(middle_colon_pos + 1);
10184 if (slash_to_mid == mid_to_end) {
10188 split_pos = middle_colon_pos;
10191 split_pos = colons[0];
10195 split_pos = colons[0];
10198 event_name =
var_name.substr(0, split_pos);
10199 tag_name =
var_name.substr(split_pos + 1);
10205 std::string path =
"History/Display/";
10210 MVOdb* o = odb->Chdir(path.c_str());
10216 o->RD(
"Minimum", &hp->
minimum);
10217 o->RD(
"Maximum", &hp->
maximum);
10227 std::vector<std::string> hist_vars;
10228 std::vector<std::string> hist_formula;
10229 std::vector<std::string> hist_colour;
10230 std::vector<std::string> hist_label;
10231 std::vector<bool> hist_show_raw_value;
10232 std::vector<double> hist_factor;
10233 std::vector<double> hist_offset;
10234 std::vector<double> hist_voffset;
10236 o->RSA(
"Variables", &hist_vars);
10237 o->RSA(
"Formula", &hist_formula);
10238 o->RSA(
"Colour", &hist_colour);
10239 o->RSA(
"Label", &hist_label);
10240 o->RBA(
"Show raw value", &hist_show_raw_value);
10241 o->RDA(
"Factor", &hist_factor);
10242 o->RDA(
"Offset", &hist_offset);
10243 o->RDA(
"VOffset", &hist_voffset);
10249 bool all_zero =
true;
10250 for (
size_t i=0;
i<hist_factor.size();
i++) {
10251 if (hist_factor[
i] != 0)
10255 for (
size_t i=0;
i<hist_factor.size();
i++) {
10256 hist_factor[
i] = 1.0;
10261 size_t num = std::max(hist_vars.size(), hist_formula.size());
10262 num = std::max(num, hist_colour.size());
10263 num = std::max(num, hist_label.size());
10264 num = std::max(num, hist_show_raw_value.size());
10265 num = std::max(num, hist_factor.size());
10266 num = std::max(num, hist_offset.size());
10267 num = std::max(num, hist_voffset.size());
10269 hist_vars.resize(num);
10270 hist_formula.resize(num);
10271 hist_colour.resize(num);
10272 hist_label.resize(num);
10273 hist_show_raw_value.resize(num);
10274 hist_factor.resize(num, 1.0);
10275 hist_offset.resize(num, 0.0);
10276 hist_voffset.resize(num, 0.0);
10278 for (
size_t i=0;
i<num;
i++) {
10285 v.
label = hist_label[
i];
10299 hp->
vars.push_back(v);
10372 hp->
vars.push_back(v);
10387 int seln = atoi(p->
getparam(
"seln"));
10388 for (
int i=0;
i<seln;
i++) {
10390 sprintf(
str,
"sel%d",
i);
10393 if (par.length() < 1)
10396 std::string event_name, tag_name;
10399 if (tag_name ==
"")
10409 hp.
vars.push_back(v);
10415 if (strlen(group) < 1) {
10416 cm_msg(
MERROR,
"SaveHistPlotToOdb",
"Error: Cannot write history plot to ODB, group \"%s\", panel \"%s\", invalid group name", group, panel);
10420 if (strlen(panel) < 1) {
10421 cm_msg(
MERROR,
"SaveHistPlotToOdb",
"Error: Cannot write history plot to ODB, group \"%s\", panel \"%s\", invalid panel name", group, panel);
10425 std::string path =
"History/Display/";
10433 MVOdb* o = odb->Chdir(path.c_str(),
true);
10435 o->WS(
"Timescale", hp.
timescale.c_str());
10436 o->WD(
"Minimum", hp.
minimum);
10437 o->WD(
"Maximum", hp.
maximum);
10446 std::vector<std::string> hist_vars;
10447 std::vector<std::string> hist_formula;
10448 std::vector<std::string> hist_colour;
10449 std::vector<std::string> hist_label;
10450 std::vector<bool> hist_show_raw_value;
10451 std::vector<double> hist_factor;
10452 std::vector<double> hist_offset;
10453 std::vector<double> hist_voffset;
10455 for (
size_t i=0;
i<hp.
vars.size();
i++) {
10456 hist_vars.push_back(hp.
vars[
i].event_name +
":" + hp.
vars[
i].tag_name);
10457 hist_formula.push_back(hp.
vars[
i].formula);
10458 hist_colour.push_back(hp.
vars[
i].colour);
10459 hist_label.push_back(hp.
vars[
i].label);
10460 hist_show_raw_value.push_back(hp.
vars[
i].show_raw_value);
10461 hist_factor.push_back(hp.
vars[
i].factor);
10462 hist_offset.push_back(hp.
vars[
i].offset);
10463 hist_voffset.push_back(hp.
vars[
i].voffset);
10466 if (hp.
vars.size() > 0) {
10467 o->WSA(
"Variables", hist_vars, 64);
10468 o->WSA(
"Formula", hist_formula, 64);
10471 o->WBA(
"Show raw value", hist_show_raw_value);
10472 o->WDA(
"Factor", hist_factor);
10473 o->WDA(
"Offset", hist_offset);
10474 o->WDA(
"VOffset", hist_voffset);
10476 o->Delete(
"Variables");
10477 o->Delete(
"Formula");
10478 o->Delete(
"Colour");
10479 o->Delete(
"Label");
10480 o->Delete(
"Show raw value");
10481 o->Delete(
"Factor");
10482 o->Delete(
"Offset");
10483 o->Delete(
"VOffset");
10494 bool something_deleted =
false;
10495 for (
unsigned i=0;
i<hp.
vars.size();
i++) {
10496 if (hp.
vars[
i].order <= 0) {
10498 something_deleted =
true;
10501 if (!something_deleted)
10510 bool need_sort =
false;
10511 for (
size_t i=1;
i<hp.
vars.size();
i++) {
10512 if (hp.
vars[
i-1].order >= hp.
vars[
i].order) {
10530 int max_display_events = 20;
10531 int max_display_tags = 200;
10532 char str[256], hcmd[256];
10534 odb->RI(
"History/MaxDisplayEvents", &max_display_events,
true);
10535 odb->RI(
"History/MaxDisplayTags", &max_display_tags,
true);
10537 mstrlcpy(hcmd, p->
getparam(
"hcmd"),
sizeof(hcmd));
10541 strcpy(hcmd,
"Refresh");
10561 if (strlen(p->
getparam(
"seln")) > 0)
10572 sprintf(
str,
"?cmd=oldhistory&group=%s&panel=%s", hgroup, hpanel);
10581 r->
rsprintf(
"<table class=\"mtable\">");
10583 r->
rsprintf(
"<tr><th colspan=11 class=\"subStatusTitle\">History Panel \"%s\" / \"%s\"</th></tr>\n", hgroup, hpanel);
10586 r->
rsprintf(
"<tr><td colspan=11>\n");
10588 r->
rsprintf(
"<input type=button value=Refresh ");
10589 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">\n");
10591 r->
rsprintf(
"<input type=button value=Save ");
10592 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Save';document.form1.submit()\">\n");
10595 r->
rsprintf(
"<input type=button value=Cancel ");
10596 std::string url =
"?cmd=oldhistory&group=";
10600 url +=
"&hcmd=Cancel";
10605 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10608 r->
rsprintf(
"<input type=button value=\"Edit in ODB\"");
10609 std::string url =
"?cmd=odb&odb_path=";
10610 url +=
"/History/Display/";
10614 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10617 r->
rsprintf(
"<input type=button value=\"Edit in new editor\"");
10618 std::string url =
"?cmd=hs_edit";
10627 r->
rsprintf(
"onclick=\"window.location.search='%s'\">\n", url.c_str());
10629 r->
rsprintf(
"<input type=button value=\"Clear history cache\"");
10630 r->
rsprintf(
"onclick=\"document.form1.hcmd.value='Clear history cache';document.form1.submit()\">\n");
10631 r->
rsprintf(
"<input type=button value=\"Delete panel\"");
10632 r->
rsprintf(
"onclick=\"window.location.search='?cmd=oldhistory&group=%s&panel=%s&hcmd=Delete%%20panel'\">\n", hgroup, hpanel);
10635 r->
rsprintf(
"<tr><td colspan=11>\n");
10638 int sort_vars = *p->
getparam(
"sort_vars");
10639 r->
rsprintf(
"<input type=checkbox %s name=sort_vars value=1 onclick=\"this.form.submit();\">Sort variable names", sort_vars?
"checked":
"");
10642 int old_vars = *p->
getparam(
"old_vars");
10643 r->
rsprintf(
" <input type=checkbox %s name=old_vars value=1 onclick=\"this.form.submit();\">Show deleted and renamed variables", old_vars?
"checked":
"");
10646 r->
rsprintf(
" <input type=checkbox checked name=show_factor value=1 onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">");
10648 r->
rsprintf(
" <input type=checkbox name=show_factor value=1 onclick=\"document.form1.hcmd.value='Refresh';document.form1.submit()\">");
10649 r->
rsprintf(
"Show factor and offset\n");
10652 r->
rsprintf(
"<input type=hidden name=cmd value=Oldhistory>\n");
10653 r->
rsprintf(
"<input type=hidden name=hcmd value=Refresh>\n");
10654 r->
rsprintf(
"<input type=hidden name=panel value=\"%s\">\n", hpanel);
10655 r->
rsprintf(
"<input type=hidden name=group value=\"%s\">\n", hgroup);
10658 r->
rsprintf(
"<input type=hidden name=redir value=\"%s\">\n", p->
getparam(
"redir"));
10662 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Time scale (in units 'm', 'h', 'd'):</td>\n");
10663 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());
10665 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Minimum (set to '-inf' for autoscale):</td>\n");
10666 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=minimum value=%f></td><td colspan=4></td></tr>\n", hp.
minimum);
10668 r->
rsprintf(
"<tr><td colspan=4 style='text-align:right'>Maximum (set to 'inf' for autoscale):</td>\n");
10669 r->
rsprintf(
"<td colspan=3><input type=text size=12 name=maximum value=%f></td><td colspan=4></td></tr>\n", hp.
maximum);
10671 r->
rsprintf(
"<tr><td colspan=11>");
10674 r->
rsprintf(
"<input type=checkbox checked name=zero_ylow value=1>");
10676 r->
rsprintf(
"<input type=checkbox name=zero_ylow value=1>");
10677 r->
rsprintf(
"Zero Y; axis\n");
10680 r->
rsprintf(
"<input type=checkbox checked name=log_axis value=1>");
10682 r->
rsprintf(
"<input type=checkbox name=log_axis value=1>");
10683 r->
rsprintf(
"Logarithmic Y axis\n");
10686 r->
rsprintf(
" <input type=checkbox checked name=run_markers value=1>");
10688 r->
rsprintf(
" <input type=checkbox name=run_markers value=1>");
10689 r->
rsprintf(
"Show run markers\n");
10692 r->
rsprintf(
" <input type=checkbox checked name=show_values value=1>");
10694 r->
rsprintf(
" <input type=checkbox name=show_values value=1>");
10695 r->
rsprintf(
"Show values of variables\n");
10698 r->
rsprintf(
" <input type=checkbox checked name=show_fill value=1>");
10700 r->
rsprintf(
" <input type=checkbox name=show_fill value=1>");
10701 r->
rsprintf(
"Show graph fill\n");
10715 time_t t = time(NULL);
10720 std::vector<std::string> events;
10725 if (events.size() == 0)
10729 for (
unsigned i=0;
i<events.size();
i++)
10730 printf(
"event %d: \"%s\"\n",
i, events[
i].c_str());
10735 std::sort(events.begin(), events.end(),
cmp_events1);
10737 if (strlen(p->
getparam(
"cmdx")) > 0) {
10738 r->
rsprintf(
"<tr><th colspan=8 class=\"subStatusTitle\">List of available history variables</th></tr>\n");
10739 r->
rsprintf(
"<tr><th colspan=1>Sel<th colspan=1>Equipment<th colspan=1>Event<th colspan=1>Variable</tr>\n");
10741 std::string cmdx = p->
xgetparam(
"cmdx");
10742 std::string xeqname;
10745 for (
unsigned e=0;
e<events.size();
e++) {
10746 std::string eqname;
10747 eqname = events[
e].substr(0, events[
e].find(
"/"));
10749 if (eqname.length() < 1)
10750 eqname = events[
e];
10753 if (eqname != xeqname)
10756 std::string qcmd =
"Expand " + eqname;
10760 bool collapsed =
true;
10765 if (strlen(p->
getparam(qcmd.c_str())) > 0)
10769 if (eqname == xeqname)
10774 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10775 r->
rsprintf(
"<td><input type=submit name=cmdx value=\"%s\"></td>\n", qcmd.c_str());
10783 r->
rsprintf(
"<tr><input type=hidden name=\"%s\" value=%d></tr>\n", qcmd.c_str(), 1);
10785 std::string rcmd =
"Expand " + events[
e];
10794 if (strlen(p->
getparam(rcmd.c_str())) > 0)
10800 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10801 r->
rsprintf(
"<td>%s</td>\n", events[
e].c_str());
10802 r->
rsprintf(
"<td><input type=submit name=cmdx value=\"%s\"></td>\n", rcmd.c_str());
10807 r->
rsprintf(
"<tr><input type=hidden name=\"%s\" value=%d></tr>\n", rcmd.c_str(), 1);
10811 std::vector<TAG> tags;
10818 std::sort(tags.begin(), tags.end(),
cmp_tags);
10820 for (
unsigned v=0; v<tags.size(); v++) {
10822 for (
unsigned j=0;
j<tags[v].n_data;
j++) {
10825 if (tags[v].n_data == 1)
10826 sprintf(tagname,
"%s", tags[v].
name);
10828 sprintf(tagname,
"%s[%d]", tags[v].
name,
j);
10830 bool checked =
false;
10841 r->
rsprintf(
"<td><input type=checkbox %s name=\"sel%d\" value=\"%s:%s\"></td>\n", checked?
"checked":
"",
i++, events[
e].c_str(), tagname);
10842 r->
rsprintf(
"<td>%s</td>\n", eqname.c_str());
10843 r->
rsprintf(
"<td>%s</td>\n", events[
e].c_str());
10844 r->
rsprintf(
"<td>%s</td>\n", tagname);
10854 r->
rsprintf(
"<input type=hidden name=seln value=%d>\n",
i);
10855 r->
rsprintf(
"<input type=submit value=\"Add Selected\">\n");
10860 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>New history: displayed_value = formula(history_value)</td></tr>\n");
10861 r->
rsprintf(
"<tr><td colspan=11 style='text-align:left'>Old history: displayed_value = offset + factor*(history_value - voffset)</td></tr>\n");
10862 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");
10863 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");
10864 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");
10865 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");
10868 r->
rsprintf(
"<th>Col<th>Event<th>Variable<th>Formula<th>Colour<th>Label<th>Raw<th>Order");
10870 r->
rsprintf(
"<th>Factor<th>Offset<th>VOffset");
10876 size_t nvars = hp.
vars.size();
10881 if (
index < nvars) {
10884 r->
rsprintf(
"<td style=\"background-color:%s\"> <td>\n", hp.
vars[
index].colour.c_str());
10891 r->
rsprintf(
"<select name=\"event%d\" size=1 onChange=\"document.form1.submit()\">\n", (
int)
index);
10896 r->
rsprintf(
"<option value=\"/empty\"><empty>\n");
10898 if (
index==nvars) {
10899 for (
unsigned e=0;
e<events.size();
e++) {
10900 const char *p = events[
e].c_str();
10901 r->
rsprintf(
"<option value=\"%s\">%s\n", p, p);
10903 }
else if ((
int)events.size() > max_display_events) {
10905 r->
rsprintf(
"<option>(%d events omitted)\n", (
int)events.size());
10907 bool found =
false;
10908 for (
unsigned e=0;
e<events.size();
e++) {
10909 const char *s =
"";
10910 const char *p = events[
e].c_str();
10915 r->
rsprintf(
"<option %s value=\"%s\">%s\n", s, p, p);
10918 const char *p = hp.
vars[
index].event_name.c_str();
10919 r->
rsprintf(
"<option selected value=\"%s\">%s\n", p, p);
10928 if (
index < nvars) {
10929 bool found_tag =
false;
10930 std::string selected_tag = hp.
vars[
index].tag_name;
10934 std::vector<TAG> tags;
10941 printf(
"Compare %d\n",
cmp_names(
"AAA",
"BBB"));
10942 printf(
"Compare %d\n",
cmp_names(
"BBB",
"AAA"));
10943 printf(
"Compare %d\n",
cmp_names(
"AAA",
"AAA"));
10944 printf(
"Compare %d\n",
cmp_names(
"A",
"AAA"));
10945 printf(
"Compare %d\n",
cmp_names(
"A111",
"A1"));
10946 printf(
"Compare %d\n",
cmp_names(
"A111",
"A2"));
10947 printf(
"Compare %d\n",
cmp_names(
"A111",
"A222"));
10948 printf(
"Compare %d\n",
cmp_names(
"A111a",
"A111b"));
10952 std::sort(tags.begin(), tags.end(),
cmp_tags);
10955 printf(
"Event [%s] %d tags\n", hp.
vars[
index].event_name.c_str(), (
int)tags.size());
10957 for (
unsigned v=0; v<tags.size(); v++) {
10958 printf(
"tag[%d] [%s]\n", v, tags[v].
name);
10962 unsigned count_tags = 0;
10963 for (
unsigned v=0; v<tags.size(); v++)
10964 count_tags += tags[v].n_data;
10968 if ((
int)count_tags < max_display_tags) {
10969 for (
unsigned v=0; v<tags.size(); v++) {
10971 for (
unsigned j=0;
j<tags[v].n_data;
j++) {
10972 std::string tagname;
10974 if (tags[v].n_data == 1)
10975 tagname = tags[v].name;
10978 sprintf(buf,
"[%d]",
j);
10979 tagname = std::string(tags[v].
name) + buf;
10982 if (
equal_ustring(selected_tag.c_str(), tagname.c_str())) {
10983 r->
rsprintf(
"<option selected value=\"%s\">%s\n", tagname.c_str(), tagname.c_str());
10987 r->
rsprintf(
"<option value=\"%s\">%s\n", tagname.c_str(), tagname.c_str());
10996 if (hp.
vars[
index].tag_name.length() > 0)
11000 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());
11001 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());
11004 r->
rsprintf(
"<td><input type=checkbox checked name=\"raw%d\" value=1></td>", (
int)
index);
11006 r->
rsprintf(
"<td><input type=checkbox name=\"raw%d\" value=1></td>", (
int)
index);
11007 r->
rsprintf(
"<td><input type=text size=3 maxlength=32 name=\"ord%d\" value=\"%d\"></td>\n", (
int)
index, hp.
vars[
index].order);
11009 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"factor%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].factor);
11010 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"offset%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].offset);
11011 r->
rsprintf(
"<td><input type=text size=6 maxlength=32 name=\"voffset%d\" value=\"%g\"></td>\n", (
int)
index, hp.
vars[
index].voffset);
11015 r->
rsprintf(
"<input type=hidden name=\"voffset%d\" value=\"%f\">\n", (
int)
index, hp.
vars[
index].voffset);
11018 r->
rsprintf(
"<td colspan=2><input type=submit name=cmdx value=\"List all variables\"></td>\n");
11028 r->
rsprintf(
"</body></html>\r\n");
11048 sprintf(
str,
"/History/Display/%s/%s", group, panel);
11051 sprintf(
str,
"Cannot find /History/Display/%s/%s in ODB\n", group, panel);
11057 BOOL runmarker = 1;
11058 size =
sizeof(runmarker);
11063 std::string
ts =
"1h";
11088 time_t starttime = endtime - scale;
11095 sprintf(
str,
"History error, status %d\n",
status);
11103 int *i_var = (
int *)malloc(
sizeof(
int)*hsdata->
nvars);
11105 assert(i_var != NULL);
11107 for (
int i = 0;
i < hsdata->
nvars;
i++)
11113 for (
int i = 0;
i < hsdata->
nvars;
i++)
11116 if ((t == 0) || (hsdata->
t[
i][0] > t))
11117 t = hsdata->
t[
i][0];
11119 if (t == 0 && hsdata->
nvars > 1) {
11120 show_error(r,
"No history available for choosen period");
11125 int run_index = -1;
11126 int state_index = -1;
11127 int n_run_number = 0;
11128 time_t* t_run_number = NULL;
11130 for (
int i = 0;
i < hsdata->
nvars;
i++) {
11133 t_run_number = hsdata->
t[
i];
11143 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
11145 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
11146 r->
rsprintf(
"Cache-control: private, max-age=0, no-cache\r\n");
11147 r->
rsprintf(
"Expires: Fri, 01 Jan 1983 00:00:00 GMT\r\n");
11148 r->
rsprintf(
"Content-Type: text/plain\r\n");
11149 r->
rsprintf(
"Content-disposition: attachment; filename=\"export.csv\"\r\n");
11154 r->
rsprintf(
"Time, Timestamp, Run, Run State, ");
11158 for (
int i = 0, first = 1;
i < hsdata->
nvars;
i++) {
11175 printf(
"hsdata %p, t %d, irun %d\n", hsdata, (
int)t, i_run);
11179 while (i_run < n_run_number-1 && t_run_number[i_run+1] <= t)
11185 for (
int i = 0;
i < hsdata->
nvars;
i++)
11191 for (
int i = 0 ;
i < hsdata->
nvars ;
i++)
11198 printf(
"step to time %d: ", (
int)t);
11199 for (
int i = 0;
i < hsdata->
nvars;
i++) {
11202 printf(
" done: %d\n",
done);
11209 localtime_r(&t, &tms);
11213 strcpy(fmt,
"%Y.%m.%d %H:%M:%S");
11215 strftime(
str,
sizeof(
str), fmt, &tms);
11217 if (t_run_number && run_index>=0 && state_index>=0) {
11218 if (t_run_number[i_run] <= t)
11219 r->
rsprintf(
"%s, %d, %.0f, %.0f, ",
str, (
int)t, hsdata->
v[run_index][i_run], hsdata->
v[state_index][i_run]);
11226 for (
int i= 0 ;
i < hsdata->
nvars ;
i++)
11227 printf(
" %d (%g)", i_var[
i], hsdata->
v[
i][i_var[
i]]);
11231 for (
int i=0, first=1 ;
i<hsdata->
nvars ;
i++) {
11246 for (
int i = 0 ;
i < hsdata->
nvars ;
i++)
11248 int xdt = hsdata->
t[
i][i_var[
i]+1] - t;
11250 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);
11251 if (dt <= 0 || xdt < dt)
11256 printf(
"dt %d\n", dt);
11272 HNDLE hDB, hkey, hikeyp, hkeyp, hkeybutton;
11275 char hgroup[256], hpanel[256], hcmd[256];
11276 const char def_button[][
NAME_LENGTH] = {
"10m",
"1h",
"3h",
"12h",
"24h",
"3d",
"7d" };
11280 hcmd[0] = hgroup[0] = hpanel[0] = 0;
11283 mstrlcpy(hgroup, p->
getparam(
"group"),
sizeof(hgroup));
11285 mstrlcpy(hpanel, p->
getparam(
"panel"),
sizeof(hpanel));
11287 mstrlcpy(hcmd, p->
getparam(
"hcmd"),
sizeof(hcmd));
11292 redir +=
"?cmd=oldhistory&group=";
11294 redir +=
"&panel=";
11311 redir +=
"?cmd=oldhistory&group=";
11313 redir +=
"&panel=";
11332 r->
rsprintf(
"<table class=\"dialogTable\">");
11333 r->
rsprintf(
"<tr><th class=\"subStatusTitle\" colspan=2>New History Item</th><tr>");
11334 r->
rsprintf(
"<tr><td align=center colspan=2>\n");
11335 r->
rsprintf(
"Select group: ");
11336 r->
rsprintf(
"<select id=\"group\" name=\"group\">\n");
11342 for (
i = 0;;
i++) {
11355 if (!hkey ||
i == 0)
11356 r->
rsprintf(
"<option>Default</option>\n");
11359 r->
rsprintf(
"Or enter new group name: ");
11360 r->
rsprintf(
"<input type=text size=15 maxlength=31 id=new_group name=new_group>\n");
11362 r->
rsprintf(
"<tr><td align=center colspan=2>\n");
11363 r->
rsprintf(
"<br>Panel name: ");
11364 r->
rsprintf(
"<input type=text size=15 maxlength=31 id=panel name=panel><br><br>\n");
11367 r->
rsprintf(
"<tr><td align=center colspan=2>");
11368 std::string
str =
"?cmd=oldhistory&hcmd=createnew";
11369 str +=
"&new_group='+document.getElementById('new_group').value+'";
11370 str +=
"&group='+document.getElementById('group').value+'";
11371 str +=
"&panel='+document.getElementById('panel').value+'";
11372 r->
rsprintf(
"<input type=button value=Submit onclick=\"window.location.search='%s'\">\n",
str.c_str());
11378 r->
rsprintf(
"</body></html>\r\n");
11385 path +=
"/History/Display/";
11397 while (hpanel[0] ==
' ') {
11399 mstrlcpy(
str, hpanel+1,
sizeof(
str));
11400 mstrlcpy(hpanel,
str,
sizeof(hpanel));
11402 while (strlen(hpanel)> 1 && hpanel[strlen(hpanel)-1] ==
' ')
11403 hpanel[strlen(hpanel)-1] = 0;
11407 mstrlcpy(hgroup, p->
getparam(
"new_group"),
sizeof(hgroup));
11414 const char* pscale = p->
getparam(
"scale");
11415 if (pscale == NULL || *pscale == 0)
11417 const char* pwidth = p->
getparam(
"width");
11418 if (pwidth == NULL || *pwidth == 0)
11420 const char* pheight = p->
getparam(
"height");
11421 if (pheight == NULL || *pheight == 0)
11423 const char* pindex = p->
getparam(
"index");
11424 if (pindex == NULL || *pindex == 0)
11431 std::string bgcolor =
"FFFFFF";
11435 std::string fgcolor =
"000000";
11439 std::string gridcolor =
"A0A0A0";
11445 time_t endtime = 0;
11448 else if (p->
isparam(
"htime"))
11451 if (pscale && *pscale)
11457 if (pindex && *pindex)
11458 index = atoi(pindex);
11470 char* fbuffer = (
char*)
M_MALLOC(fsize);
11471 assert(fbuffer != NULL);
11482 }
else if (atoi(pmag) > 0) {
11483 width = atoi(pmag);
11488 generate_hist_graph(odb, r, hgroup, hpanel, fbuffer, &fsize, width, height, endtime, scale,
index, labels, bgcolor.c_str(), fgcolor.c_str(), gridcolor.c_str());
11493 if (dir.length() > 0 && dir[dir.length()-1] !=
DIR_SEPARATOR)
11496 time_t now = time(NULL);
11497 localtime_r(&now, &tms);
11500 tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday,
11501 tms.tm_hour, tms.tm_min, tms.tm_sec, hpanel);
11505 fh = open(fname.c_str(), O_CREAT | O_RDWR |
O_BINARY, 0644);
11507 cm_msg(
MERROR,
"show_hist_page",
"Cannot write attachment file \"%s\", open() errno %d (%s)", fname.c_str(), errno, strerror(errno));
11509 int wr =
write(fh, fbuffer, fsize);
11511 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));
11517 if (strlen(url) > 1 && url[strlen(url)-1] !=
'/')
11518 mstrlcat(url,
"/",
sizeof(url));
11519 mstrlcat(url,
"?cmd=New&fa=",
sizeof(url));
11528 std::string
str =
msprintf(
"\\HS\\%s.gif", hpanel);
11532 if (strchr(
str.c_str(),
'?'))
11546 if (strchr(
str.c_str(),
'?'))
11553 if (strchr(
str.c_str(),
'?'))
11560 show_elog_new(r, hpanel, NULL,
FALSE,
str.c_str(),
"../../EL/");
11571 if (strstr(dec_path,
".gif")) {
11580 }
else if (atoi(pwidth) > 0) {
11581 width = atoi(pwidth);
11582 if (atoi(pheight) > 0)
11583 height = atoi(pheight);
11585 height = (int)(0.625 * width);
11590 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());
11598 time_t now = time(NULL);
11604 time_t last_written = 0;
11607 endtime = last_written + scale/2;
11613 time_t last_written = 0;
11616 if (last_written != endtime)
11617 endtime = last_written + scale/2;
11623 endtime -= scale/2;
11630 endtime += scale/2;
11642 endtime -= scale / 4;
11649 endtime += scale / 2;
11655 int xrefresh = refresh;
11660 r->
rsprintf(
"<script type=\"text/javascript\" src=\"midas.js\"></script>\n");
11661 r->
rsprintf(
"<script type=\"text/javascript\" src=\"mhttpd.js\"></script>\n");
11664 r->
rsprintf(
"<table class=\"mtable\">");
11665 r->
rsprintf(
"<tr><th class=\"mtableheader\" colspan=2>History</th></tr>");
11671 path +=
"/History/Display/";
11677 r->
rsprintf(
"<h1>Error: History panel \"%s\" in group \"%s\" does not exist</h1>\n", hpanel, hgroup);
11681 r->
rsprintf(
"</body></html>\r\n");
11687 if (pscale && *pscale)
11688 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%d>\n", scale);
11691 if (hpanel[0] && !
equal_ustring(hpanel,
"All") && hgroup[0]) {
11693 path +=
"/History/Display/";
11697 path +=
"/Timescale";
11699 std::string scalestr =
"1h";
11708 r->
rsprintf(
"<input type=hidden name=hscale id=hscale value=%s>\n", scalestr.c_str());
11715 if (pwidth && *pwidth)
11716 r->
rsprintf(
"<input type=hidden name=hwidth id=hwidth value=%s>\n", pwidth);
11717 if (pheight && *pheight)
11718 r->
rsprintf(
"<input type=hidden name=hheight id=hheight value=%s>\n", pheight);
11719 if (pindex && *pindex)
11720 r->
rsprintf(
"<input type=hidden name=hindex id=hindex value=%s>\n", pindex);
11724 if (hgroup[0] == 0) {
11726 r->
rsprintf(
"<tr><td colspan=2><input type=\"button\" name=\"New\" value=\"New\" ");
11727 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New'\"></td></tr>\n");
11730 r->
rsprintf(
"<tr><td colspan=2 style=\"text-align:left;\">\n");
11732 r->
rsprintf(
"<b>Please select panel:</b><br>\n");
11735 r->
rsprintf(
"<table class=\"historyTable\">");
11738 r->
rsprintf(
"<tr><td colspan=2 class=\"titleCell\">\n");
11742 r->
rsprintf(
"<a href=\"?cmd=oldhistory&group=All\">ALL</a>\n");
11750 strcpy(
str,
"System:Trigger per sec.");
11770 for (
i = 0;;
i++) {
11779 char enc_name[256];
11780 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11786 r->
rsprintf(
"<tr><td class=\"titleCell\"><a href=\"?cmd=oldhistory&group=%s\">%s</a></td>\n<td>", enc_name,
key.
name);
11788 for (
j = 0;;
j++) {
11799 char enc_iname[256];
11800 mstrlcpy(enc_iname, ikey.
name,
sizeof(enc_iname));
11801 urlEncode(enc_iname,
sizeof(enc_iname));
11804 r->
rsprintf(
"<small><b>%s</b></small> ", ikey.
name);
11806 r->
rsprintf(
"<small><a href=\"?cmd=oldhistory&group=%s&panel=%s\">%s</a></small> \n", enc_name, enc_iname, ikey.
name);
11817 r->
rsprintf(
"<tr><td colspan=2>\n");
11821 r->
rsprintf(
"<select title=\"Select group\" id=\"fgroup\" onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value;\">\n");
11826 for (
i = 0;;
i++) {
11846 r->
rsprintf(
"<option selected value=\"%s\">%s\n",
"ALL",
"ALL");
11848 r->
rsprintf(
"<option value=\"%s\">%s\n",
"ALL",
"ALL");
11852 r->
rsprintf(
" Panel:\n");
11853 r->
rsprintf(
"<select title=\"Select panel\" id=\"fpanel\" ");
11854 r->
rsprintf(
"onChange=\"window.location.search='?cmd=oldhistory&group='+document.getElementById('fgroup').value+");
11855 r->
rsprintf(
"'&panel='+document.getElementById('fpanel').value;\">\n");
11859 for (
i = 0;;
i++) {
11878 r->
rsprintf(
"<option value=\"\">- all -\n");
11880 r->
rsprintf(
"<option selected value=\"\">- all -\n");
11886 r->
rsprintf(
"<input type=submit value=\"Go\">\n");
11889 r->
rsprintf(
" <input type=\"button\" name=\"New\" value=\"New\" ");
11890 r->
rsprintf(
"onClick=\"window.location.href='?cmd=oldhistory&hcmd=New&group=%s'\">\n", hgroup);
11892 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Reset\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Reset&group=%s&panel=%s'\">\n", hgroup, hpanel);
11894 r->
rsprintf(
"<input type=\"button\" name=\"Cmd\" value=\"Query\" onClick=\"window.location.href='?cmd=oldhistory&hcmd=Query&group=%s&panel=%s'\">\n", hgroup, hpanel);
11896 double xendtime = endtime;
11899 double xstarttime = xendtime - scale;
11901 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);
11909 if (hgroup[0] && !
equal_ustring(hgroup,
"ALL") && hpanel[0] == 0) {
11910 std::string strwidth =
"Small";
11914 path +=
"/History/Display/";
11918 for (
i = 0 ;;
i++) {
11926 char enc_name[256];
11927 mstrlcpy(enc_name,
key.
name,
sizeof(enc_name));
11931 ref +=
"graph.gif?width=";
11933 ref +=
"&cmd=oldhistory&group=";
11939 ref2 +=
"?cmd=oldhistory&group=";
11944 if (endtime != 0) {
11946 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
11954 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
11956 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
11960 r->
rsprintf(
"Group \"%s\" not found", hgroup);
11970 path +=
"/History/Display/";
11974 path +=
"/Buttons";
11976 if (hkeybutton == 0) {
11981 cm_msg(
MERROR,
"show_hist_page",
"Cannot create history panel with invalid ODB path \"%s\"", path.c_str());
11988 r->
rsprintf(
"function histDisp(p) {\n");
11989 r->
rsprintf(
" var params = '?cmd=oldhistory&group=%s&panel=%s';\n", hgroup, hpanel);
11990 r->
rsprintf(
" params += '&'+p;\n");
11991 r->
rsprintf(
" if (document.getElementById(\'hscale\') !== null)\n");
11992 r->
rsprintf(
" params += '&hscale='+document.getElementById(\'hscale\').value;\n");
11993 r->
rsprintf(
" if (document.getElementById(\'htime\') !== null)\n");
11994 r->
rsprintf(
" params += '&htime='+document.getElementById(\'htime\').value;\n");
11995 r->
rsprintf(
" if (document.getElementById(\'hwdith\') !== null)\n");
11996 r->
rsprintf(
" params += '&hwidth='+document.getElementById(\'hwidth\').value;\n");
11997 r->
rsprintf(
" if (document.getElementById(\'hindex\') !== null)\n");
11998 r->
rsprintf(
" params += '&hindex='+document.getElementById(\'hindex\').value;\n");
11999 r->
rsprintf(
" window.location.search = params;\n");
12007 size =
sizeof(
str);
12009 r->
rsprintf(
"<input type=\"button\" title=\"display last %s\" value=%s onclick=\"histDisp('scale=%s')\">\n",
str,
str,
str);
12012 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')\">");
12013 r->
rsprintf(
"<input type=\"button\" value=\"<<\" title=\"go back in time to last available data\" onclick=\"histDisp('shift=leftmax')\">");
12014 r->
rsprintf(
"<input type=\"button\" value=\"<\" title=\"go back in time\" onclick=\"histDisp('shift=left')\">");
12016 r->
rsprintf(
"<input type=\"button\" value=\" + \" title=\"zoom in\" onclick=\"histDisp('shift=zoomin')\">");
12017 r->
rsprintf(
"<input type=\"button\" value=\" - \" title=\"zoom out\" onclick=\"histDisp('shift=zoomout')\">");
12019 if (endtime != 0) {
12020 r->
rsprintf(
"<input type=\"button\" value=\">\" title=\"go forward in time\" onclick=\"histDisp('shift=right')\">");
12021 r->
rsprintf(
"<input type=\"button\" value=\">>\" title=\"go to currently updated fresh data\" onclick=\"histDisp('shift=rightmax')\">");
12025 r->
rsprintf(
"<input type=\"button\" value=\"Large\" title=\"large display\" onclick=\"histDisp('width=Large')\">\n");
12026 r->
rsprintf(
"<input type=\"button\" value=\"Small\" title=\"large display\" onclick=\"histDisp('width=Small')\">\n");
12027 r->
rsprintf(
"<input type=\"button\" value=\"Create Elog\" title=\"large display\" onclick=\"histDisp('hcmd=Create Elog')\">\n");
12028 r->
rsprintf(
"<input type=\"button\" value=\"Config\" title=\"large display\" onclick=\"histDisp('hcmd=Config')\">\n");
12029 r->
rsprintf(
"<input type=\"button\" value=\"Export\" title=\"large display\" onclick=\"histDisp('hcmd=Export')\">\n");
12032 char paramstr[256];
12035 sprintf(paramstr + strlen(paramstr),
"&scale=%d", scale);
12037 sprintf(paramstr + strlen(paramstr),
"&time=%s",
time_to_string(endtime).c_str());
12038 if (pwidth && *pwidth)
12039 sprintf(paramstr + strlen(paramstr),
"&width=%s", pwidth);
12041 std::string wi =
"640";
12043 sprintf(paramstr + strlen(paramstr),
"&width=%s", wi.c_str());
12045 if (pheight && *pheight)
12046 sprintf(paramstr + strlen(paramstr),
"&height=%s", pheight);
12049 r->
rsprintf(
"<map name=\"%s\">\r\n", hpanel);
12051 if (!(pindex && *pindex)) {
12053 path +=
"/History/Display/";
12057 path +=
"/Variables";
12070 ref +=
"?cmd=oldhistory&group=";
12081 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());
12085 std::string ref =
"?cmd=oldhistory&group=";
12099 else if (atoi(pwidth) > 0)
12100 width = atoi(pwidth);
12104 r->
rsprintf(
" <area shape=rect coords=\"%d,%d,%d,%d\" href=\"%s\">\r\n", 0, 0, width, 20, ref.c_str());
12110 if (pindex && *pindex)
12111 sprintf(paramstr + strlen(paramstr),
"&index=%s", pindex);
12115 ref +=
"graph.gif?cmd=oldhistory&group=";
12122 r->
rsprintf(
"<tr><td colspan=2><img src=\"%s\" usemap=\"#%s\"></tr>\n", ref.c_str(), hpanel);
12129 for (
i = 0,
k = 0;;
i++) {
12137 char enc_group_name[256];
12138 mstrlcpy(enc_group_name,
key.
name,
sizeof(enc_group_name));
12139 urlEncode(enc_group_name,
sizeof(enc_group_name));
12141 for (
j = 0;;
j++,
k++) {
12150 char enc_panel_name[256];
12151 mstrlcpy(enc_panel_name, ikey.
name,
sizeof(enc_panel_name));
12152 urlEncode(enc_panel_name,
sizeof(enc_panel_name));
12155 ref +=
"graph.gif?width=Small";
12156 ref +=
"&cmd=oldhistory&group=";
12157 ref += enc_group_name;
12159 ref += enc_panel_name;
12162 ref2 +=
"?cmd=oldhistory&group=";
12163 ref2 += enc_group_name;
12165 ref2 += enc_panel_name;
12167 if (endtime != 0) {
12169 sprintf(tmp,
"time=%s&scale=%d",
time_to_string(endtime).c_str(), scale);
12177 r->
rsprintf(
"<tr><td><a href=\"%s\"><img src=\"%s\"></a>\n", ref2.c_str(), ref.c_str());
12179 r->
rsprintf(
"<td><a href=\"%s\"><img src=\"%s\"></a></tr>\n", ref2.c_str(), ref.c_str());
12186 r->
rsprintf(
"</body></html>\r\n");
12195 const unsigned char *picon;
12196 char str[256], format[256];
12199 if (strstr(icon,
"favicon.ico") != 0) {
12202 }
else if (strstr(icon,
"favicon.png") != 0) {
12208 r->
rsprintf(
"HTTP/1.1 200 Document follows\r\n");
12210 r->
rsprintf(
"Accept-Ranges: bytes\r\n");
12214 now += (int) (3600 * 24);
12216 gmtime_r(&now, &gmt_tms);
12217 strcpy(format,
"%A, %d-%b-%y %H:%M:%S GMT");
12218 strftime(
str,
sizeof(
str), format, &gmt_tms);
12222 r->
rsprintf(
"Content-Type: image/x-icon\r\n");
12224 r->
rsprintf(
"Content-Type: image/png\r\n");
12226 r->
rsprintf(
"Content-Length: %d\r\n\r\n", length);
12272 if (strstr(dec_path,
"favicon.ico") != 0 ||
12273 strstr(dec_path,
"favicon.png")) {
12278 const char* password = p->
getparam(
"pwd");
12279 const char* wpassword = p->
getparam(
"wpwd");
12280 const char* command = p->
getparam(
"cmd");
12303 if (!password[0] && hkey) {
12305 int size =
sizeof(
str);
12309 db_find_key(
hDB, 0,
"/Experiment/Security/Allowed programs/mhttpd", &hkey);
12310 if (hkey == 0 && strcmp(
c->cookie_pwd.c_str(),
str) != 0) {
12321 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12330 gmtime_r(&now, &gmt_tms);
12333 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12335 r->
rsprintf(
"Set-Cookie: midas_pwd=%s; path=/; expires=%s\r\n",
12338 r->
rsprintf(
"Location: ./\n\n<html>redir</html>\r\n");
12342 if (wpassword[0]) {
12347 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12356 gmtime_r(&now, &gmt_tms);
12359 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:%M:%S GMT", &gmt_tms);
12361 r->
rsprintf(
"Set-Cookie: midas_wpwd=%s; path=/; expires=%s\r\n",
ss_crypt(wpassword,
"mi"),
str);
12364 r->
rsprintf(
"Location: %s\n\n<html>redir</html>\r\n",
str);
12370 if (strlen(dec_path) > 3 &&
12371 dec_path[strlen(dec_path)-3] ==
'm' &&
12372 dec_path[strlen(dec_path)-2] ==
'p' &&
12373 dec_path[strlen(dec_path)-1] ==
'3') {
12374 if (strrchr(dec_path,
'/'))
12383 if (strstr(dec_path,
"midas.js")) {
12388 if (strstr(dec_path,
"midas.css")) {
12395 if (strstr(dec_path,
"mhttpd.js")) {
12402 if (strstr(dec_path,
"obsolete.js")) {
12409 if (strstr(dec_path,
"mhttpd.css")) {
12416 if (strstr(dec_path,
"controls.js")) {
12449 path +=
"/Script/";
12475 path +=
"/CustomScript/";
12476 path += p->
getparam(
"customscript");
12503 std::string filename = custom[
"Status"];
12547 !(dec_path[0] ==
'H' && dec_path[1] ==
'S' && dec_path[2] ==
'/')) {
12663 show_mscb_page(p, r,
c->refresh);
12665 show_error(r,
"MSCB support not compiled into this version of mhttpd");
12683 if (strncmp(command,
"Trigger", 7) == 0) {
12696 mstrlcpy(eq_name, command + 8,
sizeof(eq_name));
12697 if (strchr(eq_name,
' '))
12698 *strchr(eq_name,
' ') = 0;
12702 path +=
"/Equipment/";
12704 path +=
"/Common/Frontend name";
12711 path +=
"/Equipment/";
12713 path +=
"/Common/Event ID";
12720 str +=
"Frontend \"";
12722 str +=
"\" not running!";
12729 str +=
"Cannot connect to frontend \"";
12751 if (strncmp(command,
"Next Subrun", 11) == 0) {
12772 mstrlcpy(
str,
"?cmd=set",
sizeof(
str));
12776 const char* group = p->
getparam(
"group");
12798 if (
equal_ustring(command,
"CNAF") || strncmp(dec_path,
"CNAF", 4) == 0) {
12814 std::string external_elog_url;
12815 int size =
sizeof(external_elog);
12818 if (external_elog && (external_elog_url.length() > 0)) {
12819 redirect(r, external_elog_url.c_str());
12829 mstrlcpy(cmdx, command,
sizeof(cmdx));
12838 if (
equal_ustring(command,
"Create ELog from this page")) {
12840 redir +=
"?cmd=New+elog";
12841 redir +=
"&odb_path=";
12864 int refresh = atoi(p->
getparam(
"refr"));
12867 r->
rsprintf(
"HTTP/1.1 302 Found\r\n");
12874 now += 3600 * 24 * 365;
12877 gmtime_r(&now, &gmt_tms);
12880 strftime(
str,
sizeof(
str),
"%A, %d-%b-%Y %H:00:00 GMT", &gmt_tms);
12882 r->
rsprintf(
"Set-Cookie: midas_refr=%d; path=/; expires=%s\r\n", refresh,
str);
12883 r->
rsprintf(
"Location: ./\r\n\r\n<html>redir</html>\r\n");
12930 int write_access =
TRUE;
12931 db_find_key(
hDB, 0,
"/Experiment/Security/Web Password", &hkey);
12934 int size =
sizeof(
str);
12936 if (strcmp(
c->cookie_wpwd.c_str(),
str) == 0)
12937 write_access =
TRUE;
12939 write_access =
FALSE;
12942 std::string odb_path;
12944 odb_path = p->
getparam(
"odb_path");
12975 if ((command[0]==0) && dec_path[0]) {
12977 std::string new_url =
"./?cmd=odb";
12984 if ((command[0]==0) && dec_path[0]) {
12990 for (
const char* s = dec_path; *s; s++) {
12994 std::string new_url;
12999 for (
int i=0;
i<level;
i++) {
13005 new_url +=
"?cmd=odb";
13006 new_url +=
"&odb_path=";
13033 std::string odb_path;
13038 odb_path +=
"/Custom/Images/";
13039 odb_path += dec_path;
13040 odb_path +=
"/Background";
13047 if (strstr(dec_path,
"..")) {
13049 str +=
"Invalid custom gif name \'";
13051 str +=
"\' contains \'..\'";
13062 bool found_custom =
false;
13065 odb_path +=
"/Custom/";
13066 odb_path += dec_path;
13073 found_custom =
true;
13076 odb_path +=
"/Custom/";
13077 odb_path += dec_path;
13085 found_custom =
true;
13088 odb_path +=
"/Custom/";
13089 odb_path += dec_path;
13097 found_custom =
true;
13102 if (found_custom) {
13104 if (strstr(dec_path,
"..")) {
13106 str +=
"Invalid custom page name \'";
13108 str +=
"\' contains \'..\'";
13123 std::string custom_path;
13126 if (strstr(dec_path,
"..")) {
13128 str +=
"Invalid custom file name \'";
13130 str +=
"\' contains \'..\'";
13154 if (strlen(p->
getparam(
"path")) > 0) {
13168 r->
rsprintf(
"HTTP/1.1 400 Bad Request\r\n");
13172 r->
rsprintf(
"Error: Invalid URL \"%s\" or query \"%s\" or command \"%s\"\n", p->
getparam(
"path"), p->
getparam(
"query"), command);
13179 int len = strlen(query_string);
13180 char *buf = (
char *)malloc(len+1);
13181 assert(buf != NULL);
13182 memcpy(buf, query_string, len+1);
13184 p = strtok(p,
"&");
13185 while (p != NULL) {
13187 p = strchr(p,
'=');
13196 p = strtok(NULL,
"&");
13210 param->initparam();
13213 mstrlcpy(path, url + 1,
sizeof(path));
13215 mstrlcpy(path,
string + 1,
sizeof(path));
13217 if (strchr(path,
'?'))
13218 *strchr(path,
'?') = 0;
13221 param->setparam(
"path", path);
13223 assert(query_string != NULL);
13227 param->setparam(
"query", query_string);
13229 char dec_path[256];
13230 mstrlcpy(dec_path, path,
sizeof(dec_path));
13234 param->freeparam();
13242 bool debug_decode_post =
false;
13251 mstrlcpy(path, url + 1,
sizeof(path));
13253 mstrlcpy(path, header + 1,
sizeof(path));
13254 if (strchr(path,
'?'))
13255 *strchr(path,
'?') = 0;
13256 if (strchr(path,
' '))
13257 *strchr(path,
' ') = 0;
13259 param->setparam(
"path", path);
13263 const char* pinit = string;
13269 if (strstr(
string, boundary))
13270 string = strstr(
string, boundary) + strlen(boundary);
13272 if (debug_decode_post)
13273 printf(
"decode_post: -->[%s]<--\n",
string);
13277 if (strstr(
string,
"name=")) {
13278 const char* pitem = strstr(
string,
"name=") + 5;
13279 if (*pitem ==
'\"')
13284 if (strncmp(pitem,
"attfile", 7) == 0) {
13285 int n = pitem[7] -
'1';
13291 if (strstr(pitem,
"filename=")) {
13292 const char* p = strstr(pitem,
"filename=") + 9;
13295 if (strstr(p,
"\r\n\r\n"))
13296 string = strstr(p,
"\r\n\r\n") + 4;
13297 else if (strstr(p,
"\r\r\n\r\r\n"))
13298 string = strstr(p,
"\r\r\n\r\r\n") + 6;
13303 if (strchr(pp,
'\"'))
13304 *strchr(pp,
'\"') = 0;
13308 sprintf(
str,
"attachment%d",
n);
13309 if (debug_decode_post)
13315 const char* ptmp = string;
13316 const char* p = NULL;
13318 while (*ptmp !=
'-')
13321 p = strstr(ptmp, boundary);
13332 ptmp += strlen(ptmp);
13339 char* buf = (
char*)malloc(size+1);
13343 memcpy(buf,
string, size);
13347 if (debug_decode_post)
13351 string = strstr(p, boundary) + strlen(boundary);
13353 const char* p = pitem;
13354 if (strstr(p,
"\r\n\r\n"))
13355 p = strstr(p,
"\r\n\r\n") + 4;
13356 else if (strstr(p,
"\r\r\n\r\r\n"))
13357 p = strstr(p,
"\r\r\n\r\r\n") + 6;
13359 char* ppitem = (
char*)strchr(pitem,
'\"');
13363 char* pb = (
char*)(strstr(p, boundary));
13365 string = pb + strlen(boundary);
13367 char* ptmp = (
char*)(p + (strlen(p) - 1));
13368 while (*ptmp ==
'-' || *ptmp ==
'\n' || *ptmp ==
'\r')
13374 if (debug_decode_post)
13375 printf(
"decode_post: [%s] = [%s]\n", pitem, p);
13376 param->setparam(pitem, p);
13379 while (*
string ==
'-' || *
string ==
'\n' || *
string ==
'\r')
13385 char dec_path[256];
13386 mstrlcpy(dec_path, path,
sizeof(dec_path));
13411 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo corrected successfully");
13413 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13417 cm_msg(
MERROR,
"check_odb_records",
"ODB subtree /Runinfo does not exist");
13420 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Runinfo created successfully");
13422 cm_msg(
MERROR,
"check_odb_records",
"Cannot create ODB subtree /Runinfo, db_create_record() status %d",
status);
13426 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Runinfo, db_check_record() status %d",
status);
13432 for (
i = 0 ;;
i++) {
13442 cm_msg(
MINFO,
"check_odb_records",
"ODB subtree /Equipment/%s/Common corrected successfully",
key.
name);
13444 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13447 cm_msg(
MERROR,
"check_odb_records",
"Cannot correct ODB subtree /Equipment/%s/Common, db_check_record() status %d",
key.
name,
status);
13467#ifdef HAVE_MONGOOSE6
13468static std::vector<std::string> gUserAllowedHosts;
13471#ifdef HAVE_MONGOOSE6
13472static const std::string gOdbAllowedHosts =
"/Experiment/Security/mhttpd hosts/Allowed hosts";
13475#ifdef HAVE_MONGOOSE6
13479 cm_msg(
MINFO,
"load_allowed_hosts",
"Reloading mhttpd hosts access control list via hotlink callback");
13484 for (
unsigned int i=0;
i<gUserAllowedHosts.size();
i++)
13489 for (
int i=0; ;
i++) {
13498 if (s.length() < 1)
13511 if (
total - last < 5) {
13512 int new_size = last + 10;
13516 cm_msg(
MERROR,
"load_allowed_hosts",
"Cannot resize the allowed hosts access control list, db_resize_string(%d) status %d", new_size,
status);
13521static int init_allowed_hosts()
13535 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot create the mhttpd hosts access control list, db_get_value_string() status %d",
status);
13542 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot find the mhttpd hosts access control list, db_find_key() status %d",
status);
13546 load_allowed_hosts(
hDB, 0, 0, NULL);
13551 cm_msg(
MERROR,
"init_allowed_hosts",
"Cannot watch the mhttpd hosts access control list, db_watch() status %d",
status);
13558 int check_midas_acl(
const struct sockaddr *sa,
int len) {
13563 char hname[NI_MAXHOST];
13567 const char* status_string =
"success";
13569 status = getnameinfo(sa, len, hname,
sizeof(hname), NULL, 0, 0);
13572 status_string = gai_strerror(
status);
13577 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
status, status_string);
13582 if (strcmp(hname,
"localhost.localdomain") == 0)
13584 if (strcmp(hname,
"localhost") == 0)
13592 printf(
"Rejecting connection from \'%s\'\n", hname);
13596int open_listening_socket(
int port)
13599 struct sockaddr_in bind_addr;
13602 int lsock =
socket(AF_INET, SOCK_STREAM, 0);
13605 printf(
"Cannot create socket, socket() errno %d (%s)\n", errno, strerror(errno));
13610 memset(&bind_addr, 0,
sizeof(bind_addr));
13611 bind_addr.sin_family = AF_INET;
13612 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
13613 bind_addr.sin_port = htons((
short) port);
13617 status = setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (
char *) &flag,
sizeof(
INT));
13620 printf(
"Cannot setsockopt(SOL_SOCKET, SO_REUSEADDR), errno %d (%s)\n", errno, strerror(errno));
13624 status = bind(lsock, (
struct sockaddr *) &bind_addr,
sizeof(bind_addr));
13627 printf(
"Cannot bind() to port %d, bind() errno %d (%s)\n", port, errno, strerror(errno));
13634 printf(
"Cannot listen() on port %d, errno %d (%s), bye!\n", port, errno, strerror(errno));
13638 printf(
"mhttpd is listening on port %d\n", port);
13646int try_file_mg(
const char* try_dir,
const char* filename, std::string& path, FILE** fpp,
bool trace)
13652 if (strlen(try_dir) < 1)
13660 FILE*
fp = fopen(path.c_str(),
"r");
13664 printf(
"file \"%s\": OK!\n", path.c_str());
13666 printf(
"file \"%s\": not found.\n", path.c_str());
13679int find_file_mg(
const char* filename, std::string& path, FILE** fpp,
bool trace)
13696 try_file_mg(exptdir.c_str(), filename, path, NULL,
false);
13700#ifdef HAVE_MONGOOSE6
13704#ifdef HAVE_MONGOOSE616
13708extern void cs_md5(
char buf[33], ...);
13716#ifdef HAVE_MONGOOSE616
13717static bool multithread_mg =
true;
13720#ifdef HAVE_MONGOOSE6
13721static struct mg_mgr mgr_mg;
13745 if (!exptname.empty())
13763 size_t uri_len,
const char *ha1,
size_t ha1_len,
13764 const char *nonce,
size_t nonce_len,
const char *nc,
13765 size_t nc_len,
const char *cnonce,
size_t cnonce_len,
13766 const char *qop,
size_t qop_len,
char *resp) {
13767 static const char colon[] =
":";
13768 static const size_t one = 1;
13771 cs_md5(ha2, method, method_len, colon, one, uri, uri_len, NULL);
13772 cs_md5(resp, ha1, ha1_len, colon, one, nonce, nonce_len, colon, one, nc,
13773 nc_len, colon, one, cnonce, cnonce_len, colon, one, qop, qop_len,
13774 colon, one, ha2,
sizeof(ha2) - 1, NULL);
13784 unsigned long now = (
unsigned long) time(NULL);
13785 unsigned long val = (
unsigned long) strtoul(nonce, NULL, 16);
13786 return now < val || now - val < 3600;
13795 const char *domain) {
13797 "HTTP/1.1 401 Unauthorized\r\n"
13798 "WWW-Authenticate: Digest qop=\"auth\", "
13799 "realm=\"%s\", nonce=\"%lu\"\r\n"
13800 "Content-Length: 0\r\n\r\n",
13801 domain, (
unsigned long) time(NULL));
13814 cm_msg(
MERROR,
"mongoose",
"mongoose web server cannot find password file \"%s\"", path.c_str());
13815 cm_msg(
MERROR,
"mongoose",
"please create password file: touch %s", path.c_str());
13819 bool have_realm =
false;
13827 while (fgets(buf,
sizeof(buf),
fp) != NULL) {
13829 char f_domain[256];
13832 if (sscanf(buf,
"%[^:]:%[^:]:%s", f_user, f_domain, f_ha1) == 3) {
13835 e.username = f_user;
13836 e.password = f_ha1;
13838 if (
e.realm == auth->
realm) {
13850#ifdef HAVE_MONGOOSE6
13851std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13853 assert(!
"this code is untested!");
13859 if (buf_size == 0) {
13861 buf = (
char*)malloc(buf_size);
13862 assert(buf != NULL);
13872 if (size < buf_size) {
13873 std::string s = buf;
13878 buf_size = buf_size*2 + 16;
13879 buf = (
char*)realloc(buf, buf_size);
13880 assert(buf != NULL);
13885#ifdef HAVE_MONGOOSE616
13886std::string find_var_mg(
struct mg_str *hdr,
const char*
var_name)
13893 assert(buf != NULL);
13894 std::string s = buf;
13902 char expected_response[33];
13914 std::string user = find_var_mg(hdr,
"username");
13915 std::string cnonce = find_var_mg(hdr,
"cnonce");
13916 std::string
response = find_var_mg(hdr,
"response");
13917 std::string uri = find_var_mg(hdr,
"uri");
13918 std::string qop = find_var_mg(hdr,
"qop");
13919 std::string nc = find_var_mg(hdr,
"nc");
13920 std::string nonce = find_var_mg(hdr,
"nonce");
13922 if (user.length()<1)
return "";
13923 if (cnonce.length()<1)
return "";
13924 if (
response.length()<1)
return "";
13925 if (uri.length()<1)
return "";
13926 if (qop.length()<1)
return "";
13927 if (nc.length()<1)
return "";
13928 if (nonce.length()<1)
return "";
13935 const char* uri_end = strchr(hm->
uri.
p,
' ');
13936 if (!uri_end)
return "";
13938 size_t uri_length = uri_end - hm->
uri.
p;
13940 if (uri_length != uri.length())
13943 int cmp = strncmp(hm->
uri.
p, uri.c_str(), uri_length);
13952 if (
e->username != user)
13954 if (
e->realm != auth->
realm)
13956 const char* f_ha1 =
e->password.c_str();
13957 int uri_len = hm->
uri.
len;
13958 if (hm->
uri.
p[uri_len] ==
'?')
13961 hm->
uri.
p, uri_len,
13962 f_ha1, strlen(f_ha1),
13963 nonce.c_str(), nonce.length(),
13964 nc.c_str(), nc.length(),
13965 cnonce.c_str(), cnonce.length(),
13966 qop.c_str(), qop.length(),
13967 expected_response);
13968 int cmp = strcasecmp(
response.c_str(), expected_response);
13971 return e->username;
13978#ifdef HAVE_MONGOOSE616
13980struct HostlistCacheEntry
13982 time_t time_created = 0;
13983 time_t time_last_used = 0;
13984 int count_used = 0;
13987 uint32_t ipv4addr = 0;
13988 struct in6_addr ipv6addr;
13989 std::string hostname;
13990 int gai_status = 0;
13991 std::string gai_strerror;
13995static std::vector<HostlistCacheEntry*> gHostlistCache;
13997static void print_hostlist_cache()
13999 time_t now = time(NULL);
14001 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14002 HostlistCacheEntry*
e = gHostlistCache[
i];
14008 printf(
"%3d: %s \"%s\", ok %d, count_used %d, age created: %d, last_used %d",
14010 e->ipv4?
"IPv4":(
e->ipv6?
"IPv6":
"????"),
14011 e->hostname.c_str(),
14014 (int)(now -
e->time_created),
14015 (int)(now -
e->time_last_used));
14017 if (
e->gai_status) {
14018 printf(
", getnameinfo() status %d (%s)",
e->gai_status,
e->gai_strerror.c_str());
14025static bool mongoose_check_hostlist(
const union socket_address *sa)
14027 time_t now = time(NULL);
14030 uint32_t ipv4addr = 0;
14031 struct in6_addr ipv6addr;
14033 if (sa->
sa.sa_family == AF_INET) {
14035 ipv4addr = sa->
sin.sin_addr.s_addr;
14036 }
else if (sa->
sa.sa_family == AF_INET6) {
14038 memcpy(&ipv6addr, &sa->
sin6.sin6_addr,
sizeof(ipv6addr));
14040 printf(
"Rejecting connection from unknown address family %d (AF_xxx)\n", sa->
sa.sa_family);
14044 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14045 HostlistCacheEntry*
e = gHostlistCache[
i];
14051 if ((ipv4 ==
e->ipv4) && (ipv4addr ==
e->ipv4addr)) {
14053 e->time_last_used = now;
14058 if ((ipv6 ==
e->ipv6) && (memcmp(&ipv6addr, &
e->ipv6addr,
sizeof(ipv6addr)) == 0)) {
14060 e->time_last_used = now;
14067 if (
e->time_last_used < now - 24*60*60) {
14068 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);
14069 gHostlistCache[
i] = NULL;
14076 assert(ipv4 || ipv6);
14078 HostlistCacheEntry*
e =
new HostlistCacheEntry;
14080 bool found =
false;
14081 for (
unsigned i=0;
i<gHostlistCache.size();
i++) {
14082 if (gHostlistCache[
i] == NULL) {
14083 gHostlistCache[
i] =
e;
14088 gHostlistCache.push_back(
e);
14091 e->time_created = now;
14092 e->time_last_used = now;
14097 e->ipv4addr = ipv4addr;
14099 memcpy(&
e->ipv6addr, &ipv6addr,
sizeof(ipv6addr));
14102 char hname[NI_MAXHOST];
14105 e->gai_status = getnameinfo(&sa->
sa,
sizeof(*sa), hname,
sizeof(hname), NULL, 0, 0);
14107 if (
e->gai_status) {
14108 e->gai_strerror = gai_strerror(
e->gai_status);
14110 printf(
"Rejecting connection from \'%s\', getnameinfo() status %d (%s)\n", hname,
e->gai_status,
e->gai_strerror.c_str());
14116 printf(
"connection from \"%s\"\n", hname);
14118 e->hostname = hname;
14121 if (
e->hostname ==
"localhost.localdomain")
14123 else if (
e->hostname ==
"localhost")
14134 printf(
"Rejecting connection from \'%s\'\n", hname);
14137 print_hostlist_cache();
14146 return std::string(s->
p, s->
len);
14151 size_t nlen = strlen(
name);
14165 if (cookies.length() < 1)
14167 const char* p = strstr(cookies.c_str(), cookie_name);
14170 const char* v = p+strlen(cookie_name);
14188 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> accept\n", nc, ev, ev_data);
14192 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);
14201 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> send %d bytes\n", nc, ev, ev_data, *(
int*)ev_data);
14205 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p -> close\n", nc, ev, ev_data);
14209 printf(
"handle_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
14218 char cookie_pwd[256];
14219 char cookie_wpwd[256];
14220 char cookie_cpwd[256];
14223 cookie_wpwd[0] = 0;
14224 cookie_cpwd[0] = 0;
14227 if (s.length() > 0) {
14228 mstrlcpy(cookie_pwd, s.c_str(),
sizeof(cookie_pwd));
14229 cookie_pwd[strcspn(cookie_pwd,
" ;\r\n")] = 0;
14234 mstrlcpy(cookie_wpwd, s.c_str(),
sizeof(cookie_pwd));
14235 cookie_wpwd[strcspn(cookie_wpwd,
" ;\r\n")] = 0;
14240 mstrlcpy(cookie_cpwd, s.c_str(),
sizeof(cookie_pwd));
14241 cookie_cpwd[strcspn(cookie_cpwd,
" ;\r\n")] = 0;
14247 if (s.length() > 0)
14248 c->refresh = atoi(s.c_str());
14256 c->cookie_pwd = cookie_pwd;
14257 c->cookie_wpwd = cookie_wpwd;
14258 c->cookie_cpwd = cookie_cpwd;
14261#define RESPONSE_SENT 1
14262#define RESPONSE_QUEUED 2
14263#define RESPONSE_501 3
14273#ifdef HAVE_MONGOOSE6
14288 decode_get(rr, NULL, &cookies, uri, query_string, t);
14297#ifdef HAVE_MONGOOSE6
14309#ifdef HAVE_MONGOOSE6
14329#ifdef HAVE_MONGOOSE616
14331static uint32_t s_ncseqno = 1;
14333struct MongooseNcUserData
14335 uint32_t ncseqno = 0;
14337 MongooseNcUserData()
14339 ncseqno = s_ncseqno++;
14343 ~MongooseNcUserData()
14355 const MongooseNcUserData* ncud = (
const MongooseNcUserData*)nc->
user_data;
14356 return ncud->ncseqno;
14359static uint32_t s_wseqno = 1;
14361struct MongooseWorkObject
14363 uint32_t wseqno = 0;
14365 uint32_t wncseqno = 0;
14366 bool http_get =
false;
14367 bool http_post =
false;
14368 bool mjsonrpc =
false;
14370 std::string origin;
14372 std::string query_string;
14373 std::string post_body;
14374 std::string post_boundary;
14376 bool send_done =
false;
14380 wseqno = s_wseqno++;
14382 wncseqno = GetNcSeqno(nc);
14387 ~MongooseWorkObject()
14397struct MongooseThreadObject
14399 std::atomic_bool fIsRunning{
false};
14400 std::thread* fThread = NULL;
14403 std::deque<MongooseWorkObject*> fQueue;
14404 std::condition_variable fNotify;
14417static std::vector<MongooseThreadObject*> gMongooseThreads;
14419static void mongoose_thread(MongooseThreadObject*);
14421MongooseThreadObject* FindThread(
void* nc)
14425 MongooseThreadObject* last_not_connected = NULL;
14427 for (
auto it : gMongooseThreads) {
14428 MongooseThreadObject* to = it;
14429 if (to->fNc == nc) {
14433 if (to->fNc == NULL) {
14434 last_not_connected = to;
14438 if (last_not_connected) {
14439 MongooseThreadObject* to = last_not_connected;
14445 MongooseThreadObject* to =
new MongooseThreadObject();
14451 gMongooseThreads.push_back(to);
14453 printf(
"Mongoose web server is using %d threads \r", (
int)gMongooseThreads.size());
14456 to->fThread =
new std::thread(mongoose_thread, to);
14461void FreeThread(
void* nc)
14465 for (
auto it : gMongooseThreads) {
14466 MongooseThreadObject* to = it;
14467 if (to->fNc == nc) {
14477static void mongoose_queue(
mg_connection* nc, MongooseWorkObject* w)
14480 MongooseThreadObject* to = FindThread(nc);
14481 assert(to->fNc == nc);
14483 to->fQueue.push_back(w);
14484 to->fMutex.unlock();
14485 to->fNotify.notify_one();
14488static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag =
false);
14492 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14493 w->http_get =
true;
14496 w->query_string = query_string;
14499 mongoose_queue(nc, w);
14506 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14507 w->http_post =
true;
14510 w->query_string = query_string;
14512 w->post_boundary = boundary;
14515 mongoose_queue(nc, w);
14520static int queue_mjsonrpc(
struct mg_connection *nc,
const std::string& origin,
const std::string& post_body,
RequestTrace* t)
14522 MongooseWorkObject* w =
new MongooseWorkObject(nc);
14523 w->mjsonrpc =
true;
14524 w->origin = origin;
14525 w->post_body = post_body;
14528 mongoose_queue(nc, w);
14533static int thread_http_get(
mg_connection *nc, MongooseWorkObject *w)
14550 decode_get(rr, NULL, &w->cookies, w->uri.c_str(), w->query_string.c_str(), w->t);
14571 bool close_flag =
false;
14589static int thread_http_post(
mg_connection *nc, MongooseWorkObject *w)
14591 const char* post_data = w->post_body.c_str();
14592 int post_data_len = w->post_body.length();
14607 decode_post(rr, NULL, (
char*)post_data, w->post_boundary.c_str(), post_data_len, &w->cookies, w->uri.c_str(), w->t);
14610 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14623 bool close_flag =
false;
14639static int thread_mjsonrpc(
mg_connection *nc, MongooseWorkObject *w)
14641 w->t->fRPC = w->post_body;
14656 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14659 reply->GetArrayBuffer(&ptr, &size);
14661 std::string headers;
14662 headers +=
"HTTP/1.1 200 OK\n";
14663 if (w->origin.length() > 0)
14664 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14666 headers +=
"Access-Control-Allow-Origin: *\n";
14667 headers +=
"Access-Control-Allow-Credentials: true\n";
14668 headers +=
"Content-Length: " +
toString(size) +
"\n";
14669 headers +=
"Content-Type: application/octet-stream\n";
14675 std::string send = headers +
"\n";
14679 mongoose_send(nc, w, send.c_str(), send.length(), ptr, size);
14688 std::string reply_string = reply->Stringify();
14689 int reply_length = reply_string.length();
14691 std::string headers;
14692 headers +=
"HTTP/1.1 200 OK\n";
14693 if (w->origin.length() > 0)
14694 headers +=
"Access-Control-Allow-Origin: " + w->origin +
"\n";
14696 headers +=
"Access-Control-Allow-Origin: *\n";
14697 headers +=
"Access-Control-Allow-Credentials: true\n";
14698 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14699 headers +=
"Content-Type: application/json\n";
14703 printf(
"-----------------------\nSending headers: %s", headers.c_str());
14704 std::string r = reply_string.substr(0, 128);
14705 printf(
"-----------------------\nSending reply (%d bytes): %s\n\n\n", (
int)reply_string.size(), r.c_str());
14708 std::string send = headers +
"\n" + reply_string;
14712 mongoose_send(nc, w, send.c_str(), send.length(), NULL, 0);
14721static int thread_work_function(
mg_connection *nc, MongooseWorkObject *w)
14724 return thread_http_get(nc, w);
14725 else if (w->http_post)
14726 return thread_http_post(nc, w);
14727 else if (w->mjsonrpc)
14728 return thread_mjsonrpc(nc, w);
14738 char boundary[256];
14741 if (ct.length() > 0) {
14742 const char* s = strstr(ct.c_str(),
"boundary=");
14744 mstrlcpy(boundary, s+9,
sizeof(boundary));
14747#ifdef HAVE_MONGOOSE616
14748 if (multithread_mg)
14749 return queue_decode_post(nc, msg, boundary, uri, query_string, t);
14756 const char* post_data = msg->
body.
p;
14757 int post_data_len = msg->
body.
len;
14761#ifdef HAVE_MONGOOSE6
14774 decode_post(rr, NULL, (
char*)post_data, boundary, post_data_len, &cookies, uri, t);
14777 printf(
"handle_decode_post: return buffer length %d bytes, strlen %d\n", rr->
return_length, (
int)strlen(rr->
return_buffer));
14780#ifdef HAVE_MONGOOSE6
14790#ifdef HAVE_MONGOOSE6
14813 printf(
"handle_http_get: uri [%s], query [%s]\n", uri, query_string.c_str());
14815 if (query_string ==
"mjsonrpc_schema") {
14817 std::string reply = s->Stringify();
14820 int reply_length = reply.length();
14822 const std::string origin_header =
find_header_mg(msg,
"Origin");
14824 std::string headers;
14825 headers +=
"HTTP/1.1 200 OK\n";
14826 if (origin_header.length() > 0)
14827 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14829 headers +=
"Access-Control-Allow-Origin: *\n";
14830 headers +=
"Access-Control-Allow-Credentials: true\n";
14831 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14832 headers +=
"Content-Type: application/json\n";
14838 std::string send = headers +
"\n" + reply;
14842 mg_send(nc, send.c_str(), send.length());
14849 if (query_string ==
"mjsonrpc_schema_text") {
14854 int reply_length = reply.length();
14856 const std::string origin_header =
find_header_mg(msg,
"Origin");
14858 std::string headers;
14859 headers +=
"HTTP/1.1 200 OK\n";
14860 if (origin_header.length() > 0)
14861 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14863 headers +=
"Access-Control-Allow-Origin: *\n";
14864 headers +=
"Access-Control-Allow-Credentials: true\n";
14865 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14866 headers +=
"Content-Type: text/plain\n";
14872 std::string send = headers +
"\n" + reply;
14876 mg_send(nc, send.c_str(), send.length());
14883#ifdef HAVE_MONGOOSE616
14884 if (multithread_mg)
14885 return queue_decode_get(nc, msg, uri, query_string.c_str(), t);
14894 std::string post_data =
mgstr(&msg->
body);
14897 printf(
"handle_http_post: uri [%s], query [%s], post data %d bytes\n", uri, query_string.c_str(), (
int)post_data.length());
14899 printf(
"handle_http_post: post data = \n%s\n", post_data.c_str());
14901 if (query_string.substr(0, 8) ==
"mjsonrpc") {
14902 const std::string origin_header =
find_header_mg(msg,
"Origin");
14903 const std::string ctype_header =
find_header_mg(msg,
"Content-Type");
14905 if (strstr(ctype_header.c_str(),
"application/json") == NULL) {
14906 std::string headers;
14907 headers +=
"HTTP/1.1 415 Unsupported Media Type\n";
14914 printf(
"handle_http_post: unsupported media type \"%s\"\n", ctype_header.c_str());
14916 std::string send = headers +
"\n";
14920 mg_send(nc, send.c_str(), send.length());
14927#ifdef HAVE_MONGOOSE616
14928 if (multithread_mg)
14929 return queue_mjsonrpc(nc, origin_header, post_data, t);
14934 t->
fRPC = post_data;
14936#ifdef HAVE_MONGOOSE6
14947#ifdef HAVE_MONGOOSE6
14951 if (reply->GetType() == MJSON_ARRAYBUFFER) {
14954 reply->GetArrayBuffer(&ptr, &size);
14956 std::string headers;
14957 headers +=
"HTTP/1.1 200 OK\n";
14958 if (origin_header.length() > 0)
14959 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14961 headers +=
"Access-Control-Allow-Origin: *\n";
14962 headers +=
"Access-Control-Allow-Credentials: true\n";
14963 headers +=
"Content-Length: " +
toString(size) +
"\n";
14964 headers +=
"Content-Type: application/octet-stream\n";
14970 std::string send = headers +
"\n";
14974 mg_send(nc, send.c_str(), send.length());
14984 std::string reply_string = reply->Stringify();
14985 int reply_length = reply_string.length();
14987 std::string headers;
14988 headers +=
"HTTP/1.1 200 OK\n";
14989 if (origin_header.length() > 0)
14990 headers +=
"Access-Control-Allow-Origin: " + std::string(origin_header) +
"\n";
14992 headers +=
"Access-Control-Allow-Origin: *\n";
14993 headers +=
"Access-Control-Allow-Credentials: true\n";
14994 headers +=
"Content-Length: " +
toString(reply_length) +
"\n";
14995 headers +=
"Content-Type: application/json\n";
15001 std::string send = headers +
"\n" + reply_string;
15005 mg_send(nc, send.c_str(), send.length());
15050 const std::string origin_header =
find_header_mg(msg,
"Origin");
15053 printf(
"handle_http_options_cors: origin [%s]\n", origin_header.c_str());
15055 std::string headers;
15056 headers +=
"HTTP/1.1 200 OK\n";
15058 if (origin_header.length() > 0)
15059 headers +=
"Access-Control-Allow-Origin: " + origin_header +
"\n";
15061 headers +=
"Access-Control-Allow-Origin: *\n";
15062 headers +=
"Access-Control-Allow-Headers: Content-Type\n";
15063 headers +=
"Access-Control-Allow-Credentials: true\n";
15064 headers +=
"Access-Control-Max-Age: 120\n";
15065 headers +=
"Content-Length: 0\n";
15066 headers +=
"Content-Type: text/plain\n";
15070 std::string send = headers +
"\n";
15074 mg_send(nc, send.c_str(), send.length());
15083#ifdef HAVE_MONGOOSE616
15084static MVOdb* gProxyOdb = NULL;
15091 std::string uri_encoded =
mgstr(&msg->
uri);
15092 std::string uri =
UrlDecode(uri_encoded.c_str());
15095 printf(
"handle_http_message: method [%s] uri [%s] proto [%s]\n", method.c_str(), uri.c_str(),
mgstr(&msg->
proto).c_str());
15101 t->
fQuery = query_string;
15105 if (method ==
"OPTIONS" && query_string ==
"mjsonrpc" &&
mg_get_http_header(msg,
"Access-Control-Request-Method") != NULL) {
15128 printf(
"handle_http_message: auth user: \"%s\"\n", username.c_str());
15130 if (username.length() == 0) {
15132 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());
15144#ifdef HAVE_MONGOOSE616
15146 std::string::size_type p1 = uri.find(
"/", 1);
15147 if (p1 == uri.length()-1) {
15148 std::string
response =
"404 Not Found (Proxy name is missing)";
15154 std::string::size_type p2 = uri.find(
"/", p1+1);
15155 if (p2 == std::string::npos) {
15156 std::string
response =
"404 Not Found (Proxy URL should end with a slash)";
15162 std::string p = uri.substr(p1+1, p2-p1-1);
15164 if (p.length() < 1) {
15165 std::string
response =
"404 Not Found (Double-slash or Proxy name is too short)";
15171 std::string destination;
15172 gProxyOdb->RS(p.c_str(), &destination);
15173 if (destination.length() < 1) {
15174 std::string
response =
"404 Not Found (Proxy not found in ODB)";
15179 }
else if (destination[0] ==
'#') {
15180 std::string
response =
"404 Not Found (Proxy commented-out in ODB)";
15186 std::string
response =
"404 Not Found (Proxy address should not end with a slash)";
15192 std::string
response =
"404 Not Found (Proxy address does not start with http";
15205 printf(
"proxy: uri [%s] mount [%s] upstream [%s]\n", uri.c_str(),
mgstr(&mount).c_str(),
mgstr(&upstream).c_str());
15207 mg_http_reverse_proxy(nc, msg, mount, upstream);
15216 if (method ==
"GET")
15218 else if (method ==
"POST")
15223 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15225 std::string
response =
"501 Not Implemented";
15236#ifdef HAVE_MONGOOSE6
15238static void handle_http_event_mg(
struct mg_connection *nc,
int ev,
void *ev_data)
15243 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15248 printf(
"handle_http_event_mg: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15253static void handle_http_redirect(
struct mg_connection *nc,
int ev,
void *ev_data)
15260 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p -> http request\n", nc, ev, ev_data);
15262 mg_printf(nc,
"HTTP/1.1 302 Found\r\nLocation: https://%s%s\r\n\r\n",
15263 ((std::string*)(nc->
user_data))->c_str(),
15270 printf(
"handle_http_redirect: nc %p, ev %d, ev_data %p\n", nc, ev, ev_data);
15276#ifdef HAVE_MONGOOSE616
15281static std::atomic_bool s_shutdown{
false};
15282static struct mg_mgr s_mgr;
15283static std::atomic_int s_rseqno{1};
15284static std::mutex s_mg_broadcast_mutex;
15288struct work_request {
15290 MongooseWorkObject* w;
15295struct work_result {
15297 uint32_t check = 0x12345678;
15299 MongooseWorkObject* w = NULL;
15300 const char* p1 = NULL;
15302 const char* p2 = NULL;
15304 bool close_flag =
false;
15305 bool send_501 =
false;
15309static void mongoose_queue(
void *nc, MongooseWorkObject *w)
15311 struct work_request req = {nc, w};
15315 if (
write(s_sock[0], &req,
sizeof(req)) < 0) {
15316 fprintf(stderr,
"mongoose_queue: Error: write(s_sock(0)) error %d (%s)\n", errno, strerror(errno));
15322static void on_work_complete(
struct mg_connection *nc,
int ev,
void *ev_data)
15325 struct work_result *res = (
struct work_result *)ev_data;
15327 assert(res != NULL);
15328 assert(res->w != NULL);
15339 if (GetNcSeqno(nc) != res->w->wncseqno)
15344 if (res->send_501) {
15345 std::string
response =
"501 Not Implemented";
15351 mg_send(nc, res->p1, res->s1);
15354 mg_send(nc, res->p2, res->s2);
15356 if (res->close_flag) {
15363 res->w->send_done =
true;
15366static void mongoose_send(
mg_connection* nc, MongooseWorkObject* w,
const char* p1,
size_t s1,
const char* p2,
size_t s2,
bool close_flag)
15369 struct work_result res;
15372 res.rseqno = s_rseqno++;
15377 res.close_flag = close_flag;
15378 res.send_501 =
false;
15420 s_mg_broadcast_mutex.lock();
15421 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15422 s_mg_broadcast_mutex.unlock();
15425static void mongoose_send_501(
mg_connection* nc, MongooseWorkObject* w)
15427 struct work_result res;
15430 res.rseqno = s_rseqno++;
15435 res.close_flag =
false;
15436 res.send_501 =
true;
15439 s_mg_broadcast_mutex.lock();
15440 mg_broadcast(&s_mgr, on_work_complete, (
void *)&res,
sizeof(res));
15441 s_mg_broadcast_mutex.unlock();
15445void *worker_thread_proc(
void *
param)
15448 struct work_request req = {0};
15450 while ((!
_abort) && (! s_shutdown)) {
15451 int rd =
read(s_sock[1], &req,
sizeof(req));
15457 if (
_abort || s_shutdown) {
15460 fprintf(stderr,
"worker_thread_proc: Error: read(s_sock(1)) returned %d, error %d (%s)\n", rd, errno, strerror(errno));
15467 int response = thread_work_function(req.nc, req.w);
15471 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15472 mongoose_send_501(req.nc, req.w);
15475 req.w->t->fCompleted =
true;
15487static void mongoose_thread(MongooseThreadObject* to)
15491 std::unique_lock<std::mutex> ulm(to->fMutex, std::defer_lock);
15493 to->fIsRunning =
true;
15495 while ((!
_abort) && (! s_shutdown)) {
15496 MongooseWorkObject *w = NULL;
15499 while (to->fQueue.empty()) {
15501 to->fNotify.wait(ulm);
15502 if (
_abort || s_shutdown) {
15507 if (
_abort || s_shutdown) {
15511 w = to->fQueue.front();
15512 to->fQueue.pop_front();
15517 int response = thread_work_function(w->nc, w);
15521 printf(
"handle_http_message: sending 501 Not Implemented error\n");
15522 mongoose_send_501(w->nc, w);
15527 if (!w->send_done) {
15533 w->t->fCompleted =
true;
15541 to->fIsRunning =
false;
15546static bool mongoose_hostlist_enabled(
const struct mg_connection *nc);
15548static void ev_handler(
struct mg_connection *nc,
int ev,
void *ev_data)
15562 printf(
"ev_handler: connection %p, event %d\n", nc, ev);
15568 nc->
user_data =
new MongooseNcUserData();
15571 printf(
"ev_handler: connection %p, MG_EV_ACCEPT, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15576 }
else if (mongoose_hostlist_enabled(nc)) {
15577 if (!mongoose_check_hostlist(&nc->
sa)) {
15584 printf(
"ev_handler: connection %p, MG_EV_RECV, %d bytes\n", nc, *(
int*)ev_data);
15593 printf(
"ev_handler: connection %p, MG_EV_SEND, %d bytes\n", nc, *(
int*)ev_data);
15598 printf(
"ev_handler: connection %p, MG_EV_HTTP_CHUNK\n", nc);
15609 printf(
"ev_handler: connection %p, MG_EV_HTTP_REQUEST \"%s\" \"%s\"\n", nc,
mgstr(&msg->
method).c_str(),
mgstr(&msg->
uri).c_str());
15621 printf(
"ev_handler: connection %p, MG_EV_CLOSE, user_data %p, ncseqno %d\n", nc, nc->
user_data, GetNcSeqno(nc));
15626 MongooseNcUserData* ncud = (MongooseNcUserData*)nc->
user_data;
15635#define FLAG_HTTPS MG_F_USER_1
15636#define FLAG_PASSWORDS MG_F_USER_2
15637#define FLAG_HOSTLIST MG_F_USER_3
15646 return flags & FLAG_PASSWORDS;
15649static bool mongoose_hostlist_enabled(
const struct mg_connection *nc)
15656 return flags & FLAG_HOSTLIST;
15659static int mongoose_listen(
const char* address,
int flags)
15663 if (flags & FLAG_HTTPS) {
15664 cm_msg(
MERROR,
"mongoose_listen",
"https port \"%s\" requested, but mhttpd compiled without MG_ENABLE_SSL", address);
15671 cm_msg(
MERROR,
"mongoose_listen",
"Cannot mg_bind address \"%s\"", address);
15675 if (
flags & FLAG_HTTPS) {
15677 std::string cert_file;
15682 cm_msg(
MERROR,
"mongoose_listen",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
15683 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");
15684 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");
15688 printf(
"Mongoose web server will use https certificate file \"%s\"\n", cert_file.c_str());
15690 const char* errmsg =
mg_set_ssl(nc, cert_file.c_str(), NULL);
15692 cm_msg(
MERROR,
"mongoose_listen",
"Cannot enable https with certificate file \"%s\", error: %s", cert_file.c_str(), errmsg);
15706 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");
15711static int mongoose_init(MVOdb* odb,
bool no_passwords,
bool no_hostlist,
const std::vector<std::string>& user_hostlist)
15713 bool enable_localhost_port =
true;
15714 int localhost_port = 8080;
15715 bool localhost_port_passwords =
false;
15717 bool enable_insecure_port =
false;
15718 int insecure_port = 8081;
15719 bool insecure_port_passwords =
true;
15720 bool insecure_port_hostlist =
true;
15722 bool enable_https_port =
false;
15723 int https_port = 8443;
15724 bool https_port_passwords =
true;
15725 bool https_port_hostlist =
false;
15727 std::vector<std::string> hostlist;
15728 hostlist.push_back(
"localhost");
15730 bool enable_ipv6 =
true;
15732 odb->RB(
"Enable localhost port", &enable_localhost_port,
true);
15733 odb->RI(
"localhost port", &localhost_port,
true);
15734 odb->RB(
"localhost port passwords", &localhost_port_passwords,
true);
15735 odb->RB(
"Enable insecure port", &enable_insecure_port,
true);
15736 odb->RI(
"insecure port", &insecure_port,
true);
15737 odb->RB(
"insecure port passwords", &insecure_port_passwords,
true);
15738 odb->RB(
"insecure port host list", &insecure_port_hostlist,
true);
15739 odb->RB(
"Enable https port", &enable_https_port,
true);
15740 odb->RI(
"https port", &https_port,
true);
15741 odb->RB(
"https port passwords", &https_port_passwords,
true);
15742 odb->RB(
"https port host list", &https_port_hostlist,
true);
15743 odb->RSA(
"Host list", &hostlist,
true, 10, 256);
15744 odb->RB(
"Enable IPv6", &enable_ipv6,
true);
15747 gProxyOdb = odb->Chdir(
"Proxy",
true);
15748 std::string proxy_example =
"#http://localhost:8080";
15749 gProxyOdb->RS(
"example", &proxy_example,
true);
15755 && ((enable_localhost_port && localhost_port_passwords)
15756 || (enable_insecure_port && insecure_port_passwords)
15757 || (enable_https_port && https_port_passwords))) {
15761 printf(
"mongoose_init: Error: Cannot initialize authorization object!\n");
15766 printf(
"Password protection is off\n");
15770 && ((enable_insecure_port && insecure_port_hostlist)
15771 || (enable_https_port && https_port_hostlist))) {
15775 for (
unsigned int i=0;
i<user_hostlist.size();
i++)
15778 for (
unsigned i=0;
i<hostlist.size();
i++) {
15779 std::string s = hostlist[
i];
15780 if (s.length() < 1)
15790 printf(
"Hostlist active, connections will be accepted only from: ");
15798 printf(
"Hostlist off, connections from anywhere will be accepted\n");
15803 bool listen_failed =
false;
15805 if (enable_localhost_port) {
15807 sprintf(
str,
"localhost:%d", localhost_port);
15810 listen_failed =
true;
15812 sprintf(
str,
"[::1]:%d", localhost_port);
15815 listen_failed =
true;
15819 if (enable_insecure_port) {
15822 if (insecure_port_passwords)
15823 flags |= FLAG_PASSWORDS;
15824 if (insecure_port_hostlist)
15825 flags |= FLAG_HOSTLIST;
15827 sprintf(
str,
"[::]:%d", insecure_port);
15830 listen_failed =
true;
15832 sprintf(
str,
"%d", insecure_port);
15835 listen_failed =
true;
15839 if (enable_https_port) {
15842 if (https_port_passwords)
15843 flags |= FLAG_PASSWORDS;
15844 if (https_port_hostlist)
15845 flags |= FLAG_HOSTLIST;
15846 flags |= FLAG_HTTPS;
15848 sprintf(
str,
"[::]:%d", https_port);
15851 listen_failed =
true;
15853 sprintf(
str,
"%d", https_port);
15856 listen_failed =
true;
15860 if (listen_failed) {
15861 cm_msg(
MERROR,
"mongoose_init",
"Failed to listen on a TCP port enabled in ODB /WebServer");
15868static void mongoose_poll(
int msec = 200)
15873static void mongoose_cleanup()
15875 printf(
"Mongoose web server shutting down\n");
15880 if (s_mgr.active_connections) {
15892 for (
auto it : gMongooseThreads) {
15893 MongooseThreadObject* to = it;
15894 to->fNotify.notify_one();
15898 for (
int i=0;
i<10;
i++) {
15899 int count_running = 0;
15900 for (
auto it : gMongooseThreads) {
15901 MongooseThreadObject* to = it;
15903 if (to->fIsRunning) {
15907 printf(
"Mongoose web server shutting down, %d threads still running\n", count_running);
15908 if (count_running == 0)
15910 mongoose_poll(1000);
15914 for (
auto it : gMongooseThreads) {
15915 MongooseThreadObject* to = it;
15917 if (to->fIsRunning) {
15918 cm_msg(
MERROR,
"mongoose",
"thread failed to shut down");
15921 to->fThread->join();
15922 delete to->fThread;
15925 gMongooseThreads.clear();
15933 for (
auto e : gHostlistCache) {
15936 gHostlistCache.clear();
15946 printf(
"Mongoose web server shut down\n");
15951#ifdef HAVE_MONGOOSE6
15958int start_mg(
int user_http_port,
int user_https_port,
int socket_priviledged_port,
int verbose)
15973 int http_port = 8080;
15974 int https_port = 8443;
15975 int http_redirect_to_https = 1;
15977 size =
sizeof(http_port);
15980 size =
sizeof(https_port);
15983 size =
sizeof(http_redirect_to_https);
15986 bool need_cert_file =
false;
15987 bool need_password_file =
false;
15989 if (user_http_port)
15990 http_port = user_http_port;
15992 if (user_https_port)
15993 https_port = user_https_port;
15996 need_cert_file =
true;
15997 need_password_file =
true;
16001 http_redirect_to_https = 0;
16003 if (http_port && !http_redirect_to_https) {
16006 need_password_file =
false;
16009 if (socket_priviledged_port >= 0) {
16011 need_password_file =
false;
16012 printf(
"Mongoose web server password portection is disabled: serving unencrypted http on port 80\n");
16015 bool have_at_least_one_port =
false;
16017 std::string cert_file;
16019 if (need_cert_file) {
16023 cm_msg(
MERROR,
"mongoose",
"cannot find SSL certificate file \"%s\"", cert_file.c_str());
16024 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");
16028 printf(
"Mongoose web server will use SSL certificate file \"%s\"\n", cert_file.c_str());
16031 if (need_password_file) {
16035 printf(
"Error: Cannot initialize authorization object!\n");
16040 printf(
"Mongoose web server will not use password protection\n");
16044 printf(
"start_mg!\n");
16047 signal(SIGPIPE, SIG_IGN);
16054 if (!request_mutex) {
16062 if (socket_priviledged_port >= 0) {
16065 cm_msg(
MERROR,
"mongoose",
"Cannot create mg_connection for set-uid-root privileged port");
16070#ifdef MG_ENABLE_THREADS
16076 have_at_least_one_port =
true;
16077 printf(
"mongoose web server is listening on the set-uid-root privileged port\n");
16080 if (http_port != 80) {
16082 sprintf(
str,
"%d", http_port);
16085 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", http_port);
16089#ifdef MG_ENABLE_THREADS
16094 if (http_redirect_to_https) {
16097 sprintf(
str,
"%d", https_port);
16098 std::string s = hostname +
":" + std::string(
str);
16101 printf(
"mongoose web server is redirecting HTTP port %d to https://%s\n", http_port, s.c_str());
16106 have_at_least_one_port =
true;
16107 printf(
"mongoose web server is listening on the HTTP port %d\n", http_port);
16111#ifdef MG_ENABLE_SSL
16113 sprintf(
str,
"%d", https_port);
16116 cm_msg(
MERROR,
"mongoose",
"Cannot bind to port %d", https_port);
16121#ifdef MG_ENABLE_THREADS
16127 have_at_least_one_port =
true;
16128 printf(
"mongoose web server is listening on the HTTPS port %d\n", https_port);
16130 cm_msg(
MERROR,
"mongoose",
"https port %d requested, but mhttpd compiled without MG_ENABLE_SSL", https_port);
16135 if (!have_at_least_one_port) {
16136 cm_msg(
MERROR,
"mongoose",
"cannot start: no ports defined");
16146 printf(
"stop_mg!\n");
16152 printf(
"stop_mg done!\n");
16167#ifdef HAVE_MONGOOSE6
16178#ifdef HAVE_MONGOOSE6
16195 doc->
D(
"get current value of mhttpd http_trace");
16196 doc->
P(NULL, 0,
"there are no input parameters");
16197 doc->
R(NULL, MJSON_INT,
"current value of http_trace");
16208 doc->
D(
"set new value of mhttpd http_trace");
16209 doc->
P(NULL, MJSON_INT,
"new value of http_trace");
16210 doc->
R(NULL, MJSON_INT,
"new value of http_trace");
16230#ifdef HAVE_MONGOOSE6
16231 int user_http_port = 0;
16232 int user_https_port = 0;
16234#ifdef HAVE_MONGOOSE616
16235 bool no_passwords =
false;
16236 bool no_hostlist =
false;
16238 const char *myname =
"mhttpd";
16240 setbuf(stdout, NULL);
16241 setbuf(stderr, NULL);
16244 signal(SIGPIPE, SIG_IGN);
16247#ifdef HAVE_MONGOOSE6
16252 int socket_priviledged_port = -1;
16256 if (getuid() != geteuid()) {
16259 printf(
"mhttpd is running in setuid-root mode.\n");
16261 socket_priviledged_port = open_listening_socket(port80);
16262 if (socket_priviledged_port < 0) {
16263 printf(
"Cannot open listening socket on TCP port %d, aborting.\n", port80);
16268 status = setuid(getuid());
16270 printf(
"Cannot give up root privelege, aborting.\n");
16273 status = setuid(getuid());
16275 printf(
"Cannot give up root privelege, aborting.\n");
16282 char midas_hostname[256];
16283 char midas_expt[256];
16286 cm_get_environment(midas_hostname,
sizeof(midas_hostname), midas_expt,
sizeof(midas_expt));
16289#ifdef HAVE_MONGOOSE6
16290 gUserAllowedHosts.clear();
16292 std::vector<std::string> user_hostlist;
16294 for (
int i = 1;
i < argc;
i++) {
16295 if (argv[
i][0] ==
'-' && argv[
i][1] ==
'D')
16297 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'v')
16299 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'E')
16301 else if (argv[
i][0] ==
'-' && argv[
i][1] ==
'H') {
16303#ifdef HAVE_MONGOOSE6
16304 }
else if (strcmp(argv[
i],
"--http") == 0) {
16306 user_http_port = atoi(argv[
i+1]);
16308 }
else if (strcmp(argv[
i],
"--https") == 0) {
16310 user_https_port = atoi(argv[
i+1]);
16313 }
else if (strcmp(argv[
i],
"--trace-mg") == 0) {
16317 }
else if (strcmp(argv[
i],
"--trace-mg-verbose") == 0) {
16319 }
else if (strcmp(argv[
i],
"--no-trace-mg-recv") == 0) {
16321 }
else if (strcmp(argv[
i],
"--no-trace-mg-send") == 0) {
16323 }
else if (strcmp(argv[
i],
"--verbose-mg") == 0) {
16325#ifdef HAVE_MONGOOSE616
16326 }
else if (strcmp(argv[
i],
"--no-multithread") == 0) {
16327 multithread_mg =
false;
16328 }
else if (strcmp(argv[
i],
"--no-passwords") == 0) {
16329 no_passwords =
true;
16330 }
else if (strcmp(argv[
i],
"--no-hostlist") == 0) {
16331 no_hostlist =
true;
16333 }
else if (argv[
i][0] ==
'-') {
16334 if (
i + 1 >= argc || argv[
i + 1][0] ==
'-')
16336 if (argv[
i][1] ==
'h')
16337 mstrlcpy(midas_hostname, argv[++
i],
sizeof(midas_hostname));
16338 else if (argv[
i][1] ==
'e')
16339 mstrlcpy(midas_expt, argv[++
i],
sizeof(midas_hostname));
16340 else if (argv[
i][1] ==
'a') {
16341#ifdef HAVE_MONGOOSE6
16342 gUserAllowedHosts.push_back(argv[++
i]);
16344 user_hostlist.push_back(argv[++
i]);
16346 }
else if (argv[
i][1] ==
'p') {
16347 printf(
"Option \"-p port_number\" for the old web server is obsolete.\n");
16348 printf(
"mongoose web server is the new default, port number is set in ODB or with \"--http port_number\".\n");
16349 printf(
"To run the obsolete old web server, please use \"--oldserver\" switch.\n");
16353 printf(
"usage: %s [-h Hostname[:port]] [-e Experiment] [-v] [-D] [-a Hostname]\n\n", argv[0]);
16354 printf(
" -a add hostname to the hostlist of hosts allowed to connect to mhttpd\n");
16355 printf(
" -e experiment to connect to\n");
16356 printf(
" -h connect to midas server (mserver) on given host\n");
16357 printf(
" -v display verbose HTTP communication\n");
16358 printf(
" -D become a daemon\n");
16359 printf(
" -E only display ELog system\n");
16360 printf(
" -H only display history plots\n");
16361#ifdef HAVE_MONGOOSE6
16362 printf(
" --http port - bind to specified HTTP port (default is ODB \"/Experiment/midas http port\")\n");
16363 printf(
" --https port - bind to specified HTTP port (default is ODB \"/Experiment/midas https port\")\n");
16365 printf(
" --verbose-mg - trace mongoose web requests\n");
16366 printf(
" --trace-mg - trace mongoose events\n");
16367 printf(
" --no-trace-mg-recv - do not trace mongoose recv events\n");
16368 printf(
" --no-trace-mg-send - dop not trace mongoose send events\n");
16369#ifdef HAVE_MONGOOSE616
16370 printf(
" --no-multithread - disable mongoose multithreading\n");
16371 printf(
" --no-passwords - disable password protection\n");
16372 printf(
" --no-hostlist - disable access control host list\n");
16380 printf(
"Becoming a daemon...\n");
16386 FILE *
f = fopen(
"/var/run/mhttpd.pid",
"w");
16394 myname =
"mhttpd_history";
16422 MVOdb *odb = MakeMidasOdb(
hDB);
16430 printf(
"check_odb_records() failed, see messages and midas.log, bye!\n");
16435#ifdef HAVE_MONGOOSE6
16436 if (init_allowed_hosts() !=
SUCCESS) {
16437 printf(
"init_allowed_hosts() failed, see messages and midas.log, bye!\n");
16444 printf(
"mhttpd allowed hosts list: ");
16452 printf(
"mhttpd allowed hosts list is empty\n");
16475#ifdef HAVE_MONGOOSE6
16476 status = start_mg(user_http_port, user_https_port, socket_priviledged_port,
verbose);
16479 printf(
"could not start the mongoose web server, see messages and midas.log, bye!\n");
16485#ifdef HAVE_MONGOOSE616
16489 signal(SIGPIPE, SIG_IGN);
16505 MVOdb* o = odb->Chdir(
"WebServer",
true);
16506 status = mongoose_init(o, no_passwords, no_hostlist, user_hostlist);
16509 printf(
"Error: Could not start the mongoose web server, see messages and midas.log, bye!\n");
16517#ifdef HAVE_MONGOOSE6
16522#ifdef HAVE_MONGOOSE616
16543 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)