]> git.vomp.tv Git - jsonserver.git/blob - handler.c
New Makefile, min VDR now 1.7.35
[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, "recrename")) success = jsonserver_recrename(js, postData);
78   else if (!strcmp(wvrequest, "recstop")) success = jsonserver_recstop(js, postData);
79   else if (!strcmp(wvrequest, "channellist")) success = jsonserver_channellist(js);
80   else if (!strcmp(wvrequest, "channelschedule")) success = jsonserver_channelschedule(js, postData);
81   else if (!strcmp(wvrequest, "getscheduleevent")) success = jsonserver_getscheduleevent(js, postData);
82   else if (!strcmp(wvrequest, "timerlist")) success = jsonserver_timerlist(js);
83   else if (!strcmp(wvrequest, "timerdel")) success = jsonserver_timerdel(js, postData);
84   else if (!strcmp(wvrequest, "timerset")) success = jsonserver_timerset(js, postData);
85   else if (!strcmp(wvrequest, "timersetactive")) success = jsonserver_timersetactive(js, postData);
86   else if (!strcmp(wvrequest, "timerisrecording")) success = jsonserver_timerisrecording(js, postData);
87
88   
89   if (!success) return 0; // the specific handler failed badly
90
91   // Now js will be filled
92
93   Json::StyledWriter sw;
94   std::string jsonout = sw.write(js);
95   mg_printf(conn, "%s", "HTTP/1.0 200 OK\r\n");
96   mg_printf(conn, "%s", "Content-Type: text/plain\r\n\r\n");
97   mg_write(conn, jsonout.c_str(), jsonout.length());
98   return 1;
99
100   
101 /*
102   else if (event == MG_EVENT_LOG)
103   {
104     if (request_info->status_code == 400) // bad request
105     {
106       log->log("Mongoose", Log::DEBUG, "400 BAD REQUEST:");
107       log->log("Mongoose", Log::DEBUG, request_info->request_method);
108       log->log("Mongoose", Log::DEBUG, request_info->uri);
109       log->log("Mongoose", Log::DEBUG, request_info->http_version);
110       log->log("Mongoose", Log::DEBUG, request_info->query_string);
111       log->log("Mongoose", Log::DEBUG, request_info->log_message);
112       for (int i = 0; i < request_info->num_headers; i++)
113       {
114         log->log("Mongoose", Log::DEBUG, "%s: %s", request_info->http_headers[i].name, request_info->http_headers[i].value);
115       }
116     }
117     else
118     {
119       log->log("Mongoose", Log::DEBUG, request_info->log_message);
120       log->log("Mongoose", Log::DEBUG, request_info->uri);
121     }
122     return (void*)1;
123   }
124   
125   // other events not handled:
126   // MG_HTTP_ERROR, MG_INIT_SSL
127   // Let mongoose do something with those
128
129   return NULL;
130
131 */
132   
133 }
134
135 bool jsonserver_gettime(Json::Value& js)
136 {
137   Log* log = Log::getInstance();
138   log->log("JSONServer", Log::DEBUG, "gettime");
139
140   struct timeval tv;
141   gettimeofday(&tv, NULL);
142   
143   js["Time"] = (Json::UInt64)tv.tv_sec;
144   js["MTime"] = (Json::UInt)(tv.tv_usec/1000);
145   js["Result"] = true;
146   return true;
147 }
148
149 bool jsonserver_diskstats(Json::Value& js)
150 {
151   Log* log = Log::getInstance();
152   log->log("JSONServer", Log::DEBUG, "diskstats");
153   
154   int FreeMB;
155   int UsedMB;
156   int Percent = VideoDiskSpace(&FreeMB, &UsedMB);
157   
158   js["FreeMiB"] = FreeMB;
159   js["UsedMiB"] = UsedMB;
160   js["Percent"] = Percent;
161   
162   js["Result"] = true;
163   return true;
164 }
165
166 bool jsonserver_reclist(Json::Value& js)
167 {
168   Log* log = Log::getInstance();
169   log->log("JSONServer", Log::DEBUG, "reclist");
170
171   Json::Value jsrecordings;
172   cRecordings Recordings;
173   Recordings.Load();
174   for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
175   {
176     Json::Value oneRec;
177     oneRec["StartTime"] = (Json::UInt)recording->Start();
178     oneRec["Length"] = (Json::UInt)recording->LengthInSeconds();
179     oneRec["IsNew"] = recording->IsNew();
180     oneRec["Name"] = recording->Name();
181     oneRec["Filename"] = recording->FileName();
182     oneRec["FileSizeMB"] = recording->FileSizeMB();
183
184     cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
185     if (rc) oneRec["CurrentlyRecording"] = true;
186     else    oneRec["CurrentlyRecording"] = false;
187     
188     jsrecordings.append(oneRec);
189   }
190   js["Recordings"] = jsrecordings;
191   
192   return true;
193 }
194
195 bool jsonserver_recinfo(Json::Value& js, const char* postData)
196 {
197   Log* log = Log::getInstance();
198   log->log("JSONServer", Log::DEBUG, "recinfo");
199
200   char reqfilename[1000];
201   int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
202   if (mgv1 == -1)
203   {
204     log->log("JSONServer", Log::ERR, "Could not decode filename");
205     js["Result"] = false;
206     js["Error"] = "Could not decode filename";
207     return true;
208   }
209
210   log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
211   
212   cRecordings Recordings;
213   Recordings.Load(); // probably have to do this
214   cRecording *recording = Recordings.GetByName(reqfilename);
215
216   if (!recording)
217   {
218     log->log("JSONServer", Log::ERR, "recinfo found no recording");
219     js["Result"] = false;
220     return true;
221   }
222
223   js["IsNew"] = recording->IsNew();
224   js["LengthInSeconds"] = recording->LengthInSeconds();
225   js["FileSizeMB"] = recording->FileSizeMB();
226   js["Name"] = recording->Name() ? recording->Name() : Json::Value::null;
227   js["Priority"] = recording->Priority();
228   js["LifeTime"] = recording->Lifetime();
229   js["Start"] = (Json::UInt)recording->Start();
230
231   js["ResumePoint"] = 0;
232   cResumeFile ResumeFile(recording->FileName(), recording->IsPesRecording());
233   if (ResumeFile.Read() >= 0) js["ResumePoint"] = ResumeFile.Read();
234
235   js["CurrentlyRecordingStart"] = 0;
236   js["CurrentlyRecordingStop"] = 0;
237   cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
238   if (rc)
239   {
240     js["CurrentlyRecordingStart"] = (Json::UInt)rc->Timer()->StartTime();
241     js["CurrentlyRecordingStop"] = (Json::UInt)rc->Timer()->StopTime();
242   }
243
244   const cRecordingInfo *info = recording->Info();
245   if (info)
246   {
247     js["ChannelName"] = info->ChannelName() ? info->ChannelName() : Json::Value::null;
248     js["Title"] = info->Title() ? info->Title() : Json::Value::null;
249     js["ShortText"] = info->ShortText() ? info->ShortText() : Json::Value::null;
250     js["Description"] = info->Description() ? info->Description() : Json::Value::null;
251
252     const cComponents* components = info->Components();
253     if (!components)
254     {
255       js["Components"] = Json::Value::null;
256     }
257     else
258     {
259       Json::Value jscomponents;
260
261       tComponent* component;
262       for (int i = 0; i < components->NumComponents(); i++)
263       {
264         component = components->Component(i);
265
266         Json::Value oneComponent;
267         oneComponent["Stream"] = component->stream;
268         oneComponent["Type"] = component->type;
269         oneComponent["Language"] = component->language ? component->language : Json::Value::null;
270         oneComponent["Description"] = component->description ? component->description : Json::Value::null;
271         jscomponents.append(oneComponent);
272       }
273
274       js["Components"] = jscomponents;
275     }
276   }
277
278   js["Result"] = true;
279   return true;
280 }
281
282 bool jsonserver_recstop(Json::Value& js, const char* postData)
283 {
284   Log* log = Log::getInstance();
285   log->log("JSONServer", Log::DEBUG, "recstop");
286   
287   char reqfilename[1000];
288   int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
289   if (mgv1 == -1)
290   {
291     log->log("JSONServer", Log::ERR, "Could not decode filename");
292     js["Result"] = false;
293     js["Error"] = "Could not decode filename";
294     return true;
295   }
296   
297   log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
298   
299   cRecordings Recordings;
300   Recordings.Load(); // probably have to do this
301   cRecording *recording = Recordings.GetByName(reqfilename);
302   
303   if (!recording)
304   {
305     log->log("JSONServer", Log::ERR, "recstop found no recording");
306     js["Result"] = false;
307     return true;
308   }
309
310   cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
311   if (!rc)
312   {
313     log->log("JSONServer", Log::ERR, "recstop - not currently recording");
314     js["Result"] = false;
315     return true;
316   }
317
318   if (Timers.BeingEdited())
319   {
320     log->log("JSONServer", Log::ERR, "recstop - timers being edited elsewhere");
321     js["Result"] = false;
322     return true;
323   }
324
325   cTimer* timer = rc->Timer();
326   if (!timer)
327   {
328     log->log("JSONServer", Log::ERR, "recstop - timer not found");
329     js["Result"] = false;
330     return true;
331   }
332   
333   timer->ClrFlags(tfActive);
334   Timers.SetModified();
335   
336   js["Result"] = true;
337   return true;
338 }  
339   
340 bool jsonserver_recdel(Json::Value& js, const char* postData)
341 {
342   Log* log = Log::getInstance();
343   log->log("JSONServer", Log::DEBUG, "recdel");
344
345   char reqfilename[1000];
346   int mgv1 = mg_get_var(postData, strlen(postData), "filename", reqfilename, 1000);
347   if (mgv1 == -1)
348   {
349     log->log("JSONServer", Log::ERR, "Could not decode filename");
350     js["Result"] = false;
351     js["Error"] = "Could not decode filename";
352     return true;
353   }
354
355   log->log("JSONServer", Log::DEBUG, "%s", reqfilename);
356   
357   cRecordings Recordings;
358   Recordings.Load(); // probably have to do this
359   cRecording *recording = Recordings.GetByName(reqfilename);
360
361   if (!recording)
362   {
363     js["Result"] = false;
364     js["Error"] = "Could not find recording to delete";
365     return true;
366   }
367
368   log->log("JSONServer", Log::DEBUG, "Deleting recording: %s", recording->Name());
369   cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
370   if (rc)
371   {
372     js["Result"] = false;
373     js["Error"] = "This recording is still recording.. ho ho";
374     return true;
375   }
376
377   if (recording->Delete())
378   {
379     ::Recordings.DelByName(recording->FileName());
380     js["Result"] = true;
381   }
382   else
383   {
384     js["Result"] = false;
385     js["Error"] = "Failed to delete recording";
386   }
387
388   return true;
389 }
390
391 bool jsonserver_recmove(Json::Value& js, const char* postData)
392 {
393   Log* log = Log::getInstance();
394   log->log("JSONServer", Log::DEBUG, "recmove");
395
396   char* fileNameToMove = NULL;
397   char* requestedNewPath = NULL;
398   char* dateDirName = NULL;
399   char* titleDirName = NULL;
400   char* folderName = NULL;
401   char* newContainer = NULL;
402   char* newDir = NULL;
403   
404   try
405   {
406     int postDataLen = strlen(postData)+1;
407     fileNameToMove = new char[postDataLen];
408     int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToMove, postDataLen);
409     requestedNewPath = new char[postDataLen];
410     int mgv2 = mg_get_var(postData, postDataLen-1, "newpath", requestedNewPath, postDataLen);
411
412     if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToMove) || !strlen(requestedNewPath))
413     {
414       log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
415       throw 1;
416     }
417
418     cRecordings Recordings;
419     Recordings.Load(); // probably have to do this
420     cRecording* recordingObj = Recordings.GetByName(fileNameToMove);
421     if (!recordingObj) throw 2;
422     
423     cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
424     if (rc) throw 3;
425
426     log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->Name());
427     log->log("JSONServer", Log::DEBUG, "moving recording: %s", recordingObj->FileName());
428     log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewPath);
429
430     const char* t = recordingObj->FileName();
431
432     int k, j, m;
433
434     // Find the datedirname
435     for(k = strlen(t) - 1; k >= 0; k--)
436     {
437       if (t[k] == '/')
438       {
439         log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
440         dateDirName = new char[strlen(&t[k+1]) + 1];
441         strcpy(dateDirName, &t[k+1]);
442         break;
443       }
444     }
445
446     // Find the titledirname
447
448     for(j = k-1; j >= 0; j--)
449     {
450       if (t[j] == '/')
451       {
452         log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
453         titleDirName = new char[k - j];
454         memcpy(titleDirName, &t[j+1], k - j - 1);
455         titleDirName[k - j - 1] = '\0';
456         break;
457       }
458     }
459
460     // Find the foldername
461
462     log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
463     if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
464     {
465       for(m = j-1; m >= 0; m--)
466       {
467         if (t[m] == '/')
468         {
469           log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
470           folderName = new char[j - m];
471           memcpy(folderName, &t[m+1], j - m - 1);
472           folderName[j - m - 1] = '\0';
473           break;
474         }
475       }
476     }
477
478     ExchangeChars(requestedNewPath, true);
479
480     log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
481     log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
482     log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
483     if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
484     log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewPath);
485
486     // Could be a new path - construct that first and test
487     newContainer = new char[strlen(VideoDirectory) + strlen(requestedNewPath) + strlen(titleDirName) + 1];
488     sprintf(newContainer, "%s%s", VideoDirectory, requestedNewPath);
489     log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
490     struct stat dstat;
491     int statret = stat(newContainer, &dstat);
492     if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
493     {
494       log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
495       int mkdirret = mkdir(newContainer, 0755);
496       if (mkdirret != 0) throw 4;
497     }
498     else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
499     {
500       // Something exists but it's not a dir
501       throw 5;
502     }
503
504     // New path now created or was there already
505
506     sprintf(newContainer, "%s%s%s", VideoDirectory, requestedNewPath, titleDirName);
507     log->log("JSONServer", Log::DEBUG, "%s", newContainer);
508
509     statret = stat(newContainer, &dstat);
510     if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
511     {
512       log->log("JSONServer", Log::DEBUG, "new dir does not exist (2)");
513       int mkdirret = mkdir(newContainer, 0755);
514       if (mkdirret != 0) throw 6;
515     }
516     else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
517     {
518       // Something exists but it's not a dir
519       throw 7;
520     }
521
522     // Ok, the directory container has been made, or it pre-existed.
523
524     newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
525     sprintf(newDir, "%s/%s", newContainer, dateDirName);
526
527     log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
528     if (rename(t, newDir) != 0) throw 8;
529     
530     // Success. Test for remove old dir containter
531     char* tempOldTitleDir = new char[k+1];
532     memcpy(tempOldTitleDir, t, k);
533     tempOldTitleDir[k] = '\0';
534     log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
535     rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
536     delete[] tempOldTitleDir;
537
538     // Test for remove old foldername
539     if (folderName)
540     {
541       char* tempOldFolderName = new char[j+1];
542       memcpy(tempOldFolderName, t, j);
543       tempOldFolderName[j] = '\0';
544       log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldfoldername: %s", j+1, j, strlen(tempOldFolderName), tempOldFolderName);
545       /*
546       DESCRIPTION
547       rmdir() deletes a directory, which must be empty.
548       ENOTEMPTY - pathname  contains  entries  other than . and ..
549       So, should be safe to call rmdir on non-empty dir
550       */
551       rmdir(tempOldFolderName); // can't do anything about a fail result at this point.
552       delete[] tempOldFolderName;
553     }
554
555     ::Recordings.Update();
556     js["Result"] = true;
557     js["NewRecordingFileName"] = newDir;
558   }
559   catch (int e)
560   {
561     js["Result"] = false;
562     if (e == 1)
563     {
564       log->log("JSONServer", Log::ERR, "Bad parameters");
565       js["Error"] = "Bad request parameters";
566     }
567     else if (e == 2)
568     {
569       log->log("JSONServer", Log::ERR, "Could not find recording to move");
570       js["Error"] = "Bad filename";
571     }
572     else if (e == 3)
573     {
574       log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
575       js["Error"] = "Cannot move recording in progress";
576     }
577     else if (e == 4)
578     {
579       log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
580       js["Error"] = "Failed to create new directory (1)";
581     }
582     else if (e == 5)
583     {
584       log->log("JSONServer", Log::ERR, "Something already exists? (1)");
585       js["Error"] = "Something already exists at the new path (1)";
586     }
587     else if (e == 6)
588     {
589       log->log("JSONServer", Log::ERR, "Failed to make new dir (2)");
590       js["Error"] = "Failed to create new directory (2)";
591     }
592     else if (e == 7)
593     {
594       log->log("JSONServer", Log::ERR, "Something already exists?");
595       js["Error"] = "Something already exists at the new path";
596     }
597     else if (e == 8)
598     {
599       log->log("JSONServer", Log::ERR, "Rename failed");
600       js["Error"] = "Move failed";
601     }
602   }
603
604   if (fileNameToMove)   delete[] fileNameToMove;
605   if (requestedNewPath) delete[] requestedNewPath;
606   if (dateDirName)      delete[] dateDirName;
607   if (titleDirName)     delete[] titleDirName;
608   if (folderName)       delete[] folderName;
609   if (newContainer)     delete[] newContainer;
610   if (newDir)           delete[] newDir;
611
612   return true;
613 }
614
615 bool jsonserver_recrename(Json::Value& js, const char* postData)
616 {
617   Log* log = Log::getInstance();
618   log->log("JSONServer", Log::DEBUG, "recrename");
619   
620   char* fileNameToRename = NULL;
621   char* requestedNewName = NULL;
622   char* dateDirName = NULL;
623   char* titleDirName = NULL;
624   char* folderName = NULL;
625   char* newContainer = NULL;
626   char* newDir = NULL;
627   
628   try
629   {
630     int postDataLen = strlen(postData)+1;
631     fileNameToRename = new char[postDataLen];
632     int mgv1 = mg_get_var(postData, postDataLen-1, "filename", fileNameToRename, postDataLen);
633     requestedNewName = new char[postDataLen];
634     int mgv2 = mg_get_var(postData, postDataLen-1, "newname", requestedNewName, postDataLen);
635     
636     if ((mgv1 == -1) || (mgv2 == -1) || !strlen(fileNameToRename) || !strlen(requestedNewName))
637     {
638       log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
639       throw 1;
640     }
641     
642     cRecordings Recordings;
643     Recordings.Load(); // probably have to do this
644     cRecording* recordingObj = Recordings.GetByName(fileNameToRename);
645     if (!recordingObj) throw 2;
646     
647     cRecordControl *rc = cRecordControls::GetRecordControl(recordingObj->FileName());
648     if (rc) throw 3;
649     
650     log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->Name());
651     log->log("JSONServer", Log::DEBUG, "renaming recording: %s", recordingObj->FileName());
652     log->log("JSONServer", Log::DEBUG, "to: %s", requestedNewName);
653     
654     const char* t = recordingObj->FileName();
655     
656     int k, j, m;
657     
658     // Find the datedirname
659     for(k = strlen(t) - 1; k >= 0; k--)
660     {
661       if (t[k] == '/')
662       {
663         log->log("JSONServer", Log::DEBUG, "l1: %i", strlen(&t[k+1]) + 1);
664         dateDirName = new char[strlen(&t[k+1]) + 1];
665         strcpy(dateDirName, &t[k+1]);
666         break;
667       }
668     }
669     
670     // Find the titledirname
671     
672     for(j = k-1; j >= 0; j--)
673     {
674       if (t[j] == '/')
675       {
676         log->log("JSONServer", Log::DEBUG, "l2: %i", k - j);
677         titleDirName = new char[k - j];
678         memcpy(titleDirName, &t[j+1], k - j - 1);
679         titleDirName[k - j - 1] = '\0';
680         break;
681       }
682     }
683     
684     // Find the foldername
685     
686     log->log("JSONServer", Log::DEBUG, "j = %u, strlenvd = %u", j, strlen(VideoDirectory));
687     if (j > (int)strlen(VideoDirectory)) // Rec is in a subfolder now
688     {
689       for(m = j-1; m >= 0; m--)
690       {
691         if (t[m] == '/')
692         {
693           log->log("JSONServer", Log::DEBUG, "l3: %i", j - m);
694           folderName = new char[j - m];
695           memcpy(folderName, &t[m+1], j - m - 1);
696           folderName[j - m - 1] = '\0';
697           break;
698         }
699       }
700     }
701     
702     ExchangeChars(requestedNewName, true);
703     
704     log->log("JSONServer", Log::DEBUG, "datedirname: %s", dateDirName);
705     log->log("JSONServer", Log::DEBUG, "titledirname: %s", titleDirName);
706     log->log("JSONServer", Log::DEBUG, "viddir: %s", VideoDirectory);
707     if (folderName) log->log("JSONServer", Log::DEBUG, "folderName: %s", folderName);
708     log->log("JSONServer", Log::DEBUG, "EC: %s", requestedNewName);
709    
710     // Could be a new path - construct that first and test
711
712     if (folderName)
713     {
714       newContainer = new char[strlen(VideoDirectory) + 1 + strlen(folderName) + 1 + strlen(requestedNewName) + 1];
715       sprintf(newContainer, "%s/%s/%s", VideoDirectory, folderName, requestedNewName);
716     }
717     else
718     {
719       newContainer = new char[strlen(VideoDirectory) + 1 + strlen(requestedNewName) + 1];
720       sprintf(newContainer, "%s/%s", VideoDirectory, requestedNewName);
721     }
722     log->log("JSONServer", Log::DEBUG, "NPT: %s", newContainer);
723     struct stat dstat;
724     int statret = stat(newContainer, &dstat);
725     if ((statret == -1) && (errno == ENOENT)) // Dir does not exist
726     {
727       log->log("JSONServer", Log::DEBUG, "new path does not exist (1)");
728       int mkdirret = mkdir(newContainer, 0755);
729       if (mkdirret != 0) throw 4;
730     }
731     else if ((statret == 0) && (! (dstat.st_mode && S_IFDIR)))
732     {
733       // Something exists but it's not a dir
734       throw 5;
735     }
736     
737     // New path now created or was there already
738     
739     newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
740     sprintf(newDir, "%s/%s", newContainer, dateDirName);
741     
742     log->log("JSONServer", Log::DEBUG, "doing rename '%s' '%s'", t, newDir);
743     if (rename(t, newDir) != 0) throw 8;
744     
745     // Success. Test for remove old dir containter
746     char* tempOldTitleDir = new char[k+1];
747     memcpy(tempOldTitleDir, t, k);
748     tempOldTitleDir[k] = '\0';
749     log->log("JSONServer", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(tempOldTitleDir), tempOldTitleDir);
750     rmdir(tempOldTitleDir); // can't do anything about a fail result at this point.
751     delete[] tempOldTitleDir;
752     
753     ::Recordings.Update();
754     js["Result"] = true;
755     js["NewRecordingFileName"] = newDir;
756   }
757   catch (int e)
758   {
759     js["Result"] = false;
760     if (e == 1)
761     {
762       log->log("JSONServer", Log::ERR, "Bad parameters");
763       js["Error"] = "Bad request parameters";
764     }
765     else if (e == 2)
766     {
767       log->log("JSONServer", Log::ERR, "Could not find recording to move");
768       js["Error"] = "Bad filename";
769     }
770     else if (e == 3)
771     {
772       log->log("JSONServer", Log::ERR, "Could not move recording, it is still recording");
773       js["Error"] = "Cannot move recording in progress";
774     }
775     else if (e == 4)
776     {
777       log->log("JSONServer", Log::ERR, "Failed to make new dir (1)");
778       js["Error"] = "Failed to create new directory (1)";
779     }
780     else if (e == 5)
781     {
782       log->log("JSONServer", Log::ERR, "Something already exists? (1)");
783       js["Error"] = "Something already exists at the new path (1)";
784     }
785     else if (e == 8)
786     {
787       log->log("JSONServer", Log::ERR, "Rename failed");
788       js["Error"] = "Move failed";
789     }
790   }
791   
792   if (fileNameToRename) delete[] fileNameToRename;
793   if (requestedNewName) delete[] requestedNewName;
794   if (dateDirName)      delete[] dateDirName;
795   if (titleDirName)     delete[] titleDirName;
796   if (folderName)       delete[] folderName;
797   if (newContainer)     delete[] newContainer;
798   if (newDir)           delete[] newDir;
799   
800   return true;
801 }
802
803 bool jsonserver_channellist(Json::Value& js)
804 {
805   Log* log = Log::getInstance();
806   log->log("JSONServer", Log::DEBUG, "channellist");
807
808   Json::Value jschannels;
809   
810 //  int type;
811   for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
812   {
813     if (!channel->GroupSep())
814     {
815 //      log->log("JSONServer", Log::DEBUG, "name: '%s'", channel->Name());
816
817 //      if (channel->Vpid()) type = 1;
818 //      else if (channel->Apid(0)) type = 2;
819 //      else continue;
820
821       Json::Value oneChannel;
822       oneChannel["Number"] = channel->Number();
823 //      oneChannel["Type"] = type;
824       oneChannel["Name"] = channel->Name();
825 //#if VDRVERSNUM < 10703
826 //      oneChannel["VType"] = 2;
827 //#else
828 //      oneChannel["VType"] = channel->Vtype();
829 //#endif
830       jschannels.append(oneChannel);    
831     }
832   }
833   js["Channels"] = jschannels;
834   
835   return true;
836 }
837
838 bool jsonserver_channelschedule(Json::Value& js, const char* postData)
839 {
840   Log* log = Log::getInstance();
841   log->log("JSONServer", Log::DEBUG, "channelschedule '%s'", postData);
842
843   char sChannelNumber[15];  int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);  
844   char sStartTime[15];      int mgv2 = mg_get_var(postData, strlen(postData), "starttime", sStartTime, 15);  
845   char sDuration[15];       int mgv3 = mg_get_var(postData, strlen(postData), "duration", sDuration, 15);  
846
847   if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) )
848   {
849     log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i", mgv1, mgv2, mgv3);
850     js["Result"] = false;
851     js["Error"] = "Bad request parameters";
852     return true;
853   }
854
855   int channelNumber = atoi(sChannelNumber);
856   int startTime = atoi(sStartTime); 
857   int duration = atoi(sDuration); 
858
859   cChannel* channel = NULL;
860   for (channel = Channels.First(); channel; channel = Channels.Next(channel))
861   {
862     if (channel->GroupSep()) continue;
863     if (channel->Number() == channelNumber) break;
864   }
865
866   if (!channel)
867   {
868     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
869     js["Result"] = false;
870     js["Error"] = "Could not find channel";
871     return true;
872   }
873
874   cSchedulesLock MutexLock;
875   const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
876   if (!Schedules)
877   {
878     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
879     js["Result"] = false;
880     js["Error"] = "Internal schedules error (1)";
881     return true;
882   }
883   const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
884   if (!Schedule)     
885   {
886     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
887     js["Result"] = false;
888     js["Error"] = "Internal schedules error (2)";
889     return true;
890   }
891     
892   Json::Value jsevents;
893
894   for (const cEvent* event = Schedule->Events()->First(); event; event = Schedule->Events()->Next(event))
895   {
896     //in the past filter
897     if ((event->StartTime() + event->Duration()) < time(NULL)) continue;
898    //start time filter
899     if ((event->StartTime() + event->Duration()) <= startTime) continue;
900     //duration filter
901     if (event->StartTime() >= (startTime + duration)) continue;
902
903     Json::Value oneEvent;
904     oneEvent["ID"] = event->EventID();
905     oneEvent["Time"] = (Json::UInt)event->StartTime();
906     oneEvent["Duration"] = event->Duration();
907     oneEvent["Title"] = event->Title() ? event->Title() : "";
908     oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
909     //oneEvent["Description"] = event->Description() ? event->Description() : "";
910     jsevents.append(oneEvent);
911   }
912
913   js["Result"] = true;
914   js["Events"] = jsevents;
915   return true;
916 }
917
918 bool jsonserver_getscheduleevent(Json::Value& js, const char* postData)
919 {
920   Log* log = Log::getInstance();
921   log->log("JSONServer", Log::DEBUG, "getscheduleevent '%s'", postData);
922   
923   char sChannelNumber[15];  int mgv1 = mg_get_var(postData, strlen(postData), "channelnumber", sChannelNumber, 15);
924   char sEventID[15];        int mgv2 = mg_get_var(postData, strlen(postData), "eventid", sEventID, 15);
925   
926   if ( (mgv1 == -1) || (mgv2 == -1) )
927   {
928     log->log("JSONServer", Log::ERR, "request mgvs: %i %i", mgv1, mgv2);
929     js["Result"] = false;
930     js["Error"] = "Bad request parameters";
931     return true;
932   }
933
934   int channelNumber = atoi(sChannelNumber);
935   int eventID = atoi(sEventID);
936   
937   const cEvent* event = jsonserver_getEvent(js, channelNumber, eventID, 0);
938   if (!event)
939   {
940     js["Result"] = false;
941     return true;
942   }
943   
944   Json::Value oneEvent;
945   oneEvent["ID"] = event->EventID();
946   oneEvent["Time"] = (Json::UInt)event->StartTime();
947   oneEvent["Duration"] = event->Duration();
948   oneEvent["Title"] = event->Title() ? event->Title() : "";
949   oneEvent["ShortText"] = event->ShortText() ? event->ShortText() : "";
950   oneEvent["Description"] = event->Description() ? event->Description() : "";
951   oneEvent["HasTimer"] = event->HasTimer();
952   oneEvent["RunningStatus"] = event->RunningStatus();
953
954   js["Result"] = true;
955   js["Event"] = oneEvent;
956   return true;
957 }
958
959 const cEvent* jsonserver_getEvent(Json::Value& js, int channelNumber, int eventID, int aroundTime)
960 {
961   Log* log = Log::getInstance();
962   
963   cChannel* channel = NULL;
964   for (channel = Channels.First(); channel; channel = Channels.Next(channel))
965   {
966     if (channel->GroupSep()) continue;
967     if (channel->Number() == channelNumber) break;
968   }
969
970   if (!channel)
971   {
972     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
973     js["Error"] = "Could not find channel";
974     return NULL;
975   }
976
977   cSchedulesLock MutexLock;
978   const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
979   if (!Schedules)
980   {
981     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
982     js["Error"] = "Internal schedules error (1)";
983     return NULL;
984   }
985   
986   const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
987   if (!Schedule)
988   {
989     log->log("JSONServer", Log::ERR, "Could not find requested channel: %i", channelNumber);
990     js["Error"] = "Internal schedules error (2)";
991     return NULL;
992   }
993   
994   const cEvent* event = NULL;
995   if (eventID)
996   {
997     event = Schedule->GetEvent(eventID);
998   }
999   else
1000   {
1001     event = Schedule->GetEventAround(aroundTime);
1002   }
1003   
1004   if (!event)
1005   {
1006     log->log("JSONServer", Log::ERR, "Could not find requested event: %i", eventID);
1007     js["Error"] = "Internal schedules error (3)";
1008     return NULL;
1009   }
1010
1011   return event;
1012 }
1013
1014 bool jsonserver_timerlist(Json::Value& js)
1015 {
1016   Log* log = Log::getInstance();
1017   log->log("JSONServer", Log::DEBUG, "timerlist");
1018
1019   Json::Value jstimers;
1020   
1021   cTimer *timer;
1022   int numTimers = Timers.Count();
1023
1024   for (int i = 0; i < numTimers; i++)
1025   {
1026     timer = Timers.Get(i);
1027     Json::Value oneTimer;
1028     oneTimer["Active"] = timer->HasFlags(tfActive);
1029     oneTimer["Recording"] = timer->Recording();
1030     oneTimer["Pending"] = timer->Pending();
1031     oneTimer["Priority"] = timer->Priority();
1032     oneTimer["Lifetime"] = timer->Lifetime();
1033     oneTimer["ChannelNumber"] = timer->Channel()->Number();
1034     oneTimer["ChannelID"] = (const char *)timer->Channel()->GetChannelID().ToString();
1035     oneTimer["StartTime"] = (int)timer->StartTime();
1036     oneTimer["StopTime"] = (int)timer->StopTime();
1037     oneTimer["Day"] = (int)timer->Day();
1038     oneTimer["WeekDays"] = timer->WeekDays();
1039     oneTimer["Name"] = timer->File();
1040     
1041     const cEvent* event = timer->Event();
1042     if (event)
1043     {
1044       oneTimer["EventID"] = event->EventID();
1045     }
1046     else
1047     {
1048       int channelNumber = timer->Channel()->Number();
1049       int aroundTime = timer->StartTime() + 1;
1050       log->log("JSONServer", Log::DEBUG, "%i", aroundTime);
1051
1052       const cEvent* eventAround = jsonserver_getEvent(js, channelNumber, 0, aroundTime);
1053       if (eventAround)
1054       {
1055         oneTimer["EventID"] = eventAround->EventID();
1056       }
1057       else
1058       {
1059         oneTimer["EventID"] = 0;
1060       }
1061     }
1062
1063     jstimers.append(oneTimer);
1064   }
1065   
1066   js["Timers"] = jstimers;
1067   js["Result"] = true;
1068   return true;
1069 }
1070
1071 bool jsonserver_timerset(Json::Value& js, const char* postData)
1072 {
1073   Log* log = Log::getInstance();
1074   log->log("JSONServer", Log::DEBUG, "timerset");
1075
1076   char sTimerString[1024];   int mgv1 = mg_get_var(postData, strlen(postData), "timerstring", sTimerString, 1024);  
1077
1078   if (mgv1 == -1)
1079   {
1080     log->log("JSONServer", Log::ERR, "Could not get timerstring");
1081     js["Result"] = false;
1082     js["Error"] = "Bad request parameters";
1083     return true;
1084   }
1085
1086   log->log("JSONServer", Log::DEBUG, "'%s'", sTimerString);
1087   cTimer *timer = new cTimer;
1088   if (!timer->Parse(sTimerString))
1089   {
1090     delete timer;
1091     js["Result"] = false;
1092     js["Error"] = "Failed to parse timer request details";
1093     return true;
1094   }
1095
1096   cTimer *t = Timers.GetTimer(timer);
1097   if (t)
1098   {
1099     delete timer;
1100     js["Result"] = false;
1101     js["Error"] = "Timer already exists";
1102     return true;
1103   }
1104
1105   Timers.Add(timer);
1106   Timers.SetModified();
1107   js["Result"] = true;
1108   return true;
1109 }
1110
1111 bool jsonserver_timersetactive(Json::Value& js, const char* postData)
1112 {
1113   Log* log = Log::getInstance();
1114   log->log("JSONServer", Log::DEBUG, "timersetactive");
1115
1116   char rChannelID[50];  int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1117   char rName[1024];  int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1118   char rStartTime[20];  int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1119   char rStopTime[20];  int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1120   char rWeekDays[50];  int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1121   char tNewActive[20];  int mgv6 = mg_get_var(postData, strlen(postData), "SetActive", tNewActive, 20);
1122
1123   if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1) || (mgv6 == -1))
1124   {
1125     log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5, mgv6);
1126     js["Result"] = false;
1127     js["Error"] = "Bad request parameters";
1128     return true;
1129   }
1130
1131   log->log("JSONServer", Log::DEBUG, "timersetactive: %s %s:%s:%s:%s:%s", tNewActive, rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1132
1133   cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1134   if (timer)
1135   {
1136     if (strcmp(tNewActive, "true") == 0)
1137     {
1138       timer->SetFlags(tfActive);
1139     }
1140     else if (strcmp(tNewActive, "false") == 0)
1141     {
1142       timer->ClrFlags(tfActive);
1143     }
1144     else
1145     {
1146       js["Result"] = false;
1147       js["Error"] = "Bad request parameters";
1148       return true;
1149     }
1150
1151     js["Result"] = true;
1152
1153     Timers.SetModified();
1154
1155     return true;
1156   }
1157
1158   js["Result"] = false;
1159   js["Error"] = "Timer not found";
1160   return true;
1161 }
1162
1163 cTimer* jsonserver_findTimer(const char* rChannelID, const char* rName, const char* rStartTime, const char* rStopTime, const char* rWeekDays)
1164 {
1165   Log* log = Log::getInstance();
1166   
1167   int numTimers = Timers.Count();
1168   cTimer* timer;
1169   for (int i = 0; i < numTimers; i++)
1170   {
1171     timer = Timers.Get(i);
1172
1173     log->log("JSONServer", Log::DEBUG, "findtimer current: %s", (const char*)timer->ToText(true));
1174     log->log("JSONServer", Log::DEBUG, "findtimer: %s", (const char*)timer->Channel()->GetChannelID().ToString());
1175     log->log("JSONServer", Log::DEBUG, "findtimer: %s", rChannelID);
1176     log->log("JSONServer", Log::DEBUG, "findtimer: %s", timer->File());
1177     log->log("JSONServer", Log::DEBUG, "findtimer: %s", rName);
1178     log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StartTime());
1179     log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStartTime);
1180     log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->StopTime());
1181     log->log("JSONServer", Log::DEBUG, "findtimer: %s", rStopTime);
1182     log->log("JSONServer", Log::DEBUG, "findtimer: %i", timer->WeekDays());
1183     log->log("JSONServer", Log::DEBUG, "findtimer: %s", rWeekDays);
1184     
1185     if (
1186             (strcmp(timer->Channel()->GetChannelID().ToString(), rChannelID) == 0)
1187          && (strcmp(timer->File(), rName) == 0)
1188          && (timer->StartTime() == atoi(rStartTime))
1189          && (timer->StopTime() == atoi(rStopTime))
1190          && (timer->WeekDays() == atoi(rWeekDays))
1191        )
1192     {
1193       log->log("JSONServer", Log::DEBUG, "found");
1194       return timer;
1195     }
1196   }
1197   log->log("JSONServer", Log::DEBUG, "no timer found");
1198   return NULL;
1199 }
1200
1201 bool jsonserver_timerdel(Json::Value& js, const char* postData)
1202 {
1203   Log* log = Log::getInstance();
1204   log->log("JSONServer", Log::DEBUG, "timerdel");
1205   
1206   char rChannelID[50];  int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1207   char rName[1024];  int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1208   char rStartTime[20];  int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1209   char rStopTime[20];  int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1210   char rWeekDays[50];  int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1211   
1212   if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1213   {
1214     log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1215     js["Result"] = false;
1216     js["Error"] = "Bad request parameters";
1217     return true;
1218   }
1219   
1220   log->log("JSONServer", Log::DEBUG, "timerdel: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1221   
1222   if (Timers.BeingEdited())
1223   {
1224     log->log("JSONServer", Log::ERR, "Unable to delete timer - timers being edited at VDR");
1225     js["Result"] = false;
1226     js["Error"] = "Timers being edited at VDR";
1227     return true;
1228   }
1229
1230   cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1231   if (timer)
1232   {
1233     if (timer->Recording())
1234     {
1235       log->log("JSONServer", Log::ERR, "Unable to delete timer - timer is running");
1236       js["Result"] = false;
1237       js["Error"] = "Timer is running";
1238       return true;
1239     }
1240
1241     // delete
1242
1243     Timers.Del(timer);
1244     Timers.SetModified();
1245     js["Result"] = true;
1246     return true;
1247   }
1248   
1249   js["Result"] = false;
1250   js["Error"] = "Timer not found";
1251   return true;
1252 }
1253
1254 bool jsonserver_timerisrecording(Json::Value& js, const char* postData)
1255 {
1256   Log* log = Log::getInstance();
1257   log->log("JSONServer", Log::DEBUG, "timerisrecording");
1258
1259   char rChannelID[50];  int mgv1 = mg_get_var(postData, strlen(postData), "ChannelID", rChannelID, 50);
1260   char rName[1024];  int mgv2 = mg_get_var(postData, strlen(postData), "Name", rName, 1024);
1261   char rStartTime[20];  int mgv3 = mg_get_var(postData, strlen(postData), "StartTime", rStartTime, 20);
1262   char rStopTime[20];  int mgv4 = mg_get_var(postData, strlen(postData), "StopTime", rStopTime, 20);
1263   char rWeekDays[50];  int mgv5 = mg_get_var(postData, strlen(postData), "WeekDays", rWeekDays, 20);
1264
1265   if ( (mgv1 == -1) || (mgv2 == -1) || (mgv3 == -1) || (mgv4 == -1) || (mgv5 == -1))
1266   {
1267     log->log("JSONServer", Log::ERR, "request mgvs: %i %i %i %i %i", mgv1, mgv2, mgv3, mgv4, mgv5);
1268     js["Result"] = false;
1269     js["Error"] = "Bad request parameters";
1270     return true;
1271   }
1272   
1273   log->log("JSONServer", Log::DEBUG, "timerisrecording: %s:%s:%s:%s:%s", rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1274   
1275   cTimer* timer = jsonserver_findTimer(rChannelID, rName, rStartTime, rStopTime, rWeekDays);
1276   if (timer)
1277   {
1278     js["Recording"] = timer->Recording();
1279     js["Pending"] = timer->Pending();
1280     js["Result"] = true;
1281     return true;
1282   }
1283   
1284   js["Result"] = false;
1285   js["Error"] = "Timer not found";
1286   return true;
1287 }