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