]> git.vomp.tv Git - jsonserver.git/blob - handler.c
Find event for timer in list even when timer is inactive
[jsonserver.git] / handler.c
1 #include "handler.h"
2
3 #include <string.h>
4 #include <stdlib.h>
5 #include <sys/time.h>
6 #include <jsoncpp/json/json.h>
7 #include <string>
8
9 #include <vdr/videodir.h>
10 #include <vdr/recording.h>
11 #include <vdr/menu.h>
12 #include <vdr/timers.h>
13
14 #include "log.h"
15
16 int jsonserver_request_handler(struct mg_connection *conn)
17 {
18   Log* log = Log::getInstance();
19   const struct mg_request_info *request_info = mg_get_request_info(conn);
20   
21   if (strcmp(request_info->uri, "/jsonserver")) return 0; // not for us
22
23   char wvrequest[20];
24   int wvrl = mg_get_var(request_info->query_string, strlen(request_info->query_string), "req", wvrequest, 20);
25   if (wvrl == -1)
26   {
27     log->log("JSONServer", Log::ERR, "Could not decode req");
28     return 0;
29   }
30
31 /*
32   if (!strcmp(request_info->request_method, "OPTIONS"))
33   {
34     mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n");
35     mg_printf(conn, "%s", "Access-Control-Allow-Origin: *\r\n");
36     mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");
37     return (void*)1;
38   }
39 */
40
41   // Get POST data
42   char postData[10000];
43   postData[0] = '\0';
44   if (!strcmp(request_info->request_method, "POST"))
45   {
46     const char* contentLength = mg_get_header(conn, "Content-Length");
47     int contentLengthI = atoi(contentLength);
48     log->log("JSONServer", Log::DEBUG, "POST data content length: %i", contentLengthI);
49     if (contentLengthI > 10000)
50     {
51       log->log("JSONServer", Log::DEBUG, "Length > 10000, rejecting");
52       return 0;
53     }
54
55     if (contentLengthI > 0)
56     {
57       // FIXME - assume for now that all post data will be small enough to have arrived immediately
58       int bytesRead = mg_read(conn, postData, contentLengthI);
59       if (bytesRead != contentLengthI)
60       {
61         log->log("JSONServer", Log::DEBUG, "Could not read up to contentLength");
62         return 0;
63       }
64       postData[contentLengthI] = '\0';
65     }
66   }
67
68   Json::Value js;
69   bool success = false;
70
71   if      (!strcmp(wvrequest, "gettime")) success = jsonserver_gettime(js);
72   else if (!strcmp(wvrequest, "diskstats")) success = jsonserver_diskstats(js);
73   else if (!strcmp(wvrequest, "reclist")) success = jsonserver_reclist(js);
74   else if (!strcmp(wvrequest, "recinfo")) success = jsonserver_recinfo(js, postData);
75   else if (!strcmp(wvrequest, "recdel")) success = jsonserver_recdel(js, postData);
76   else if (!strcmp(wvrequest, "recmove")) success = jsonserver_recmove(js, postData);
77   else if (!strcmp(wvrequest, "recstop")) success = jsonserver_recstop(js, postData);
78   else if (!strcmp(wvrequest, "channellist")) success = jsonserver_channellist(js);
79   else if (!strcmp(wvrequest, "channelschedule")) success = jsonserver_channelschedule(js, postData);
80   else if (!strcmp(wvrequest, "getscheduleevent")) success = jsonserver_getscheduleevent(js, postData);
81   else if (!strcmp(wvrequest, "timerlist")) success = jsonserver_timerlist(js);
82   else if (!strcmp(wvrequest, "timerdel")) success = jsonserver_timerdel(js, postData);
83   else if (!strcmp(wvrequest, "timerset")) success = jsonserver_timerset(js, postData);
84   else if (!strcmp(wvrequest, "timersetactive")) success = jsonserver_timersetactive(js, postData);
85   
86   if (!success) return 0; // the specific handler failed badly
87
88   // Now js will be filled
89
90   Json::StyledWriter sw;
91   std::string jsonout = sw.write(js);
92   mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n");
93   mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");
94   mg_write(conn, jsonout.c_str(), jsonout.length());
95   return 1;
96
97   
98 /*
99   else if (event == MG_EVENT_LOG)
100   {
101     if (request_info->status_code == 400) // bad request
102     {
103       log->log("Mongoose", Log::DEBUG, "400 BAD REQUEST:");
104       log->log("Mongoose", Log::DEBUG, request_info->request_method);
105       log->log("Mongoose", Log::DEBUG, request_info->uri);
106       log->log("Mongoose", Log::DEBUG, request_info->http_version);
107       log->log("Mongoose", Log::DEBUG, request_info->query_string);
108       log->log("Mongoose", Log::DEBUG, request_info->log_message);
109       for (int i = 0; i < request_info->num_headers; i++)
110       {
111         log->log("Mongoose", Log::DEBUG, "%s: %s", request_info->http_headers[i].name, request_info->http_headers[i].value);
112       }
113     }
114     else
115     {
116       log->log("Mongoose", Log::DEBUG, request_info->log_message);
117       log->log("Mongoose", Log::DEBUG, request_info->uri);
118     }
119     return (void*)1;
120   }
121   
122   // other events not handled:
123   // MG_HTTP_ERROR, MG_INIT_SSL
124   // Let mongoose do something with those
125
126   return NULL;
127
128 */
129   
130 }
131
132 bool jsonserver_gettime(Json::Value& js)
133 {
134   Log* log = Log::getInstance();
135   log->log("JSONServer", Log::DEBUG, "gettime");
136
137   struct timeval tv;
138   gettimeofday(&tv, NULL);
139   
140   js["Time"] = (Json::UInt64)tv.tv_sec;
141   js["MTime"] = (Json::UInt)(tv.tv_usec/1000);
142   js["Result"] = true;
143   return true;
144 }
145
146 bool jsonserver_diskstats(Json::Value& js)
147 {
148   Log* log = Log::getInstance();
149   log->log("JSONServer", Log::DEBUG, "diskstats");
150   
151   int FreeMB;
152   int UsedMB;
153   int Percent = VideoDiskSpace(&FreeMB, &UsedMB);
154   
155   js["FreeMiB"] = FreeMB;
156   js["UsedMiB"] = UsedMB;
157   js["Percent"] = Percent;
158   
159   js["Result"] = true;
160   return true;
161 }
162
163 bool jsonserver_reclist(Json::Value& js)
164 {
165   Log* log = Log::getInstance();
166   log->log("JSONServer", Log::DEBUG, "reclist");
167
168   Json::Value jsrecordings;
169   cRecordings Recordings;
170   Recordings.Load();
171   for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
172   {
173     Json::Value oneRec;
174     oneRec["StartTime"] = (Json::UInt)recording->Start();
175     oneRec["Length"] = (Json::UInt)recording->LengthInSeconds();
176     oneRec["IsNew"] = recording->IsNew();
177     oneRec["Name"] = recording->Name();
178     oneRec["Filename"] = recording->FileName();
179     oneRec["FileSizeMB"] = recording->FileSizeMB();
180     jsrecordings.append(oneRec);
181   }
182   js["Recordings"] = jsrecordings;
183   
184   return true;
185 }
186
187 bool jsonserver_recinfo(Json::Value& js, const char* postData)
188 {
189   Log* log = Log::getInstance();
190   log->log("JSONServer", Log::DEBUG, "recinfo");
191
192   char reqfilename[1000];
193   int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
194   if (mgv1 == -1)
195   {
196     log->log("JSONServer", Log::ERR, "Could not decode filename");
197     js["Result"] = false;
198     js["Error"] = "Could not decode filename";
199     return true;
200   }
201
202   log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
203   
204   cRecordings Recordings;
205   Recordings.Load(); // probably have to do this
206   cRecording *recording = Recordings.GetByName(reqfilename);
207
208   if (!recording)
209   {
210     log->log("JSONServer", Log::ERR, "recinfo found no recording");
211     js["Result"] = false;
212     return true;
213   }
214
215   js["IsNew"] = recording->IsNew();
216   js["LengthInSeconds"] = recording->LengthInSeconds();
217   js["FileSizeMB"] = recording->FileSizeMB();
218   js["Name"] = recording->Name() ? recording->Name() : Json::Value::null;
219   js["Priority"] = recording->Priority();
220   js["LifeTime"] = recording->Lifetime();
221   js["Start"] = (Json::UInt)recording->Start();
222
223   js["ResumePoint"] = 0;
224   cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
225   if (ResumeFile.Read() >= 0) js["ResumePoint"] = ResumeFile.Read();
226
227   js["CurrentlyRecordingStart"] = 0;
228   js["CurrentlyRecordingStop"] = 0;
229   cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
230   if (rc)
231   {
232     js["CurrentlyRecordingStart"] = (Json::UInt)rc->Timer()->StartTime();
233     js["CurrentlyRecordingStop"] = (Json::UInt)rc->Timer()->StopTime();
234   }
235
236   const cRecordingInfo *info = recording->Info();
237   if (info)
238   {
239     js["ChannelName"] = info->ChannelName() ? info->ChannelName() : Json::Value::null;
240     js["Title"] = info->Title() ? info->Title() : Json::Value::null;
241     js["ShortText"] = info->ShortText() ? info->ShortText() : Json::Value::null;
242     js["Description"] = info->Description() ? info->Description() : Json::Value::null;
243
244     const cComponents* components = info->Components();
245     if (!components)
246     {
247       js["Components"] = Json::Value::null;
248     }
249     else
250     {
251       Json::Value jscomponents;
252
253       tComponent* component;
254       for (int i = 0; i < components->NumComponents(); i++)
255       {
256         component = components->Component(i);
257
258         Json::Value oneComponent;
259         oneComponent["Stream"] = component->stream;
260         oneComponent["Type"] = component->type;
261         oneComponent["Language"] = component->language ? component->language : Json::Value::null;
262         oneComponent["Description"] = component->description ? component->description : Json::Value::null;
263         jscomponents.append(oneComponent);
264       }
265
266       js["Components"] = jscomponents;
267     }
268   }
269
270   js["Result"] = true;
271   return true;
272 }
273
274 bool jsonserver_recstop(Json::Value& js, const char* postData)
275 {
276   Log* log = Log::getInstance();
277   log->log("JSONServer", Log::DEBUG, "recstop");
278   
279   char reqfilename[1000];
280   int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
281   if (mgv1 == -1)
282   {
283     log->log("JSONServer", Log::ERR, "Could not decode filename");
284     js["Result"] = false;
285     js["Error"] = "Could not decode filename";
286     return true;
287   }
288   
289   log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
290   
291   cRecordings Recordings;
292   Recordings.Load(); // probably have to do this
293   cRecording *recording = Recordings.GetByName(reqfilename);
294   
295   if (!recording)
296   {
297     log->log("JSONServer", Log::ERR, "recstop found no recording");
298     js["Result"] = false;
299     return true;
300   }
301
302   cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
303   if (!rc)
304   {
305     log->log("JSONServer", Log::ERR, "recstop - not currently recording");
306     js["Result"] = false;
307     return true;
308   }
309
310   if (Timers.BeingEdited())
311   {
312     log->log("JSONServer", Log::ERR, "recstop - timers being edited elsewhere");
313     js["Result"] = false;
314     return true;
315   }
316
317   cTimer* timer = rc->Timer();
318   if (!timer)
319   {
320     log->log("JSONServer", Log::ERR, "recstop - timer not found");
321     js["Result"] = false;
322     return true;
323   }
324   
325   timer->ClrFlags(tfActive);
326   Timers.SetModified();
327   
328   js["Result"] = true;
329   return true;
330 }  
331   
332 bool jsonserver_recdel(Json::Value& js, const char* postData)
333 {
334   Log* log = Log::getInstance();
335   log->log("JSONServer", Log::DEBUG, "recdel");
336
337   char reqfilename[1000];
338   int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
339   if (mgv1 == -1)
340   {
341     log->log("JSONServer", Log::ERR, "Could not decode filename");
342     js["Result"] = false;
343     js["Error"] = "Could not decode filename";
344     return true;
345   }
346
347   log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
348   
349   cRecordings Recordings;
350   Recordings.Load(); // probably have to do this
351   cRecording *recording = Recordings.GetByName(reqfilename);
352
353   if (!recording)
354   {
355     js["Result"] = false;
356     js["Error"] = "Could not find recording to delete";
357     return true;
358   }
359
360   log->log("JSONServer", Log::DEBUG, "Deleting recording: %s", recording->Name());
361   cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
362   if (rc)
363   {
364     js["Result"] = false;
365     js["Error"] = "This recording is still recording.. ho ho";
366     return true;
367   }
368
369   if (recording->Delete())
370   {
371     ::Recordings.DelByName(recording->FileName());
372     js["Result"] = true;
373   }
374   else
375   {
376     js["Result"] = false;
377     js["Error"] = "Failed to delete recording";
378   }
379
380   return true;
381 }
382
383 bool jsonserver_recmove(Json::Value& js, const char* postData)
384 {
385   Log* log = Log::getInstance();
386   log->log("JSONServer", Log::DEBUG, "recmove");
387
388   char* fileNameToMove = NULL;
389   char* requestedNewPath = NULL;
390   char* dateDirName = NULL;
391   char* titleDirName = NULL;
392   char* folderName = NULL;
393   char* newContainer = NULL;
394   char* newDir = NULL;
395   
396   try
397   {
398     int postDataLen = strlen(postData)+1;
399     fileNameToMove = new char[postDataLen];
400     int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToMove, postDataLen);
401     requestedNewPath = new char[postDataLen];
402     int mgv2 = mg_get_var(postData, postDataLen-1, "newpath", requestedNewPath, postDataLen);
403
404     if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToMove) || !strlen(requestedNewPath))
405     {
406       log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
407       throw 1;
408     }
409
410     cRecordings Recordings;
411     Recordings.Load(); // probably have to do this
412     cRecording* recordingObj = Recordings.GetByName(fileNameToMove);
413     if (!recordingObj) throw 2;
414     
415     cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
416     if (rc) throw 3;
417
418     log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->Name());
419     log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->FileName());
420     log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewPath);
421
422     const char* t = recordingObj->FileName();
423
424     int k, j, m;
425
426     // Find the datedirname
427     for(k = strlen(t) - 1; k >= 0; k--)
428     {
429       if (t[k] == '/')
430       {
431         log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
432         dateDirName = new char[strlen(&t[k+1]) + 1];
433         strcpy(dateDirName, &t[k+1]);
434         break;
435       }
436     }
437
438     // Find the titledirname
439
440     for(j = k-1; j >= 0; j--)
441     {
442       if (t[j] == '/')
443       {
444         log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
445         titleDirName = new char[k - j];
446         memcpy(titleDirName, &t[j+1], k - j - 1);
447         titleDirName[k - j - 1] = '\0';
448         break;
449       }
450     }
451
452     // Find the foldername
453
454     log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
455     if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
456     {
457       for(m = j-1; m >= 0; m--)
458       {
459         if (t[m] == '/')
460         {
461           log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
462           folderName = new char[j - m];
463           memcpy(folderName, &t[m+1], j - m - 1);
464           folderName[j - m - 1] = '\0';
465           break;
466         }
467       }
468     }
469
470     ExchangeChars(requestedNewPath, true);
471
472     log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
473     log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
474     log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
475     if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
476     log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewPath);
477
478     // Could be a new path - construct that first and test
479     newContainer = new char[strlen(VideoDirectory) + strlen(requestedNewPath) + strlen(titleDirName) + 1];
480     sprintf(newContainer, "%s%s", VideoDirectory, requestedNewPath);
481     log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
482     struct stat dstat;
483     int statret = stat(newContainer, &dstat);
484     if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
485     {
486       log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
487       int mkdirret = mkdir(newContainer, 0755);
488       if (mkdirret != 0) throw 4;
489     }
490     else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
491     {
492       // Something exists but it's not a dir
493       throw 5;
494     }
495
496     // New path now created or was there already
497
498     sprintf(newContainer, "%s%s%s", VideoDirectory, requestedNewPath, titleDirName);
499     log->log("JSONServer", Log::DEBUG, "%s", newContainer);
500
501     statret = stat(newContainer, &dstat);
502     if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
503     {
504       log->log("JSONServer", Log::DEBUG, "new dir does not exist (2)");
505       int mkdirret = mkdir(newContainer, 0755);
506       if (mkdirret != 0) throw 6;
507     }
508     else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
509     {
510       // Something exists but it's not a dir
511       throw 7;
512     }
513
514     // Ok, the directory container has been made, or it pre-existed.
515
516     newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
517     sprintf(newDir, "%s/%s", newContainer, dateDirName);
518
519     log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
520     if (rename(t, newDir) != 0) throw 8;
521     
522     // Success. Test for remove old dir containter
523     char* tempOldTitleDir = new char[k+1];
524     memcpy(tempOldTitleDir, t, k);
525     tempOldTitleDir[k] = '\0';
526     log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
527     rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
528     delete[] tempOldTitleDir;
529
530     // Test for remove old foldername
531     if (folderName)
532     {
533       char* tempOldFolderName = new char[j+1];
534       memcpy(tempOldFolderName, t, j);
535       tempOldFolderName[j] = '\0';
536       log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldfoldername: %s", j+1, j, strlen(tempOldFolderName), tempOldFolderName);
537       /*
538       DESCRIPTION
539       rmdir() deletes a directory, which must be empty.
540       ENOTEMPTY - pathname  contains  entries  other than . and ..
541       So, should be safe to call rmdir on non-empty dir
542       */
543       rmdir(tempOldFolderName); // can't do anything about a fail result at this point.
544       delete[] tempOldFolderName;
545     }
546
547     ::Recordings.Update();
548     js["Result"] = true;
549     js["NewRecordingFileName"] = newDir;
550   }
551   catch (int e)
552   {
553     js["Result"] = false;
554     if (e == 1)
555     {
556       log->log("JSONServer", Log::ERR, "Bad parameters");
557       js["Error"] = "Bad request parameters";
558     }
559     else if (e == 2)
560     {
561       log->log("JSONServer", Log::ERR, "Could not find recording to move");
562       js["Error"] = "Bad filename";
563     }
564     else if (e == 3)
565     {
566       log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
567       js["Error"] = "Cannot move recording in progress";
568     }
569     else if (e == 4)
570     {
571       log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
572       js["Error"] = "Failed to create new directory (1)";
573     }
574     else if (e == 5)
575     {
576       log->log("JSONServer", Log::ERR, "Something already exists? (1)");
577       js["Error"] = "Something already exists at the new path (1)";
578     }
579     else if (e == 6)
580     {
581       log->log("JSONServer", Log::ERR, "Failed to make new dir (2)");
582       js["Error"] = "Failed to create new directory (2)";
583     }
584     else if (e == 7)
585     {
586       log->log("JSONServer", Log::ERR, "Something already exists?");
587       js["Error"] = "Something already exists at the new path";
588     }
589     else if (e == 8)
590     {
591       log->log("JSONServer", Log::ERR, "Rename failed");
592       js["Error"] = "Move failed";
593     }
594   }
595
596   if (fileNameToMove)   delete[] fileNameToMove;
597   if (requestedNewPath) delete[] requestedNewPath;
598   if (dateDirName)      delete[] dateDirName;
599   if (titleDirName)     delete[] titleDirName;
600   if (folderName)       delete[] folderName;
601   if (newContainer)     delete[] newContainer;
602   if (newDir)           delete[] newDir;
603
604   return true;
605 }
606
607 bool jsonserver_channellist(Json::Value& js)
608 {
609   Log* log = Log::getInstance();
610   log->log("JSONServer", Log::DEBUG, "channellist");
611
612   Json::Value jschannels;
613   
614 //  int type;
615   for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
616   {
617     if (!channel->GroupSep())
618     {
619 //      log->log("JSONServer", Log::DEBUG, "name: '%s'", channel->Name());
620
621 //      if (channel->Vpid()) type = 1;
622 //      else if (channel->Apid(0)) type = 2;
623 //      else continue;
624
625       Json::Value oneChannel;
626       oneChannel["Number"] = channel->Number();
627 //      oneChannel["Type"] = type;
628       oneChannel["Name"] = channel->Name();
629 //#if VDRVERSNUM < 10703
630 //      oneChannel["VType"] = 2;
631 //#else
632 //      oneChannel["VType"] = channel->Vtype();
633 //#endif
634       jschannels.append(oneChannel);    
635     }
636   }
637   js["Channels"] = jschannels;
638   
639   return true;
640 }
641
642 bool jsonserver_channelschedule(Json::Value& js, const char* postData)
643 {
644   Log* log = Log::getInstance();
645   log->log("JSONServer", Log::DEBUG, "channelschedule '%s'", postData);
646
647   char sChannelNumber[15];  int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);  
648   char sStartTime[15];      int mgv2 = mg_get_var(postData, strlen(postData), "starttime", sStartTime, 15);  
649   char sDuration[15];       int mgv3 = mg_get_var(postData, strlen(postData), "duration", sDuration, 15);  
650
651   if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) )
652   {
653     log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i", mgv1, mgv2, mgv3);
654     js["Result"] = false;
655     js["Error"] = "Bad request parameters";
656     return true;
657   }
658
659   int channelNumber = atoi(sChannelNumber);
660   int startTime = atoi(sStartTime); 
661   int duration = atoi(sDuration); 
662
663   cChannel* channel = NULL;
664   for (channel = Channels.First(); channel; channel = Channels.Next(channel))
665   {
666     if (channel->GroupSep()) continue;
667     if (channel->Number() == channelNumber) break;
668   }
669
670   if (!channel)
671   {
672     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
673     js["Result"] = false;
674     js["Error"] = "Could not find channel";
675     return true;
676   }
677
678   cSchedulesLock MutexLock;
679   const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
680   if (!Schedules)
681   {
682     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
683     js["Result"] = false;
684     js["Error"] = "Internal schedules error (1)";
685     return true;
686   }
687   const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
688   if (!Schedule)     
689   {
690     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
691     js["Result"] = false;
692     js["Error"] = "Internal schedules error (2)";
693     return true;
694   }
695     
696   Json::Value jsevents;
697
698   for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event))
699   {
700     //in the past filter
701     if ((event->StartTime() + event->Duration()) < time(NULL)) continue;
702    //start time filter
703     if ((event->StartTime() + event->Duration()) <= startTime) continue;
704     //duration filter
705     if (event->StartTime() >= (startTime + duration)) continue;
706
707     Json::Value oneEvent;
708     oneEvent["ID"] = event->EventID();
709     oneEvent["Time"] = (Json::UInt)event->StartTime();
710     oneEvent["Duration"] = event->Duration();
711     oneEvent["Title"] = event->Title() ? event->Title() : "";
712     oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
713     //oneEvent["Description"] = event->Description() ? event->Description() : "";
714     jsevents.append(oneEvent);
715   }
716
717   js["Result"] = true;
718   js["Events"] = jsevents;
719   return true;
720 }
721
722 bool jsonserver_getscheduleevent(Json::Value& js, const char* postData)
723 {
724   Log* log = Log::getInstance();
725   log->log("JSONServer", Log::DEBUG, "getscheduleevent '%s'", postData);
726   
727   char sChannelNumber[15];  int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
728   char sEventID[15];        int mgv2 = mg_get_var(postData, strlen(postData), "eventid", sEventID, 15);
729   
730   if ( (mgv1 == -1) || (mgv2 == -1) )
731   {
732     log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
733     js["Result"] = false;
734     js["Error"] = "Bad request parameters";
735     return true;
736   }
737
738   int channelNumber = atoi(sChannelNumber);
739   int eventID = atoi(sEventID);
740   
741   const cEvent* event = jsonserver_getEvent(js, channelNumber, eventID, 0);
742   if (!event)
743   {
744     js["Result"] = false;
745     return true;
746   }
747   
748   Json::Value oneEvent;
749   oneEvent["ID"] = event->EventID();
750   oneEvent["Time"] = (Json::UInt)event->StartTime();
751   oneEvent["Duration"] = event->Duration();
752   oneEvent["Title"] = event->Title() ? event->Title() : "";
753   oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
754   oneEvent["Description"] = event->Description() ? event->Description() : "";
755   oneEvent["HasTimer"] = event->HasTimer();
756   oneEvent["RunningStatus"] = event->RunningStatus();
757
758   js["Result"] = true;
759   js["Event"] = oneEvent;
760   return true;
761 }
762
763 const cEvent* jsonserver_getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime)
764 {
765   Log* log = Log::getInstance();
766   
767   cChannel* channel = NULL;
768   for (channel = Channels.First(); channel; channel = Channels.Next(channel))
769   {
770     if (channel->GroupSep()) continue;
771     if (channel->Number() == channelNumber) break;
772   }
773
774   if (!channel)
775   {
776     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
777     js["Error"] = "Could not find channel";
778     return NULL;
779   }
780
781   cSchedulesLock MutexLock;
782   const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
783   if (!Schedules)
784   {
785     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
786     js["Error"] = "Internal schedules error (1)";
787     return NULL;
788   }
789   
790   const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
791   if (!Schedule)
792   {
793     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
794     js["Error"] = "Internal schedules error (2)";
795     return NULL;
796   }
797   
798   const cEvent* event = NULL;
799   if (eventID)
800   {
801     event = Schedule->GetEvent(eventID);
802   }
803   else
804   {
805     event = Schedule->GetEventAround(aroundTime);
806   }
807   
808   if (!event)
809   {
810     log->log("JSONServer", Log::ERR, "Could not find requested event: %i", eventID);
811     js["Error"] = "Internal schedules error (3)";
812     return NULL;
813   }
814
815   return event;
816 }
817
818 bool jsonserver_timerlist(Json::Value& js)
819 {
820   Log* log = Log::getInstance();
821   log->log("JSONServer", Log::DEBUG, "timerlist");
822
823   Json::Value jstimers;
824   
825   cTimer *timer;
826   int numTimers = Timers.Count();
827
828   for (int i = 0; i < numTimers; i++)
829   {
830     timer = Timers.Get(i);
831     Json::Value oneTimer;
832     oneTimer["Active"] = timer->HasFlags(tfActive);
833     oneTimer["Recording"] = timer->Recording();
834     oneTimer["Pending"] = timer->Pending();
835     oneTimer["Priority"] = timer->Priority();
836     oneTimer["Lifetime"] = timer->Lifetime();
837     oneTimer["ChannelNumber"] = timer->Channel()->Number();
838     oneTimer["ChannelID"] = (const char *)timer->Channel()->GetChannelID().ToString();
839     oneTimer["StartTime"] = (int)timer->StartTime();
840     oneTimer["StopTime"] = (int)timer->StopTime();
841     oneTimer["Day"] = (int)timer->Day();
842     oneTimer["WeekDays"] = timer->WeekDays();
843     oneTimer["Name"] = timer->File();
844
845     const cEvent* event = timer->Event();
846     if (event)
847     {
848       oneTimer["EventID"] = event->EventID();
849     }
850     else
851     {
852       int channelNumber = timer->Channel()->Number();
853       int aroundTime = timer->StartTime() + 1;
854       log->log("JSONServer", Log::DEBUG, "%i", aroundTime);
855       //((timer->StopTime() - timer->StartTime()) / 2);
856
857       const cEvent* eventAround = jsonserver_getEvent(js, channelNumber, 0, aroundTime);
858       if (eventAround)
859       {
860         oneTimer["EventID"] = eventAround->EventID();
861       }
862       else
863       {
864         oneTimer["EventID"] = 0;
865       }
866     }
867
868     jstimers.append(oneTimer);
869   }
870   
871   js["Timers"] = jstimers;
872   js["Result"] = true;
873   return true;
874 }
875
876 bool jsonserver_timerdel(Json::Value& js, const char* postData)
877 {
878   Log* log = Log::getInstance();
879   log->log("JSONServer", Log::DEBUG, "timerdel");
880
881   char sdelChannel[15];   int mgv1 = mg_get_var(postData, strlen(postData), "delchannel", sdelChannel, 15);  
882   char sdelWeekdays[15];  int mgv2 = mg_get_var(postData, strlen(postData), "delweekdays", sdelWeekdays, 15);  
883   char sdelDay[15];       int mgv3 = mg_get_var(postData, strlen(postData), "delday", sdelDay, 15);  
884   char sdelStart[15];     int mgv4 = mg_get_var(postData, strlen(postData), "delstart", sdelStart, 15);  
885   char sdelStop[15];      int mgv5 = mg_get_var(postData, strlen(postData), "delstop", sdelStop, 15);  
886
887   if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1) )
888   {
889     log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
890     js["Result"] = false;
891     js["Error"] = "Bad request parameters";
892     return true;
893   }
894
895   int delChannel = atoi(sdelChannel); 
896   int delWeekdays = atoi(sdelWeekdays); 
897   int delDay = atoi(sdelDay); 
898   int delStart = atoi(sdelStart); 
899   int delStop = atoi(sdelStop); 
900
901   cTimer* ti = NULL;
902   for (ti = Timers.First(); ti; ti = Timers.Next(ti))
903   {
904     if  ( (ti->Channel()->Number() == delChannel)
905      &&   ((ti->WeekDays() && (ti->WeekDays() == delWeekdays)) || (!ti->WeekDays() && (ti->Day() == delDay)))
906      &&   (ti->StartTime() == delStart)
907      &&   (ti->StopTime() == delStop) )
908        break;
909   }
910   
911   if (!ti)
912   {
913     log->log("JSONServer", Log::ERR, "Could not find timer");
914     js["Result"] = false;
915     js["Error"] = "Could not find timer";
916     return true;
917   }
918
919   if (Timers.BeingEdited())
920   {
921     log->log("JSONServer", Log::ERR, "Unable to delete timer - timers being edited at VDR");
922     js["Result"] = false;
923     js["Error"] = "Timers being edited at VDR";
924     return true; 
925   }
926   
927   if (ti->Recording())
928   {
929     log->log("JSONServer", Log::ERR, "Unable to delete timer - timer is running");
930     js["Result"] = false;
931     js["Error"] = "Timer is running";
932     return true;
933   }
934   
935   Timers.Del(ti);
936   Timers.SetModified();
937   js["Result"] = true;
938     
939   return true;
940 }
941
942 bool jsonserver_timerset(Json::Value& js, const char* postData)
943 {
944   Log* log = Log::getInstance();
945   log->log("JSONServer", Log::DEBUG, "timerset");
946
947   char sTimerString[1024];   int mgv1 = mg_get_var(postData, strlen(postData), "timerstring", sTimerString, 1024);  
948
949   if (mgv1 == -1)
950   {
951     log->log("JSONServer", Log::ERR, "Could not get timerstring");
952     js["Result"] = false;
953     js["Error"] = "Bad request parameters";
954     return true;
955   }
956
957   log->log("JSONServer", Log::DEBUG, "'%s'", sTimerString);
958   cTimer *timer = new cTimer;
959   if (!timer->Parse(sTimerString))
960   {
961     delete timer;
962     js["Result"] = false;
963     js["Error"] = "Failed to parse timer request details";
964     return true;
965   }
966
967   cTimer *t = Timers.GetTimer(timer);
968   if (t)
969   {
970     delete timer;
971     js["Result"] = false;
972     js["Error"] = "Timer already exists";
973     return true;
974   }
975
976   Timers.Add(timer);
977   Timers.SetModified();
978   js["Result"] = true;
979   return true;
980 }
981
982 bool jsonserver_timersetactive(Json::Value& js, const char* postData)
983 {
984   Log* log = Log::getInstance();
985   log->log("JSONServer", Log::DEBUG, "timersetactive");
986
987   char tChannelID[30];  int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", tChannelID, 30);
988   char tStartTime[15];  int mgv2 = mg_get_var(postData, strlen(postData), "StartTime", tStartTime, 15);
989   char tStopTime[15];   int mgv3 = mg_get_var(postData, strlen(postData), "StopTime", tStopTime, 15);
990   char tNewActive[15];  int mgv4 = mg_get_var(postData, strlen(postData), "SetActive", tNewActive, 15);
991
992   if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) )
993   {
994     log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i", mgv1, mgv2, mgv3, mgv4);
995     js["Result"] = false;
996     js["Error"] = "Bad request parameters";
997     return true;
998   }
999
1000   log->log("JSONServer", Log::DEBUG, "timersetactive: %s %s %s %s", tChannelID, tStartTime, tStopTime, tNewActive);
1001
1002   int StartTime = atoi(tStartTime);
1003   int StopTime = atoi(tStopTime);
1004
1005   cTimer *timer;
1006   int numTimers = Timers.Count();
1007   for (int i = 0; i < numTimers; i++)
1008   {
1009     timer = Timers.Get(i);
1010     if (   (strcmp(timer->Channel()->GetChannelID().ToString(), tChannelID) == 0)
1011         && (timer->StartTime() == StartTime)
1012         && (timer->StopTime() == StopTime)
1013        )
1014     {
1015       // Found
1016
1017       if (strcmp(tNewActive, "true") == 0)
1018       {
1019         timer->SetFlags(tfActive);
1020       }
1021       else if (strcmp(tNewActive, "false") == 0)
1022       {
1023         timer->ClrFlags(tfActive);
1024       }
1025       else
1026       {
1027         js["Result"] = false;
1028         js["Error"] = "Bad request parameters";
1029         return true;
1030       }
1031       Timers.SetModified();
1032       
1033       js["Result"] = true;
1034       return true;
1035     }
1036   }
1037
1038   js["Result"] = false;
1039   js["Error"] = "Timer not found";
1040   return true;
1041 }