source: trunk/module-webif.c@ 9131

Last change on this file since 9131 was 9131, checked in by theparasol, 9 years ago
  • commit 9093 reverted partly changes to preferlocalcards -> fixed!
  • Property svn:eol-style set to LF
File size: 207.2 KB
Line 
1#include "globals.h"
2
3#ifdef WEBIF
4//
5// OSCam HTTP server module
6//
7
8#include "module-anticasc.h"
9#include "module-cacheex.h"
10#include "module-cccam.h"
11#include "module-cccam-data.h"
12#include "module-dvbapi.h"
13#include "module-newcamd.h"
14#include "module-stat.h"
15#include "module-webif.h"
16#include "module-webif-lib.h"
17#include "module-webif-tpl.h"
18#include "oscam-conf-mk.h"
19#include "oscam-config.h"
20#include "oscam-files.h"
21#include "oscam-garbage.h"
22#include "oscam-cache.h"
23#include "oscam-client.h"
24#include "oscam-lock.h"
25#include "oscam-net.h"
26#include "oscam-reader.h"
27#include "oscam-string.h"
28#include "oscam-time.h"
29#include "oscam-work.h"
30
31extern struct s_cardreader cardreaders[CS_MAX_MOD];
32extern char cs_confdir[];
33extern uint32_t ecmcwcache_size;
34extern uint8_t cs_http_use_utf8;
35extern uint32_t cfg_sidtab_generation;
36extern int32_t exit_oscam;
37
38extern char *entitlement_type[];
39extern char *RDR_CD_TXT[];
40extern char *loghist;
41extern char *loghistptr;
42
43int32_t ssl_active = 0;
44char noncekey[33];
45pthread_key_t getkeepalive;
46static pthread_key_t getip;
47pthread_key_t getssl;
48static CS_MUTEX_LOCK http_lock;
49CS_MUTEX_LOCK *lock_cs;
50
51static pthread_t httpthread;
52static int32_t sock;
53enum refreshtypes { REFR_ACCOUNTS, REFR_CLIENTS, REFR_SERVER, REFR_ANTICASC, REFR_SERVICES };
54
55/* constants for menuactivating */
56#define MNU_STATUS 0
57#define MNU_CONFIG 1
58#define MNU_READERS 2
59#define MNU_USERS 3
60#define MNU_SERVICES 4
61#define MNU_FILES 5
62#define MNU_FAILBAN 6
63#define MNU_CACHEEX 7
64#define MNU_SCRIPT 8
65#define MNU_SHUTDOWN 9
66#define MNU_TOTAL_ITEMS 10 // sum of items above
67/* constants for submenuactivating */
68#define MNU_CFG_GLOBAL 0
69#define MNU_CFG_LOADBAL 1
70#define MNU_CFG_CAMD33 2
71#define MNU_CFG_CAMD35 3
72#define MNU_CFG_CAMD35TCP 4
73#define MNU_CFG_NEWCAMD 5
74#define MNU_CFG_RADEGAST 6
75#define MNU_CFG_CCCAM 7
76#define MNU_CFG_ANTICASC 8
77#define MNU_CFG_MONITOR 9
78#define MNU_CFG_SERIAL 10
79#define MNU_CFG_DVBAPI 11
80#define MNU_CFG_WEBIF 12
81#define MNU_CFG_LCD 13
82
83#define MNU_CFG_FVERSION 12
84#define MNU_CFG_FCONF 13
85#define MNU_CFG_FUSER 14
86#define MNU_CFG_FSERVER 15
87#define MNU_CFG_FSERVICES 16
88#define MNU_CFG_FSRVID 17
89#define MNU_CFG_FPROVID 18
90#define MNU_CFG_FTIERS 19
91#define MNU_CFG_FLOGFILE 20
92#define MNU_CFG_FUSERFILE 21
93#define MNU_CFG_FACLOG 22
94#define MNU_CFG_FDVBAPI 23
95#define MNU_CFG_CACHE 24
96#define MNU_CFG_WHITELIST 25
97#define MNU_CFG_TOTAL_ITEMS 26 // sum of items above. Use it for "All inactive" in function calls too.
98
99static void refresh_oscam(enum refreshtypes refreshtype)
100{
101
102 switch(refreshtype)
103 {
104 case REFR_ACCOUNTS:
105 cs_log("Refresh Accounts requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
106 cs_accounts_chk();
107 break;
108
109 case REFR_CLIENTS:
110 cs_log("Refresh Clients requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
111 cs_reinit_clients(cfg.account);
112 break;
113
114 case REFR_SERVER:
115 cs_log("Refresh Server requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
116 //kill(first_client->pid, SIGHUP);
117 //todo how I can refresh the server after global settings
118 break;
119
120 case REFR_SERVICES:
121 cs_log("Refresh Services requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
122 //init_sidtab();
123 cs_accounts_chk();
124 break;
125
126#ifdef CS_ANTICASC
127 case REFR_ANTICASC:
128 cs_log("Refresh Anticascading requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
129 ac_init_stat();
130 struct s_client *cl;
131 struct s_auth *account;
132 for(cl = first_client->next; cl ; cl = cl->next)
133 {
134 if(cl->typ == 'c' && (account = cl->account))
135 {
136 cl->ac_limit = (account->ac_users * 100 + 80) * cfg.ac_stime;
137 }
138 }
139 break;
140#endif
141 default:
142 break;
143 }
144}
145/*
146 * load historical values from ringbuffer and return it in the right order
147 * as string. Value should be freed with free_mk_t()
148 */
149static char *get_ecm_historystring(struct s_client *cl)
150{
151
152 if(cl)
153 {
154 int32_t k, i, pos = 0, needed = 1, v;
155 char *value, *dot = "";
156 int32_t ptr = cl->cwlastresptimes_last;
157
158 needed = CS_ECM_RINGBUFFER_MAX * 6; //5 digits + delimiter
159 if(!cs_malloc(&value, needed)) { return ""; }
160
161 k = ptr + 1;
162 for(i = 0; i < CS_ECM_RINGBUFFER_MAX; i++)
163 {
164 if(k >= CS_ECM_RINGBUFFER_MAX)
165 { k = 0; }
166 v = cl->cwlastresptimes[k].duration;
167 if(v > 0 && v < (int32_t)cfg.ctimeout * 5)
168 {
169 pos += snprintf(value + pos, needed - pos, "%s%d", dot, v);
170 dot = ",";
171 }
172 k++;
173 }
174 if(strlen(value) == 0)
175 {
176 free(value);
177 return "";
178 }
179 else { return value; }
180
181 }
182 else
183 {
184 return "";
185 }
186}
187
188static char *get_ecm_fullhistorystring(struct s_client *cl)
189{
190
191 if(cl)
192 {
193 int32_t k, i, pos = 0, needed = 1, v;
194 char *value, *dot = "";
195 int32_t ptr = cl->cwlastresptimes_last;
196
197 needed = CS_ECM_RINGBUFFER_MAX * 20; //5 digits + : + returncode(2) + : + time(10) + delimiter
198 if(!cs_malloc(&value, needed)) { return ""; }
199
200 k = ptr + 1;
201 for(i = 0; i < CS_ECM_RINGBUFFER_MAX; i++)
202 {
203 if(k >= CS_ECM_RINGBUFFER_MAX)
204 { k = 0; }
205 v = cl->cwlastresptimes[k].duration;
206 if(v > 0 && v < (int32_t)cfg.ctimeout * 5)
207 {
208 pos += snprintf(value + pos, needed - pos, "%s%d:%d:%ld", dot, cl->cwlastresptimes[k].duration, cl->cwlastresptimes[k].rc, cl->cwlastresptimes[k].timestamp);
209 dot = ",";
210 }
211 k++;
212 }
213
214 return (value);
215
216 }
217 else
218 {
219 return "";
220 }
221}
222
223/*
224 * Set the active menu to a different CSS class
225 */
226static void setActiveMenu(struct templatevars *vars, int8_t active)
227{
228 int8_t i;
229 for(i = 0; i < MNU_TOTAL_ITEMS; i++)
230 {
231 tpl_printf(vars, TPLADD, "TMP", "MENUACTIVE%d", i);
232 if(i == active)
233 { tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "menu_selected"); }
234 else
235 { tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "menu"); }
236 }
237}
238
239/*
240 * Set the active submenu to a different CSS class
241 */
242static void setActiveSubMenu(struct templatevars *vars, int8_t active)
243{
244 int8_t i;
245 for(i = 0; i < MNU_CFG_TOTAL_ITEMS; i++)
246 {
247 tpl_printf(vars, TPLADD, "TMP", "CMENUACTIVE%d", i);
248 if(i == active)
249 { tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "configmenu_selected"); }
250 else
251 { tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "configmenu"); }
252 }
253}
254
255static void webif_save_config(char *section, struct templatevars *vars, struct uriparams *params)
256{
257 if(!streq(getParam(params, "action"), "execute"))
258 { return; }
259 if(cfg.http_readonly)
260 {
261 tpl_addMsg(vars, "WebIf is in readonly mode. No changes are possible!");
262 return;
263 }
264 int i;
265 int cnt = (*params).paramcount;
266 for(i = 0; i < cnt; i++)
267 {
268 char *token = (*params).params[i];
269 char *value = (*params).values[i];
270 if(!streq(token, "part") && !streq(token, "action"))
271 { config_set(section, token, value); }
272 }
273 if(write_config() == 0)
274 {
275 tpl_addMsg(vars, "Configuration was saved. You should restart OSCam now.");
276 enum refreshtypes ref_type = REFR_SERVER;
277 if(streq(getParam(params, "part"), "anticasc"))
278 { ref_type = REFR_ANTICASC; }
279 refresh_oscam(ref_type);
280 }
281 else
282 {
283 tpl_addMsg(vars, "ERROR: Failed to write config file!!!");
284 }
285}
286
287static char *send_oscam_config_global(struct templatevars *vars, struct uriparams *params)
288{
289 setActiveSubMenu(vars, MNU_CFG_GLOBAL);
290
291 webif_save_config("global", vars, params);
292
293 if(IP_ISSET(cfg.srvip))
294 { tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.srvip)); }
295 tpl_printf(vars, TPLADD, "NICE", "%d", cfg.nice);
296 tpl_printf(vars, TPLADD, "BINDWAIT", "%d", cfg.bindwait);
297 tpl_printf(vars, TPLADD, "NETPRIO", "%d", cfg.netprio);
298 tpl_printf(vars, TPLADD, "PIDFILE", "%s", ESTR(cfg.pidfile));
299
300
301 if(cfg.usrfile != NULL) { tpl_addVar(vars, TPLADD, "USERFILE", cfg.usrfile); }
302 if(cfg.disableuserfile == 1) { tpl_addVar(vars, TPLADD, "DISABLEUSERFILECHECKED", "selected"); }
303 if(cfg.usrfileflag == 1) { tpl_addVar(vars, TPLADD, "USERFILEFLAGCHECKED", "selected"); }
304 if(cfg.mailfile != NULL) { tpl_addVar(vars, TPLADD, "MAILFILE", cfg.mailfile); }
305 if(cfg.disablemail == 1) { tpl_addVar(vars, TPLADD, "DISABLEMAILCHECKED", "selected"); }
306
307 char *value = mk_t_logfile();
308 tpl_addVar(vars, TPLADD, "LOGFILE", value);
309 free_mk_t(value);
310 if(cfg.disablelog == 1) { tpl_addVar(vars, TPLADD, "DISABLELOGCHECKED", "selected"); }
311 tpl_printf(vars, TPLADD, "MAXLOGSIZE", "%d", cfg.max_log_size);
312
313 if(cfg.logduplicatelines)
314 { tpl_addVar(vars, TPLADD, "LOGDUPSCHECKED", "selected"); }
315
316 if(cfg.cwlogdir != NULL) { tpl_addVar(vars, TPLADD, "CWLOGDIR", cfg.cwlogdir); }
317 if(cfg.emmlogdir != NULL) { tpl_addVar(vars, TPLADD, "EMMLOGDIR", cfg.emmlogdir); }
318 tpl_addVar(vars, TPLADD, "ECMFMT", cfg.ecmfmt);
319 tpl_printf(vars, TPLADD, "LOGHISTORYSIZE", "%u", cfg.loghistorysize);
320
321 tpl_printf(vars, TPLADD, "CLIENTTIMEOUT", "%u", cfg.ctimeout);
322 tpl_printf(vars, TPLADD, "FALLBACKTIMEOUT", "%u", cfg.ftimeout);
323 tpl_printf(vars, TPLADD, "CLIENTMAXIDLE", "%u", cfg.cmaxidle);
324
325
326 value = mk_t_caidvaluetab(&cfg.ftimeouttab);
327 tpl_addVar(vars, TPLADD, "FALLBACKTIMEOUT_PERCAID", value);
328 free_mk_t(value);
329
330 tpl_printf(vars, TPLADD, "SLEEP", "%d", cfg.tosleep);
331 if(cfg.ulparent) { tpl_addVar(vars, TPLADD, "UNLOCKPARENTALCHECKED", "selected"); }
332
333 if(cfg.block_same_ip) { tpl_addVar(vars, TPLADD, "BLOCKSAMEIPCHECKED", "selected"); }
334 if(cfg.block_same_name) { tpl_addVar(vars, TPLADD, "BLOCKSAMENAMECHECKED", "selected"); }
335
336 if(cfg.waitforcards == 1) { tpl_addVar(vars, TPLADD, "WAITFORCARDSCHECKED", "selected"); }
337 tpl_printf(vars, TPLADD, "EXTRADELAY", "%d", cfg.waitforcards_extra_delay);
338 if(cfg.preferlocalcards == 1)
339 {
340 tpl_addVar(vars, TPLADD, "PREFERCACHEEX", "selected");
341 }
342 else if(cfg.preferlocalcards == 2)
343 {
344 tpl_addVar(vars, TPLADD, "PREFERLOCALCARDS", "selected");
345 }
346
347 if(cfg.c35_suppresscmd08)
348 { tpl_addVar(vars, TPLADD, "SUPPRESSCMD08", "checked"); }
349
350
351 if(cfg.reader_restart_seconds)
352 { tpl_printf(vars, TPLADD, "READERRESTARTSECONDS", "%d", cfg.reader_restart_seconds); }
353
354 if(cfg.dropdups)
355 { tpl_addVar(vars, TPLADD, "DROPDUPSCHECKED", "selected"); }
356
357 if(cfg.resolve_gethostbyname == 1)
358 { tpl_addVar(vars, TPLADD, "RESOLVER1", "selected"); }
359 else
360 { tpl_addVar(vars, TPLADD, "RESOLVER0", "selected"); }
361
362 tpl_printf(vars, TPLADD, "FAILBANTIME", "%d", cfg.failbantime);
363 tpl_printf(vars, TPLADD, "FAILBANCOUNT", "%d", cfg.failbancount);
364
365 if(cfg.double_check == 1)
366 { tpl_addVar(vars, TPLADD, "DCHECKCSELECTED", "selected"); }
367 value = mk_t_caidtab(&cfg.double_check_caid);
368 tpl_addVar(vars, TPLADD, "DOUBLECHECKCAID", value);
369 free_mk_t(value);
370
371#ifdef LEDSUPPORT
372 if(cfg.enableled == 1)
373 { tpl_addVar(vars, TPLADD, "ENABLELEDSELECTED1", "selected"); }
374 else if(cfg.enableled == 2)
375 { tpl_addVar(vars, TPLADD, "ENABLELEDSELECTED2", "selected"); }
376#endif
377
378 return tpl_getTpl(vars, "CONFIGGLOBAL");
379}
380
381#ifdef WITH_LB
382static char *send_oscam_config_loadbalancer(struct templatevars *vars, struct uriparams *params)
383{
384 setActiveSubMenu(vars, MNU_CFG_LOADBAL);
385
386 if(strlen(getParam(params, "button")) > 0)
387 {
388 if(cfg.http_readonly)
389 {
390 tpl_addMsg(vars, "WebIf is in readonly mode. No changes are possible!");
391 }
392 else
393 {
394 if(strcmp(getParam(params, "button"), "Load Stats") == 0)
395 {
396 clear_all_stat();
397 load_stat_from_file();
398 tpl_addMsg(vars, "Stats loaded from file");
399 }
400
401 if(strcmp(getParam(params, "button"), "Save Stats") == 0)
402 {
403 save_stat_to_file(1);
404 tpl_addMsg(vars, "Stats saved to file");
405 }
406
407 if(strcmp(getParam(params, "button"), "Clear Stats") == 0)
408 {
409 clear_all_stat();
410 tpl_addMsg(vars, "Stats cleared completly");
411 }
412
413 if(strcmp(getParam(params, "button"), "Clear Timeouts") == 0)
414 {
415 clean_all_stats_by_rc(E_TIMEOUT, 0);
416 tpl_addMsg(vars, "Stats cleared Timeouts");
417 }
418
419 if(strcmp(getParam(params, "button"), "Clear Not Founds") == 0)
420 {
421 clean_all_stats_by_rc(E_NOTFOUND, 0);
422 tpl_addMsg(vars, "Stats cleared Not Founds");
423 }
424 }
425 }
426
427 webif_save_config("global", vars, params);
428
429 tpl_printf(vars, TPLADD, "TMP", "LBMODE%d", cfg.lb_mode);
430 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
431
432 tpl_printf(vars, TPLADD, "LBSAVE", "%d", cfg.lb_save);
433 if(cfg.lb_savepath) { tpl_addVar(vars, TPLADD, "LBSAVEPATH", cfg.lb_savepath); }
434
435 tpl_printf(vars, TPLADD, "LBNBESTREADERS", "%d", cfg.lb_nbest_readers);
436 char *value = mk_t_caidvaluetab(&cfg.lb_nbest_readers_tab);
437 tpl_addVar(vars, TPLADD, "LBNBESTPERCAID", value);
438 free_mk_t(value);
439 tpl_printf(vars, TPLADD, "LBNFBREADERS", "%d", cfg.lb_nfb_readers);
440 tpl_printf(vars, TPLADD, "LBMAXREADERS", "%d", cfg.lb_max_readers);
441 tpl_printf(vars, TPLADD, "LBMINECMCOUNT", "%d", cfg.lb_min_ecmcount);
442 tpl_printf(vars, TPLADD, "LBMAXECEMCOUNT", "%d", cfg.lb_max_ecmcount);
443 tpl_printf(vars, TPLADD, "LBRETRYLIMIT", "%d", cfg.lb_retrylimit);
444
445 value = mk_t_caidvaluetab(&cfg.lb_retrylimittab);
446 tpl_addVar(vars, TPLADD, "LBRETRYLIMITS", value);
447 free_mk_t(value);
448
449 tpl_printf(vars, TPLADD, "LBREOPENSECONDS", "%d", cfg.lb_reopen_seconds);
450 tpl_printf(vars, TPLADD, "LBCLEANUP", "%d", cfg.lb_stat_cleanup);
451
452 value = mk_t_caidtab(&cfg.lb_noproviderforcaid);
453 tpl_addVar(vars, TPLADD, "LBNOPROVIDERFORCAID", value);
454 free_mk_t(value);
455
456 if(cfg.lb_auto_betatunnel) { tpl_addVar(vars, TPLADD, "LBAUTOBETATUNNEL", "selected"); }
457 if(cfg.lb_auto_betatunnel_mode == 1)
458 {
459 tpl_addVar(vars, TPLADD, "LBAUTOBETATUNNELMODE1", "selected");
460 }
461 else if(cfg.lb_auto_betatunnel_mode == 2)
462 {
463 tpl_addVar(vars, TPLADD, "LBAUTOBETATUNNELMODE2", "selected");
464 }
465 else if(cfg.lb_auto_betatunnel_mode == 3)
466 {
467 tpl_addVar(vars, TPLADD, "LBAUTOBETATUNNELMODE3", "selected");
468 }
469 else if(cfg.lb_auto_betatunnel_mode == 4)
470 {
471 tpl_addVar(vars, TPLADD, "LBAUTOBETATUNNELMODE4", "selected");
472 }
473 else if(cfg.lb_auto_betatunnel_mode == 5)
474 {
475 tpl_addVar(vars, TPLADD, "LBAUTOBETATUNNELMODE5", "selected");
476 }
477 else if(cfg.lb_auto_betatunnel_mode == 6)
478 {
479 tpl_addVar(vars, TPLADD, "LBAUTOBETATUNNELMODE6", "selected");
480 }
481 tpl_printf(vars, TPLADD, "LBPREFERBETA", "%d", cfg.lb_auto_betatunnel_prefer_beta);
482
483 if(cfg.lb_auto_timeout) { tpl_addVar(vars, TPLADD, "LBAUTOTIMEOUT", "selected"); }
484 tpl_printf(vars, TPLADD, "LBAUTOTIMEOUTP", "%d", cfg.lb_auto_timeout_p);
485 tpl_printf(vars, TPLADD, "LBAUTOTIMEOUTT", "%d", cfg.lb_auto_timeout_t);
486
487 return tpl_getTpl(vars, "CONFIGLOADBALANCER");
488}
489#endif
490
491#ifdef MODULE_CAMD33
492static char *send_oscam_config_camd33(struct templatevars *vars, struct uriparams *params)
493{
494 int32_t i;
495
496 setActiveSubMenu(vars, MNU_CFG_CAMD33);
497
498 webif_save_config("camd33", vars, params);
499
500 if(cfg.c33_port)
501 {
502 tpl_printf(vars, TPLADD, "PORT", "%d", cfg.c33_port);
503 if(IP_ISSET(cfg.c33_srvip)) { tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.c33_srvip)); }
504 if(cfg.c33_passive == 1) { tpl_addVar(vars, TPLADD, "PASSIVECHECKED", "selected"); }
505
506 for(i = 0; i < (int) sizeof(cfg.c33_key); ++i) { tpl_printf(vars, TPLAPPEND, "KEY", "%02X", cfg.c33_key[i]); }
507 char *value = mk_t_iprange(cfg.c33_plain);
508 tpl_addVar(vars, TPLADD, "NOCRYPT", value);
509 free_mk_t(value);
510 }
511
512 return tpl_getTpl(vars, "CONFIGCAMD33");
513}
514#endif
515
516#ifdef MODULE_CAMD35
517static char *send_oscam_config_camd35(struct templatevars *vars, struct uriparams *params)
518{
519 setActiveSubMenu(vars, MNU_CFG_CAMD35);
520
521 webif_save_config("cs357x", vars, params);
522
523 if(cfg.c35_port)
524 {
525 tpl_printf(vars, TPLADD, "PORT", "%d", cfg.c35_port);
526 if(IP_ISSET(cfg.c35_srvip))
527 { tpl_addVar(vars, TPLAPPEND, "SERVERIP", cs_inet_ntoa(cfg.c35_srvip)); }
528
529 if(cfg.c35_udp_suppresscmd08)
530 { tpl_addVar(vars, TPLADD, "SUPPRESSCMD08UDP", "checked"); }
531
532 }
533 return tpl_getTpl(vars, "CONFIGCAMD35");
534}
535#endif
536
537#ifdef MODULE_CAMD35_TCP
538static char *send_oscam_config_camd35tcp(struct templatevars *vars, struct uriparams *params)
539{
540 setActiveSubMenu(vars, MNU_CFG_CAMD35TCP);
541
542 webif_save_config("cs378x", vars, params);
543
544 if((cfg.c35_tcp_ptab.nports > 0) && (cfg.c35_tcp_ptab.ports[0].s_port > 0))
545 {
546
547 char *value = mk_t_camd35tcp_port();
548 tpl_addVar(vars, TPLADD, "PORT", value);
549 free_mk_t(value);
550
551 if(IP_ISSET(cfg.c35_tcp_srvip))
552 { tpl_addVar(vars, TPLAPPEND, "SERVERIP", cs_inet_ntoa(cfg.c35_tcp_srvip)); }
553
554 if(cfg.c35_tcp_suppresscmd08)
555 { tpl_addVar(vars, TPLADD, "SUPPRESSCMD08TCP", "checked"); }
556 }
557 return tpl_getTpl(vars, "CONFIGCAMD35TCP");
558}
559#endif
560
561static char *send_oscam_config_cache(struct templatevars *vars, struct uriparams *params)
562{
563 setActiveSubMenu(vars, MNU_CFG_CACHE);
564
565 webif_save_config("cache", vars, params);
566
567 tpl_printf(vars, TPLADD, "CACHEDELAY", "%u", cfg.delay);
568
569 tpl_printf(vars, TPLADD, "MAXCACHETIME", "%d", cfg.max_cache_time);
570
571#ifdef CS_CACHEEX
572 char *value = NULL;
573 value = mk_t_cacheex_valuetab(&cfg.cacheex_wait_timetab);
574 tpl_addVar(vars, TPLADD, "WAIT_TIME", value);
575 free_mk_t(value);
576
577 tpl_printf(vars, TPLADD, "MAX_HIT_TIME", "%d", cfg.max_hitcache_time);
578
579 if(cfg.cacheex_enable_stats == 1)
580 { tpl_addVar(vars, TPLADD, "CACHEEXSTATSSELECTED", "selected"); }
581
582 if(cfg.csp_port)
583 { tpl_printf(vars, TPLADD, "PORT", "%d", cfg.csp_port); }
584
585 if(IP_ISSET(cfg.csp_srvip))
586 { tpl_addVar(vars, TPLAPPEND, "SERVERIP", cs_inet_ntoa(cfg.csp_srvip)); }
587
588 value = mk_t_cacheex_hitvaluetab(&cfg.csp.filter_caidtab);
589 tpl_addVar(vars, TPLADD, "CSP_ECM_FILTER", value);
590 free_mk_t(value);
591
592 tpl_addVar(vars, TPLADD, "ARCHECKED", (cfg.csp.allow_request == 1) ? "checked" : "");
593 tpl_addVar(vars, TPLADD, "ARFCHECKED", (cfg.csp.allow_reforward == 1) ? "checked" : "");
594#endif
595
596#ifdef CW_CYCLE_CHECK
597#ifndef CS_CACHEEX
598 char *value = NULL;
599#endif
600 if(cfg.cwcycle_check_enable == 1)
601 {
602 tpl_addVar(vars, TPLADD, "CWCYCLECHECK", "selected");
603 }
604 value = mk_t_caidtab(&cfg.cwcycle_check_caidtab);
605 tpl_addVar(vars, TPLADD, "CWCYCLECHECKCAID", value);
606 free_mk_t(value);
607
608 tpl_printf(vars, TPLADD, "MAXCYCLELIST", "%d", cfg.maxcyclelist);
609 tpl_printf(vars, TPLADD, "KEEPCYCLETIME", "%d", cfg.keepcycletime);
610
611 if(cfg.onbadcycle == 1)
612 {
613 tpl_addVar(vars, TPLADD, "ONBADCYCLE1", "selected");
614 }
615 if(cfg.cwcycle_dropold == 1)
616 {
617 tpl_addVar(vars, TPLADD, "DROPOLD", "selected");
618 }
619 switch(cfg.cwcycle_sensitive)
620 {
621 case 2:
622 tpl_addVar(vars, TPLADD, "CWCSEN2", "selected");
623 break;
624 case 3:
625 tpl_addVar(vars, TPLADD, "CWCSEN3", "selected");
626 break;
627 case 4:
628 tpl_addVar(vars, TPLADD, "CWCSEN4", "selected");
629 break;
630 }
631 if(cfg.cwcycle_allowbadfromffb == 1)
632 {
633 tpl_addVar(vars, TPLADD, "ALLOWBADFROMFFB", "selected");
634 }
635#endif
636
637 return tpl_getTpl(vars, "CONFIGCACHE");
638}
639
640#ifdef MODULE_NEWCAMD
641static char *send_oscam_config_newcamd(struct templatevars *vars, struct uriparams *params)
642{
643 int32_t i;
644
645 setActiveSubMenu(vars, MNU_CFG_NEWCAMD);
646
647 webif_save_config("newcamd", vars, params);
648
649 if((cfg.ncd_ptab.nports > 0) && (cfg.ncd_ptab.ports[0].s_port > 0))
650 {
651
652 char *value = mk_t_newcamd_port();
653 tpl_addVar(vars, TPLADD, "PORT", value);
654 free_mk_t(value);
655
656 if(IP_ISSET(cfg.ncd_srvip))
657 { tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.ncd_srvip)); }
658
659 for(i = 0; i < (int32_t)sizeof(cfg.ncd_key); i++)
660 { tpl_printf(vars, TPLAPPEND, "KEY", "%02X", cfg.ncd_key[i]); }
661
662 value = mk_t_iprange(cfg.ncd_allowed);
663 tpl_addVar(vars, TPLADD, "ALLOWED", value);
664 free_mk_t(value);
665
666 if(cfg.ncd_keepalive)
667 { tpl_addVar(vars, TPLADD, "KEEPALIVE", "checked"); }
668 if(cfg.ncd_mgclient)
669 { tpl_addVar(vars, TPLADD, "MGCLIENTCHK", "checked"); }
670 }
671 return tpl_getTpl(vars, "CONFIGNEWCAMD");
672}
673#endif
674
675#ifdef MODULE_RADEGAST
676static char *send_oscam_config_radegast(struct templatevars *vars, struct uriparams *params)
677{
678 setActiveSubMenu(vars, MNU_CFG_RADEGAST);
679
680 webif_save_config("radegast", vars, params);
681
682 tpl_printf(vars, TPLADD, "PORT", "%d", cfg.rad_port);
683 if(IP_ISSET(cfg.rad_srvip))
684 { tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.rad_srvip)); }
685 tpl_addVar(vars, TPLADD, "USER", cfg.rad_usr);
686
687 char *value = mk_t_iprange(cfg.rad_allowed);
688 tpl_addVar(vars, TPLADD, "ALLOWED", value);
689 free_mk_t(value);
690
691 return tpl_getTpl(vars, "CONFIGRADEGAST");
692}
693#endif
694
695#ifdef MODULE_CCCAM
696static char *send_oscam_config_cccam(struct templatevars *vars, struct uriparams *params)
697{
698
699 setActiveSubMenu(vars, MNU_CFG_CCCAM);
700
701 if(strcmp(getParam(params, "button"), "Refresh global list") == 0)
702 {
703 cs_debug_mask(D_TRACE, "Entitlements: Refresh Shares start");
704#ifdef MODULE_CCCSHARE
705 refresh_shares();
706#endif
707 cs_debug_mask(D_TRACE, "Entitlements: Refresh Shares finished");
708 tpl_addMsg(vars, "Refresh Shares started");
709 }
710
711 webif_save_config("cccam", vars, params);
712
713 if(streq(getParam(params, "action"), "execute") && !cfg.http_readonly)
714 { cc_update_nodeid(); }
715
716 char *value = mk_t_cccam_port();
717 tpl_addVar(vars, TPLAPPEND, "PORT", value);
718 free_mk_t(value);
719
720 if(IP_ISSET(cfg.cc_srvip))
721 { tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.cc_srvip)); }
722
723 tpl_printf(vars, TPLADD, "RESHARE", "%d", cfg.cc_reshare);
724
725 if(!strcmp((char *)cfg.cc_version, "2.0.11"))
726 {
727 tpl_addVar(vars, TPLADD, "VERSIONSELECTED0", "selected");
728 }
729 else if(!strcmp((char *)cfg.cc_version, "2.1.1"))
730 {
731 tpl_addVar(vars, TPLADD, "VERSIONSELECTED1", "selected");
732 }
733 else if(!strcmp((char *)cfg.cc_version, "2.1.2"))
734 {
735 tpl_addVar(vars, TPLADD, "VERSIONSELECTED2", "selected");
736 }
737 else if(!strcmp((char *)cfg.cc_version, "2.1.3"))
738 {
739 tpl_addVar(vars, TPLADD, "VERSIONSELECTED3", "selected");
740 }
741 else if(!strcmp((char *)cfg.cc_version, "2.1.4"))
742 {
743 tpl_addVar(vars, TPLADD, "VERSIONSELECTED4", "selected");
744 }
745 else if(!strcmp((char *)cfg.cc_version, "2.2.0"))
746 {
747 tpl_addVar(vars, TPLADD, "VERSIONSELECTED5", "selected");
748 }
749 else if(!strcmp((char *)cfg.cc_version, "2.2.1"))
750 {
751 tpl_addVar(vars, TPLADD, "VERSIONSELECTED6", "selected");
752 }
753 else if(!strcmp((char *)cfg.cc_version, "2.3.0"))
754 {
755 tpl_addVar(vars, TPLADD, "VERSIONSELECTED7", "selected");
756 }
757
758 tpl_printf(vars, TPLADD, "UPDATEINTERVAL", "%d", cfg.cc_update_interval);
759 tpl_printf(vars, TPLADD, "RECV_TIMEOUT", "%u", cfg.cc_recv_timeout);
760 if(cfg.cc_stealth)
761 { tpl_addVar(vars, TPLADD, "STEALTH", "selected"); }
762
763 tpl_printf(vars, TPLADD, "NODEID", "%02X%02X%02X%02X%02X%02X%02X%02X",
764 cfg.cc_fixed_nodeid[0], cfg.cc_fixed_nodeid[1], cfg.cc_fixed_nodeid[2], cfg.cc_fixed_nodeid[3],
765 cfg.cc_fixed_nodeid[4], cfg.cc_fixed_nodeid[5], cfg.cc_fixed_nodeid[6], cfg.cc_fixed_nodeid[7]);
766
767 tpl_printf(vars, TPLADD, "TMP", "MINIMIZECARDSELECTED%d", cfg.cc_minimize_cards);
768 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
769
770 tpl_printf(vars, TPLADD, "TMP", "RESHAREMODE%d", cfg.cc_reshare_services);
771 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
772
773 tpl_printf(vars, TPLADD, "TMP", "IGNRSHRSELECTED%d", cfg.cc_ignore_reshare);
774 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
775
776 if(cfg.cc_forward_origin_card)
777 { tpl_addVar(vars, TPLADD, "FORWARDORIGINCARD", "selected"); }
778
779 if(cfg.cc_keep_connected)
780 { tpl_addVar(vars, TPLADD, "KEEPCONNECTED", "selected"); }
781
782
783 return tpl_getTpl(vars, "CONFIGCCCAM");
784}
785#endif
786
787static bool is_ext(const char *path, const char *ext)
788{
789 size_t lenpath = strlen(path);
790 size_t lenext = strlen(ext);
791 if(lenext > lenpath)
792 { return 0; }
793 return memcmp(path + lenpath - lenext, ext, lenext) == 0;
794}
795
796static char *send_oscam_config_webif(struct templatevars *vars, struct uriparams *params)
797{
798 int32_t i;
799
800 setActiveSubMenu(vars, MNU_CFG_WEBIF);
801
802 webif_save_config("webif", vars, params);
803
804 tpl_printf(vars, TPLADD, "HTTPPORT", "%s%d", cfg.http_use_ssl ? "+" : "", cfg.http_port);
805 if(IP_ISSET(cfg.http_srvip))
806 { tpl_addVar(vars, TPLAPPEND, "SERVERIP", cs_inet_ntoa(cfg.http_srvip)); }
807
808 tpl_addVar(vars, TPLADD, "HTTPUSER", cfg.http_user);
809 tpl_addVar(vars, TPLADD, "HTTPPASSWORD", cfg.http_pwd);
810
811 // css style selector
812 tpl_printf(vars, TPLADD, "CSSOPTIONS", "\t\t\t\t\t\t<option value=\"\"%s>embedded</option>\n",
813 cfg.http_css ? " selected" : "");
814
815 if(cfg.http_tpl)
816 {
817 char path[255];
818 tpl_getFilePathInSubdir(cfg.http_tpl, "", "style", ".css", path, 255);
819 if(file_exists(path))
820 tpl_printf(vars, TPLAPPEND, "CSSOPTIONS", "\t\t\t\t\t\t<option value=\"%s\"%s>%s (template)</option>\n",
821 path,
822 cfg.http_css && strstr(cfg.http_css, path) ? " selected" : "",
823 path);
824 }
825
826 DIR *hdir;
827 struct dirent entry;
828 struct dirent *result;
829 if((hdir = opendir(cs_confdir)) != NULL)
830 {
831 while(cs_readdir_r(hdir, &entry, &result) == 0 && result != NULL)
832 {
833 if(is_ext(entry.d_name, ".css"))
834 {
835 tpl_printf(vars, TPLAPPEND, "CSSOPTIONS", "\t\t\t\t\t\t<option value=\"%s%s\"%s>%s%s</option>\n",
836 cs_confdir,
837 entry.d_name,
838 cfg.http_css && strstr(cfg.http_css, entry.d_name) ? " selected" : "",
839 cs_confdir, entry.d_name);
840 }
841 }
842 closedir(hdir);
843 }
844
845 if(cfg.http_prepend_embedded_css)
846 { tpl_addVar(vars, TPLADD, "HTTPPREPENDEMBEDDEDCSS", "checked"); }
847
848 tpl_addVar(vars, TPLADD, "HTTPHELPLANG", cfg.http_help_lang);
849 tpl_printf(vars, TPLADD, "HTTPREFRESH", "%d", cfg.http_refresh);
850 tpl_addVar(vars, TPLADD, "HTTPTPL", cfg.http_tpl);
851 tpl_addVar(vars, TPLADD, "HTTPSCRIPT", cfg.http_script);
852 tpl_addVar(vars, TPLADD, "HTTPJSCRIPT", cfg.http_jscript);
853
854 if(cfg.http_hide_idle_clients > 0) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
855 tpl_addVar(vars, TPLADD, "HTTPHIDETYPE", cfg.http_hide_type);
856 if(cfg.http_showpicons > 0) { tpl_addVar(vars, TPLADD, "SHOWPICONSCHECKED", "checked"); }
857
858 char *value = mk_t_iprange(cfg.http_allowed);
859 tpl_addVar(vars, TPLADD, "HTTPALLOW", value);
860 free_mk_t(value);
861
862 for(i = 0; i < MAX_HTTP_DYNDNS; i++)
863 {
864 if(cfg.http_dyndns[i][0])
865 {
866 tpl_addVar(vars, TPLAPPEND, "HTTPDYNDNS", i > 0 ? "," : "");
867 tpl_addVar(vars, TPLAPPEND, "HTTPDYNDNS", (char *)cfg.http_dyndns[i]);
868 }
869 }
870
871 if(cfg.http_full_cfg)
872 { tpl_addVar(vars, TPLADD, "HTTPSAVEFULLSELECT", "selected"); }
873
874#ifdef WITH_SSL
875 if(cfg.http_force_sslv3)
876 { tpl_addVar(vars, TPLADD, "HTTPFORCESSLV3SELECT", "selected"); }
877#endif
878
879 tpl_printf(vars, TPLADD, "AULOW", "%d", cfg.aulow);
880 tpl_printf(vars, TPLADD, "HIDECLIENTTO", "%d", cfg.hideclient_to);
881
882 return tpl_getTpl(vars, "CONFIGWEBIF");
883}
884
885#ifdef LCDSUPPORT
886static char *send_oscam_config_lcd(struct templatevars *vars, struct uriparams *params)
887{
888 setActiveSubMenu(vars, MNU_CFG_LCD);
889
890 webif_save_config("lcd", vars, params);
891
892 if(cfg.enablelcd)
893 { tpl_addVar(vars, TPLADD, "ENABLELCDSELECTED", "selected"); }
894 if(cfg.lcd_output_path != NULL)
895 { tpl_addVar(vars, TPLADD, "LCDOUTPUTPATH", cfg.lcd_output_path); }
896 if(cfg.lcd_hide_idle)
897 { tpl_addVar(vars, TPLADD, "LCDHIDEIDLE", "selected"); }
898 tpl_printf(vars, TPLADD, "LCDREFRESHINTERVAL", "%d", cfg.lcd_write_intervall);
899
900 return tpl_getTpl(vars, "CONFIGLCD");
901}
902#endif
903
904#ifdef MODULE_MONITOR
905static char *send_oscam_config_monitor(struct templatevars *vars, struct uriparams *params)
906{
907 setActiveSubMenu(vars, MNU_CFG_MONITOR);
908
909 webif_save_config("monitor", vars, params);
910
911 tpl_printf(vars, TPLADD, "MONPORT", "%d", cfg.mon_port);
912 if(IP_ISSET(cfg.mon_srvip))
913 { tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.mon_srvip)); }
914
915 tpl_printf(vars, TPLADD, "AULOW", "%d", cfg.aulow);
916 tpl_printf(vars, TPLADD, "HIDECLIENTTO", "%d", cfg.hideclient_to);
917
918 char *value = mk_t_iprange(cfg.mon_allowed);
919 tpl_addVar(vars, TPLADD, "NOCRYPT", value);
920 free_mk_t(value);
921
922 //Monlevel selector
923 tpl_printf(vars, TPLADD, "TMP", "MONSELECTED%d", cfg.mon_level);
924 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
925
926 return tpl_getTpl(vars, "CONFIGMONITOR");
927}
928#endif
929
930#ifdef MODULE_SERIAL
931static char *send_oscam_config_serial(struct templatevars *vars, struct uriparams *params)
932{
933 setActiveSubMenu(vars, MNU_CFG_SERIAL);
934
935 webif_save_config("serial", vars, params);
936
937 if(cfg.ser_device)
938 {
939 char sdevice[strlen(cfg.ser_device)];
940 cs_strncpy(sdevice, cfg.ser_device, sizeof(sdevice));
941 char *ptr, *saveptr1 = NULL;
942 char delimiter[2];
943 delimiter[0] = 1;
944 delimiter[1] = '\0';
945 for(ptr = strtok_r(sdevice, delimiter, &saveptr1); ptr; ptr = strtok_r(NULL, delimiter, &saveptr1))
946 {
947 tpl_addVar(vars, TPLADD, "SERIALDEVICE", xml_encode(vars, ptr));
948 tpl_addVar(vars, TPLAPPEND, "DEVICES", tpl_getTpl(vars, "CONFIGSERIALDEVICEBIT"));
949 }
950 }
951
952 tpl_addVar(vars, TPLADD, "SERIALDEVICE", "");
953 tpl_addVar(vars, TPLAPPEND, "DEVICES", tpl_getTpl(vars, "CONFIGSERIALDEVICEBIT"));
954
955 return tpl_getTpl(vars, "CONFIGSERIAL");
956}
957#endif
958
959#ifdef HAVE_DVBAPI
960extern const char *boxdesc[];
961
962static char *send_oscam_config_dvbapi(struct templatevars *vars, struct uriparams *params)
963{
964 int32_t i;
965
966 setActiveSubMenu(vars, MNU_CFG_DVBAPI);
967
968 webif_save_config("dvbapi", vars, params);
969
970 if(cfg.dvbapi_enabled > 0)
971 { tpl_addVar(vars, TPLADD, "ENABLEDCHECKED", "checked"); }
972
973 if(cfg.dvbapi_au > 0)
974 { tpl_addVar(vars, TPLADD, "AUCHECKED", "checked"); }
975
976 if(cfg.dvbapi_delayer > 0)
977 { tpl_printf(vars, TPLADD, "DELAYER", "%d", cfg.dvbapi_delayer); }
978
979 tpl_printf(vars, TPLADD, "BOXTYPE", "<option value=\"\"%s>None</option>\n", cfg.dvbapi_boxtype == 0 ? " selected" : "");
980 for(i = 1; i <= BOXTYPES; i++)
981 {
982 tpl_printf(vars, TPLAPPEND, "BOXTYPE", "<option%s>%s</option>\n", cfg.dvbapi_boxtype == i ? " selected" : "", boxdesc[i]);
983 }
984
985 tpl_addVar(vars, TPLADD, "USER", cfg.dvbapi_usr);
986
987 //PMT Mode
988 tpl_printf(vars, TPLADD, "TMP", "PMTMODESELECTED%d", cfg.dvbapi_pmtmode);
989 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
990
991 //Request Mode
992 tpl_printf(vars, TPLADD, "TMP", "REQMODESELECTED%d", cfg.dvbapi_requestmode);
993 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
994
995 return tpl_getTpl(vars, "CONFIGDVBAPI");
996}
997#endif
998
999#ifdef CS_ANTICASC
1000static char *send_oscam_config_anticasc(struct templatevars *vars, struct uriparams *params)
1001{
1002 setActiveSubMenu(vars, MNU_CFG_ANTICASC);
1003
1004 webif_save_config("anticasc", vars, params);
1005
1006 if(cfg.ac_enabled > 0) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
1007 tpl_printf(vars, TPLADD, "NUMUSERS", "%d", cfg.ac_users);
1008 tpl_printf(vars, TPLADD, "SAMPLETIME", "%d", cfg.ac_stime);
1009 tpl_printf(vars, TPLADD, "SAMPLES", "%d", cfg.ac_samples);
1010
1011 tpl_printf(vars, TPLADD, "TMP", "PENALTY%d", cfg.ac_penalty);
1012 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1013
1014 if(cfg.ac_logfile)
1015 { tpl_addVar(vars, TPLADD, "ACLOGFILE", cfg.ac_logfile); }
1016 tpl_printf(vars, TPLADD, "FAKEDELAY", "%d", cfg.ac_fakedelay);
1017 tpl_printf(vars, TPLADD, "DENYSAMPLES", "%d", cfg.ac_denysamples);
1018 return tpl_getTpl(vars, "CONFIGANTICASC");
1019}
1020#endif
1021
1022static char *send_oscam_config(struct templatevars *vars, struct uriparams *params)
1023{
1024
1025 setActiveMenu(vars, MNU_CONFIG);
1026
1027 char *part = getParam(params, "part");
1028 if(!strcmp(part, "webif")) { return send_oscam_config_webif(vars, params); }
1029#ifdef MODULE_MONITOR
1030 else if(!strcmp(part, "monitor")) { return send_oscam_config_monitor(vars, params); }
1031#endif
1032#ifdef LCDSUPPORT
1033 else if(!strcmp(part, "lcd")) { return send_oscam_config_lcd(vars, params); }
1034#endif
1035#ifdef MODULE_CAMD33
1036 else if(!strcmp(part, "camd33")) { return send_oscam_config_camd33(vars, params); }
1037#endif
1038#ifdef MODULE_CAMD35
1039 else if(!strcmp(part, "camd35")) { return send_oscam_config_camd35(vars, params); }
1040#endif
1041#ifdef MODULE_CAMD35_TCP
1042 else if(!strcmp(part, "camd35tcp")) { return send_oscam_config_camd35tcp(vars, params); }
1043#endif
1044 else if(!strcmp(part, "cache")) { return send_oscam_config_cache(vars, params); }
1045#ifdef MODULE_NEWCAMD
1046 else if(!strcmp(part, "newcamd")) { return send_oscam_config_newcamd(vars, params); }
1047#endif
1048#ifdef MODULE_RADEGAST
1049 else if(!strcmp(part, "radegast")) { return send_oscam_config_radegast(vars, params); }
1050#endif
1051#ifdef MODULE_CCCAM
1052 else if(!strcmp(part, "cccam")) { return send_oscam_config_cccam(vars, params); }
1053#endif
1054#ifdef HAVE_DVBAPI
1055 else if(!strcmp(part, "dvbapi")) { return send_oscam_config_dvbapi(vars, params); }
1056#endif
1057#ifdef CS_ANTICASC
1058 else if(!strcmp(part, "anticasc")) { return send_oscam_config_anticasc(vars, params); }
1059#endif
1060#ifdef MODULE_SERIAL
1061 else if(!strcmp(part, "serial")) { return send_oscam_config_serial(vars, params); }
1062#endif
1063#ifdef WITH_LB
1064 else if(!strcmp(part, "loadbalancer")) { return send_oscam_config_loadbalancer(vars, params); }
1065#endif
1066 else { return send_oscam_config_global(vars, params); }
1067}
1068
1069static void inactivate_reader(struct s_reader *rdr)
1070{
1071 struct s_client *cl = rdr->client;
1072 if(cl)
1073 { kill_thread(cl); }
1074}
1075
1076static bool picon_exists(char *name)
1077{
1078 char picon_name[64], path[255];
1079 if(!cfg.http_tpl)
1080 { return false; }
1081 snprintf(picon_name, sizeof(picon_name) - 1, "IC_%s", name);
1082 return strlen(tpl_getTplPath(picon_name, cfg.http_tpl, path, sizeof(path) - 1)) && file_exists(path);
1083}
1084
1085static char *send_oscam_reader(struct templatevars *vars, struct uriparams *params, int32_t apicall)
1086{
1087 struct s_reader *rdr;
1088 int32_t i;
1089
1090 if(!apicall) { setActiveMenu(vars, MNU_READERS); }
1091 if(cfg.http_refresh > 0)
1092 {
1093 tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", cfg.http_refresh);
1094 tpl_addVar(vars, TPLADD, "REFRESHURL", "readers.html");
1095 tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
1096 }
1097 if((strcmp(getParam(params, "action"), "disable") == 0) || (strcmp(getParam(params, "action"), "enable") == 0))
1098 {
1099 if(cfg.http_readonly)
1100 {
1101 tpl_addMsg(vars, "WebIf is in readonly mode. Enabling or disabling readers is not possible!");
1102 }
1103 else
1104 {
1105 rdr = get_reader_by_label(getParam(params, "label"));
1106 if(rdr)
1107 {
1108 if(strcmp(getParam(params, "action"), "enable") == 0)
1109 {
1110 if(!rdr->enable)
1111 {
1112 rdr->enable = 1;
1113 }
1114 }
1115 else
1116 {
1117 if(rdr->enable)
1118 {
1119 rdr->enable = 0;
1120 }
1121 }
1122 restart_cardreader(rdr, 1);
1123 if(write_server() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
1124 }
1125 }
1126 }
1127
1128 if(strcmp(getParam(params, "action"), "delete") == 0)
1129 {
1130 if(cfg.http_readonly)
1131 {
1132 tpl_addMsg(vars, "WebIf is in readonly mode. No deletion will be made!");
1133 }
1134 else
1135 {
1136 rdr = get_reader_by_label(getParam(params, "label"));
1137 if(rdr)
1138 {
1139 inactivate_reader(rdr);
1140 ll_remove(configured_readers, rdr);
1141
1142 free_reader(rdr);
1143
1144 if(write_server() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
1145 }
1146 }
1147 }
1148
1149 if(strcmp(getParam(params, "action"), "reread") == 0)
1150 {
1151 rdr = get_reader_by_label(getParam(params, "label"));
1152 if(rdr)
1153 {
1154 struct s_client *cl = rdr->client;
1155 //reset the counters
1156 for(i = 0; i < 4; i++)
1157 {
1158 rdr->emmerror[i] = 0;
1159 rdr->emmwritten[i] = 0;
1160 rdr->emmskipped[i] = 0;
1161 rdr->emmblocked[i] = 0;
1162 }
1163
1164 if(rdr->enable == 1 && cl && cl->typ == 'r')
1165 {
1166 add_job(cl, ACTION_READER_CARDINFO, NULL, 0);
1167 }
1168 }
1169 }
1170
1171 LL_ITER itr = ll_iter_create(configured_readers);
1172
1173 if(!apicall)
1174 {
1175 for(i = 0, rdr = ll_iter_next(&itr); rdr && rdr->label[0]; rdr = ll_iter_next(&itr), i++) { ; }
1176 tpl_printf(vars, TPLADD, "NEXTREADER", "Reader-%d", i); //Next Readername
1177 }
1178
1179 ll_iter_reset(&itr); //going to iterate all configured readers
1180 while((rdr = ll_iter_next(&itr)))
1181 {
1182 struct s_client *cl = rdr->client;
1183 if(rdr->label[0] && rdr->typ)
1184 {
1185
1186 // used for API and WebIf
1187 tpl_addVar(vars, TPLADD, "READERNAME", xml_encode(vars, rdr->label));
1188 tpl_addVar(vars, TPLADD, "READERNAMEENC", urlencode(vars, rdr->label));
1189 tpl_addVar(vars, TPLADD, "CTYP", reader_get_type_desc(rdr, 0));
1190
1191 // used only for WebIf
1192 if(!apicall)
1193 {
1194 if(rdr->enable)
1195 { tpl_addVar(vars, TPLADD, "READERCLASS", "enabledreader"); }
1196 else
1197 { tpl_addVar(vars, TPLADD, "READERCLASS", "disabledreader"); }
1198
1199 if(cfg.http_showpicons)
1200 {
1201 if(picon_exists(xml_encode(vars, rdr->label)))
1202 {
1203 tpl_printf(vars, TPLADD, "READERICON",
1204 "<img class=\"readericon\" src=\"image?i=IC_%s\" TITLE=\"%s\">",
1205 xml_encode(vars, rdr->label), xml_encode(vars, rdr->label));
1206 }
1207 else
1208 {
1209 tpl_addVar(vars, TPLADD, "READERICON", xml_encode(vars, rdr->label));
1210 }
1211 if(picon_exists(xml_encode(vars, reader_get_type_desc(rdr, 0))))
1212 {
1213 tpl_printf(vars, TPLADD, "READERTYPEICON",
1214 "<img class=\"readertypeicon\" src=\"image?i=IC_%s\" TITLE=\"%s\">",
1215 reader_get_type_desc(rdr, 0), reader_get_type_desc(rdr, 0));
1216 }
1217 else
1218 {
1219 tpl_addVar(vars, TPLADD, "READERTYPEICON", reader_get_type_desc(rdr, 0));
1220 }
1221 }
1222 else
1223 {
1224 tpl_addVar(vars, TPLADD, "READERICON", xml_encode(vars, rdr->label));
1225 tpl_addVar(vars, TPLADD, "READERTYPEICON", reader_get_type_desc(rdr, 0));
1226 }
1227 char *value = mk_t_group(rdr->grp);
1228 tpl_addVar(vars, TPLADD, "GROUPS", value);
1229 free_mk_t(value);
1230 tpl_printf(vars, TPLADD, "EMMERRORUK", "%d", rdr->emmerror[UNKNOWN]);
1231 tpl_printf(vars, TPLADD, "EMMERRORG", "%d", rdr->emmerror[GLOBAL]);
1232 tpl_printf(vars, TPLADD, "EMMERRORS", "%d", rdr->emmerror[SHARED]);
1233 tpl_printf(vars, TPLADD, "EMMERRORUQ", "%d", rdr->emmerror[UNIQUE]);
1234
1235 tpl_printf(vars, TPLADD, "EMMWRITTENUK", "%d", rdr->emmwritten[UNKNOWN]);
1236 tpl_printf(vars, TPLADD, "EMMWRITTENG", "%d", rdr->emmwritten[GLOBAL]);
1237 tpl_printf(vars, TPLADD, "EMMWRITTENS", "%d", rdr->emmwritten[SHARED]);
1238 tpl_printf(vars, TPLADD, "EMMWRITTENUQ", "%d", rdr->emmwritten[UNIQUE]);
1239
1240 tpl_printf(vars, TPLADD, "EMMSKIPPEDUK", "%d", rdr->emmskipped[UNKNOWN]);
1241 tpl_printf(vars, TPLADD, "EMMSKIPPEDG", "%d", rdr->emmskipped[GLOBAL]);
1242 tpl_printf(vars, TPLADD, "EMMSKIPPEDS", "%d", rdr->emmskipped[SHARED]);
1243 tpl_printf(vars, TPLADD, "EMMSKIPPEDUQ", "%d", rdr->emmskipped[UNIQUE]);
1244
1245 tpl_printf(vars, TPLADD, "EMMBLOCKEDUK", "%d", rdr->emmblocked[UNKNOWN]);
1246 tpl_printf(vars, TPLADD, "EMMBLOCKEDG", "%d", rdr->emmblocked[GLOBAL]);
1247 tpl_printf(vars, TPLADD, "EMMBLOCKEDS", "%d", rdr->emmblocked[SHARED]);
1248 tpl_printf(vars, TPLADD, "EMMBLOCKEDUQ", "%d", rdr->emmblocked[UNIQUE]);
1249
1250 tpl_printf(vars, TPLADD, "ECMSOK", "%u (%.2f%%)", rdr->ecmsok, rdr->ecmshealthok);
1251 tpl_printf(vars, TPLADD, "ECMSNOK", "%u (%.2f%%)", rdr->ecmsnok, rdr->ecmshealthnok);
1252 tpl_printf(vars, TPLADD, "ECMSFILTEREDHEAD", "%d", rdr->ecmsfilteredhead);
1253 tpl_printf(vars, TPLADD, "ECMSFILTEREDLEN", "%d", rdr->ecmsfilteredlen);
1254#ifdef WITH_LB
1255 tpl_printf(vars, TPLADD, "LBWEIGHT", "%d", rdr->lb_weight);
1256#endif
1257 if(!is_network_reader(rdr)) //reader is physical
1258 {
1259 tpl_addVar(vars, TPLADD, "REFRICO", "image?i=ICREF");
1260 tpl_addVar(vars, TPLADD, "READERREFRESH", tpl_getTpl(vars, "READERREFRESHBIT"));
1261 tpl_addVar(vars, TPLADD, "ENTICO", "image?i=ICENT");
1262 tpl_addVar(vars, TPLADD, "ENTITLEMENT", tpl_getTpl(vars, "READERENTITLEBIT"));
1263 }
1264 else
1265 {
1266 tpl_addVar(vars, TPLADD, "READERREFRESH", "");
1267 if(rdr->typ == R_CCCAM)
1268 {
1269 tpl_addVar(vars, TPLADD, "ENTICO", "image?i=ICENT");
1270 tpl_addVar(vars, TPLADD, "ENTITLEMENT", tpl_getTpl(vars, "READERENTITLEBIT"));
1271 }
1272 else
1273 {
1274 tpl_addVar(vars, TPLADD, "ENTITLEMENT", "");
1275 }
1276 }
1277
1278 if(rdr->enable == 0)
1279 {
1280 tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICENA");
1281 tpl_addVar(vars, TPLADD, "SWITCHTITLE", "Enable this reader");
1282 tpl_addVar(vars, TPLADD, "SWITCH", "enable");
1283 tpl_addVar(vars, TPLADD, "WRITEEMM", "");
1284 }
1285 else
1286 {
1287 tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICDIS");
1288 tpl_addVar(vars, TPLADD, "SWITCHTITLE", "Disable this reader");
1289 tpl_addVar(vars, TPLADD, "SWITCH", "disable");
1290
1291 tpl_addVar(vars, TPLADD, "EMMICO", "image?i=ICEMM");
1292 tpl_addVar(vars, TPLADD, "WRITEEMM", tpl_getTpl(vars, "READERWRITEEMMBIT"));
1293 }
1294
1295 // Add to WebIf Template
1296 tpl_addVar(vars, TPLAPPEND, "READERLIST", tpl_getTpl(vars, "READERSBIT"));
1297
1298 }
1299 else
1300 {
1301
1302 // used only for API
1303 tpl_addVar(vars, TPLADD, "APIREADERENABLED", !rdr->enable ? "0" : "1");
1304 if(cl)
1305 { tpl_printf(vars, TPLADD, "APIREADERTYPE", "%c", cl->typ ? cl->typ : 'x'); }
1306
1307 // Add to API Template
1308 tpl_addVar(vars, TPLAPPEND, "APIREADERLIST", tpl_getTpl(vars, "APIREADERSBIT"));
1309 }
1310 }
1311 }
1312
1313 if(!apicall)
1314 {
1315#ifdef MODULE_CAMD33
1316 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>camd33</option>\n");
1317#endif
1318#ifdef MODULE_CAMD35
1319 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>camd35</option>\n");
1320#endif
1321#ifdef MODULE_CAMD35_TCP
1322 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>cs378x</option>\n");
1323#endif
1324#ifdef MODULE_NEWCAMD
1325 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>newcamd</option>\n");
1326 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>newcamd524</option>\n");
1327#endif
1328#ifdef MODULE_CCCAM
1329 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>cccam</option>\n");
1330#endif
1331#ifdef MODULE_GBOX
1332 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>gbox</option>\n");
1333#endif
1334#ifdef MODULE_RADEGAST
1335 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>radegast</option>\n");
1336#endif
1337#ifdef MODULE_SERIAL
1338 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>serial</option>\n");
1339#endif
1340#ifdef MODULE_CONSTCW
1341 tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>constcw</option>\n");
1342#endif
1343
1344 for(i = 0; i < CS_MAX_MOD; i++)
1345 {
1346 if(cardreaders[i].desc)
1347 { tpl_printf(vars, TPLAPPEND, "ADDPROTOCOL", "<option>%s</option>\n", xml_encode(vars, cardreaders[i].desc)); }
1348 }
1349 return tpl_getTpl(vars, "READERS");
1350 }
1351 else
1352 {
1353 return tpl_getTpl(vars, "APIREADERS");
1354 }
1355}
1356
1357static char *send_oscam_reader_config(struct templatevars *vars, struct uriparams *params)
1358{
1359 int32_t i;
1360 int32_t apicall = 0;
1361 char *reader_ = getParam(params, "label");
1362 char *value;
1363
1364 struct s_reader *rdr;
1365
1366 if(!apicall) { setActiveMenu(vars, MNU_READERS); }
1367
1368 if(strcmp(getParam(params, "action"), "Add") == 0)
1369 {
1370 // Add new reader
1371 struct s_reader *newrdr;
1372 if(!cs_malloc(&newrdr, sizeof(struct s_reader))) { return "0"; }
1373 for(i = 0; i < (*params).paramcount; ++i)
1374 {
1375 if(strcmp((*params).params[i], "action"))
1376 { chk_reader((*params).params[i], (*params).values[i], newrdr); }
1377 }
1378 module_reader_set(newrdr);
1379 reader_ = newrdr->label;
1380 reader_set_defaults(newrdr);
1381 newrdr->enable = 0; // do not start the reader because must configured before
1382 ll_append(configured_readers, newrdr);
1383 }
1384 else if(strcmp(getParam(params, "action"), "Save") == 0)
1385 {
1386
1387 rdr = get_reader_by_label(getParam(params, "label"));
1388 if(!rdr)
1389 { return NULL; }
1390 //if (is_network_reader(rdr))
1391 // inactivate_reader(rdr); //Stop reader before reinitialization
1392 char servicelabels[1024] = "";
1393 char servicelabelslb[1024] = "";
1394
1395 for(i = 0; i < (*params).paramcount; ++i)
1396 {
1397 if((strcmp((*params).params[i], "reader")) && (strcmp((*params).params[i], "action")))
1398 {
1399 if(!strcmp((*params).params[i], "services"))
1400 { snprintf(servicelabels + strlen(servicelabels), sizeof(servicelabels) - strlen(servicelabels), "%s,", (*params).values[i]); }
1401 else if(!strcmp((*params).params[i], "lb_whitelist_services"))
1402 { snprintf(servicelabelslb + strlen(servicelabelslb), sizeof(servicelabelslb) - strlen(servicelabelslb), "%s,", (*params).values[i]); }
1403 else
1404 /*if(strlen((*params).values[i]) > 0)*/
1405 { chk_reader((*params).params[i], (*params).values[i], rdr); }
1406 }
1407 //printf("param %s value %s\n",(*params).params[i], (*params).values[i]);
1408 }
1409 chk_reader("services", servicelabels, rdr);
1410 chk_reader("lb_whitelist_services", servicelabelslb, rdr);
1411
1412 if(is_network_reader(rdr)) //physical readers make trouble if re-started
1413 {
1414 restart_cardreader(rdr, 1);
1415 }
1416
1417 if(write_server() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
1418 }
1419
1420 rdr = get_reader_by_label(reader_);
1421 if(!rdr)
1422 { return NULL; }
1423
1424 // Label, Description
1425 if(!apicall)
1426 {
1427 tpl_addVar(vars, TPLADD, "READERNAME", xml_encode(vars, rdr->label));
1428 tpl_addVar(vars, TPLADD, "DESCRIPTION", xml_encode(vars, rdr->description));
1429 }
1430 else
1431 {
1432 tpl_addVar(vars, TPLADD, "READERNAME", rdr->label);
1433 tpl_addVar(vars, TPLADD, "DESCRIPTION", rdr->description);
1434 }
1435
1436 // enabled
1437 if(!apicall)
1438 {
1439 tpl_addVar(vars, TPLADD, "ENABLED", (rdr->enable == 1) ? "checked" : "");
1440 }
1441 else
1442 {
1443 tpl_addVar(vars, TPLADD, "ENABLEDVALUE", (rdr->enable == 1) ? "1" : "0");
1444 }
1445
1446 // Account
1447 if(!apicall)
1448 {
1449 tpl_addVar(vars, TPLADD, "ACCOUNT", xml_encode(vars, rdr->r_usr));
1450 tpl_addVar(vars, TPLADD, "PASSWORD", xml_encode(vars, rdr->r_pwd));
1451 //TODO Remove USER PASS if they dont display
1452 tpl_addVar(vars, TPLADD, "USER", rdr->r_usr);
1453 tpl_addVar(vars, TPLADD, "PASS", rdr->r_pwd);
1454 }
1455 else
1456 {
1457 tpl_addVar(vars, TPLADD, "ACCOUNT", rdr->r_usr);
1458 tpl_addVar(vars, TPLADD, "PASSWORD", rdr->r_pwd);
1459 //TODO Remove USER PASS if they dont display
1460 tpl_addVar(vars, TPLADD, "USER", rdr->r_usr);
1461 tpl_addVar(vars, TPLADD, "PASS", rdr->r_pwd);
1462 }
1463
1464 // Key Newcamd
1465 for(i = 0; i < (int32_t)sizeof(rdr->ncd_key); i++)
1466 { tpl_printf(vars, TPLAPPEND, "NCD_KEY", "%02X", rdr->ncd_key[i]); }
1467
1468 // Pincode
1469 tpl_addVar(vars, TPLADD, "PINCODE", rdr->pincode);
1470
1471 // Emmfile Path
1472 if(rdr->emmfile) { tpl_addVar(vars, TPLADD, "EMMFILE", (char *)rdr->emmfile); }
1473
1474 // Inactivity timeout
1475 tpl_printf(vars, TPLADD, "INACTIVITYTIMEOUT", "%d", rdr->tcp_ito);
1476
1477 // Receive timeout
1478 tpl_printf(vars, TPLADD, "RECEIVETIMEOUT", "%d", rdr->tcp_rto);
1479
1480 // Connect on init (newcamd only)
1481 if(!apicall)
1482 {
1483 tpl_addVar(vars, TPLADD, "CONNECTONINITCHECKED", (rdr->ncd_connect_on_init == 1) ? "checked" : "");
1484 }
1485 else
1486 {
1487 tpl_addVar(vars, TPLADD, "CONNECTONINITCHECKED", (rdr->ncd_connect_on_init == 1) ? "1" : "0");
1488 }
1489
1490 // Reset Cycle
1491 tpl_printf(vars, TPLADD, "RESETCYCLE", "%d", rdr->resetcycle);
1492
1493 // Disable Serverfilter
1494 if(!apicall)
1495 {
1496 tpl_addVar(vars, TPLADD, "DISABLESERVERFILTERCHECKED", (rdr->ncd_disable_server_filt == 1) ? "checked" : "");
1497 }
1498 else
1499 {
1500 tpl_addVar(vars, TPLADD, "DISABLESERVERFILTERVALUE", (rdr->ncd_disable_server_filt == 1) ? "1" : "0");
1501 }
1502
1503#ifdef MODULE_GHTTP
1504 // Use SSL
1505 if(!apicall)
1506 {
1507 tpl_addVar(vars, TPLADD, "USESSLCHECKED", (rdr->ghttp_use_ssl == 1) ? "checked" : "");
1508 }
1509 else
1510 {
1511 tpl_addVar(vars, TPLADD, "USESSLVALUE", (rdr->ghttp_use_ssl == 1) ? "1" : "0");
1512 }
1513#endif
1514
1515 // Fallback
1516 if(!apicall)
1517 {
1518 tpl_addVar(vars, TPLADD, "FALLBACKCHECKED", (rdr->fallback == 1) ? "checked" : "");
1519 }
1520 else
1521 {
1522 tpl_addVar(vars, TPLADD, "FALLBACKVALUE", (rdr->fallback == 1) ? "1" : "0");
1523 }
1524
1525 // Fallback per caid
1526 value = mk_t_ftab(&rdr->fallback_percaid);
1527 tpl_addVar(vars, TPLADD, "FALLBACK_PERCAID", value);
1528 free_mk_t(value);
1529
1530#ifdef CS_CACHEEX
1531 // Cacheex
1532 if(!apicall)
1533 {
1534 tpl_printf(vars, TPLADD, "TMP", "CACHEEXSELECTED%d", rdr->cacheex.mode);
1535 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1536 }
1537 else
1538 {
1539 tpl_printf(vars, TPLADD, "CACHEEX", "%d", rdr->cacheex.mode);
1540 }
1541 tpl_printf(vars, TPLADD, "CACHEEX_MAXHOP", "%d", rdr->cacheex.maxhop);
1542 value = mk_t_cacheex_hitvaluetab(&rdr->cacheex.filter_caidtab);
1543 //if (strlen(value) > 0)
1544 tpl_printf(vars, TPLADD, "CACHEEX_ECM_FILTER", "%s", value);
1545 free_mk_t(value);
1546
1547 tpl_addVar(vars, TPLADD, "DCCHECKED", (rdr->cacheex.drop_csp == 1) ? "checked" : "");
1548 tpl_addVar(vars, TPLADD, "ARCHECKED", (rdr->cacheex.allow_request == 1) ? "checked" : "");
1549#endif
1550
1551 // BoxID
1552 if(rdr->boxid)
1553 { tpl_printf(vars, TPLADD, "BOXID", "%08X", rdr->boxid); }
1554
1555 // Fix 9993
1556 if(!apicall)
1557 {
1558 tpl_addVar(vars, TPLADD, "FIX9993CHECKED", (rdr->fix_9993 == 1) ? "checked" : "");
1559 }
1560 else
1561 {
1562 tpl_addVar(vars, TPLADD, "FIX9993VALUE", (rdr->fix_9993 == 1) ? "1" : "0");
1563 }
1564
1565 // Drop CWs with wrong checksum:
1566 if(!apicall)
1567 {
1568 tpl_addVar(vars, TPLADD, "DROPBADCWSCHECKED", (rdr->dropbadcws == 1) ? "checked" : "");
1569 }
1570 else
1571 {
1572 tpl_addVar(vars, TPLADD, "DROPBADCWSVALUE", (rdr->dropbadcws == 1) ? "1" : "0");
1573 }
1574
1575 // Disable CWs checksum test:
1576 if(!apicall)
1577 {
1578 tpl_addVar(vars, TPLADD, "DISABLECRCCWSCHECKED", (rdr->disablecrccws == 1) ? "checked" : "");
1579 }
1580 else
1581 {
1582 tpl_addVar(vars, TPLADD, "DISABLECRCCWSVALUE", (rdr->disablecrccws == 1) ? "1" : "0");
1583 }
1584
1585 // Set reader to use GPIO
1586 if(!apicall)
1587 {
1588 tpl_addVar(vars, TPLADD, "USE_GPIOCHECKED", rdr->use_gpio ? "checked" : "");
1589 }
1590 else
1591 {
1592 tpl_addVar(vars, TPLADD, "USE_GPIOVALUE", rdr->use_gpio ? "1" : "0");
1593 }
1594
1595 // AUdisabled
1596 if(!apicall)
1597 {
1598 tpl_addVar(vars, TPLADD, "AUDISABLED", (rdr->audisabled == 1) ? "checked" : "");
1599 }
1600 else
1601 {
1602 tpl_addVar(vars, TPLADD, "AUDISABLEDVALUE", (rdr->audisabled == 1) ? "1" : "0");
1603 }
1604
1605 // AUprovid
1606 if(rdr->auprovid)
1607 { tpl_printf(vars, TPLADD, "AUPROVID", "%06X", rdr->auprovid); }
1608
1609 if(rdr->ecmnotfoundlimit)
1610 { tpl_printf(vars, TPLADD, "ECMNOTFOUNDLIMIT", "%u", rdr->ecmnotfoundlimit); }
1611
1612 // Force Irdeto
1613 if(!apicall)
1614 {
1615 tpl_addVar(vars, TPLADD, "FORCEIRDETOCHECKED", (rdr->force_irdeto == 1) ? "checked" : "");
1616 }
1617 else
1618 {
1619 tpl_addVar(vars, TPLADD, "FORCEIRDETOVALUE", (rdr->force_irdeto == 1) ? "1" : "0");
1620 }
1621
1622 // needsemmfirst
1623
1624 if(!apicall)
1625 {
1626 tpl_addVar(vars, TPLADD, "NEEDSEMMFIRST", (rdr->needsemmfirst == 1) ? "checked" : "");
1627 }
1628 else
1629 {
1630 tpl_addVar(vars, TPLADD, "NEEDSEMMFIRST", (rdr->needsemmfirst == 1) ? "1" : "0");
1631 }
1632
1633 // RSA Key
1634 int32_t len = check_filled(rdr->rsa_mod, 120);
1635 if(len > 0)
1636 {
1637 if(len > 64) { len = 120; }
1638 else { len = 64; }
1639 for(i = 0; i < len; i++) { tpl_printf(vars, TPLAPPEND, "RSAKEY", "%02X", rdr->rsa_mod[i]); }
1640 }
1641
1642 // BoxKey
1643 if(check_filled(rdr->boxkey, sizeof(rdr->boxkey)))
1644 {
1645 for(i = 0; i < (int32_t)sizeof(rdr->boxkey) ; i++)
1646 { tpl_printf(vars, TPLAPPEND, "BOXKEY", "%02X", rdr->boxkey[i]); }
1647 }
1648
1649 // ins7E
1650 if(rdr->ins7E[0x1A])
1651 {
1652 for(i = 0; i < 26 ; i++) { tpl_printf(vars, TPLAPPEND, "INS7E", "%02X", rdr->ins7E[i]); }
1653 }
1654
1655 // ins7E11
1656 if(rdr->ins7E11[0x01])
1657 {
1658 tpl_printf(vars, TPLAPPEND, "INS7E11", "%02X", rdr->ins7E11[0]);
1659 }
1660
1661 // ATR
1662 if(rdr->atr[0])
1663 for(i = 0; i < rdr->atrlen / 2; i++)
1664 { tpl_printf(vars, TPLAPPEND, "ATR", "%02X", rdr->atr[i]); }
1665
1666 // ECM Whitelist
1667 value = mk_t_ecmwhitelist(rdr->ecmWhitelist);
1668 tpl_addVar(vars, TPLADD, "ECMWHITELIST", value);
1669 free_mk_t(value);
1670
1671 // ECM Header Whitelist
1672 value = mk_t_ecmheaderwhitelist(rdr->ecmHeaderwhitelist);
1673 tpl_addVar(vars, TPLADD, "ECMHEADERWHITELIST", value);
1674 free_mk_t(value);
1675
1676 // Deprecated
1677 if(!apicall)
1678 {
1679 tpl_addVar(vars, TPLADD, "DEPRECATEDCHECKED", (rdr->deprecated == 1) ? "checked" : "");
1680 }
1681 else
1682 {
1683 tpl_addVar(vars, TPLADD, "DEPRECATEDVALUE", (rdr->deprecated == 1) ? "1" : "0");
1684 }
1685
1686 // Smargopatch
1687 if(!apicall)
1688 {
1689 tpl_addVar(vars, TPLADD, "SMARGOPATCHCHECKED", (rdr->smargopatch == 1) ? "checked" : "");
1690 }
1691 else
1692 {
1693 tpl_addVar(vars, TPLADD, "SMARGOPATCHVALUE", (rdr->smargopatch == 1) ? "1" : "0");
1694 }
1695
1696 // Autospeed
1697 if(!apicall)
1698 {
1699 tpl_addVar(vars, TPLADD, "AUTOSPEEDCHECKED", (rdr->autospeed == 1) ? "checked" : "");
1700 }
1701 else
1702 {
1703 tpl_addVar(vars, TPLADD, "AUTOSPEEDVALUE", (rdr->autospeed == 1) ? "1" : "0");
1704 }
1705
1706 // sc8in1 dtrrts patch
1707 if(!apicall)
1708 {
1709 tpl_addVar(vars, TPLADD, "SC8IN1DTRRTSPATCHCHECKED", (rdr->sc8in1_dtrrts_patch == 1) ? "checked" : "");
1710 }
1711 else
1712 {
1713 tpl_addVar(vars, TPLADD, "SC8IN1DTRRTSPATCHVALUE", (rdr->sc8in1_dtrrts_patch == 1) ? "1" : "0");
1714 }
1715
1716 // Detect
1717 if(rdr->detect & 0x80)
1718 { tpl_printf(vars, TPLADD, "DETECT", "!%s", RDR_CD_TXT[rdr->detect & 0x7f]); }
1719 else
1720 { tpl_addVar(vars, TPLADD, "DETECT", RDR_CD_TXT[rdr->detect & 0x7f]); }
1721
1722 // Ratelimit
1723 if(rdr->ratelimitecm)
1724 {
1725 tpl_printf(vars, TPLADD, "RATELIMITECM", "%d", rdr->ratelimitecm);
1726 tpl_printf(vars, TPLADD, "RATELIMITTIME", "%d", rdr->ratelimittime);
1727 tpl_printf(vars, TPLADD, "SRVIDHOLDTIME", "%d", rdr->srvidholdtime);
1728 // ECMUNIQUE
1729 if(!apicall)
1730 {
1731 tpl_addVar(vars, TPLADD, "ECMUNIQUECHECKED", (rdr->ecmunique == 1) ? "checked" : "");
1732 }
1733 else
1734 {
1735 tpl_addVar(vars, TPLADD, "ECMUNIQUE", (rdr->ecmunique == 1) ? "1" : "0");
1736 }
1737 }
1738 // Cooldown
1739 if(rdr->cooldown[0] && rdr->cooldown[1])
1740 {
1741 tpl_printf(vars, TPLADD, "COOLDOWNDELAY", "%d", rdr->cooldown[0]);
1742 tpl_printf(vars, TPLADD, "COOLDOWNTIME", "%d", rdr->cooldown[1]);
1743 }
1744 // Frequencies
1745 tpl_printf(vars, TPLADD, "MHZ", "%d", rdr->mhz);
1746 tpl_printf(vars, TPLADD, "CARDMHZ", "%d", rdr->cardmhz);
1747
1748 // Device
1749 if(!apicall)
1750 {
1751 tpl_addVar(vars, TPLADD, "DEVICE", xml_encode(vars, rdr->device));
1752 }
1753 else
1754 {
1755 tpl_addVar(vars, TPLADD, "DEVICE", rdr->device);
1756 }
1757
1758 if(rdr->r_port)
1759 { tpl_printf(vars, TPLAPPEND, "DEVICE", ",%d", rdr->r_port); }
1760 if(rdr->l_port)
1761 {
1762 if(rdr->r_port)
1763 { tpl_printf(vars, TPLAPPEND, "DEVICE", ",%d", rdr->l_port); }
1764 else
1765 { tpl_printf(vars, TPLAPPEND, "DEVICE", ",,%d", rdr->l_port); }
1766 }
1767
1768 // Group
1769 value = mk_t_group(rdr->grp);
1770 tpl_addVar(vars, TPLADD, "GRP", value);
1771 free_mk_t(value);
1772
1773#ifdef WITH_LB
1774 if(rdr->lb_weight)
1775 { tpl_printf(vars, TPLADD, "LBWEIGHT", "%d", rdr->lb_weight); }
1776#endif
1777
1778 //services
1779 if(!apicall)
1780 {
1781 struct s_sidtab *sidtab = cfg.sidtab;
1782 //build matrix
1783 i = 0;
1784 while(sidtab != NULL)
1785 {
1786 tpl_addVar(vars, TPLADD, "SIDLABEL", xml_encode(vars, sidtab->label));
1787 if(rdr->sidtabs.ok & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
1788 else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
1789 tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "READERCONFIGSIDOKBIT"));
1790 if(rdr->sidtabs.no & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
1791 else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
1792 tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "READERCONFIGSIDNOBIT"));
1793 if(rdr->lb_sidtabs.ok & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
1794 else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
1795 tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "READERCONFIGSIDLBOKBIT"));
1796 sidtab = sidtab->next;
1797 i++;
1798 }
1799 }
1800 else
1801 {
1802 value = mk_t_service(&rdr->sidtabs);
1803 if(strlen(value) > 0)
1804 { tpl_addVar(vars, TPLADD, "SERVICES", value); }
1805 free_mk_t(value);
1806 }
1807
1808 // CAID
1809 value = mk_t_caidtab(&rdr->ctab);
1810 tpl_addVar(vars, TPLADD, "CAIDS", value);
1811 free_mk_t(value);
1812
1813 // AESkeys
1814 value = mk_t_aeskeys(rdr);
1815 tpl_addVar(vars, TPLADD, "AESKEYS", value);
1816 free_mk_t(value);
1817
1818 //ident
1819 value = mk_t_ftab(&rdr->ftab);
1820 tpl_addVar(vars, TPLADD, "IDENTS", value);
1821 free_mk_t(value);
1822
1823 //CHID
1824 value = mk_t_ftab(&rdr->fchid);
1825 tpl_addVar(vars, TPLADD, "CHIDS", value);
1826 free_mk_t(value);
1827
1828 //class
1829 value = mk_t_cltab(&rdr->cltab);
1830 tpl_addVar(vars, TPLADD, "CLASS", value);
1831 free_mk_t(value);
1832
1833 if(rdr->cachemm)
1834 { tpl_printf(vars, TPLADD, "EMMCACHE", "%d,%d,%d", rdr->cachemm, rdr->rewritemm, rdr->logemm); }
1835
1836 //savenano
1837 value = mk_t_nano(rdr->s_nano);
1838 tpl_addVar(vars, TPLADD, "SAVENANO", value);
1839 free_mk_t(value);
1840
1841 //blocknano
1842 value = mk_t_nano(rdr->b_nano);
1843 tpl_addVar(vars, TPLADD, "BLOCKNANO", value);
1844 free_mk_t(value);
1845
1846 // Blocke EMM
1847 if(!apicall)
1848 {
1849 tpl_addVar(vars, TPLADD, "BLOCKEMMUNKNOWNCHK", (rdr->blockemm & EMM_UNKNOWN) ? "checked" : "");
1850 tpl_addVar(vars, TPLADD, "BLOCKEMMUNIQCHK", (rdr->blockemm & EMM_UNIQUE) ? "checked" : "");
1851 tpl_addVar(vars, TPLADD, "BLOCKEMMSHAREDCHK", (rdr->blockemm & EMM_SHARED) ? "checked" : "");
1852 tpl_addVar(vars, TPLADD, "BLOCKEMMGLOBALCHK", (rdr->blockemm & EMM_GLOBAL) ? "checked" : "");
1853 }
1854 else
1855 {
1856 tpl_addVar(vars, TPLADD, "BLOCKEMMUNKNOWNVALUE", (rdr->blockemm & EMM_UNKNOWN) ? "1" : "0");
1857 tpl_addVar(vars, TPLADD, "BLOCKEMMUNIQVALUE", (rdr->blockemm & EMM_UNIQUE) ? "1" : "0");
1858 tpl_addVar(vars, TPLADD, "BLOCKEMMSHAREDVALUE", (rdr->blockemm & EMM_SHARED) ? "1" : "0");
1859 tpl_addVar(vars, TPLADD, "BLOCKEMMGLOBALVALUE", (rdr->blockemm & EMM_GLOBAL) ? "1" : "0");
1860 }
1861
1862 // Save EMM
1863 if(!apicall)
1864 {
1865 tpl_addVar(vars, TPLADD, "SAVEEMMUNKNOWNCHK", (rdr->saveemm & EMM_UNKNOWN) ? "checked" : "");
1866 tpl_addVar(vars, TPLADD, "SAVEEMMUNIQCHK", (rdr->saveemm & EMM_UNIQUE) ? "checked" : "");
1867 tpl_addVar(vars, TPLADD, "SAVEEMMSHAREDCHK", (rdr->saveemm & EMM_SHARED) ? "checked" : "");
1868 tpl_addVar(vars, TPLADD, "SAVEEMMGLOBALCHK", (rdr->saveemm & EMM_GLOBAL) ? "checked" : "");
1869 }
1870 else
1871 {
1872 tpl_addVar(vars, TPLADD, "SAVEEMMUNKNOWNVALUE", (rdr->saveemm & EMM_UNKNOWN) ? "1" : "0");
1873 tpl_addVar(vars, TPLADD, "SAVEEMMUNIQVALUE", (rdr->saveemm & EMM_UNIQUE) ? "1" : "0");
1874 tpl_addVar(vars, TPLADD, "SAVEEMMSHAREDVALUE", (rdr->saveemm & EMM_SHARED) ? "1" : "0");
1875 tpl_addVar(vars, TPLADD, "SAVEEMMGLOBALVALUE", (rdr->saveemm & EMM_GLOBAL) ? "1" : "0");
1876 }
1877
1878 value = mk_t_emmbylen(rdr);
1879 if(strlen(value) > 0)
1880 { tpl_addVar(vars, TPLADD, "BLOCKEMMBYLEN", value); }
1881 free_mk_t(value);
1882
1883#ifdef MODULE_CCCAM
1884 if(!strcmp(rdr->cc_version, "2.0.11"))
1885 {
1886 tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED0", "selected");
1887 }
1888 else if(!strcmp(rdr->cc_version, "2.1.1"))
1889 {
1890 tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED1", "selected");
1891 }
1892 else if(!strcmp(rdr->cc_version, "2.1.2"))
1893 {
1894 tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED2", "selected");
1895 }
1896 else if(!strcmp(rdr->cc_version, "2.1.3"))
1897 {
1898 tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED3", "selected");
1899 }
1900 else if(!strcmp(rdr->cc_version, "2.1.4"))
1901 {
1902 tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED4", "selected");
1903 }
1904 else if(!strcmp(rdr->cc_version, "2.2.0"))
1905 {
1906 tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED5", "selected");
1907 }
1908 else if(!strcmp(rdr->cc_version, "2.2.1"))
1909 {
1910 tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED6", "selected");
1911 }
1912 else if(!strcmp(rdr->cc_version, "2.3.0"))
1913 {
1914 tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED7", "selected");
1915 }
1916#endif
1917
1918 tpl_printf(vars, TPLADD, "TMP", "NDSVERSION%d", rdr->ndsversion);
1919 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1920
1921 tpl_printf(vars, TPLADD, "TMP", "NAGRAREAD%d", rdr->nagra_read);
1922 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1923
1924#ifdef MODULE_CCCAM
1925 tpl_printf(vars, TPLADD, "CCCMAXHOPS", "%d", rdr->cc_maxhops);
1926 tpl_printf(vars, TPLADD, "CCCMINDOWN", "%d", rdr->cc_mindown);
1927 tpl_printf(vars, TPLADD, "CCCRESHARE", "%d", rdr->cc_reshare);
1928 tpl_printf(vars, TPLADD, "RESHARE", "%d", cfg.cc_reshare);
1929 tpl_printf(vars, TPLADD, "CCCRECONNECT", "%d", rdr->cc_reconnect);
1930
1931 if(rdr->cc_want_emu)
1932 { tpl_addVar(vars, TPLADD, "CCCWANTEMUCHECKED", "checked"); }
1933 if(rdr->cc_keepalive)
1934 { tpl_addVar(vars, TPLADD, "KEEPALIVECHECKED", "selected"); }
1935#endif
1936
1937 tpl_addVar(vars, TPLADD, "PROTOCOL", reader_get_type_desc(rdr, 0));
1938
1939 // Show only parameters which needed for the reader
1940 switch(rdr->typ)
1941 {
1942 case R_CONSTCW:
1943 case R_DB2COM1:
1944 case R_DB2COM2:
1945 case R_MOUSE :
1946 case R_MP35:
1947 case R_SC8in1 :
1948 case R_SMART :
1949 case R_INTERNAL:
1950 case R_SERIAL :
1951 case R_PCSC :
1952 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1953 break;
1954 case R_CAMD35 :
1955 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCAMD35BIT"));
1956 break;
1957 case R_CS378X :
1958 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCS378XBIT"));
1959 break;
1960 case R_RADEGAST:
1961 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGRADEGASTBIT"));
1962 break;
1963 case R_GHTTP:
1964 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGGHTTPBIT"));
1965 break;
1966 case R_NEWCAMD:
1967 if(rdr->ncd_proto == NCD_525)
1968 {
1969 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGNCD525BIT"));
1970 }
1971 else if(rdr->ncd_proto == NCD_524)
1972 {
1973 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGNCD524BIT"));
1974 }
1975 break;
1976#ifdef MODULE_CCCAM
1977 case R_CCCAM :
1978 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCCCAMBIT"));
1979 break;
1980#endif
1981 default :
1982 tpl_addMsg(vars, "Error: protocol not resolvable");
1983 tpl_addMsg(vars, tpl_printf(vars, TPLADD, "TMP", "Error: protocol number: %d readername: %s", rdr->typ, xml_encode(vars, rdr->label)));
1984 break;
1985
1986 }
1987
1988#ifdef MODULE_CCCAM
1989 if(rdr->typ != R_CCCAM)
1990 {
1991 tpl_printf(vars, TPLADD, "CCCHOP", "%d", rdr->cc_hop);
1992 tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGHOPBIT"));
1993 }
1994#endif
1995
1996 return tpl_getTpl(vars, "READERCONFIG");
1997}
1998
1999static char *send_oscam_reader_stats(struct templatevars *vars, struct uriparams *params, int32_t apicall)
2000{
2001
2002 if(!apicall) { setActiveMenu(vars, MNU_READERS); }
2003
2004 int8_t error;
2005 struct s_client *cl = NULL;
2006 struct s_reader *rdr;
2007
2008 rdr = get_reader_by_label(getParam(params, "label"));
2009 error = (rdr ? 0 : 1);
2010
2011 if(!error && rdr)
2012 {
2013 cl = rdr->client;
2014 error = (cl ? 0 : 1);
2015 }
2016
2017 if(error)
2018 {
2019 tpl_addVar(vars, TPLAPPEND, "READERSTATSROW", "<TR><TD colspan=\"8\"> No statistics found - Reader exist and active?</TD></TR>");
2020 if(!apicall)
2021 { return tpl_getTpl(vars, "READERSTATS"); }
2022 else
2023 { return tpl_getTpl(vars, "APIREADERSTATS"); }
2024 }
2025
2026#ifdef WITH_LB
2027 char *stxt[] = {"found", "cache1", "cache2", "cache3",
2028 "not found", "timeout", "sleeping",
2029 "fake", "invalid", "corrupt", "no card", "expdate",
2030 "disabled", "stopped"
2031 };
2032
2033 if(strcmp(getParam(params, "action"), "resetstat") == 0)
2034 {
2035 char *rcs = getParam(params, "rc");
2036 int32_t retval = 0;
2037 if(strlen(rcs) > 0)
2038 {
2039 int8_t rc;
2040 rc = atoi(rcs);
2041 retval = clean_stat_by_rc(rdr, rc, 0);
2042 cs_log("Reader %s stats %d %s entr%s deleted by WebIF from %s",
2043 rdr->label, retval, stxt[rc],
2044 retval == 1 ? "y" : "ies",
2045 cs_inet_ntoa(GET_IP()));
2046 }
2047 else
2048 {
2049 clear_reader_stat(rdr);
2050 cs_log("Reader %s stats resetted by WebIF from %s", rdr->label, cs_inet_ntoa(GET_IP()));
2051 }
2052
2053 }
2054
2055 if(strcmp(getParam(params, "action"), "deleterecord") == 0)
2056 {
2057 char *record = getParam(params, "record");
2058 if(strlen(record) > 0)
2059 {
2060 int32_t retval = 0;
2061 uint32_t caid, provid, sid, cid, len;
2062 sscanf(record, "%4x:%6x:%4x:%4x:%4x", &caid, &provid, &sid, &cid, &len);
2063 retval = clean_stat_by_id(rdr, caid, provid, sid, cid, len);
2064 cs_log("Reader %s stats %d entr%s deleted by WebIF from %s",
2065 rdr->label, retval,
2066 retval == 1 ? "y" : "ies",
2067 cs_inet_ntoa(GET_IP()));
2068 }
2069 }
2070
2071 if(strcmp(getParam(params, "action"), "updateecmlen") == 0)
2072 {
2073 update_ecmlen_from_stat(rdr);
2074 write_server();
2075 }
2076
2077#endif
2078
2079 if(!apicall)
2080 {
2081 tpl_addVar(vars, TPLADD, "LABEL", xml_encode(vars, rdr->label));
2082 tpl_addVar(vars, TPLADD, "ENCODEDLABEL", urlencode(vars, rdr->label));
2083 }
2084 else
2085 {
2086 tpl_addVar(vars, TPLADD, "READERNAME", rdr->label);
2087 }
2088
2089
2090
2091 if(apicall)
2092 {
2093 int32_t i, emmcount = 0;
2094 char *ttxt[] = {"unknown", "unique", "shared", "global"};
2095
2096 for(i = 0; i < 4; i++)
2097 {
2098 tpl_addVar(vars, TPLADD, "EMMRESULT", "error");
2099 tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
2100 tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmerror[i]);
2101 tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
2102 emmcount += rdr->emmerror[i];
2103 tpl_printf(vars, TPLADD, "TOTALERROR", "%d", emmcount);
2104 }
2105 emmcount = 0;
2106 for(i = 0; i < 4; i++)
2107 {
2108 tpl_addVar(vars, TPLADD, "EMMRESULT", "written");
2109 tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
2110 tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmwritten[i]);
2111 tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
2112 emmcount += rdr->emmwritten[i];
2113 tpl_printf(vars, TPLADD, "TOTALWRITTEN", "%d", emmcount);
2114 }
2115 emmcount = 0;
2116 for(i = 0; i < 4; i++)
2117 {
2118 tpl_addVar(vars, TPLADD, "EMMRESULT", "skipped");
2119 tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
2120 tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmskipped[i]);
2121 tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
2122 emmcount += rdr->emmskipped[i];
2123 tpl_printf(vars, TPLADD, "TOTALSKIPPED", "%d", emmcount);
2124 }
2125 emmcount = 0;
2126 for(i = 0; i < 4; i++)
2127 {
2128 tpl_addVar(vars, TPLADD, "EMMRESULT", "blocked");
2129 tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
2130 tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmblocked[i]);
2131 tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
2132 emmcount += rdr->emmblocked[i];
2133 tpl_printf(vars, TPLADD, "TOTALBLOCKED", "%d", emmcount);
2134 }
2135 }
2136
2137 if(apicall)
2138 {
2139 char *txt = "UNDEF";
2140 switch(rdr->card_status)
2141 {
2142 case NO_CARD:
2143 txt = "OFF";
2144 break;
2145 case UNKNOWN:
2146 txt = "UNKNOWN";
2147 break;
2148 case CARD_NEED_INIT:
2149 txt = "NEEDINIT";
2150 break;
2151 case CARD_INSERTED:
2152 if(cl->typ == 'p')
2153 { txt = "CONNECTED"; }
2154 else
2155 { txt = "CARDOK"; }
2156 break;
2157 case CARD_FAILURE:
2158 txt = "ERROR";
2159 break;
2160 default:
2161 txt = "UNDEF";
2162 }
2163 tpl_addVar(vars, TPLADD, "READERSTATUS", txt);
2164 tpl_printf(vars, TPLADD, "READERCAID", "%04X", rdr->caid);
2165 }
2166
2167 int32_t rowcount = 0;
2168 uint64_t ecmcount = 0;
2169 time_t lastaccess = 0;
2170
2171#ifdef WITH_LB
2172 int32_t rc2hide = (-1);
2173 if(strlen(getParam(params, "hide")) > 0)
2174 { rc2hide = atoi(getParam(params, "hide")); }
2175
2176 if(rdr->lb_stat)
2177 {
2178 int32_t statsize;
2179 // @todo alno: sort by click, 0=ascending, 1=descending (maybe two buttons or reverse on second click)
2180 READER_STAT **statarray = get_sorted_stat_copy(rdr, 0, &statsize);
2181 char channame[32];
2182 for(; rowcount < statsize; ++rowcount)
2183 {
2184 READER_STAT *s = statarray[rowcount];
2185 if(!(s->rc == rc2hide))
2186 {
2187 struct tm lt;
2188 localtime_r(&s->last_received.time, &lt); // fixme we need walltime!
2189 ecmcount += s->ecm_count;
2190 if(!apicall)
2191 {
2192 tpl_printf(vars, TPLADD, "CHANNEL", "%04X:%06X:%04X:%04X", s->caid, s->prid, s->srvid, s->chid);
2193 tpl_addVar(vars, TPLADD, "CHANNELNAME", xml_encode(vars, get_servicename(cur_client(), s->srvid, s->caid, channame)));
2194 tpl_printf(vars, TPLADD, "ECMLEN", "%04hX", s->ecmlen);
2195 tpl_addVar(vars, TPLADD, "RC", stxt[s->rc]);
2196 tpl_printf(vars, TPLADD, "TIME", "%dms", s->time_avg);
2197 if(s->time_stat[s->time_idx])
2198 { tpl_printf(vars, TPLADD, "TIMELAST", "%dms", s->time_stat[s->time_idx]); }
2199 else
2200 { tpl_addVar(vars, TPLADD, "TIMELAST", ""); }
2201 tpl_printf(vars, TPLADD, "COUNT", "%d", s->ecm_count);
2202
2203 if(s->last_received.time)
2204 {
2205 tpl_printf(vars, TPLADD, "LAST", "%02d.%02d.%02d %02d:%02d:%02d", lt.tm_mday, lt.tm_mon + 1, lt.tm_year % 100, lt.tm_hour, lt.tm_min, lt.tm_sec);
2206
2207 }
2208 else
2209 {
2210 tpl_addVar(vars, TPLADD, "LAST", "never");
2211 }
2212 }
2213 else
2214 {
2215 tpl_printf(vars, TPLADD, "ECMCAID", "%04X", s->caid);
2216 tpl_printf(vars, TPLADD, "ECMPROVID", "%06X", s->prid);
2217 tpl_printf(vars, TPLADD, "ECMSRVID", "%04X", s->srvid);
2218 tpl_printf(vars, TPLADD, "ECMLEN", "%04hX", s->ecmlen);
2219 tpl_addVar(vars, TPLADD, "ECMCHANNELNAME", xml_encode(vars, get_servicename(cur_client(), s->srvid, s->caid, channame)));
2220 tpl_printf(vars, TPLADD, "ECMTIME", "%d", s->time_avg);
2221 tpl_printf(vars, TPLADD, "ECMTIMELAST", "%d", s->time_stat[s->time_idx]);
2222 tpl_printf(vars, TPLADD, "ECMRC", "%d", s->rc);
2223 tpl_addVar(vars, TPLADD, "ECMRCS", stxt[s->rc]);
2224 if(s->last_received.time)
2225 {
2226 char tbuffer [30];
2227 strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
2228 tpl_addVar(vars, TPLADD, "ECMLAST", tbuffer);
2229 }
2230 else
2231 {
2232 tpl_addVar(vars, TPLADD, "ECMLAST", "");
2233 }
2234 tpl_printf(vars, TPLADD, "ECMCOUNT", "%d", s->ecm_count);
2235
2236 if(s->last_received.time > lastaccess)
2237 { lastaccess = s->last_received.time; }
2238 }
2239
2240 if(!apicall)
2241 {
2242 if(s->rc == E_NOTFOUND)
2243 {
2244 tpl_addVar(vars, TPLAPPEND, "READERSTATSROWNOTFOUND", tpl_getTpl(vars, "READERSTATSBIT"));
2245 tpl_addVar(vars, TPLADD, "READERSTATSNFHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"6\">Not found</TD>");
2246 tpl_printf(vars, TPLAPPEND, "READERSTATSNFHEADLINE", "<TD CLASS=\"subheadline\" colspan=\"2\"><A HREF=\"readerstats.html?label=%s&amp;action=resetstat&amp;rc=4\">delete all %s</A></TD></TR>\n",
2247 urlencode(vars, rdr->label),
2248 stxt[s->rc]);
2249 }
2250 else if(s->rc == E_TIMEOUT)
2251 {
2252 tpl_addVar(vars, TPLAPPEND, "READERSTATSROWTIMEOUT", tpl_getTpl(vars, "READERSTATSBIT"));
2253 tpl_addVar(vars, TPLADD, "READERSTATSTOHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"6\">Timeout</TD>");
2254 tpl_printf(vars, TPLAPPEND, "READERSTATSTOHEADLINE", "<TD CLASS=\"subheadline\" colspan=\"2\"><A HREF=\"readerstats.html?label=%s&amp;action=resetstat&amp;rc=5\">delete all %s</A></TD></TR>\n",
2255 urlencode(vars, rdr->label),
2256 stxt[s->rc]);
2257 }
2258 else
2259 { tpl_addVar(vars, TPLAPPEND, "READERSTATSROWFOUND", tpl_getTpl(vars, "READERSTATSBIT")); }
2260 }
2261 else
2262 {
2263
2264 tpl_addVar(vars, TPLAPPEND, "ECMSTATS", tpl_getTpl(vars, "APIREADERSTATSECMBIT"));
2265 }
2266 }
2267 }
2268 free(statarray);
2269 }
2270 else
2271#endif
2272 tpl_addVar(vars, TPLAPPEND, "READERSTATSROW", "<TR><TD colspan=\"8\"> No statistics found </TD></TR>");
2273
2274 tpl_printf(vars, TPLADD, "ROWCOUNT", "%d", rowcount);
2275
2276 if(lastaccess > 0)
2277 {
2278 char tbuffer [30];
2279 struct tm lt;
2280 localtime_r(&lastaccess, &lt);
2281 strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
2282 tpl_addVar(vars, TPLADD, "LASTACCESS", tbuffer);
2283 }
2284 else
2285 {
2286 tpl_addVar(vars, TPLADD, "LASTACCESS", "");
2287 }
2288
2289 if(apicall)
2290 {
2291 if(cl)
2292 {
2293 char *value = get_ecm_historystring(cl);
2294 tpl_addVar(vars, TPLADD, "ECMHISTORY", value);
2295 free_mk_t(value);
2296 }
2297 }
2298
2299 tpl_printf(vars, TPLADD, "TOTALECM", "%" PRIu64, ecmcount);
2300
2301 if(!apicall)
2302 { return tpl_getTpl(vars, "READERSTATS"); }
2303 else
2304 { return tpl_getTpl(vars, "APIREADERSTATS"); }
2305}
2306
2307static char *send_oscam_user_config_edit(struct templatevars *vars, struct uriparams *params, int32_t apicall)
2308{
2309 struct s_auth *account, *ptr;
2310 char user[sizeof(first_client->account->usr)];
2311
2312 int32_t i;
2313
2314 if(!apicall) { setActiveMenu(vars, MNU_USERS); }
2315
2316 if(strcmp(getParam(params, "action"), "Save As") == 0) { cs_strncpy(user, getParam(params, "newuser"), sizeof(user) / sizeof(char)); }
2317 else { cs_strncpy(user, getParam(params, "user"), sizeof(user) / sizeof(char)); }
2318
2319 for(account = cfg.account; account != NULL && strcmp(user, account->usr) != 0; account = account->next) { ; }
2320
2321 // Create a new user if it doesn't yet
2322 if(account == NULL)
2323 {
2324 i = 1;
2325 while(strlen(user) < 1)
2326 {
2327 snprintf(user, sizeof(user) / sizeof(char) - 1, "NEWUSER%d", i);
2328 for(account = cfg.account; account != NULL && strcmp(user, account->usr) != 0; account = account->next) { ; }
2329 if(account != NULL) { user[0] = '\0'; }
2330 ++i;
2331 }
2332 if(!cs_malloc(&account, sizeof(struct s_auth))) { return "0"; }
2333 if(cfg.account == NULL) { cfg.account = account; }
2334 else
2335 {
2336 for(ptr = cfg.account; ptr != NULL && ptr->next != NULL; ptr = ptr->next) { ; }
2337 ptr->next = account;
2338 }
2339 account_set_defaults(account);
2340 account->disabled = 1;
2341 cs_strncpy((char *)account->usr, user, sizeof(account->usr));
2342 if(!account->grp)
2343 { account->grp = 1; }
2344 tpl_addMsg(vars, "New user has been added with default settings");
2345
2346 if(write_userdb() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
2347 // no need to refresh anything here as the account is disabled by default and there's no client with this new account anyway!
2348 }
2349
2350 if((strcmp(getParam(params, "action"), "Save") == 0) || (strcmp(getParam(params, "action"), "Save As") == 0))
2351 {
2352 char servicelabels[1024] = "";
2353
2354 for(i = 0; i < (*params).paramcount; i++)
2355 {
2356 if((strcmp((*params).params[i], "action")) &&
2357 (strcmp((*params).params[i], "user")) &&
2358 (strcmp((*params).params[i], "newuser")) &&
2359 (strcmp((*params).params[i], "part")))
2360 {
2361
2362 if(!strcmp((*params).params[i], "services"))
2363 { snprintf(servicelabels + strlen(servicelabels), sizeof(servicelabels) - strlen(servicelabels), "%s,", (*params).values[i]); }
2364 else
2365 { chk_account((*params).params[i], (*params).values[i], account); }
2366 }
2367 }
2368 chk_account("services", servicelabels, account);
2369 tpl_addMsg(vars, "Account updated");
2370
2371 refresh_oscam(REFR_CLIENTS);
2372
2373 if(write_userdb() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
2374 }
2375
2376 if(!apicall)
2377 {
2378 tpl_addVar(vars, TPLADD, "USERNAME", xml_encode(vars, account->usr));
2379 tpl_addVar(vars, TPLADD, "PASSWORD", xml_encode(vars, account->pwd));
2380 tpl_addVar(vars, TPLADD, "DESCRIPTION", xml_encode(vars, account->description));
2381 }
2382 else
2383 {
2384 tpl_addVar(vars, TPLADD, "USERNAME", account->usr);
2385 tpl_addVar(vars, TPLADD, "PASSWORD", account->pwd);
2386 tpl_addVar(vars, TPLADD, "DESCRIPTION", account->description);
2387 }
2388
2389 //Disabled
2390 if(!apicall)
2391 {
2392 if(account->disabled)
2393 { tpl_addVar(vars, TPLADD, "DISABLEDCHECKED", "selected"); }
2394 }
2395 else
2396 {
2397 tpl_printf(vars, TPLADD, "DISABLEDVALUE", "%d", account->disabled);
2398 }
2399
2400 //Expirationdate
2401 struct tm timeinfo;
2402 cs_gmtime_r(&account->expirationdate, &timeinfo);
2403 char buf [80];
2404 strftime(buf, 80, "%Y-%m-%d", &timeinfo);
2405 if(strcmp(buf, "1970-01-01")) { tpl_addVar(vars, TPLADD, "EXPDATE", buf); }
2406
2407 //Allowed TimeFrame
2408 if(account->allowedtimeframe[0] && account->allowedtimeframe[1])
2409 {
2410 tpl_printf(vars, TPLADD, "ALLOWEDTIMEFRAME", "%02d:%02d-%02d:%02d",
2411 account->allowedtimeframe[0] / 60,
2412 account->allowedtimeframe[0] % 60,
2413 account->allowedtimeframe[1] / 60,
2414 account->allowedtimeframe[1] % 60);
2415 }
2416
2417 //Group
2418 char *value = mk_t_group(account->grp);
2419 tpl_addVar(vars, TPLADD, "GROUPS", value);
2420 free_mk_t(value);
2421
2422 // allowed protocols
2423 value = mk_t_allowedprotocols(account);
2424 tpl_addVar(vars, TPLADD, "ALLOWEDPROTOCOLS", value);
2425 free_mk_t(value);
2426
2427 //Hostname
2428 tpl_addVar(vars, TPLADD, "DYNDNS", xml_encode(vars, account->dyndns));
2429
2430 //Uniq
2431 if(!apicall)
2432 {
2433 tpl_printf(vars, TPLADD, "TMP", "UNIQSELECTED%d", account->uniq);
2434 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2435 }
2436 else
2437 {
2438 tpl_printf(vars, TPLADD, "UNIQVALUE", "%d", account->uniq);
2439 }
2440
2441 //Sleep
2442 if(!account->tosleep) { tpl_addVar(vars, TPLADD, "SLEEP", "0"); }
2443 else { tpl_printf(vars, TPLADD, "SLEEP", "%d", account->tosleep); }
2444
2445 //Monlevel selector
2446 if(!apicall)
2447 {
2448 tpl_printf(vars, TPLADD, "TMP", "MONSELECTED%d", account->monlvl);
2449 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2450 }
2451 else
2452 {
2453 tpl_printf(vars, TPLADD, "MONVALUE", "%d", account->monlvl);
2454 }
2455
2456 //Au
2457 if(account->autoau == 1)
2458 { tpl_addVar(vars, TPLADD, "AUREADER", "1"); }
2459 else if(account->aureader_list)
2460 {
2461 value = mk_t_aureader(account);
2462 tpl_addVar(vars, TPLADD, "AUREADER", value);
2463 free_mk_t(value);
2464 }
2465
2466 if(!apicall)
2467 {
2468 /* SERVICES */
2469 struct s_sidtab *sidtab = cfg.sidtab;
2470 //build matrix
2471 i = 0;
2472 while(sidtab != NULL)
2473 {
2474 tpl_addVar(vars, TPLADD, "SIDLABEL", xml_encode(vars, sidtab->label));
2475 if(account->sidtabs.ok & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
2476 else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
2477 tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "USEREDITSIDOKBIT"));
2478 if(account->sidtabs.no & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
2479 else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
2480 tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "USEREDITSIDNOBIT"));
2481 sidtab = sidtab->next;
2482 i++;
2483 }
2484 }
2485 else
2486 {
2487 value = mk_t_service(&account->sidtabs);
2488 if(strlen(value) > 0)
2489 { tpl_addVar(vars, TPLADD, "SERVICES", value); }
2490 free_mk_t(value);
2491 }
2492
2493 // CAID
2494 value = mk_t_caidtab(&account->ctab);
2495 tpl_addVar(vars, TPLADD, "CAIDS", value);
2496 free_mk_t(value);
2497
2498 //ident
2499 value = mk_t_ftab(&account->ftab);
2500 tpl_addVar(vars, TPLADD, "IDENTS", value);
2501 free_mk_t(value);
2502
2503 //CHID
2504 value = mk_t_ftab(&account->fchid);
2505 tpl_addVar(vars, TPLADD, "CHIDS", value);
2506 free_mk_t(value);
2507
2508 //class
2509 value = mk_t_cltab(&account->cltab);
2510 tpl_addVar(vars, TPLADD, "CLASS", value);
2511 free_mk_t(value);
2512
2513 //Betatunnel
2514 value = mk_t_tuntab(&account->ttab);
2515 tpl_addVar(vars, TPLADD, "BETATUNNELS", value);
2516 free_mk_t(value);
2517
2518 //SUPPRESSCMD08
2519 if(!apicall)
2520 {
2521 if(account->c35_suppresscmd08)
2522 { tpl_addVar(vars, TPLADD, "SUPPRESSCMD08", "selected"); }
2523 }
2524 else
2525 {
2526 tpl_printf(vars, TPLADD, "SUPPRESSCMD08VALUE", "%d", account->c35_suppresscmd08);
2527 }
2528
2529 //Sleepsend
2530 tpl_printf(vars, TPLADD, "SLEEPSEND", "%u", account->c35_sleepsend);
2531
2532 //User Max Idle
2533 tpl_printf(vars, TPLADD, "UMAXIDLE", "%u", account->umaxidle);
2534
2535 //EMM Reassembly selector
2536 if(!apicall)
2537 {
2538 tpl_printf(vars, TPLADD, "TMP", "EMMRSELECTED%d", account->emm_reassembly);
2539 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2540 }
2541 else
2542 {
2543 tpl_printf(vars, TPLADD, "EMMRVALUE", "%d", account->emm_reassembly);
2544 }
2545
2546#ifdef CS_CACHEEX
2547 // Cacheex
2548 if(!apicall)
2549 {
2550 tpl_printf(vars, TPLADD, "TMP", "CACHEEXSELECTED%d", account->cacheex.mode);
2551 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2552
2553 }
2554 else
2555 {
2556 tpl_printf(vars, TPLADD, "CACHEEX", "%d", account->cacheex.mode);
2557 }
2558 tpl_printf(vars, TPLADD, "CACHEEX_MAXHOP", "%d", account->cacheex.maxhop);
2559
2560 value = mk_t_cacheex_hitvaluetab(&account->cacheex.filter_caidtab);
2561 //if (strlen(value) > 0)
2562 tpl_printf(vars, TPLADD, "CACHEEX_ECM_FILTER", "%s", value);
2563 free_mk_t(value);
2564
2565 tpl_addVar(vars, TPLADD, "DCCHECKED", (account->cacheex.drop_csp == 1) ? "checked" : "");
2566 tpl_addVar(vars, TPLADD, "ARCHECKED", (account->cacheex.allow_request == 1) ? "checked" : "");
2567
2568#endif
2569
2570 //Keepalive
2571 if(!apicall)
2572 {
2573 if(account->ncd_keepalive)
2574 { tpl_addVar(vars, TPLADD, "KEEPALIVE", "selected"); }
2575 }
2576 else
2577 {
2578 tpl_printf(vars, TPLADD, "KEEPALIVEVALUE", "%d", account->ncd_keepalive);
2579 }
2580
2581#ifdef CS_ANTICASC
2582 tpl_printf(vars, TPLADD, "AC_USERS", "%d", account->ac_users);
2583 tpl_printf(vars, TPLADD, "CFGNUMUSERS", "%d", cfg.ac_users);
2584 if(!apicall)
2585 {
2586 tpl_printf(vars, TPLADD, "TMP", "PENALTY%d", account->ac_penalty);
2587 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2588 char *tmp = NULL;
2589 switch(cfg.ac_penalty)
2590 {
2591 case 0:
2592 tmp = "(0) Only write to log";
2593 break;
2594 case 1:
2595 tmp = "(1) Fake DW delayed";
2596 break;
2597 case 2:
2598 tmp = "(2) Ban";
2599 break;
2600 case 3:
2601 tmp = "(3) Real DW delayed";
2602 break;
2603 }
2604 tpl_addVar(vars, TPLADD, "CFGPENALTY", tmp);
2605 }
2606 else
2607 {
2608 tpl_printf(vars, TPLADD, "PENALTYVALUE", "%d", account->ac_penalty);
2609 }
2610#endif
2611
2612#ifdef MODULE_CCCAM
2613 tpl_printf(vars, TPLADD, "CCCMAXHOPS", "%d", account->cccmaxhops);
2614 tpl_printf(vars, TPLADD, "CCCRESHARE", "%d", account->cccreshare);
2615 tpl_printf(vars, TPLADD, "RESHARE", "%d", cfg.cc_reshare);
2616
2617 //CCcam Ignore Reshare
2618 tpl_printf(vars, TPLADD, "TMP", "CCCIGNRSHRSELECTED%d", account->cccignorereshare);
2619 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2620 tpl_addVar(vars, TPLADD, "CFGIGNORERESHARE",
2621 cfg.cc_ignore_reshare == 0 ?
2622 "0 - use reshare level of Server" : "1 - use reshare level of Reader or User");
2623
2624 //CCcam Stealth Mode
2625 tpl_printf(vars, TPLADD, "TMP", "CCCSTEALTHSELECTED%d", account->cccstealth);
2626 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2627
2628 tpl_addVar(vars, TPLADD, "STEALTH", cfg.cc_stealth ? "enable" : "disable");
2629#endif
2630
2631 //Failban
2632 tpl_printf(vars, TPLADD, "FAILBAN", "%d", account->failban);
2633
2634 if(!apicall)
2635 { return tpl_getTpl(vars, "USEREDIT"); }
2636 else
2637 { return tpl_getTpl(vars, "APIUSEREDIT"); }
2638
2639}
2640
2641static void webif_add_client_proto(struct templatevars *vars, struct s_client *cl, const char *proto)
2642{
2643 tpl_addVar(vars, TPLADDONCE, "PROTOICON", "");
2644 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", "");
2645 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", "");
2646 if(!cl) { return; }
2647#ifdef MODULE_NEWCAMD
2648 if(streq(proto, "newcamd") && cl->typ == 'c')
2649 {
2650 if(cfg.http_showpicons)
2651 {
2652 char picon_name[32];
2653 snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%s_%s", (char *)proto, newcamd_get_client_name(cl->ncd_client_id));
2654 if(picon_exists(picon_name))
2655 {
2656 tpl_printf(vars, TPLADDONCE, "CLIENTPROTO", "%s (%s)", proto, newcamd_get_client_name(cl->ncd_client_id));
2657 tpl_printf(vars, TPLADD, "PROTOICON",
2658 "<img class=\"protoicon\" src=\"image?i=IC_%s_%s\" alt=\"IC_%s_%s\" title=\"Protocol %s %s\">",
2659 proto, newcamd_get_client_name(cl->ncd_client_id), proto, newcamd_get_client_name(cl->ncd_client_id), proto, newcamd_get_client_name(cl->ncd_client_id));
2660 }
2661 else
2662 {
2663 tpl_printf(vars, TPLADDONCE, "CLIENTPROTO", "%s (%s)", proto, newcamd_get_client_name(cl->ncd_client_id));
2664 tpl_printf(vars, TPLADD, "PROTOICON", "<SPAN TITLE=\"IC_%s_%s\">%s (%s)</SPAN>",
2665 proto, newcamd_get_client_name(cl->ncd_client_id), proto, newcamd_get_client_name(cl->ncd_client_id));
2666 }
2667 }
2668 else
2669 {
2670 tpl_printf(vars, TPLADDONCE, "PROTOICON", "%s (%s)", proto, newcamd_get_client_name(cl->ncd_client_id));
2671 tpl_printf(vars, TPLADDONCE, "CLIENTPROTO", "%s (%s)", proto, newcamd_get_client_name(cl->ncd_client_id));
2672 }
2673 return;
2674 }
2675#endif
2676#ifdef MODULE_CCCAM
2677 if(strncmp(proto, "cccam", 5) == 0)
2678 {
2679 struct cc_data *cc = cl->cc;
2680 if(cc && cc->remote_version && cc->remote_build)
2681 {
2682 if(cfg.http_showpicons)
2683 {
2684 char picon_name[32];
2685 snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%s_%s_%s", proto, cc->remote_version, cc->remote_build);
2686 if(picon_exists(picon_name))
2687 {
2688 tpl_printf(vars, TPLADDONCE, "CLIENTPROTO", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
2689 tpl_printf(vars, TPLADD, "CLIENTPROTOTITLE", "cccam extinfo: %s missing icon: IC_%s_%s_%s", cc->extended_mode ? cc->remote_oscam : "", proto, cc->remote_version, cc->remote_build);
2690 tpl_printf(vars, TPLADD, "PROTOICON",
2691 "<img class=\"protoicon\" src=\"image?i=IC_%s_%s_%s\" alt=\"IC_%s (%s-%s)\" title=\"Protocol %s (%s-%s) %s\">",
2692 proto, cc->remote_version, cc->remote_build, proto, cc->remote_version, cc->remote_build, proto, cc->remote_version, cc->remote_build, cc->extended_mode ? cc->remote_oscam : "");
2693 }
2694 else
2695 {
2696 tpl_printf(vars, TPLADD, "PROTOICON", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
2697 tpl_printf(vars, TPLADDONCE, "CLIENTPROTO", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
2698 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", cc->extended_mode ? cc->remote_oscam : "");
2699 }
2700 }
2701 else
2702 {
2703 tpl_printf(vars, TPLADDONCE, "PROTOICON", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
2704 tpl_printf(vars, TPLADDONCE, "CLIENTPROTO", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
2705 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", cc->extended_mode ? cc->remote_oscam : "");
2706 }
2707 }
2708 return;
2709 }
2710#endif
2711 if(cfg.http_showpicons)
2712 {
2713 char picon_name[32];
2714 snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%s", proto);
2715 if(picon_exists(picon_name))
2716 {
2717 tpl_printf(vars, TPLADD, "PROTOICON", "<img class=\"protoicon\" src=\"image?i=IC_%s\" alt=\"IC_%s\" title=\"Protocol %s\">", proto, proto, proto);
2718 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", (char *)proto);
2719 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", "");
2720 }
2721 else
2722 {
2723 tpl_printf(vars, TPLADD, "PROTOICON", "<SPAN TITLE=\"IC_%s\">%s</SPAN>", proto, proto);
2724 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", (char *)proto);
2725 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", "");
2726 }
2727 }
2728 else
2729 {
2730 tpl_addVar(vars, TPLADDONCE, "PROTOICON", (char *)proto);
2731 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", (char *)proto);
2732 tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", "");
2733 }
2734}
2735
2736static void clear_account_stats(struct s_auth *account)
2737{
2738 account->cwfound = 0;
2739 account->cwcache = 0;
2740 account->cwnot = 0;
2741 account->cwtun = 0;
2742 account->cwignored = 0;
2743 account->cwtout = 0;
2744 account->emmok = 0;
2745 account->emmnok = 0;
2746#ifdef CW_CYCLE_CHECK
2747 account->cwcycledchecked = 0;
2748 account->cwcycledok = 0;
2749 account->cwcyclednok = 0;
2750 account->cwcycledign = 0;
2751#endif
2752 cacheex_clear_account_stats(account);
2753}
2754
2755static void clear_all_account_stats(void)
2756{
2757 struct s_auth *account = cfg.account;
2758 while(account)
2759 {
2760 clear_account_stats(account);
2761 account = account->next;
2762 }
2763}
2764
2765static void clear_system_stats(void)
2766{
2767 first_client->cwfound = 0;
2768 first_client->cwcache = 0;
2769 first_client->cwnot = 0;
2770 first_client->cwtun = 0;
2771 first_client->cwignored = 0;
2772 first_client->cwtout = 0;
2773 first_client->emmok = 0;
2774 first_client->emmnok = 0;
2775 cacheex_clear_client_stats(first_client);
2776}
2777
2778static void kill_account_thread(struct s_auth *account)
2779{
2780 struct s_client *cl;
2781 for(cl = first_client->next; cl ; cl = cl->next)
2782 {
2783 if(cl->account == account)
2784 {
2785 if(get_module(cl)->type & MOD_CONN_NET)
2786 {
2787 kill_thread(cl);
2788 }
2789 else
2790 {
2791 cl->account = first_client->account;
2792 }
2793 }
2794 }
2795}
2796
2797static char *send_oscam_user_config(struct templatevars *vars, struct uriparams *params, int32_t apicall)
2798{
2799 struct s_auth *account;
2800 struct s_client *cl;
2801 char *user = getParam(params, "user");
2802 int32_t found = 0;
2803
2804 if(!apicall) { setActiveMenu(vars, MNU_USERS); }
2805
2806 if(strcmp(getParam(params, "action"), "reinit") == 0)
2807 {
2808 if(!cfg.http_readonly)
2809 { refresh_oscam(REFR_ACCOUNTS); }
2810 }
2811
2812 if(strcmp(getParam(params, "action"), "delete") == 0)
2813 {
2814 if(cfg.http_readonly)
2815 {
2816 tpl_addMsg(vars, "WebIf is in readonly mode. No deletion will be made!");
2817 }
2818 else
2819 {
2820 struct s_auth *account_prev = NULL;
2821
2822 for(account = cfg.account; (account); account = account->next)
2823 {
2824 if(strcmp(account->usr, user) == 0)
2825 {
2826 if(account_prev == NULL)
2827 { cfg.account = account->next; }
2828 else
2829 { account_prev->next = account->next; }
2830 ll_clear(account->aureader_list);
2831 kill_account_thread(account);
2832 add_garbage(account);
2833 found = 1;
2834 break;
2835 }
2836 account_prev = account;
2837 }
2838 if(found > 0)
2839 {
2840 if(write_userdb() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
2841 }
2842 else { tpl_addMsg(vars, "Sorry but the specified user doesn't exist. No deletion will be made!"); }
2843 }
2844 }
2845
2846 if((strcmp(getParam(params, "action"), "disable") == 0) || (strcmp(getParam(params, "action"), "enable") == 0))
2847 {
2848 account = get_account_by_name(getParam(params, "user"));
2849 if(account)
2850 {
2851 if(strcmp(getParam(params, "action"), "disable") == 0)
2852 {
2853 account->disabled = 1;
2854 kill_account_thread(account);
2855 }
2856 else
2857 { account->disabled = 0; }
2858 if(write_userdb() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
2859 }
2860 else
2861 {
2862 tpl_addMsg(vars, "Sorry but the specified user doesn't exist. No deletion will be made!");
2863 }
2864 }
2865
2866 if(strcmp(getParam(params, "action"), "resetstats") == 0)
2867 {
2868 account = get_account_by_name(getParam(params, "user"));
2869 if(account) { clear_account_stats(account); }
2870 }
2871
2872 if(strcmp(getParam(params, "action"), "resetserverstats") == 0)
2873 {
2874 clear_system_stats();
2875 }
2876
2877 if(strcmp(getParam(params, "action"), "resetalluserstats") == 0)
2878 {
2879 clear_all_account_stats();
2880 }
2881
2882 if((strcmp(getParam(params, "part"), "adduser") == 0) && (!cfg.http_readonly))
2883 {
2884 tpl_addVar(vars, TPLAPPEND, "NEWUSERFORM", tpl_getTpl(vars, "ADDNEWUSER"));
2885 }
2886 else
2887 {
2888 if(cfg.http_refresh > 0)
2889 {
2890 tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", cfg.http_refresh);
2891 tpl_addVar(vars, TPLADD, "REFRESHURL", "userconfig.html");
2892 tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
2893 }
2894 }
2895
2896
2897 /* List accounts*/
2898 char *status, *expired, *classname, *lastchan;
2899 time_t now = time((time_t *)0);
2900 int32_t isec = 0, chsec = 0;
2901
2902 char *filter = NULL;
2903 int32_t clientcount = 0;
2904 if(apicall)
2905 {
2906 filter = getParam(params, "label");
2907 }
2908
2909 int32_t total_users = 0;
2910 int32_t disabled_users = 0;
2911 int32_t expired_users = 0;
2912 int32_t active_users = 0;
2913 int32_t connected_users = 0;
2914 int32_t online_users = 0;
2915 int8_t isactive;
2916 int32_t casc_users = 0;
2917 int32_t casc_users2 = 0;
2918 int32_t n_request = 0;
2919
2920
2921 if(cfg.http_showpicons) { tpl_addVar(vars, TPLADD, "PICONHEADER", "<TH>Image</TH>"); }
2922
2923 for(account = cfg.account; (account); account = account->next)
2924 {
2925 //clear for next client
2926 total_users++;
2927 isactive = 1;
2928
2929 status = "offline";
2930 expired = "";
2931 classname = "offline";
2932 isec = 0;
2933 chsec = 0;
2934
2935 //reset caid/srevid template variables
2936 tpl_addVar(vars, TPLADD, "CLIENTCAID", "");
2937 tpl_addVar(vars, TPLADD, "CLIENTSRVID", "");
2938 tpl_addVar(vars, TPLADD, "LASTCHANNEL", "");
2939
2940 if(account->expirationdate && account->expirationdate < now)
2941 {
2942 expired = " (expired)";
2943 classname = "expired";
2944 expired_users++;
2945 isactive = 0;
2946 }
2947 else
2948 {
2949 expired = "";
2950 }
2951
2952 if(account->disabled != 0)
2953 {
2954 expired = " (disabled)";
2955 classname = "disabled";
2956 tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICENA");
2957 tpl_addVar(vars, TPLADD, "SWITCHTITLE", "Enable this account");
2958 tpl_addVar(vars, TPLADD, "SWITCH", "enable");
2959 disabled_users++;
2960 isactive = 0;
2961 }
2962 else
2963 {
2964 tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICDIS");
2965 tpl_addVar(vars, TPLADD, "SWITCHTITLE", "Disable this account");
2966 tpl_addVar(vars, TPLADD, "SWITCH", "disable");
2967 }
2968
2969 if(isactive)
2970 { active_users++; }
2971
2972 int32_t lastresponsetm = 0, latestactivity = 0;
2973 const char *proto = "";
2974 double cwrate = 0.0, cwrate2 = 0.0;
2975
2976 //search account in active clients
2977 isactive = 0;
2978 int16_t nrclients = 0;
2979 struct s_client *latestclient = NULL;
2980 for(cl = first_client->next; cl ; cl = cl->next)
2981 {
2982 if(cl->account && !strcmp(cl->account->usr, account->usr))
2983 {
2984 if(cl->lastecm > latestactivity || cl->login > latestactivity)
2985 {
2986 if(cl->lastecm > cl->login) { latestactivity = cl->lastecm; }
2987 else { latestactivity = cl->login; }
2988 latestclient = cl;
2989 }
2990 nrclients++;
2991 }
2992 }
2993 if(account->cwfound + account->cwnot + account->cwcache > 0)
2994 {
2995 cwrate = now - account->firstlogin;
2996 cwrate /= (account->cwfound + account->cwnot + account->cwcache);
2997 }
2998
2999 casc_users = 0;
3000 casc_users2 = 0;
3001 if(latestclient != NULL)
3002 {
3003 char channame[32];
3004 status = (!apicall) ? "<b>connected</b>" : "connected";
3005 if(account->expirationdate && account->expirationdate < now) { classname = "expired"; }
3006 else { classname = "connected"; }
3007 proto = client_get_proto(latestclient);
3008 if(latestclient->last_srvid != NO_SRVID_VALUE || latestclient->last_caid != NO_CAID_VALUE)
3009 { lastchan = xml_encode(vars, get_servicename(latestclient, latestclient->last_srvid, latestclient->last_caid, channame)); }
3010 else
3011 { lastchan = ""; }
3012 tpl_printf(vars, TPLADD, "CLIENTCAID", "%04X", latestclient->last_caid);
3013 tpl_printf(vars, TPLADD, "CLIENTSRVID", "%04X", latestclient->last_srvid);
3014 if(cfg.http_showpicons && !apicall)
3015 {
3016 char picon_name[32];
3017 snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%04X_%04X", latestclient->last_caid, latestclient->last_srvid);
3018 if(picon_exists(picon_name))
3019 {
3020 tpl_printf(vars, TPLADD, "LASTCHANNEL",
3021 "<img class=\"userpicon\" src=\"image?i=IC_%s\" alt=\"%s\" title=\"%s\">",
3022 picon_name, lastchan, lastchan);
3023 }
3024 else
3025 {
3026 tpl_addVar(vars, TPLADDONCE, "LASTCHANNEL", lastchan);
3027 }
3028 }
3029 else
3030 {
3031 tpl_addVar(vars, TPLADDONCE, "LASTCHANNEL", lastchan);
3032 }
3033 lastresponsetm = latestclient->cwlastresptime;
3034 tpl_addVar(vars, TPLADDONCE, "CLIENTIP", cs_inet_ntoa(latestclient->ip));
3035 connected_users++;
3036 casc_users = ll_count(latestclient->cascadeusers);
3037 LL_ITER it = ll_iter_create(latestclient->cascadeusers);
3038 struct s_cascadeuser *cu;
3039 while((cu = ll_iter_next(&it)))
3040 {
3041 if(cu->cwrate > 0)
3042 { casc_users2++; }
3043 }
3044 if(latestactivity > 0)
3045 {
3046 isec = now - latestactivity;
3047 chsec = latestclient->lastswitch ? now - latestclient->lastswitch : 0;
3048 if(isec < cfg.hideclient_to)
3049 {
3050 isactive = 1;
3051 status = (!apicall) ? "<b>online</b>" : "online";
3052 if(account->expirationdate && account->expirationdate < now) { classname = "expired"; }
3053 else { classname = "online"; }
3054 if(latestclient->cwfound + latestclient->cwnot + latestclient->cwcache > 0)
3055 {
3056 cwrate2 = now - latestclient->login;
3057 cwrate2 /= (latestclient->cwfound + latestclient->cwnot + latestclient->cwcache);
3058 tpl_printf(vars, TPLADDONCE, "CWRATE2", " (%.2f)", cwrate2);
3059 online_users++;
3060 }
3061 }
3062 }
3063 }
3064
3065 n_request = 0;
3066 if(latestclient != NULL){
3067 n_request = latestclient->n_request[0];
3068 }
3069
3070
3071 tpl_printf(vars, TPLADD, "CWOK", "%d", account->cwfound);
3072 tpl_printf(vars, TPLADD, "CWNOK", "%d", account->cwnot);
3073 tpl_printf(vars, TPLADD, "CWIGN", "%d", account->cwignored);
3074 tpl_printf(vars, TPLADD, "CWTOUT", "%d", account->cwtout);
3075#ifdef CW_CYCLE_CHECK
3076 tpl_printf(vars, TPLADD, "CWCYCLECHECKED", "%d", account->cwcycledchecked);
3077 tpl_printf(vars, TPLADD, "CWCYCLEOK", "%d", account->cwcycledok);
3078 tpl_printf(vars, TPLADD, "CWCYCLENOK", "%d", account->cwcyclednok);
3079 tpl_printf(vars, TPLADD, "CWCYCLEIGN", "%d", account->cwcycledign);
3080#endif
3081 tpl_printf(vars, TPLADD, "CWCACHE", "%d", account->cwcache);
3082 tpl_printf(vars, TPLADD, "CWTUN", "%d", account->cwtun);
3083 tpl_printf(vars, TPLADD, "EMMOK", "%d", account->emmok);
3084 tpl_printf(vars, TPLADD, "EMMNOK", "%d", account->emmnok);
3085 tpl_printf(vars, TPLADD, "CWRATE", "%.2f", cwrate);
3086 tpl_printf(vars, TPLADD, "CASCUSERS", "%d", casc_users);
3087 tpl_printf(vars, TPLADD, "CASCUSERS2", "%d", casc_users2);
3088 tpl_printf(vars, TPLADD, "CASCUSERSCOMB", "%d/%d", casc_users, casc_users2);
3089 tpl_printf(vars, TPLADD, "N_REQUEST_MIN", "%d", n_request);
3090
3091 if(isactive > 0 || !cfg.http_hide_idle_clients)
3092 {
3093
3094 tpl_printf(vars, TPLADDONCE, "CWLASTRESPONSET", "%d", lastresponsetm);
3095 tpl_addVar(vars, TPLADDONCE, "IDLESECS", sec2timeformat(vars, isec));
3096
3097 if(isactive > 0)
3098 {
3099 tpl_printf(vars, TPLADDONCE, "CLIENTTIMEONCHANNELAPI", "%d", chsec);
3100 tpl_addVar(vars, TPLADDONCE, "CLIENTTIMEONCHANNEL", sec2timeformat(vars, chsec));
3101 if(account->tosleep)
3102 {
3103 tpl_printf(vars, TPLADDONCE, "CLIENTTIMETOSLEEP", "Sleeping in %d minutes", account->tosleep - (chsec / 60));
3104 tpl_printf(vars, TPLADDONCE, "CLIENTTIMETOSLEEPAPI", "%d", account->tosleep - (chsec / 60));
3105 }
3106 else
3107 {
3108 tpl_addVar(vars, TPLADDONCE, "CLIENTTIMETOSLEEP", "No sleep defined");
3109 tpl_addVar(vars, TPLADDONCE, "CLIENTTIMETOSLEEPAPI", "undefined");
3110 }
3111 }
3112 else
3113 {
3114 tpl_addVar(vars, TPLADDONCE, "CLIENTTIMEONCHANNELAPI", "");
3115 tpl_addVar(vars, TPLADDONCE, "CLIENTTIMEONCHANNEL", "");
3116 tpl_addVar(vars, TPLADDONCE, "CLIENTTIMETOSLEEP", "");
3117 tpl_addVar(vars, TPLADDONCE, "CLIENTTIMETOSLEEPAPI", "");
3118 }
3119
3120 webif_add_client_proto(vars, latestclient, proto);
3121 }
3122 else
3123 {
3124 tpl_addVar(vars, TPLADDONCE, "PROTOICON", "");
3125 }
3126
3127 tpl_addVar(vars, TPLADD, "CLASSNAME", classname);
3128 if(cfg.http_showpicons && !apicall)
3129 {
3130 if(picon_exists(xml_encode(vars, account->usr)))
3131 {
3132 tpl_printf(vars, TPLADD, "USER",
3133 "<img class=\"usericon\" src=\"image?i=IC_%s\" TITLE=\"%s\">",
3134 xml_encode(vars, account->usr), xml_encode(vars, account->usr));
3135 }
3136 else
3137 {
3138 tpl_addVar(vars, TPLADD, "USER", xml_encode(vars, account->usr));
3139 }
3140 }
3141 else
3142 {
3143 tpl_addVar(vars, TPLADD, "USER", xml_encode(vars, account->usr));
3144 }
3145 char *value = mk_t_group(account->grp);
3146 tpl_addVar(vars, TPLADD, "GROUPS", value);
3147 free_mk_t(value);
3148 tpl_addVar(vars, TPLADD, "USERENC", urlencode(vars, account->usr));
3149 tpl_addVar(vars, TPLADD, "DESCRIPTION", xml_encode(vars, account->description ? account->description : ""));
3150 tpl_addVar(vars, TPLADD, "STATUS", status);
3151 tpl_addVar(vars, TPLAPPEND, "STATUS", expired);
3152 if(nrclients > 1) { tpl_printf(vars, TPLADDONCE, "CLIENTCOUNTNOTIFIER", "<SPAN CLASS=\"span_notifier\">%d</SPAN>", nrclients); }
3153
3154 //Expirationdate
3155 struct tm timeinfo;
3156 cs_gmtime_r(&account->expirationdate, &timeinfo);
3157 char buf [80];
3158 strftime(buf, 80, "%Y-%m-%d", &timeinfo);
3159 if(strcmp(buf, "1970-01-01")) { tpl_addVar(vars, TPLADD, "EXPDATE", buf); }
3160 else { tpl_addVar(vars, TPLADD, "EXPDATE", ""); }
3161
3162 // append row to table template
3163 if(!apicall)
3164 { tpl_addVar(vars, TPLAPPEND, "USERCONFIGS", tpl_getTpl(vars, "USERCONFIGLISTBIT")); }
3165 else if(!filter || strcmp(filter, account->usr) == 0 || strcmp(filter, "all") == 0 || strlen(filter) == 0)
3166 {
3167 tpl_addVar(vars, TPLAPPEND, "APIUSERCONFIGS", tpl_getTpl(vars, "APIUSERCONFIGLISTBIT"));
3168 ++clientcount;
3169 }
3170 }
3171
3172 tpl_printf(vars, TPLADD, "TOTAL_USERS", "%d", total_users);
3173 tpl_printf(vars, TPLADD, "TOTAL_DISABLED", "%d", disabled_users);
3174 tpl_printf(vars, TPLADD, "TOTAL_EXPIRED", "%d", expired_users);
3175 tpl_printf(vars, TPLADD, "TOTAL_ACTIVE", "%d", active_users);
3176 tpl_printf(vars, TPLADD, "TOTAL_CONNECTED", "%d", connected_users);
3177 tpl_printf(vars, TPLADD, "TOTAL_ONLINE", "%d", online_users);
3178
3179
3180 float ecmsum = first_client->cwfound + first_client->cwnot + first_client->cwignored + first_client->cwtout + first_client->cwcache; //dont count TUN its included
3181 if(ecmsum < 1) ecmsum = 1;
3182 float ecmpos = first_client->cwfound + first_client->cwcache; // dont count TUN its included
3183 if(ecmpos < 1) ecmpos = 1;
3184 float ecmneg = first_client->cwnot + first_client->cwignored + first_client->cwtout;
3185 if(ecmneg < 1) ecmneg = 1;
3186
3187 //if one of the stats overloaded, reset all stats!
3188 if(first_client->cwfound<0
3189 || first_client->cwnot<0
3190 || first_client->cwignored<0
3191 || first_client->cwtout<0
3192 || first_client->cwcache<0
3193 || first_client->cwtun<0
3194 || first_client->emmok<0
3195 || first_client->emmnok<0
3196#ifdef CS_CACHEEX
3197 || first_client->cwcacheexgot<0
3198 || first_client->cwcacheexpush<0
3199 || first_client->cwcacheexhit<0
3200#endif
3201 || (first_client->cwfound * 100 / ecmsum)<0
3202 || (first_client->cwnot * 100 / ecmsum)<0
3203 || (first_client->cwignored * 100 / ecmsum)<0
3204 || (first_client->cwtout * 100 / ecmsum)<0
3205 || (first_client->cwcache * 100 / ecmsum)<0
3206 || (first_client->cwtun * 100 / ecmsum)<0
3207 || ((first_client->cwfound + first_client->cwcache) * 100 / ecmsum)<0
3208 || ((first_client->cwnot + first_client->cwignored + first_client->cwtout) * 100 / ecmsum)<0
3209 || (first_client->cwfound * 100 / ecmpos)<0
3210 || (first_client->cwcache * 100 / ecmpos)<0
3211 || (first_client->cwnot * 100 / ecmneg)<0
3212 || (first_client->cwignored * 100 / ecmneg)<0
3213 || (first_client->cwtout * 100 / ecmneg)<0
3214 ){
3215 clear_system_stats();
3216 ecmsum = 1;
3217 ecmpos = 1;
3218 ecmneg = 1;
3219 }
3220 //end reset stats
3221
3222 tpl_printf(vars, TPLADD, "TOTAL_ECM_MIN", "%d", first_client->n_request[0]);
3223 tpl_printf(vars, TPLADD, "TOTAL_CW", "%d", (int)ecmsum);
3224 tpl_printf(vars, TPLADD, "TOTAL_CWOK", "%d", first_client->cwfound);
3225 tpl_printf(vars, TPLADD, "TOTAL_CWNOK", "%d", first_client->cwnot);
3226 tpl_printf(vars, TPLADD, "TOTAL_CWIGN", "%d", first_client->cwignored);
3227 tpl_printf(vars, TPLADD, "TOTAL_CWTOUT", "%d", first_client->cwtout);
3228 tpl_printf(vars, TPLADD, "TOTAL_CWCACHE", "%d", first_client->cwcache);
3229 tpl_printf(vars, TPLADD, "TOTAL_CWTUN", "%d", first_client->cwtun);
3230 tpl_printf(vars, TPLADD, "TOTAL_CWPOS", "%d", first_client->cwfound + first_client->cwcache);
3231 tpl_printf(vars, TPLADD, "TOTAL_CWNEG", "%d", first_client->cwnot + first_client->cwignored + first_client->cwtout);
3232
3233
3234 tpl_printf(vars, TPLADD, "REL_CWOK", "%.2f", first_client->cwfound * 100 / ecmsum);
3235 tpl_printf(vars, TPLADD, "REL_CWNOK", "%.2f", first_client->cwnot * 100 / ecmsum);
3236 tpl_printf(vars, TPLADD, "REL_CWIGN", "%.2f", first_client->cwignored * 100 / ecmsum);
3237 tpl_printf(vars, TPLADD, "REL_CWTOUT", "%.2f", first_client->cwtout * 100 / ecmsum);
3238 tpl_printf(vars, TPLADD, "REL_CWCACHE", "%.2f", first_client->cwcache * 100 / ecmsum);
3239 tpl_printf(vars, TPLADD, "REL_CWTUN", "%.2f", first_client->cwtun * 100 / ecmsum);
3240 tpl_printf(vars, TPLADD, "REL_CWPOS", "%.2f", (first_client->cwfound + first_client->cwcache) * 100 / ecmsum);
3241 tpl_printf(vars, TPLADD, "REL_CWNEG", "%.2f", (first_client->cwnot + first_client->cwignored + first_client->cwtout) * 100 / ecmsum);
3242 tpl_printf(vars, TPLADD, "REL_CWPOSOK", "%.2f", first_client->cwfound * 100 / ecmpos);
3243 tpl_printf(vars, TPLADD, "REL_CWPOSCACHE", "%.2f", first_client->cwcache * 100 / ecmpos);
3244 tpl_printf(vars, TPLADD, "REL_CWNEGNOK", "%.2f", first_client->cwnot * 100 / ecmneg);
3245 tpl_printf(vars, TPLADD, "REL_CWNEGIGN", "%.2f", first_client->cwignored * 100 / ecmneg);
3246 tpl_printf(vars, TPLADD, "REL_CWNEGTOUT", "%.2f", first_client->cwtout * 100 / ecmneg);
3247
3248
3249 if(!apicall)
3250 { return tpl_getTpl(vars, "USERCONFIGLIST"); }
3251 else
3252 {
3253 if(!filter || clientcount > 0)
3254 {
3255 return tpl_getTpl(vars, "APIUSERCONFIGLIST");
3256 }
3257 else
3258 {
3259 tpl_printf(vars, TPLADD, "APIERRORMESSAGE", "Invalid client %s", xml_encode(vars, filter));
3260 return tpl_getTpl(vars, "APIERROR");
3261 }
3262 }
3263
3264}
3265
3266#define ENTITLEMENT_PAGE_SIZE 500
3267
3268#ifdef MODULE_CCCSHARE
3269static char *get_cardsystem_desc_by_caid(uint16_t caid)
3270{
3271 if(caid >= 0x0100 && caid <= 0x01FF) { return "seca"; }
3272 if(caid >= 0x0500 && caid <= 0x05FF) { return "viaccess"; }
3273 if(caid >= 0x0600 && caid <= 0x06FF) { return "irdeto"; }
3274 if(caid >= 0x0900 && caid <= 0x09FF) { return "videoguard"; }
3275 if(caid >= 0x0B00 && caid <= 0x0BFF) { return "conax"; }
3276 if(caid >= 0x0D00 && caid <= 0x0DFF) { return "cryptoworks"; }
3277 if(caid >= 0x1700 && caid <= 0x17FF) { return "betacrypt"; }
3278 if(caid >= 0x1800 && caid <= 0x18FF) { return "nagra"; }
3279 if(caid >= 0x4B00 && caid <= 0x4BFF) { return "tongfang"; }
3280 if(caid >= 0x4AE0 && caid <= 0x4AE1) { return "drecrypt"; }
3281 if(caid == 0x5581 || caid == 0x4AEE) { return "bulcrypt"; }
3282 if(caid == 0x5501 || caid == 0x5504 || caid == 0x5511) { return "griffin"; }
3283 if(caid == 0x4ABF) { return "dgcrypt"; }
3284 return "???";
3285}
3286
3287static void print_cards(struct templatevars *vars, struct uriparams *params, struct cc_card **cardarray, int32_t cardsize,
3288 int8_t show_global_list, struct s_reader *rdr, int32_t offset, int32_t apicall)
3289{
3290 if(cardarray)
3291 {
3292 uint8_t serbuf[8];
3293 int32_t i, count = 0;
3294 char provname[83];
3295 struct cc_card *card;
3296 int32_t cardcount = 0;
3297 int32_t providercount = 0;
3298 int32_t nodecount = 0;
3299
3300 char *provider = "";
3301
3302 // @todo alno: sort by click, 0=ascending, 1=descending (maybe two buttons or reverse on second click)
3303 for(i = offset; i < cardsize; ++i)
3304 {
3305 card = cardarray[i];
3306 if(count == ENTITLEMENT_PAGE_SIZE)
3307 { break; }
3308 count++;
3309
3310 if(!apicall)
3311 {
3312 if(show_global_list)
3313 { rdr = card->origin_reader; }
3314 if(rdr)
3315 { tpl_printf(vars, TPLADD, "HOST", "%s:%d", xml_encode(vars, rdr->device), rdr->r_port); }
3316 tpl_printf(vars, TPLADD, "CAID", "%04X", card->caid);
3317 tpl_printf(vars, TPLADD, "CARDTYPE", "%02X", card->card_type);
3318 }
3319 else
3320 {
3321 tpl_printf(vars, TPLADD, "APICARDNUMBER", "%d", cardcount);
3322 tpl_printf(vars, TPLADD, "APICAID", "%04X", card->caid);
3323 tpl_printf(vars, TPLADD, "APICARDTYPE", "%02X", card->card_type);
3324 }
3325
3326 if(cc_UA_valid(card->hexserial)) //Add UA:
3327 {
3328 cc_UA_cccam2oscam(card->hexserial, serbuf, card->caid);
3329 char tmp[20];
3330 tpl_printf(vars, TPLAPPEND, "HOST", "<BR>\nUA_Oscam:%s", cs_hexdump(0, serbuf, 8, tmp, 20));
3331 tpl_printf(vars, TPLAPPEND, "HOST", "<BR>\nUA_CCcam:%s", cs_hexdump(0, card->hexserial, 8, tmp, 20));
3332 }
3333 if(!apicall)
3334 {
3335 int32_t n;
3336 LL_ITER its = ll_iter_create(card->goodsids);
3337 struct cc_srvid *srv;
3338 n = 0;
3339 tpl_addVar(vars, TPLADD, "SERVICESGOOD", "");
3340 while((srv = ll_iter_next(&its)))
3341 {
3342 tpl_printf(vars, TPLAPPEND, "SERVICESGOOD", "%04X%s", srv->sid, ++n % 10 == 0 ? "<BR>\n" : " ");
3343 }
3344
3345 its = ll_iter_create(card->badsids);
3346 n = 0;
3347 tpl_addVar(vars, TPLADD, "SERVICESBAD", "");
3348 while((srv = ll_iter_next(&its)))
3349 {
3350 tpl_printf(vars, TPLAPPEND, "SERVICESBAD", "%04X%s", srv->sid, ++n % 10 == 0 ? "<BR>\n" : " ");
3351 }
3352 }
3353
3354 tpl_addVar(vars, TPLADD, "SYSTEM", get_cardsystem_desc_by_caid(card->caid));
3355
3356 tpl_printf(vars, TPLADD, "SHAREID", "%08X", card->id);
3357 tpl_printf(vars, TPLADD, "REMOTEID", "%08X", card->remote_id);
3358 tpl_printf(vars, TPLADD, "UPHOPS", "%d", card->hop);
3359 tpl_printf(vars, TPLADD, "MAXDOWN", "%d", card->reshare);
3360
3361 LL_ITER pit = ll_iter_create(card->providers);
3362 struct cc_provider *prov;
3363
3364 providercount = 0;
3365
3366 if(!apicall)
3367 { tpl_addVar(vars, TPLADD, "PROVIDERS", ""); }
3368 else
3369 { tpl_addVar(vars, TPLADD, "PROVIDERLIST", ""); }
3370
3371 while((prov = ll_iter_next(&pit)))
3372 {
3373 provider = xml_encode(vars, get_provider(card->caid, prov->prov, provname, sizeof(provname)));
3374
3375 if(!apicall)
3376 {
3377 if(prov->sa[0] || prov->sa[1] || prov->sa[2] || prov->sa[3])
3378 {
3379 tpl_printf(vars, TPLAPPEND, "PROVIDERS", "%s SA:%02X%02X%02X%02X<BR>\n", provider, prov->sa[0], prov->sa[1], prov->sa[2], prov->sa[3]);
3380 }
3381 else
3382 {
3383 tpl_printf(vars, TPLAPPEND, "PROVIDERS", "%s<BR>\n", provider);
3384 }
3385 }
3386 else
3387 {
3388 if(prov->sa[0] || prov->sa[1] || prov->sa[2] || prov->sa[3])
3389 { tpl_printf(vars, TPLADD, "APIPROVIDERSA", "%02X%02X%02X%02X", prov->sa[0], prov->sa[1], prov->sa[2], prov->sa[3]); }
3390 else
3391 { tpl_addVar(vars, TPLADD, "APIPROVIDERSA", ""); }
3392 tpl_printf(vars, TPLADD, "APIPROVIDERCAID", "%04X", card->caid);
3393 tpl_printf(vars, TPLADD, "APIPROVIDERPROVID", "%06X", prov->prov);
3394 tpl_printf(vars, TPLADD, "APIPROVIDERNUMBER", "%d", providercount);
3395 tpl_addVar(vars, TPLADD, "APIPROVIDERNAME", xml_encode(vars, provider));
3396 tpl_addVar(vars, TPLAPPEND, "PROVIDERLIST", tpl_getTpl(vars, "APICCCAMCARDPROVIDERBIT"));
3397
3398 }
3399 providercount++;
3400 tpl_printf(vars, TPLADD, "APITOTALPROVIDERS", "%d", providercount);
3401 }
3402
3403 LL_ITER nit = ll_iter_create(card->remote_nodes);
3404 uint8_t *node;
3405
3406 nodecount = 0;
3407 if(!apicall) { tpl_addVar(vars, TPLADD, "NODES", ""); }
3408 else { tpl_addVar(vars, TPLADD, "NODELIST", ""); }
3409
3410 while((node = ll_iter_next(&nit)))
3411 {
3412
3413 if(!apicall)
3414 {
3415 tpl_printf(vars, TPLAPPEND, "NODES", "%02X%02X%02X%02X%02X%02X%02X%02X<BR>\n",
3416 node[0], node[1], node[2], node[3], node[4], node[5], node[6], node[7]);
3417 }
3418 else
3419 {
3420 tpl_printf(vars, TPLADD, "APINODE", "%02X%02X%02X%02X%02X%02X%02X%02X", node[0], node[1], node[2], node[3], node[4], node[5], node[6], node[7]);
3421 tpl_printf(vars, TPLADD, "APINODENUMBER", "%d", nodecount);
3422 tpl_addVar(vars, TPLAPPEND, "NODELIST", tpl_getTpl(vars, "APICCCAMCARDNODEBIT"));
3423 }
3424 nodecount++;
3425 tpl_printf(vars, TPLADD, "APITOTALNODES", "%d", nodecount);
3426 }
3427
3428 if(!apicall)
3429 { tpl_addVar(vars, TPLAPPEND, "CCCAMSTATSENTRY", tpl_getTpl(vars, "ENTITLEMENTCCCAMENTRYBIT")); }
3430 else
3431 { tpl_addVar(vars, TPLAPPEND, "CARDLIST", tpl_getTpl(vars, "APICCCAMCARDBIT")); }
3432
3433 cardcount++;
3434 }
3435 // set previous Link if needed
3436 if(offset >= ENTITLEMENT_PAGE_SIZE)
3437 {
3438 tpl_printf(vars, TPLAPPEND, "CONTROLS", "<A HREF=\"entitlements.html?offset=%d&globallist=%s&amp;label=%s\"> << PREVIOUS < </A>",
3439 offset - ENTITLEMENT_PAGE_SIZE,
3440 getParam(params, "globallist"),
3441 getParam(params, "label"));
3442 }
3443
3444 // set next link if needed
3445 if(cardsize > count && offset < cardsize)
3446 {
3447 tpl_printf(vars, TPLAPPEND, "CONTROLS", "<A HREF=\"entitlements.html?offset=%d&globallist=%s&amp;label=%s\"> > NEXT >> </A>",
3448 offset + ENTITLEMENT_PAGE_SIZE,
3449 getParam(params, "globallist"),
3450 getParam(params, "label"));
3451 }
3452
3453 if(!apicall)
3454 {
3455 tpl_printf(vars, TPLADD, "TOTALS", "card count=%d", cardsize);
3456 tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTCCCAMBIT"));
3457 }
3458 else
3459 {
3460 tpl_printf(vars, TPLADD, "APITOTALCARDS", "%d", cardsize);
3461 }
3462
3463 }
3464 else
3465 {
3466 if(!apicall)
3467 {
3468 tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTGENERICBIT"));
3469 tpl_addVar(vars, TPLADD, "LOGHISTORY", "no cards found<BR>\n");
3470 }
3471 else
3472 {
3473 tpl_printf(vars, TPLADD, "APITOTALCARDS", "%d", 0);
3474 }
3475 }
3476
3477}
3478#endif
3479
3480static char *send_oscam_entitlement(struct templatevars *vars, struct uriparams *params, int32_t apicall)
3481{
3482 if(!apicall) { setActiveMenu(vars, MNU_READERS); }
3483 char *reader_ = getParam(params, "label");
3484#ifdef MODULE_CCCAM
3485 char *sharelist_ = getParam(params, "globallist");
3486 int32_t show_global_list = sharelist_ && sharelist_[0] == '1';
3487
3488 struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
3489 if(show_global_list || strlen(reader_) || (rdr && rdr->typ == R_CCCAM))
3490 {
3491
3492 if(show_global_list || (rdr && rdr->typ == R_CCCAM && rdr->enable))
3493 {
3494
3495 if(show_global_list)
3496 {
3497 tpl_addVar(vars, TPLADD, "READERNAME", "GLOBAL");
3498 tpl_addVar(vars, TPLADD, "APIHOST", "GLOBAL");
3499 tpl_addVar(vars, TPLADD, "APIHOSTPORT", "GLOBAL");
3500 }
3501 else
3502 {
3503 if(!apicall)
3504 {
3505 tpl_addVar(vars, TPLADD, "READERNAME", xml_encode(vars, rdr->label));
3506 tpl_addVar(vars, TPLADD, "APIHOST", xml_encode(vars, rdr->device));
3507 }
3508 else
3509 {
3510 tpl_addVar(vars, TPLADD, "READERNAME", rdr->label);
3511 tpl_addVar(vars, TPLADD, "APIHOST", rdr->device);
3512 tpl_printf(vars, TPLADD, "APIHOSTPORT", "%d", rdr->r_port);
3513 }
3514 }
3515
3516#ifdef MODULE_CCCSHARE
3517 int32_t offset = atoi(getParam(params, "offset")); //should be 0 if parameter is missed on very first call
3518 int32_t cardsize;
3519 if(show_global_list)
3520 {
3521 int32_t i;
3522 LLIST **sharelist = get_and_lock_sharelist();
3523 LLIST *sharelist2 = ll_create("web-sharelist");
3524 for(i = 0; i < CAID_KEY; i++)
3525 {
3526 if(sharelist[i])
3527 { ll_putall(sharelist2, sharelist[i]); }
3528 }
3529 unlock_sharelist();
3530 struct cc_card **cardarray = get_sorted_card_copy(sharelist2, 0, &cardsize);
3531 ll_destroy(sharelist2);
3532 print_cards(vars, params, cardarray, cardsize, 1, NULL, offset, apicall);
3533 free(cardarray);
3534 }
3535 else
3536 {
3537 struct s_client *rc = rdr->client;
3538 struct cc_data *rcc = (rc) ? rc->cc : NULL;
3539 if(rcc && rcc->cards)
3540 {
3541 struct cc_card **cardarray = get_sorted_card_copy(rcc->cards, 0, &cardsize);
3542 print_cards(vars, params, cardarray, cardsize, 0, rdr, offset, apicall);
3543 free(cardarray);
3544 }
3545 }
3546#endif
3547
3548 }
3549 else
3550 {
3551#else
3552 if(strlen(reader_))
3553 {
3554 {
3555 struct s_reader *rdr;
3556#endif
3557 tpl_addVar(vars, TPLADD, "LOGHISTORY", "->");
3558 // normal non-cccam reader
3559
3560 rdr = get_reader_by_label(reader_);
3561
3562 if(rdr)
3563 {
3564 struct s_client *cl = rdr->client;
3565 if(rdr->ll_entitlements)
3566 {
3567
3568 time_t now = time((time_t *)0);
3569
3570 struct tm start_t, end_t;
3571 LL_ITER itr = ll_iter_create(rdr->ll_entitlements);
3572 S_ENTITLEMENT *item;
3573
3574 tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", "<BR><BR>New Structure:<BR>");
3575 char tbuffer[83];
3576 while((item = ll_iter_next(&itr)))
3577 {
3578
3579 localtime_r(&item->start, &start_t);
3580 localtime_r(&item->end, &end_t);
3581
3582 if(!apicall)
3583 { strftime(tbuffer, 30, "%Y-%m-%d", &start_t); }
3584 else
3585 { strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &start_t); }
3586 tpl_addVar(vars, TPLADD, "ENTSTARTDATE", tbuffer);
3587
3588 if(!apicall)
3589 { strftime(tbuffer, 30, "%Y-%m-%d", &end_t); }
3590 else
3591 { strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &end_t); }
3592 tpl_addVar(vars, TPLADD, "ENTENDDATE", tbuffer);
3593
3594 tpl_addVar(vars, TPLADD, "ENTEXPIERED", item->end > now ? "e_valid" : "e_expired");
3595 tpl_printf(vars, TPLADD, "ENTCAID", "%04X", item->caid);
3596 tpl_printf(vars, TPLADD, "ENTPROVID", "%06X", item->provid);
3597 tpl_printf(vars, TPLADD, "ENTID", "%08X%08X", (uint32_t)(item->id >> 32), (uint32_t)item->id);
3598 tpl_printf(vars, TPLADD, "ENTCLASS", "%08X", item->class);
3599 tpl_addVar(vars, TPLADD, "ENTTYPE", entitlement_type[item->type]);
3600
3601 char *entresname;
3602 entresname = xml_encode(vars, get_tiername((uint16_t)(item->id & 0xFFFF), item->caid, tbuffer));
3603 if(!tbuffer[0])
3604 { entresname = xml_encode(vars, get_provider(item->caid, item->provid, tbuffer, sizeof(tbuffer))); }
3605 tpl_addVar(vars, TPLADD, "ENTRESNAME", entresname);
3606
3607 if((strcmp(getParam(params, "hideexpired"), "1") != 0) || (item->end > now))
3608 { tpl_addVar(vars, TPLAPPEND, "READERENTENTRY", tpl_getTpl(vars, "ENTITLEMENTITEMBIT")); }
3609
3610 }
3611 }
3612
3613 if(cl && cl->typ)
3614 { tpl_printf(vars, TPLADD, "READERTYPE", "%c", cl->typ); }
3615 else
3616 { tpl_addVar(vars, TPLADD, "READERTYPE", "null"); }
3617 tpl_addVar(vars, TPLADD, "READERNAME", rdr->label);
3618
3619 int8_t i, j;
3620 for(i = 0; i < 15; i++) { tpl_printf(vars, TPLAPPEND, "READERROM", "%c", rdr->rom[i]); }
3621 if(rdr->hexserial[0] || rdr->hexserial[1]) { i = 0; }
3622 else { i = 2; }
3623 if(rdr->hexserial[6] || rdr->hexserial[7]) { j = 8; }
3624 else { j = 6; }
3625 for(; i < j; i++) { tpl_printf(vars, TPLAPPEND, "READERSERIAL", "%02X%s", rdr->hexserial[i], i < j - 1 ? " " : ""); }
3626 for(i = 0; i < rdr->nprov; i++)
3627 {
3628 for(j = 0; j < 4; j++) { tpl_printf(vars, TPLAPPEND, "READERPROVIDS", "%02X ", rdr->prid[i][j]); }
3629 tpl_addVar(vars, TPLAPPEND, "READERPROVIDS", i == 0 ? "(sysid)<br>\n" : "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>\n");
3630 }
3631
3632
3633
3634 if(rdr->card_valid_to)
3635 {
3636 struct tm vto_t;
3637 char vtobuffer[30];
3638 localtime_r(&rdr->card_valid_to, &vto_t);
3639 strftime(vtobuffer, 30, "%Y-%m-%d", &vto_t);
3640 tpl_addVar(vars, TPLADD, "READERCARDVALIDTO", vtobuffer);
3641 }
3642 else
3643 {
3644 tpl_addVar(vars, TPLADD, "READERCARDVALIDTO", "n/a");
3645 }
3646
3647 if(rdr->irdId[0])
3648 {
3649 for(i = 0; i < 4; i++) { tpl_printf(vars, TPLAPPEND, "READERIRDID", "%02X ", rdr->irdId[i]); }
3650 }
3651 else
3652 {
3653 tpl_addVar(vars, TPLADD, "READERIRDID", "n/a");
3654 }
3655
3656 if(rdr->card_atr_length)
3657 for(i = 0; i < rdr->card_atr_length; i++) { tpl_printf(vars, TPLAPPEND, "READERATR", "%02X ", rdr->card_atr[i]); }
3658
3659 tpl_addVar(vars, TPLADD, "READERCSYSTEM", rdr->csystem.desc);
3660
3661 tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTBIT"));
3662
3663 }
3664 else
3665 {
3666 tpl_addMsg(vars, "Reader does not exist or is not started!");
3667 }
3668 }
3669
3670 }
3671 else
3672 {
3673 tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTGENERICBIT"));
3674 }
3675
3676 if(!apicall)
3677 { return tpl_getTpl(vars, "ENTITLEMENTS"); }
3678 else
3679 { return tpl_getTpl(vars, "APICCCAMCARDLIST"); }
3680}
3681
3682static char *send_oscam_status(struct templatevars * vars, struct uriparams * params, int32_t apicall)
3683{
3684 int32_t i;
3685 char *usr;
3686 int32_t lsec, isec, chsec, con, cau = 0;
3687 time_t now = time((time_t *)0);
3688 struct tm lt;
3689
3690 if(!apicall) { setActiveMenu(vars, MNU_STATUS); }
3691 char picon_name[32];
3692 snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "oscamlogo");
3693 if(picon_exists(picon_name))
3694 {
3695 tpl_printf(vars, TPLADD, "OSCAMLOGO", "<A HREF=\"http://www.streamboard.tv/oscam/timeline\"><img class=\"oscamlogo\" src=\"image?i=IC_oscamlogo\" alt=\"Oscam %s\" title=\"Oscam %s\"></A>", CS_SVN_VERSION, CS_SVN_VERSION);
3696 }
3697 else
3698 {
3699 tpl_printf(vars, TPLADD, "OSCAMLOGO", "<A HREF=\"http://www.streamboard.tv/oscam/timeline\">Oscam r%s</A>", CS_SVN_VERSION);
3700 }
3701 if(strcmp(getParam(params, "action"), "kill") == 0)
3702 {
3703 char *cptr = getParam(params, "threadid");
3704 struct s_client *cl = NULL;
3705 if(strlen(cptr) > 1)
3706 { sscanf(cptr, "%p", (void **)(void *)&cl); }
3707
3708 if(cl && is_valid_client(cl))
3709 {
3710#ifdef HAVE_DVBAPI
3711 if(streq(cl->account->usr, cfg.dvbapi_usr))
3712 {
3713 cs_log("WebIF from %s requests to kill dvbapi client %s -> ignoring!", cs_inet_ntoa(GET_IP()), cl->account->usr);
3714 }
3715 else
3716 {
3717 kill_thread(cl);
3718 cs_log("Client %s killed by WebIF from %s", cl->account->usr, cs_inet_ntoa(GET_IP()));
3719 }
3720 }
3721#else
3722 kill_thread(cl);
3723 cs_log("Client %s killed by WebIF from %s", cl->account->usr, cs_inet_ntoa(GET_IP()));
3724 }
3725#endif
3726 }
3727
3728 if(strcmp(getParam(params, "action"), "restart") == 0)
3729 {
3730 struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
3731 if(rdr)
3732 {
3733 add_job(rdr->client, ACTION_READER_RESTART, NULL, 0);
3734 cs_log("Reader %s restarted by WebIF from %s", rdr->label, cs_inet_ntoa(GET_IP()));
3735 }
3736 }
3737
3738 char *debuglvl = getParam(params, "debug");
3739 if(strlen(debuglvl) > 0)
3740 {
3741#ifndef WITH_DEBUG
3742 cs_log("*** Warning: Debug Support not compiled in ***");
3743#else
3744 int32_t dblvl = atoi(debuglvl);
3745 if(dblvl >= 0 && dblvl <= 65535) { cs_dblevel = dblvl; }
3746 cs_log("%s debug_level=%d", "all", cs_dblevel);
3747#endif
3748 }
3749
3750 char *hide = getParam(params, "hide");
3751 if(strlen(hide) > 0)
3752 {
3753 struct s_client *hideidx = NULL;
3754 sscanf(hide, "%p", (void **)(void *)&hideidx);
3755
3756 if(hideidx && is_valid_client(hideidx))
3757 { hideidx->wihidden = 1; }
3758 }
3759
3760 char *hideidle = getParam(params, "hideidle");
3761 if(strlen(hideidle) > 0)
3762 {
3763 if(atoi(hideidle) == 2)
3764 {
3765 struct s_client *cl;
3766 for(cl = first_client; cl ; cl = cl->next)
3767 { cl->wihidden = 0; }
3768 }
3769 else
3770 {
3771 int32_t oldval = cfg.http_hide_idle_clients;
3772 config_set("webif", "httphideidleclients", hideidle);
3773 if(oldval != cfg.http_hide_idle_clients)
3774 {
3775 refresh_oscam(REFR_SERVER);
3776 }
3777 }
3778 }
3779
3780 if(cfg.http_hide_idle_clients > 0) { tpl_addVar(vars, TPLADD, "HIDEIDLECLIENTSSELECTED1", "selected"); }
3781 else { tpl_addVar(vars, TPLADD, "HIDEIDLECLIENTSSELECTED0", "selected"); }
3782
3783 int32_t user_count_all = 0, user_count_shown = 0, user_count_active = 0;
3784 int32_t reader_count_all = 0, reader_count_conn = 0;
3785 int32_t proxy_count_all = 0, proxy_count_conn = 0;
3786 int32_t shown;
3787
3788 struct s_client *cl;
3789 int8_t filtered;
3790
3791 cs_readlock(&readerlist_lock);
3792 cs_readlock(&clientlist_lock);
3793 for(i = 0, cl = first_client; cl ; cl = cl->next, i++)
3794 {
3795 if(cl->kill) { continue; }
3796#ifdef CS_CACHEEX
3797 if(get_module(cl)->listenertype != LIS_CSPUDP)
3798 {
3799#endif
3800
3801 // Reset template variables
3802 tpl_addVar(vars, TPLADD, "CLIENTLBVALUE", "");
3803 tpl_addVar(vars, TPLADD, "LASTREADER", "");
3804 tpl_addVar(vars, TPLADD, "CLIENTPROTO", "");
3805 tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", "");
3806 tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIME", "");
3807 tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIMEHIST", "");
3808 tpl_addVar(vars, TPLADD, "JSONARRAYDELIMITER", cl->next ? "," : "");
3809
3810 if(cl->typ == 'c')
3811 { user_count_all++; }
3812 else if(cl->typ == 'p')
3813 { proxy_count_all++; }
3814 else if(cl->typ == 'r')
3815 { reader_count_all++; }
3816
3817 shown = 0;
3818 if(cl->wihidden != 1)
3819 {
3820 filtered = !(cfg.http_hide_idle_clients != 1 || cl->typ != 'c' || (now - cl->lastecm) <= cfg.hideclient_to);
3821 if(!filtered && cfg.http_hide_type)
3822 {
3823 char *p = cfg.http_hide_type;
3824 while(*p && !filtered)
3825 {
3826 char type = *p++;
3827#ifdef CS_CACHEEX
3828 filtered = (type == cl->typ) || (type == 'x' && (cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode));
3829#else
3830 filtered = (type == cl->typ);
3831#endif
3832 }
3833 }
3834
3835 if(!filtered)
3836 {
3837 if(cl->typ == 'c')
3838 {
3839 user_count_shown++;
3840 if(cfg.http_hide_idle_clients != 1 && cfg.hideclient_to > 0 && (now - cl->lastecm) <= cfg.hideclient_to)
3841 {
3842 user_count_active++;
3843 tpl_addVar(vars, TPLADD, "CLIENTTYPE", "a");
3844 }
3845 else { tpl_addVar(vars, TPLADD, "CLIENTTYPE", "c"); }
3846 }
3847 else
3848 {
3849 if(cl->typ == 'r' && cl->reader->card_status == CARD_INSERTED)
3850 { reader_count_conn++; }
3851 else if(cl->typ == 'p' && (cl->reader->card_status == CARD_INSERTED || cl->reader->tcp_connected))
3852 { proxy_count_conn++; }
3853 tpl_printf(vars, TPLADD, "CLIENTTYPE", "%c", cl->typ);
3854 }
3855 if(cl->typ == 'c' || cl->typ == 'r' || cl->typ == 'p')
3856 {
3857 if(cl->lastecm >= cl->login && cl->lastecm >= cl->logout) { isec = now - cl->lastecm; }
3858 else if(cl->logout >= cl->login) { isec = now - cl->logout; }
3859 else { isec = now - cl->login; }
3860 }
3861 else { isec = now - cl->last; }
3862
3863 shown = 1;
3864 lsec = now - cl->login;
3865 chsec = now - cl->lastswitch;
3866 usr = username(cl);
3867
3868 if((cl->typ == 'r') || (cl->typ == 'p')) { usr = cl->reader->label; }
3869
3870 if(cl->dup) { con = 2; }
3871 else if((cl->tosleep) && (now - cl->lastswitch > cl->tosleep)) { con = 1; }
3872 else { con = 0; }
3873
3874 // no AU reader == 0 / AU ok == 1 / Last EMM > aulow == -1
3875 if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r')
3876 {
3877 if((cl->typ == 'c' && ll_count(cl->aureader_list) == 0) || ((cl->typ == 'p' || cl->typ == 'r') && cl->reader->audisabled)) { cau = 0; }
3878 else if((now - cl->lastemm) / 60 > cfg.aulow) { cau = -1; }
3879 else { cau = 1; }
3880
3881 if(!apicall)
3882 {
3883 if(cau == 0)
3884 {
3885 tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "OFF");
3886 }
3887 else
3888 {
3889 if(cau == -1)
3890 { tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "<a href=\"#\" class=\"tooltip\">ON"); }
3891 else
3892 { tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "<a href=\"#\" class=\"tooltip\">ACTIVE"); }
3893 tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", "<span>");
3894 if(cl->typ == 'c')
3895 {
3896 struct s_reader *rdr;
3897 LL_ITER itr = ll_iter_create(cl->aureader_list);
3898 while((rdr = ll_iter_next(&itr)))
3899 {
3900 if(rdr->audisabled)
3901 { tpl_printf(vars, TPLAPPEND, "CLIENTCAUHTTP", "(%s)<br>", xml_encode(vars, rdr->label)); }
3902 else
3903 { tpl_printf(vars, TPLAPPEND, "CLIENTCAUHTTP", "%s<br>", xml_encode(vars, rdr->label)); }
3904 }
3905 }
3906 else { tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", xml_encode(vars, cl->reader->label)); }
3907 tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", "</span></a>");
3908 }
3909 }
3910 }
3911 else
3912 {
3913 cau = 0;
3914 tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "");
3915 }
3916
3917 localtime_r(&cl->login, &lt);
3918
3919 tpl_printf(vars, TPLADD, "HIDEIDX", "%p", cl);
3920
3921 if(!apicall)
3922 {
3923 if(cl->typ == 'c' && !cfg.http_readonly)
3924 {
3925 tpl_printf(vars, TPLADD, "HIDEIDXFULL", "<A HREF =\"status.html?hide=%p\" TITLE=\"Hide this User\"><IMG CLASS=\"icon\" SRC=\"image?i=ICHID\" ALT=\"Hide\"></A>", cl);
3926 tpl_printf(vars, TPLADD, "CSIDX", "<A HREF=\"status.html?action=kill&threadid=%p\" TITLE=\"Kill this User\"><IMG CLASS=\"icon\" SRC=\"image?i=ICKIL\" ALT=\"Kill\"></A>", cl);
3927 }
3928 else if(cl->typ == 'p' && !cfg.http_readonly)
3929 {
3930 tpl_printf(vars, TPLADD, "HIDEIDXFULL", "<A HREF =\"status.html?hide=%p\" TITLE=\"Hide this Proxy\"><IMG CLASS=\"icon\" SRC=\"image?i=ICHID\" ALT=\"Hide\"></A>", cl);
3931 tpl_printf(vars, TPLADD, "CSIDX", "<A HREF=\"status.html?action=restart&amp;label=%s\" TITLE=\"Restart this Proxy\"><IMG CLASS=\"icon\" SRC=\"image?i=ICRES\" ALT=\"Restart\"></A>", urlencode(vars, cl->reader->label));
3932 }
3933 else if(cl->typ == 'r' && !cfg.http_readonly)
3934 {
3935 tpl_printf(vars, TPLADD, "HIDEIDXFULL", "<A HREF =\"status.html?hide=%p\" TITLE=\"Hide this Reader\"><IMG CLASS=\"icon\" SRC=\"image?i=ICHID\" ALT=\"Hide\"></A>", cl);
3936 tpl_printf(vars, TPLADD, "CSIDX", "<A HREF=\"status.html?action=restart&amp;label=%s\" TITLE=\"Restart this Reader\"><IMG CLASS=\"icon\" SRC=\"image?i=ICRES\" ALT=\"Restart\"></A>", urlencode(vars, cl->reader->label));
3937 }
3938 else
3939 {
3940 tpl_printf(vars, TPLADD, "HIDEIDXFULL", "%p", cl);
3941 tpl_printf(vars, TPLADD, "CSIDX", "%p&nbsp;", cl);
3942 }
3943 }
3944 else
3945 {
3946 tpl_printf(vars, TPLADD, "HIDEIDXFULL", "%p", cl);
3947 tpl_printf(vars, TPLADD, "CSIDX", "%p", cl);
3948 }
3949
3950 tpl_printf(vars, TPLADD, "CLIENTTYPE", "%c", cl->typ);
3951 tpl_printf(vars, TPLADD, "CLIENTCNR", "%d", get_threadnum(cl));
3952 tpl_addVar(vars, TPLADD, "CLIENTUSER", xml_encode(vars, usr));
3953
3954 if(cl->typ == 'c')
3955 {
3956 tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", xml_encode(vars, (cl->account && cl->account->description) ? cl->account->description : ""));
3957 }
3958 else if(cl->typ == 'p' || cl->typ == 'r')
3959 {
3960 tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", xml_encode(vars, cl->reader->description ? cl->reader->description : ""));
3961 }
3962
3963 if(!apicall)
3964 {
3965 if(cfg.http_showpicons)
3966 {
3967 if(picon_exists(xml_encode(vars, usr)))
3968 {
3969 if(cl->typ == 'c')
3970 {
3971 tpl_printf(vars, TPLADD, "STATUSUSERICON",
3972 "<A HREF=\"user_edit.html?user=%s\"><img class=\"statususericon\" src=\"image?i=IC_%s\" TITLE=\"Edit User %s\"></A>",
3973 xml_encode(vars, usr), xml_encode(vars, usr), xml_encode(vars, usr));
3974 }
3975 if(cl->typ == 'p' || cl->typ == 'r')
3976 {
3977 tpl_printf(vars, TPLADD, "STATUSUSERICON",
3978 "<A HREF=\"readerconfig.html?label=%s\"><img class=\"statususericon\" src=\"image?i=IC_%s\" TITLE=\" Edit Reader %s\"></A>",
3979 xml_encode(vars, usr), xml_encode(vars, usr), xml_encode(vars, usr));
3980 }
3981 }
3982 else
3983 {
3984 if(cl->typ == 'c')
3985 {
3986 tpl_printf(vars, TPLADD, "STATUSUSERICON",
3987 "<A class=\"statususericon\" HREF=\"user_edit.html?user=%s\" TITLE=\"Edit User %s\">%s</A>",
3988 xml_encode(vars, usr), xml_encode(vars, usr), xml_encode(vars, usr));
3989 }
3990 else
3991 {
3992 tpl_printf(vars, TPLADD, "STATUSUSERICON",
3993 "<A class=\"statususericon\" HREF=\"readerconfig.html?label=%s\" TITLE=\"Edit Reader %s\">%s</A>",
3994 xml_encode(vars, usr), xml_encode(vars, usr), xml_encode(vars, usr));
3995 }
3996 }
3997 }
3998 else
3999 {
4000 if(cl->typ == 'c')
4001 {
4002 tpl_printf(vars, TPLADD, "STATUSUSERICON",
4003 "<A class=\"statususericon\" HREF=\"user_edit.html?user=%s\" TITLE=\"Edit User %s\">%s</A>",
4004 xml_encode(vars, usr), xml_encode(vars, usr), xml_encode(vars, usr));
4005 }
4006 else
4007 {
4008 tpl_printf(vars, TPLADD, "STATUSUSERICON",
4009 "<A class=\"statususericon\" HREF=\"readerconfig.html?label=%s\" TITLE=\"Edit Reader %s\">%s</A>",
4010 xml_encode(vars, usr), xml_encode(vars, usr), xml_encode(vars, usr));
4011 }
4012 }
4013 }
4014 else
4015 {
4016 tpl_addVar(vars, TPLADD, "STATUSUSERICON", xml_encode(vars, usr));
4017 }
4018
4019 tpl_printf(vars, TPLADD, "CLIENTCAU", "%d", cau);
4020 if(!apicall)
4021 {
4022 if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r')
4023 {
4024 if(cl->crypted) { tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", "ON"); }
4025 else { tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", "OFF"); }
4026 }
4027 else { tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", ""); }
4028 }
4029 else { tpl_printf(vars, TPLADD, "CLIENTCRYPTED", "%d", cl->crypted); }
4030 tpl_addVar(vars, TPLADD, "CLIENTIP", cs_inet_ntoa(cl->ip));
4031 tpl_printf(vars, TPLADD, "CLIENTPORT", "%d", cl->port);
4032 const char *proto = client_get_proto(cl);
4033 webif_add_client_proto(vars, cl, proto);
4034
4035 if(!apicall)
4036 {
4037 if((cl->typ != 'p' && cl->typ != 'r') || cl->reader->card_status == CARD_INSERTED)
4038 {
4039 tpl_printf(vars, TPLADD, "CLIENTLOGINDATE", "%02d.%02d.%02d %02d:%02d:%02d", lt.tm_mday, lt.tm_mon + 1, lt.tm_year % 100, lt.tm_hour, lt.tm_min, lt.tm_sec);
4040 tpl_addVar(vars, TPLADD, "CLIENTLOGINSECS", sec2timeformat(vars, lsec));
4041 }
4042 else
4043 {
4044 tpl_addVar(vars, TPLADD, "CLIENTLOGINDATE", "");
4045 tpl_addVar(vars, TPLADD, "CLIENTLOGINSECS", "");
4046 }
4047 }
4048 else
4049 {
4050 char tbuffer [30];
4051 strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
4052 tpl_addVar(vars, TPLADD, "CLIENTLOGINDATE", tbuffer);
4053 tpl_printf(vars, TPLADD, "CLIENTLOGINSECS", "%d", lsec);
4054 }
4055
4056 //load historical values from ringbuffer
4057 char *value = get_ecm_historystring(cl);
4058 tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIMEHIST", value);
4059 free_mk_t(value);
4060
4061 if((isec < cfg.hideclient_to || cfg.hideclient_to == 0) && (cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r'))
4062 {
4063 if(((cl->typ != 'r') || (cl->typ != 'p')) && (cl->lastreader[0]))
4064 {
4065 tpl_printf(vars, TPLADD, "CLIENTLBVALUE", "by %s", cl->lastreader);
4066 tpl_printf(vars, TPLAPPEND, "CLIENTLBVALUE", "&nbsp;(%dms)", cl->cwlastresptime);
4067 if(apicall)
4068 { tpl_addVar(vars, TPLADD, "LASTREADER", cl->lastreader); }
4069 }
4070
4071 if(cl->last_caid != NO_CAID_VALUE)
4072 { tpl_printf(vars, TPLADD, "CLIENTCAID", "%04X", cl->last_caid); }
4073 else
4074 { tpl_addVar(vars, TPLADD, "CLIENTCAID", "none"); }
4075 if(cl->last_srvid != NO_SRVID_VALUE)
4076 { tpl_printf(vars, TPLADD, "CLIENTSRVID", "%04X", cl->last_srvid); }
4077 else
4078 { tpl_printf(vars, TPLADD, "CLIENTSRVID", "none"); }
4079 char *lastchannel;
4080 char channame[32];
4081 int32_t actual_caid = cl->last_caid;
4082 int32_t actual_srvid = cl->last_srvid;
4083 lastchannel = xml_encode(vars, get_servicename(cl, actual_srvid, actual_caid, channame));
4084 if(cl->last_caid != NO_CAID_VALUE && cl->last_srvid != NO_SRVID_VALUE)
4085 {
4086 tpl_printf(vars, TPLADD, "CLIENTCURRENTPICON", "%s", lastchannel);
4087 tpl_printf(vars, TPLADD, "CAIDSRVID", "%04X:%04X", actual_caid, actual_srvid);
4088 if(cfg.http_showpicons)
4089 {
4090 snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%04X_%04X", actual_caid, actual_srvid);
4091 if(picon_exists(picon_name))
4092 {
4093 tpl_printf(vars, TPLADD, "CLIENTCURRENTPICON",
4094 "<img class=\"clientcurrentpicon\" src=\"image?i=IC_%04X_%04X\">",
4095 actual_caid, actual_srvid);
4096 }
4097 else
4098 {
4099 tpl_printf(vars, TPLADD, "CLIENTCURRENTPICON", "%s", lastchannel);
4100 tpl_printf(vars, TPLADD, "CAIDSRVID", "%04X:%04X", actual_caid, actual_srvid);
4101 }
4102 }
4103 else
4104 {
4105 tpl_printf(vars, TPLADD, "CLIENTCURRENTPICON", "%s", lastchannel);
4106 tpl_printf(vars, TPLADD, "CAIDSRVID", "%04X:%04X", actual_caid, actual_srvid);
4107 }
4108 }
4109 tpl_printf(vars, TPLADD, "CLIENTLASTRESPONSETIME", "%d", cl->cwlastresptime ? cl->cwlastresptime : 1);
4110
4111 tpl_printf(vars, TPLADD, "CLIENTSRVPROVIDER", "%s%s", cl->last_srvidptr && cl->last_srvidptr->prov ? xml_encode(vars, cl->last_srvidptr->prov) : "", cl->last_srvidptr && cl->last_srvidptr->prov ? ": " : "");
4112 tpl_addVar(vars, TPLADD, "CLIENTSRVNAME", cl->last_srvidptr && cl->last_srvidptr->name ? xml_encode(vars, cl->last_srvidptr->name) : "");
4113 tpl_addVar(vars, TPLADD, "CLIENTSRVTYPE", cl->last_srvidptr && cl->last_srvidptr->type ? xml_encode(vars, cl->last_srvidptr->type) : "");
4114 tpl_addVar(vars, TPLADD, "CLIENTSRVDESCRIPTION", cl->last_srvidptr && cl->last_srvidptr->desc ? xml_encode(vars, cl->last_srvidptr->desc) : "");
4115 tpl_addVar(vars, TPLADD, "CLIENTTIMEONCHANNEL", sec2timeformat(vars, chsec));
4116 }
4117 else
4118 {
4119 tpl_addVar(vars, TPLADD, "CLIENTCAID", "0000");
4120 tpl_addVar(vars, TPLADD, "CLIENTSRVID", "0000");
4121 tpl_addVar(vars, TPLADD, "CAIDSRVID", "0000:0000");
4122 tpl_addVar(vars, TPLADD, "CLIENTCURRENTPICON", "");
4123 tpl_addVar(vars, TPLADD, "CLIENTSRVPROVIDER", "");
4124 tpl_addVar(vars, TPLADD, "CLIENTSRVNAME", "");
4125 tpl_addVar(vars, TPLADD, "CLIENTSRVTYPE", "");
4126 tpl_addVar(vars, TPLADD, "CLIENTSRVDESCRIPTION", "");
4127 tpl_addVar(vars, TPLADD, "CLIENTLBVALUE", "");
4128 tpl_addVar(vars, TPLADD, "CLIENTTIMEONCHANNEL", "");
4129
4130 }
4131
4132 if(!apicall)
4133 {
4134 tpl_addVar(vars, TPLADD, "CLIENTIDLESECS", sec2timeformat(vars, isec));
4135
4136 if((cl->typ != 'p' && cl->typ != 'r') || cl->reader->card_status == CARD_INSERTED)
4137 { tpl_addVar(vars, TPLADD, "CLIENTIDLESECSCLASS", "idlesec_normal"); }
4138 else
4139 { tpl_addVar(vars, TPLADD, "CLIENTIDLESECSCLASS", "idlesec_alert"); }
4140 }
4141 else
4142 {
4143 tpl_printf(vars, TPLADD, "CLIENTIDLESECS", "%d", isec);
4144 }
4145
4146 if(con == 2) { tpl_addVar(vars, TPLADD, "CLIENTCON", "Duplicate"); }
4147 else if(con == 1) { tpl_addVar(vars, TPLADD, "CLIENTCON", "Sleep"); }
4148 else
4149 {
4150 struct s_reader *rdr = cl->reader;
4151 char *txt = "OK";
4152 if(!rdr && (cl->typ == 'r' || cl->typ == 'p')) { txt = "UNKNOWN"; }
4153 else if(cl->typ == 'r' || cl->typ == 'p') //reader or proxy
4154 {
4155 if(rdr->lbvalue)
4156 { tpl_printf(vars, TPLADD, "CLIENTLBVALUE", "<A HREF=\"readerstats.html?label=%s&amp;hide=4\" TITLE=\"Show statistics for this reader/ proxy\">%d</A>", urlencode(vars, rdr->label), rdr->lbvalue); }
4157 else
4158 { tpl_printf(vars, TPLADD, "CLIENTLBVALUE", "<A HREF=\"readerstats.html?label=%s&amp;hide=4\" TITLE=\"Show statistics for this reader/ proxy\">%s</A>", urlencode(vars, rdr->label), "no data"); }
4159
4160 switch(rdr->card_status)
4161 {
4162 case NO_CARD:
4163 txt = "OFF";
4164 break;
4165 case UNKNOWN:
4166 txt = "UNKNOWN";
4167 break;
4168 case CARD_NEED_INIT:
4169 txt = "NEEDINIT";
4170 break;
4171 case CARD_INSERTED:
4172 if(cl->typ == 'p')
4173 { txt = "CONNECTED"; }
4174 else
4175 { txt = "CARDOK"; }
4176 break;
4177 case CARD_FAILURE:
4178 txt = "ERROR";
4179 break;
4180 default:
4181 txt = "UNDEF";
4182 }
4183 }
4184 tpl_addVar(vars, TPLADD, "CLIENTCON", txt);
4185
4186 if(rdr && (cl->typ == 'r') && (!apicall)) //reader
4187 {
4188 if(rdr->ll_entitlements)
4189 {
4190 LL_ITER itr = ll_iter_create(rdr->ll_entitlements);
4191 S_ENTITLEMENT *ent;
4192 uint16_t total_ent = 0;
4193 uint16_t active_ent = 0;
4194 struct tm end_t;
4195
4196 tpl_addVar(vars, TPLADD, "TMPSPAN", "<SPAN>");
4197 while((ent = ll_iter_next(&itr)))
4198 {
4199 total_ent++;
4200 if((ent->end > now) && (ent->type != 7))
4201 {
4202 if(active_ent) { tpl_addVar(vars, TPLAPPEND, "TMPSPAN", "<BR><BR>"); }
4203 active_ent++;
4204 localtime_r(&ent->end, &end_t);
4205 tpl_printf(vars, TPLAPPEND, "TMPSPAN", "%04X:%06X<BR>exp:%04d/%02d/%02d",
4206 ent->caid, ent->provid,
4207 end_t.tm_year + 1900, end_t.tm_mon + 1, end_t.tm_mday);
4208 }
4209 }
4210
4211 if(((total_ent) && (active_ent == 0)) || (total_ent == 0))
4212 {
4213 tpl_addVar(vars, TPLAPPEND, "TMPSPAN", "No active entitlements found");
4214 }
4215
4216 tpl_addVar(vars, TPLAPPEND, "TMPSPAN", "</SPAN>");
4217
4218 if(active_ent)
4219 {
4220 tpl_printf(vars, TPLADD, "TMP", "(%d entitlement%s)", active_ent, (active_ent != 1) ? "s" : "");
4221 }
4222 else
4223 {
4224 tpl_addVar(vars, TPLADD, "TMP", "(no entitlements)");
4225
4226 }
4227
4228 tpl_printf(vars, TPLAPPEND, "CLIENTCON", " <A HREF=\"entitlements.html?label=%s&hideexpired=1\" class=\"tooltip%s\">%s%s</A>",
4229 urlencode(vars, cl->reader->label),
4230 active_ent > 0 ? "" : "1",
4231 tpl_getVar(vars, "TMP"),
4232 tpl_getVar(vars, "TMPSPAN"));
4233 }
4234 else
4235 {
4236 tpl_printf(vars, TPLAPPEND, "CLIENTCON", " <A HREF=\"entitlements.html?label=%s&hideexpired=1\" class=\"tooltip\">(no entitlements)"
4237 "<SPAN>No active entitlements found</SPAN></A>",
4238 urlencode(vars, cl->reader->label));
4239 }
4240 }
4241
4242#ifdef MODULE_CCCAM
4243 if(!apicall)
4244 {
4245 if(rdr && (cl->typ == 'r' || cl->typ == 'p') && strncmp(proto, "cccam", 5) == 0 && rdr->tcp_connected && rdr->card_status != CARD_FAILURE)
4246 {
4247 struct cc_data *rcc = cl->cc;
4248 if(rcc)
4249 {
4250 LLIST *cards = rcc->cards;
4251 if(cards)
4252 {
4253 int32_t cnt = ll_count(cards);
4254 int32_t locals = rcc->num_hop1;
4255 tpl_printf(vars, TPLADD, "TMP", "(%d of %d card%s)", locals, cnt, (cnt > 1) ? "s" : "");
4256 tpl_printf(vars, TPLADD, "TMPSPAN", "<SPAN>card count=%d<BR>hop1=%d<BR>hop2=%d<BR>hopx=%d<BR>currenthops=%d<BR><BR>reshare0=%d<BR>reshare1=%d<BR>reshare2=%d<BR>resharex=%d</SPAN>",
4257 cnt,
4258 rcc->num_hop1,
4259 rcc->num_hop2,
4260 rcc->num_hopx,
4261 cl->reader->currenthops,
4262 rcc->num_reshare0,
4263 rcc->num_reshare1,
4264 rcc->num_reshare2,
4265 rcc->num_resharex);
4266
4267 tpl_printf(vars, TPLAPPEND, "CLIENTCON", " <A HREF=\"entitlements.html?label=%s\" class=\"tooltip%s\">%s%s</A>",
4268 urlencode(vars, cl->reader->label),
4269 rcc->num_reshare0 > 0 ? "1" : "",
4270 tpl_getVar(vars, "TMP"),
4271 tpl_getVar(vars, "TMPSPAN"));
4272 }
4273 }
4274 }
4275 }
4276#endif
4277 }
4278 }
4279 }
4280
4281 if(!apicall)
4282 {
4283 // select right suborder
4284 if(cl->typ == 'c')
4285 {
4286 if(shown) { tpl_addVar(vars, TPLAPPEND, "CLIENTSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT")); }
4287 if(cfg.http_hide_idle_clients == 1 || cfg.hideclient_to < 1)
4288 {
4289 tpl_printf(vars, TPLADD, "CLIENTHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"17\">Clients %d/%d</TD></TR>\n",
4290 user_count_shown, user_count_all);
4291 }
4292 else
4293 {
4294 tpl_printf(vars, TPLADD, "CLIENTHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"17\">Clients %d/%d (%d with ECM within last %d seconds)</TD></TR>\n",
4295 user_count_shown, user_count_all, user_count_active, cfg.hideclient_to);
4296 }
4297 }
4298 else if(cl->typ == 'r')
4299 {
4300 if(shown) { tpl_addVar(vars, TPLAPPEND, "READERSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT")); }
4301 tpl_printf(vars, TPLADD, "READERHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"17\">Readers %d/%d</TD></TR>\n",
4302 reader_count_conn, reader_count_all);
4303 }
4304 else if(cl->typ == 'p')
4305 {
4306 if(shown) { tpl_addVar(vars, TPLAPPEND, "PROXYSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT")); }
4307 tpl_printf(vars, TPLADD, "PROXYHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"17\">Proxies %d/%d</TD></TR>\n",
4308 proxy_count_conn, proxy_count_all);
4309 }
4310 else if(shown) { tpl_addVar(vars, TPLAPPEND, "SERVERSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT")); }
4311
4312 }
4313 else
4314 {
4315 if(shown)
4316 {
4317 if(apicall == 1)
4318 { tpl_addVar(vars, TPLAPPEND, "APISTATUSBITS", tpl_getTpl(vars, "APISTATUSBIT")); }
4319 if(apicall == 2)
4320 { tpl_addVar(vars, TPLAPPEND, "JSONSTATUSBITS", tpl_getTpl(vars, "JSONSTATUSBIT")); }
4321 }
4322 }
4323
4324#ifdef CS_CACHEEX
4325 }
4326#endif
4327
4328 }
4329 cs_readunlock(&clientlist_lock);
4330 cs_readunlock(&readerlist_lock);
4331
4332 if(cfg.loghistorysize)
4333 {
4334 char *t_loghistptr = loghistptr, *ptr1 = NULL;
4335 if(loghistptr >= loghist + (cfg.loghistorysize) - 1)
4336 { t_loghistptr = loghist; }
4337 int32_t d = 0, l1 = strlen(t_loghistptr + 1) + 2;
4338 char *lastpos = loghist + (cfg.loghistorysize) - 1;
4339
4340 for(ptr1 = t_loghistptr + l1, i = 0; i < 200; i++, ptr1 = ptr1 + l1)
4341 {
4342 l1 = strlen(ptr1) + 1;
4343 if(!d && ((ptr1 >= lastpos) || (l1 < 2)))
4344 {
4345 ptr1 = loghist;
4346 l1 = strlen(ptr1) + 1;
4347 d++;
4348 }
4349
4350 if(d && ((ptr1 >= t_loghistptr) || (l1 < 2)))
4351 { break; }
4352
4353 char p_usr[32];
4354 size_t pos1 = strcspn(ptr1, "\t") + 1;
4355 cs_strncpy(p_usr, ptr1 , pos1 > sizeof(p_usr) ? sizeof(p_usr) : pos1);
4356
4357 char *p_txt = ptr1 + pos1;
4358
4359 if(!apicall)
4360 {
4361 if(p_txt[0])
4362 tpl_printf(vars, TPLAPPEND, "LOGHISTORY",
4363 "\t\t<span class=\"%s\">%s\t\t</span><br>\n", xml_encode(vars, p_usr), xml_encode(vars, p_txt));
4364 }
4365 else
4366 {
4367 if(apicall == 1)
4368 if(strcmp(getParam(params, "appendlog"), "1") == 0)
4369 { tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", p_txt); }
4370 }
4371 }
4372 }
4373 else
4374 {
4375 tpl_addVar(vars, TPLADD, "LOGHISTORY", "loghistorysize is set to 0 in your configuration<BR>\n");
4376 }
4377
4378#ifdef WITH_DEBUG
4379 // Debuglevel Selector
4380 int32_t lvl;
4381 for(i = 0; i < MAX_DEBUG_LEVELS; i++)
4382 {
4383 lvl = 1 << i;
4384 tpl_printf(vars, TPLADD, "TMPC", "DCLASS%d", lvl);
4385 tpl_printf(vars, TPLADD, "TMPV", "DEBUGVAL%d", lvl);
4386 if(cs_dblevel & lvl)
4387 {
4388 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugls");
4389 tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel - lvl);
4390 }
4391 else
4392 {
4393 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugl");
4394 tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel + lvl);
4395 }
4396 }
4397
4398 if(cs_dblevel == D_ALL_DUMP)
4399 { tpl_addVar(vars, TPLADD, "DCLASS65535", "debugls"); }
4400 else
4401 { tpl_addVar(vars, TPLADD, "DCLASS65535", "debugl"); }
4402
4403 tpl_addVar(vars, TPLADD, "NEXTPAGE", "status.html");
4404 tpl_addVar(vars, TPLADD, "DCLASS", "debugl"); //default
4405 tpl_printf(vars, TPLADD, "ACTDEBUG", "%d", cs_dblevel);
4406 tpl_addVar(vars, TPLADD, "SDEBUG", tpl_getTpl(vars, "DEBUGSELECT"));
4407#endif
4408
4409 if(apicall)
4410 {
4411 if(apicall == 1)
4412 { return tpl_getTpl(vars, "APISTATUS"); }
4413 if(apicall == 2)
4414 { return tpl_getTpl(vars, "JSONSTATUS"); }
4415 }
4416
4417 if(config_enabled(TOUCH) && streq(tpl_getVar(vars, "SUBDIR"), TOUCH_SUBDIR))
4418 { return tpl_getTpl(vars, "TOUCH_STATUS"); }
4419 else
4420 { return tpl_getTpl(vars, "STATUS"); }
4421}
4422
4423static char *send_oscam_services_edit(struct templatevars * vars, struct uriparams * params)
4424{
4425 struct s_sidtab *sidtab, *ptr;
4426 char label[sizeof(cfg.sidtab->label)];
4427 int32_t i;
4428
4429 setActiveMenu(vars, MNU_SERVICES);
4430
4431 cs_strncpy(label, strtolower(getParam(params, "service")), sizeof(label));
4432 ++cfg_sidtab_generation;
4433 for(sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab = sidtab->next) { ; }
4434
4435 if(sidtab == NULL)
4436 {
4437 i = 1;
4438 while(strlen(label) < 1)
4439 {
4440 snprintf(label, sizeof(label) / sizeof(char) - 1, "newservice%d", i);
4441 for(sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab = sidtab->next) { ; }
4442 if(sidtab != NULL) { label[0] = '\0'; }
4443 ++i;
4444 }
4445 if(!cs_malloc(&sidtab, sizeof(struct s_sidtab))) { return "0"; }
4446
4447 if(cfg.sidtab == NULL) { cfg.sidtab = sidtab; }
4448 else
4449 {
4450 for(ptr = cfg.sidtab; ptr != NULL && ptr->next != NULL; ptr = ptr->next) { ; }
4451 ptr->next = sidtab;
4452 }
4453 cs_strncpy((char *)sidtab->label, label, sizeof(sidtab->label));
4454 ++cfg_sidtab_generation;
4455 tpl_addMsg(vars, "New service has been added");
4456 // Adding is uncritical as the new service is appended to sidtabs.ok/sidtabs.no and accounts/clients/readers have zeros there
4457 if(write_services() != 0) { tpl_addMsg(vars, "Writing services to disk failed!"); }
4458 }
4459
4460 if(strcmp(getParam(params, "action"), "Save") == 0)
4461 {
4462 for(i = 0; i < (*params).paramcount; i++)
4463 {
4464 if((strcmp((*params).params[i], "action")) && (strcmp((*params).params[i], "service")))
4465 {
4466 chk_sidtab((*params).params[i], (*params).values[i], sidtab);
4467 }
4468 }
4469 ++cfg_sidtab_generation;
4470 tpl_addMsg(vars, "Services updated");
4471 // We don't need any refresh here as accounts/clients/readers sidtabs.ok/sidtabs.no are unaffected!
4472 if(write_services() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
4473
4474 for(sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab = sidtab->next) { ; }
4475 }
4476
4477 tpl_addVar(vars, TPLADD, "LABEL", xml_encode(vars, sidtab->label));
4478 tpl_addVar(vars, TPLADD, "LABELENC", urlencode(vars, sidtab->label));
4479
4480 if(sidtab)
4481 {
4482 for(i = 0; i < sidtab->num_caid; i++)
4483 {
4484 if(i == 0) { tpl_printf(vars, TPLADD, "CAIDS", "%04X", sidtab->caid[i]); }
4485 else { tpl_printf(vars, TPLAPPEND, "CAIDS", ",%04X", sidtab->caid[i]); }
4486 }
4487 for(i = 0; i < sidtab->num_provid; i++)
4488 {
4489 if(i == 0) { tpl_printf(vars, TPLADD, "PROVIDS", "%06X", sidtab->provid[i]); }
4490 else { tpl_printf(vars, TPLAPPEND, "PROVIDS", ",%06X", sidtab->provid[i]); }
4491 }
4492 for(i = 0; i < sidtab->num_srvid; i++)
4493 {
4494 if(i == 0) { tpl_printf(vars, TPLADD, "SRVIDS", "%04X", sidtab->srvid[i]); }
4495 else { tpl_printf(vars, TPLAPPEND, "SRVIDS", ",%04X", sidtab->srvid[i]); }
4496 }
4497 }
4498 return tpl_getTpl(vars, "SERVICEEDIT");
4499}
4500
4501static void delete_from_SIDTABBITS(SIDTABBITS * orgsidtab, int32_t position, int32_t sidtablength)
4502{
4503 if(*orgsidtab)
4504 {
4505 int32_t i;
4506 SIDTABBITS newsidtab = 0;
4507 for(i = 0; i < position; ++i)
4508 {
4509 if(*orgsidtab & ((SIDTABBITS)1 << i))
4510 { newsidtab |= ((SIDTABBITS)1 << i); }
4511 }
4512 for(; i < sidtablength; ++i)
4513 {
4514 if(*orgsidtab & ((SIDTABBITS)1 << (i + 1)))
4515 { newsidtab |= ((SIDTABBITS)1 << i); }
4516 }
4517 *orgsidtab = newsidtab;
4518 }
4519}
4520
4521static char *send_oscam_services(struct templatevars * vars, struct uriparams * params)
4522{
4523 struct s_sidtab *sidtab;
4524 char *service = getParam(params, "service");
4525 char channame[32];
4526 int32_t i, counter = 0;
4527
4528 setActiveMenu(vars, MNU_SERVICES);
4529
4530 if(strcmp(getParam(params, "action"), "delete") == 0)
4531 {
4532 if(cfg.http_readonly)
4533 {
4534 tpl_addMsg(vars, "Sorry, Webif is in readonly mode. No deletion will be made!");
4535 }
4536 else
4537 {
4538 struct s_sidtab *sidtab_prev = NULL;
4539 int32_t sidtablength = -1;
4540 int32_t position = 0;
4541
4542 // Calculate sidtablength before deletion so that updating sidtabs is faster
4543 for(sidtab = cfg.sidtab; sidtab; sidtab = sidtab->next)
4544 { ++sidtablength; }
4545
4546 for(sidtab = cfg.sidtab; sidtab; sidtab = sidtab->next)
4547 {
4548 if(strcmp(sidtab->label, service) == 0)
4549 {
4550 struct s_auth *account;
4551 struct s_client *cl;
4552 struct s_reader *rdr;
4553
4554 if(!sidtab_prev)
4555 { cfg.sidtab = sidtab->next; }
4556 else
4557 { sidtab_prev->next = sidtab->next; }
4558
4559 for(account = cfg.account; (account); account = account->next)
4560 {
4561 delete_from_SIDTABBITS(&account->sidtabs.ok, position, sidtablength);
4562 delete_from_SIDTABBITS(&account->sidtabs.no, position, sidtablength);
4563
4564 for(cl = first_client->next; cl ; cl = cl->next)
4565 {
4566 if(account == cl->account)
4567 {
4568 cl->sidtabs.ok = account->sidtabs.ok;
4569 cl->sidtabs.no = account->sidtabs.no;
4570 }
4571 }
4572 }
4573
4574 LL_ITER itr = ll_iter_create(configured_readers);
4575 while((rdr = ll_iter_next(&itr)))
4576 {
4577 delete_from_SIDTABBITS(&rdr->sidtabs.ok, position, sidtablength);
4578 delete_from_SIDTABBITS(&rdr->sidtabs.no, position, sidtablength);
4579 }
4580 free_sidtab(sidtab);
4581 ++counter;
4582 break;
4583 }
4584 sidtab_prev = sidtab;
4585 position++;
4586 }
4587 if(counter > 0)
4588 {
4589 ++cfg_sidtab_generation;
4590 tpl_addMsg(vars, "Service has been deleted!");
4591 if(write_services() != 0) { tpl_addMsg(vars, "Writing services to disk failed!"); }
4592 }
4593 else { tpl_addMsg(vars, "Sorry but the specified service doesn't exist. No deletion will be made!"); }
4594 }
4595 }
4596
4597 sidtab = cfg.sidtab;
4598 // Show List
4599 counter = 0;
4600 while(sidtab != NULL)
4601 {
4602 tpl_addVar(vars, TPLADD, "SID", "");
4603 if((strcmp(getParam(params, "service"), sidtab->label) == 0) && (strcmp(getParam(params, "action"), "list") == 0))
4604 {
4605 tpl_addVar(vars, TPLADD, "SIDCLASS", "sidlist");
4606 tpl_addVar(vars, TPLAPPEND, "SID", "<div style=\"float:right;background-color:red;color:white\"><A HREF=\"services.html\" style=\"color:white;text-decoration:none\">X</A></div>");
4607 for(i = 0; i < sidtab->num_srvid; i++)
4608 {
4609 tpl_printf(vars, TPLAPPEND, "SID", "%04X : %s<BR>", sidtab->srvid[i], xml_encode(vars, get_servicename(cur_client(), sidtab->srvid[i], sidtab->caid[0], channame)));
4610 }
4611 }
4612 else
4613 {
4614 tpl_addVar(vars, TPLADD, "SIDCLASS", "");
4615 tpl_printf(vars, TPLADD, "SID", "<A HREF=\"services.html?service=%s&amp;action=list\">Show Services</A>", urlencode(vars, sidtab->label));
4616 }
4617 tpl_addVar(vars, TPLADD, "LABELENC", urlencode(vars, sidtab->label));
4618 tpl_addVar(vars, TPLADD, "LABEL", xml_encode(vars, sidtab->label));
4619 tpl_addVar(vars, TPLADD, "SIDLIST", tpl_getTpl(vars, "SERVICECONFIGSIDBIT"));
4620
4621 tpl_addVar(vars, TPLAPPEND, "SERVICETABS", tpl_getTpl(vars, "SERVICECONFIGLISTBIT"));
4622 sidtab = sidtab->next;
4623 counter++;
4624 }
4625 if(counter >= MAX_SIDBITS)
4626 {
4627 tpl_addVar(vars, TPLADD, "BTNDISABLED", "DISABLED");
4628 tpl_addMsg(vars, "Maximum Number of Services is reached");
4629 }
4630 return tpl_getTpl(vars, "SERVICECONFIGLIST");
4631}
4632
4633static char *send_oscam_savetpls(struct templatevars * vars)
4634{
4635 if(cfg.http_tpl)
4636 {
4637 tpl_printf(vars, TPLADD, "CNT", "%d", tpl_saveIncludedTpls(cfg.http_tpl));
4638 tpl_addVar(vars, TPLADD, "PATH", cfg.http_tpl);
4639 }
4640 else { tpl_addVar(vars, TPLADD, "CNT", "0"); }
4641 return tpl_getTpl(vars, "SAVETEMPLATES");
4642}
4643
4644static char *send_oscam_shutdown(struct templatevars * vars, FILE * f, struct uriparams * params, int8_t apicall, int8_t *keepalive, char *extraheader)
4645{
4646 if(!apicall) { setActiveMenu(vars, MNU_SHUTDOWN); }
4647 if(strcmp(strtolower(getParam(params, "action")), "shutdown") == 0)
4648 {
4649 *keepalive = 0;
4650 if(!apicall)
4651 {
4652 char *CSS = tpl_getUnparsedTpl("CSS", 1, "");
4653 tpl_addVar(vars, TPLADD, "STYLESHEET", CSS);
4654 free(CSS);
4655 tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", SHUTDOWNREFRESH);
4656 tpl_addVar(vars, TPLADD, "REFRESHURL", "status.html");
4657 tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
4658 tpl_printf(vars, TPLADD, "SECONDS", "%d", SHUTDOWNREFRESH);
4659 char *result = tpl_getTpl(vars, "SHUTDOWN");
4660 send_headers(f, 200, "OK", extraheader, "text/html", 0, strlen(result), NULL, 0);
4661 webif_write(result, f);
4662 cs_log("Shutdown requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
4663 }
4664 else
4665 {
4666 tpl_addVar(vars, TPLADD, "APICONFIRMMESSAGE", "shutdown");
4667 cs_log("Shutdown requested by XMLApi from %s", cs_inet_ntoa(GET_IP()));
4668 }
4669 cs_exit_oscam();
4670
4671 if(!apicall)
4672 { return "1"; }
4673 else
4674 { return tpl_getTpl(vars, "APICONFIRMATION"); }
4675
4676 }
4677 else if(strcmp(strtolower(getParam(params, "action")), "restart") == 0)
4678 {
4679 *keepalive = 0;
4680 if(!apicall)
4681 {
4682 char *CSS = tpl_getUnparsedTpl("CSS", 1, "");
4683 tpl_addVar(vars, TPLADD, "STYLESHEET", CSS);
4684 free(CSS);
4685 tpl_addVar(vars, TPLADD, "REFRESHTIME", "5");
4686 tpl_addVar(vars, TPLADD, "REFRESHURL", "status.html");
4687 tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
4688 tpl_addVar(vars, TPLADD, "SECONDS", "5");
4689 char *result = tpl_getTpl(vars, "SHUTDOWN");
4690 send_headers(f, 200, "OK", extraheader, "text/html", 0, strlen(result), NULL, 0);
4691 webif_write(result, f);
4692 cs_log("Restart requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
4693 }
4694 else
4695 {
4696 tpl_addVar(vars, TPLADD, "APICONFIRMMESSAGE", "restart");
4697 cs_log("Restart requested by XMLApi from %s", cs_inet_ntoa(GET_IP()));
4698 }
4699 cs_restart_oscam();
4700
4701 if(!apicall)
4702 { return "1"; }
4703 else
4704 { return tpl_getTpl(vars, "APICONFIRMATION"); }
4705
4706 }
4707 else
4708 {
4709 return tpl_getTpl(vars, "PRESHUTDOWN");
4710 }
4711}
4712
4713static char *send_oscam_script(struct templatevars * vars)
4714{
4715 setActiveMenu(vars, MNU_SCRIPT);
4716 char *result = "not found";
4717 int32_t rc = 0;
4718 if(!cfg.http_readonly)
4719 {
4720 if(cfg.http_script)
4721 {
4722 tpl_addVar(vars, TPLADD, "SCRIPTNAME", cfg.http_script);
4723 rc = system(cfg.http_script);
4724 if(rc == -1)
4725 {
4726 result = "done";
4727 }
4728 else
4729 {
4730 result = "failed";
4731 }
4732 }
4733 else
4734 {
4735 tpl_addVar(vars, TPLADD, "SCRIPTNAME", "no script defined");
4736 }
4737 tpl_addVar(vars, TPLADD, "SCRIPTRESULT", result);
4738 tpl_printf(vars, TPLADD, "CODE", "%d", rc);
4739 }
4740 else
4741 {
4742 tpl_addMsg(vars, "Sorry, Webif is in readonly mode. No script execution possible!");
4743 }
4744 return tpl_getTpl(vars, "SCRIPT");
4745
4746}
4747
4748static char *send_oscam_scanusb(struct templatevars * vars)
4749{
4750 setActiveMenu(vars, MNU_READERS);
4751#if !defined(__CYGWIN__)
4752 FILE *fp;
4753 int32_t err = 0;
4754 char path[1035];
4755
4756 fp = popen("lsusb -v | egrep '^Bus|^ *iSerial|^ *iProduct'", "r");
4757 if(fp == NULL)
4758 {
4759 tpl_addVar(vars, TPLADD, "USBENTRY", "Failed to run lusb");
4760 tpl_addVar(vars, TPLADD, "USBENTRY", path);
4761 tpl_addVar(vars, TPLAPPEND, "USBBIT", tpl_getTpl(vars, "SCANUSBBIT"));
4762 err = 1;
4763 }
4764
4765 if(!err)
4766 {
4767 while(fgets(path, sizeof(path) - 1, fp) != NULL)
4768 {
4769 tpl_addVar(vars, TPLADD, "USBENTRYCLASS", "");
4770 if(strstr(path, "Bus "))
4771 {
4772 tpl_addVar(vars, TPLADD, "USBENTRY", path);
4773 tpl_addVar(vars, TPLADD, "USBENTRYCLASS", "CLASS=\"scanusbsubhead\"");
4774 }
4775 else
4776 {
4777 tpl_printf(vars, TPLADD, "USBENTRY", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%s", path);
4778 }
4779 tpl_addVar(vars, TPLAPPEND, "USBBIT", tpl_getTpl(vars, "SCANUSBBIT"));
4780 }
4781 }
4782 pclose(fp);
4783#else
4784 tpl_addMsg(vars, "Function not supported in CYGWIN environment");
4785#endif
4786 return tpl_getTpl(vars, "SCANUSB");
4787}
4788
4789static void webif_process_logfile(struct templatevars * vars, struct uriparams * params, char *targetfile, size_t targetfile_len)
4790{
4791 snprintf(targetfile, targetfile_len, "%s", cfg.logfile);
4792 if(strcmp(getParam(params, "clear"), "logfile") == 0)
4793 {
4794 if(strlen(targetfile) > 0)
4795 {
4796 FILE *file = fopen(targetfile, "w");
4797 fclose(file);
4798 }
4799 }
4800#ifdef WITH_DEBUG
4801 // Debuglevel Selector
4802 int32_t i, lvl;
4803 for(i = 0; i < MAX_DEBUG_LEVELS; i++)
4804 {
4805 lvl = 1 << i;
4806 tpl_printf(vars, TPLADD, "TMPC", "DCLASS%d", lvl);
4807 tpl_printf(vars, TPLADD, "TMPV", "DEBUGVAL%d", lvl);
4808 if(cs_dblevel & lvl)
4809 {
4810 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugls");
4811 tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel - lvl);
4812 }
4813 else
4814 {
4815 tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugl");
4816 tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel + lvl);
4817 }
4818 }
4819 if(cs_dblevel == D_ALL_DUMP)
4820 { tpl_addVar(vars, TPLADD, "DCLASS65535", "debugls"); }
4821 else
4822 { tpl_addVar(vars, TPLADD, "DCLASS65535", "debugl"); }
4823 tpl_addVar(vars, TPLADD, "CUSTOMPARAM", "&file=logfile");
4824 tpl_printf(vars, TPLADD, "ACTDEBUG", "%d", cs_dblevel);
4825 tpl_addVar(vars, TPLADD, "SDEBUG", tpl_getTpl(vars, "DEBUGSELECT"));
4826 tpl_addVar(vars, TPLADD, "NEXTPAGE", "files.html");
4827#endif
4828 if(!cfg.disablelog)
4829 { tpl_printf(vars, TPLADD, "LOGMENU", "<A HREF=\"files.html?file=logfile&amp;stoplog=%d\">%s</A><SPAN CLASS=\"debugt\">&nbsp;&nbsp;|&nbsp;&nbsp;</SPAN>\n", 1, "Stop Log"); }
4830 else
4831 { tpl_printf(vars, TPLADD, "LOGMENU", "<A HREF=\"files.html?file=logfile&amp;stoplog=%d\">%s</A><SPAN CLASS=\"debugt\">&nbsp;&nbsp;|&nbsp;&nbsp;</SPAN>\n", 0, "Start Log"); }
4832 tpl_addVar(vars, TPLAPPEND, "LOGMENU", "<A HREF=\"files.html?file=logfile&amp;clear=logfile\">Clear Log</A>");
4833 return;
4834}
4835
4836static void webif_process_userfile(struct templatevars * vars, struct uriparams * params, char *targetfile, size_t targetfile_len)
4837{
4838 snprintf(targetfile, targetfile_len, "%s", cfg.usrfile);
4839 if(strcmp(getParam(params, "clear"), "usrfile") == 0)
4840 {
4841 if(strlen(targetfile) > 0)
4842 {
4843 FILE *file = fopen(targetfile, "w");
4844 fclose(file);
4845 }
4846 }
4847
4848 if(!cfg.disableuserfile)
4849 { tpl_printf(vars, TPLADD, "LOGMENU", "<A HREF=\"files.html?file=userfile&amp;stopusrlog=%d\">%s</A>&nbsp;&nbsp;|&nbsp;&nbsp;\n", 1, "Stop Log"); }
4850 else
4851 { tpl_printf(vars, TPLADD, "LOGMENU", "<A HREF=\"files.html?file=userfile&amp;stopusrlog=%d\">%s</A>&nbsp;&nbsp;|&nbsp;&nbsp;\n", 0, "Start Log"); }
4852
4853 tpl_addVar(vars, TPLAPPEND, "LOGMENU", "<A HREF=\"files.html?file=userfile&amp;clear=usrfile\">Clear Log</A>");
4854
4855 tpl_printf(vars, TPLADD, "FILTERFORMOPTIONS", "<OPTION value=\"%s\">%s</OPTION>\n", "all", "all");
4856 struct s_auth *account;
4857 for(account = cfg.account; account; account = account->next)
4858 {
4859 tpl_printf(vars, TPLAPPEND, "FILTERFORMOPTIONS", "<OPTION value=\"%s\" %s>%s</OPTION>\n",
4860 xml_encode(vars, account->usr),
4861 strcmp(getParam(params, "filter"), account->usr) ? "" : "selected",
4862 xml_encode(vars, account->usr)
4863 );
4864 }
4865 tpl_addVar(vars, TPLADD, "FILTERFORM", tpl_getTpl(vars, "FILTERFORM"));
4866}
4867
4868enum file_types { FTYPE_CONFIG, FTYPE_VERSION, FTYPE_ANTICASC, FTYPE_LOGFILE, FTYPE_USERFILE };
4869
4870struct files
4871{
4872 char *file;
4873 int menu_id;
4874 enum file_types type;
4875};
4876
4877static char *send_oscam_files(struct templatevars * vars, struct uriparams * params, int8_t apicall)
4878{
4879 bool writable = false;
4880 const struct files *entry;
4881 static const struct files config_files[] =
4882 {
4883 { "oscam.version", MNU_CFG_FVERSION, FTYPE_VERSION },
4884 { "oscam.conf", MNU_CFG_FCONF, FTYPE_CONFIG },
4885 { "oscam.user", MNU_CFG_FUSER, FTYPE_CONFIG },
4886 { "oscam.server", MNU_CFG_FSERVER, FTYPE_CONFIG },
4887 { "oscam.services", MNU_CFG_FSERVICES, FTYPE_CONFIG },
4888 { "oscam.whitelist", MNU_CFG_WHITELIST, FTYPE_CONFIG },
4889 { "oscam.srvid", MNU_CFG_FSRVID, FTYPE_CONFIG },
4890 { "oscam.provid", MNU_CFG_FPROVID, FTYPE_CONFIG },
4891 { "oscam.tiers", MNU_CFG_FTIERS, FTYPE_CONFIG },
4892#ifdef HAVE_DVBAPI
4893 { "oscam.dvbapi", MNU_CFG_FDVBAPI, FTYPE_CONFIG },
4894#endif
4895#ifdef CS_ANTICASC
4896 { "anticasc", MNU_CFG_FACLOG, FTYPE_ANTICASC },
4897#endif
4898 { "logfile", MNU_CFG_FLOGFILE, FTYPE_LOGFILE },
4899 { "userfile", MNU_CFG_FUSERFILE, FTYPE_USERFILE },
4900 { NULL, 0, 0 },
4901 };
4902
4903 if(!apicall) { setActiveMenu(vars, MNU_FILES); }
4904
4905 tpl_addVar(vars, TPLADD, "APIFILENAME", "null");
4906 tpl_addVar(vars, TPLADD, "APIWRITABLE", "0");
4907
4908 char *stoplog = getParam(params, "stoplog");
4909 if(strlen(stoplog) > 0)
4910 { cs_disable_log(atoi(stoplog)); }
4911
4912 char *stopusrlog = getParam(params, "stopusrlog");
4913 if(strlen(stopusrlog) > 0)
4914 { cfg.disableuserfile = atoi(stopusrlog); }
4915
4916 char *debuglvl = getParam(params, "debug");
4917 if(strlen(debuglvl) > 0)
4918 {
4919#ifndef WITH_DEBUG
4920 cs_log("*** Warning: Debug Support not compiled in ***");
4921#else
4922 int32_t dblvl = atoi(debuglvl);
4923 if(dblvl >= 0 && dblvl <= 65535) { cs_dblevel = dblvl; }
4924 cs_log("%s debug_level=%d", "all", cs_dblevel);
4925#endif
4926 }
4927 // Process config files
4928 char *file = getParam(params, "file");
4929 char targetfile[256] = { 0 };
4930 int menu_id = 0;
4931 for(entry = config_files; entry->file; entry++)
4932 {
4933 if(streq(file, entry->file))
4934 {
4935 if(!apicall) { setActiveSubMenu(vars, entry->menu_id); }
4936 menu_id = entry->menu_id;
4937 tpl_addVar(vars, TPLADD, "APIWRITABLE", writable ? "1" : "0");
4938 switch(entry->type)
4939 {
4940 case FTYPE_CONFIG:
4941 writable = 1;
4942 get_config_filename(targetfile, sizeof(targetfile), entry->file);
4943 break;
4944 case FTYPE_VERSION:
4945 get_tmp_dir_filename(targetfile, sizeof(targetfile), entry->file);
4946 break;
4947 case FTYPE_ANTICASC:
4948#ifdef CS_ANTICASC
4949 if(!apicall) { snprintf(targetfile, sizeof(targetfile), "%s", ESTR(cfg.ac_logfile)); }
4950#endif
4951 break;
4952 case FTYPE_LOGFILE:
4953 if(!apicall) { webif_process_logfile(vars, params, targetfile, sizeof(targetfile)); }
4954 break;
4955 case FTYPE_USERFILE:
4956 if(!apicall) { webif_process_userfile(vars, params, targetfile, sizeof(targetfile)); }
4957 break;
4958 }
4959 tpl_addVar(vars, TPLADD, "APIFILENAME", entry->file);
4960 break;
4961 }
4962 }
4963
4964 if(!strstr(targetfile, "/dev/"))
4965 {
4966 if(strcmp(getParam(params, "action"), "Save") == 0)
4967 {
4968 if((strlen(targetfile) > 0) /*&& (file_exists(targetfile) == 1)*/)
4969 {
4970 FILE *fpsave;
4971 char *fcontent = getParam(params, "filecontent");
4972 if((fpsave = fopen(targetfile, "w")))
4973 {
4974 int32_t i, lastpos = 0, len = strlen(fcontent) + 1;
4975 //write submitted file line by line to disk and remove windows linebreaks
4976 for(i = 0; i < len; ++i)
4977 {
4978 char tmp = fcontent[i];
4979 if(tmp == '\r' || tmp == '\n' || tmp == 0)
4980 {
4981 fcontent[i] = 0;
4982 fprintf(fpsave, "%s%s", fcontent + lastpos, tmp == 0 ? "" : "\n");
4983 if(tmp == '\r' && fcontent[i + 1] == '\n') { ++i; }
4984 lastpos = i + 1;
4985 }
4986 }
4987 fclose(fpsave);
4988 // Reinit on save
4989 switch(menu_id)
4990 {
4991 case MNU_CFG_FSRVID:
4992 init_srvid();
4993 break;
4994 case MNU_CFG_FUSER:
4995 cs_accounts_chk();
4996 break;
4997 case MNU_CFG_FDVBAPI:
4998 dvbapi_read_priority();
4999 break;
5000 case MNU_CFG_WHITELIST:
5001 global_whitelist_read();
5002 break;
5003 default:
5004 break;
5005 }
5006 }
5007 }
5008 }
5009
5010 if((strlen(targetfile) > 0) && (file_exists(targetfile) == 1))
5011 {
5012 FILE *fp;
5013 char buffer[256];
5014
5015 if((fp = fopen(targetfile, "r")) == NULL) { return "0"; }
5016 while(fgets(buffer, sizeof(buffer), fp) != NULL)
5017 if(!strcmp(getParam(params, "filter"), "all"))
5018 { tpl_addVar(vars, TPLAPPEND, "FILECONTENT", buffer); }
5019 else if(strstr(buffer, getParam(params, "filter")))
5020 { tpl_addVar(vars, TPLAPPEND, "FILECONTENT", buffer); }
5021 fclose(fp);
5022 }
5023 else
5024 {
5025 tpl_addVar(vars, TPLAPPEND, "FILECONTENT", "File does not exist or no file selected!");
5026 }
5027 }
5028 else
5029 {
5030 tpl_addVar(vars, TPLAPPEND, "FILECONTENT", "File not valid!");
5031 }
5032
5033 tpl_addVar(vars, TPLADD, "PART", file);
5034
5035 if(!writable)
5036 {
5037 tpl_addVar(vars, TPLADD, "WRITEPROTECTION", tpl_getTpl(vars, "WRITEPROTECTION"));
5038 tpl_addVar(vars, TPLADD, "BTNDISABLED", "DISABLED");
5039 }
5040
5041 if(!apicall)
5042 { return tpl_getTpl(vars, "FILE"); }
5043 else
5044 { return tpl_getTpl(vars, "APIFILE"); }
5045}
5046
5047static char *send_oscam_failban(struct templatevars * vars, struct uriparams * params, int8_t apicall)
5048{
5049 IN_ADDR_T ip2delete;
5050 set_null_ip(&ip2delete);
5051 LL_ITER itr = ll_iter_create(cfg.v_list);
5052 V_BAN *v_ban_entry;
5053 //int8_t apicall = 0; //remove before flight
5054
5055 if(!apicall) { setActiveMenu(vars, MNU_FAILBAN); }
5056
5057 if(strcmp(getParam(params, "action"), "delete") == 0)
5058 {
5059
5060 if(strcmp(getParam(params, "intip"), "all") == 0)
5061 {
5062 // clear whole list
5063 while((v_ban_entry = ll_iter_next(&itr)))
5064 {
5065 ll_iter_remove_data(&itr);
5066 }
5067
5068 }
5069 else
5070 {
5071 //we have a single IP
5072 cs_inet_addr(getParam(params, "intip"), &ip2delete);
5073 while((v_ban_entry = ll_iter_next(&itr)))
5074 {
5075 if(IP_EQUAL(v_ban_entry->v_ip, ip2delete))
5076 {
5077 ll_iter_remove_data(&itr);
5078 break;
5079 }
5080 }
5081 }
5082 }
5083 ll_iter_reset(&itr);
5084
5085 struct timeb now;
5086 cs_ftime(&now);
5087
5088 while((v_ban_entry = ll_iter_next(&itr)))
5089 {
5090
5091 tpl_printf(vars, TPLADD, "IPADDRESS", "%s : %d", cs_inet_ntoa(v_ban_entry->v_ip), v_ban_entry->v_port);
5092 tpl_addVar(vars, TPLADD, "VIOLATIONUSER", v_ban_entry->info ? v_ban_entry->info : "unknown");
5093 struct tm st ;
5094 localtime_r(&v_ban_entry->v_time.time, &st); // fix me, we need walltime!
5095 if(!apicall)
5096 {
5097 tpl_printf(vars, TPLADD, "VIOLATIONDATE", "%02d.%02d.%02d %02d:%02d:%02d",
5098 st.tm_mday, st.tm_mon + 1,
5099 st.tm_year % 100, st.tm_hour,
5100 st.tm_min, st.tm_sec);
5101 }
5102 else
5103 {
5104 char tbuffer [30];
5105 strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &st);
5106 tpl_addVar(vars, TPLADD, "VIOLATIONDATE", tbuffer);
5107 }
5108
5109 tpl_printf(vars, TPLADD, "VIOLATIONCOUNT", "%d", v_ban_entry->v_count);
5110
5111 int32_t gone = comp_timeb(&now, &v_ban_entry->v_time);
5112 if(!apicall)
5113 { tpl_addVar(vars, TPLADD, "LEFTTIME", sec2timeformat(vars, (cfg.failbantime * 60) - (gone / 1000))); }
5114 else
5115 { tpl_printf(vars, TPLADD, "LEFTTIME", "%d", (cfg.failbantime * 60) - (gone / 1000)); }
5116
5117 tpl_addVar(vars, TPLADD, "INTIP", cs_inet_ntoa(v_ban_entry->v_ip));
5118
5119 if(!apicall)
5120 { tpl_addVar(vars, TPLAPPEND, "FAILBANROW", tpl_getTpl(vars, "FAILBANBIT")); }
5121 else
5122 { tpl_addVar(vars, TPLAPPEND, "APIFAILBANROW", tpl_getTpl(vars, "APIFAILBANBIT")); }
5123 }
5124 if(!apicall)
5125 { return tpl_getTpl(vars, "FAILBAN"); }
5126 else
5127 { return tpl_getTpl(vars, "APIFAILBAN"); }
5128}
5129
5130static bool send_EMM(struct s_reader * rdr, uint16_t caid, struct s_cardsystem * cs, const unsigned char *emmhex, uint32_t len)
5131{
5132
5133 if(NULL != rdr && NULL != emmhex && 0 != len)
5134 {
5135 EMM_PACKET *emm_pack = NULL;
5136
5137 if(cs_malloc(&emm_pack, sizeof(EMM_PACKET)))
5138 {
5139 struct s_client *webif_client = cur_client();
5140 webif_client->grp = 0xFF; /* to access to all readers */
5141
5142 memset(emm_pack, '\0', sizeof(EMM_PACKET));
5143 emm_pack->client = webif_client;
5144 emm_pack->emmlen = len;
5145 memcpy(emm_pack->emm, emmhex, len);
5146
5147 emm_pack->caid[0] = (caid >> 8) & 0xFF;
5148 emm_pack->caid[1] = caid & 0xFF;
5149
5150 if(cs && cs->get_emm_type)
5151 {
5152 if(!cs->get_emm_type(emm_pack, rdr))
5153 {
5154 rdr_debug_mask(rdr, D_EMM, "get_emm_type() returns error");
5155 }
5156 }
5157
5158 cs_debug_mask(D_EMM, "emm is being sent to reader %s.", rdr->label);
5159 add_job(rdr->client, ACTION_READER_EMM, emm_pack, sizeof(EMM_PACKET));
5160 return true;
5161 }
5162 }
5163
5164 return false;
5165}
5166
5167static bool process_single_emm(struct templatevars * vars, struct s_reader * rdr, uint16_t caid, struct s_cardsystem * cs, const char *ep)
5168{
5169
5170 if(NULL != vars && NULL != rdr && NULL != ep)
5171 {
5172 char emmdata[1025] = {'\0'}; /*1024 + '\0'*/
5173 unsigned char emmhex[513] = {'\0'};
5174 char buff[5] = {'\0'};
5175 uint32_t len = 0;
5176 cs_strncpy(emmdata, ep, sizeof(emmdata));
5177 remove_white_chars(emmdata);
5178
5179 if('\0' != emmdata[0])
5180 {
5181 len = strlen(emmdata);
5182 tpl_addVar(vars, TPLADD, "EP", strtoupper(emmdata));
5183 if(key_atob_l(emmdata, emmhex, len))
5184 {
5185 tpl_addMsg(vars, "Single EMM has not been sent due to wrong value!");
5186 }
5187 else
5188 {
5189 len /= 2;
5190 snprintf(buff, sizeof(buff), "0x%02X", len);
5191 tpl_addVar(vars, TPLADD, "EP", strtoupper(emmdata));
5192 tpl_addVar(vars, TPLADD, "SIZE", buff);
5193
5194 if(send_EMM(rdr, caid, cs, emmhex, len))
5195 {
5196 tpl_addMsg(vars, "Single EMM has been sent.");
5197 return true;
5198 }
5199 }
5200 }
5201 }
5202 tpl_addVar(vars, TPLADD, "SIZE", "0x00");
5203 return false;
5204}
5205
5206static bool process_emm_file(struct templatevars * vars, struct s_reader * rdr, uint16_t caid, struct s_cardsystem * cs, const char *sFilePath)
5207{
5208
5209 bool bret = false;
5210 uint32_t fsize = 0;
5211 uint32_t rlines = 0;
5212 uint32_t wemms = 0;
5213 uint32_t errsize = 0;
5214 char numerrl[256] = {'\0'};
5215 char buff[20] = {'\0'};
5216
5217 if(NULL != rdr && NULL != sFilePath && '\0' != sFilePath[0])
5218 {
5219 char sMessage[128] = {0};
5220 if(true == file_exists(sFilePath))
5221 {
5222 FILE *fp;
5223 if((fp = fopen(sFilePath, "r")))
5224 {
5225 char line[2048] = {'\0'};
5226 unsigned char emmhex[513] = {'\0'};
5227 uint32_t len = 0;
5228
5229 tpl_addMsg(vars, "EMM file has been processed.");
5230 while(fgets(line, sizeof(line), fp))
5231 {
5232 ++rlines;
5233 len = strlen(remove_white_chars(line));
5234
5235 // wrong emm
5236 if(len > (sizeof(emmhex) * 2) ||
5237 key_atob_l(line, emmhex, len))
5238 {
5239 errsize += snprintf(numerrl + errsize, sizeof(numerrl) - errsize, "%d, ", rlines);
5240 continue;
5241 }
5242 len /= 2;
5243 if(send_EMM(rdr, caid, cs, emmhex, len))
5244 {
5245 ++wemms;
5246 /* Give time to process EMM, otherwise, too many jobs can be added*/
5247 cs_sleepms(1000); //TODO: use oscam signal to catch reader answer
5248 }
5249 }
5250 fsize = ftell(fp);
5251 fclose(fp);
5252 }
5253 else
5254 {
5255 snprintf(sMessage, sizeof(sMessage), "Cannot open file '%s' (errno=%d: %s)\n", sFilePath, errno, strerror(errno));
5256 tpl_addMsg(vars, sMessage);
5257 }
5258 }
5259 else
5260 {
5261 snprintf(sMessage, sizeof(sMessage), "FILE \"%s\" not found!", sFilePath);
5262 tpl_addMsg(vars, sMessage);
5263 }
5264 bret = true;
5265 }
5266
5267 snprintf(buff, sizeof(buff), "%d bytes", fsize);
5268 tpl_addVar(vars, TPLADD, "FSIZE", buff);
5269 snprintf(buff, sizeof(buff), "%d", rlines);
5270 tpl_addVar(vars, TPLADD, "NUMRLINE", buff);
5271 snprintf(buff, sizeof(buff), "%d", wemms);
5272 tpl_addVar(vars, TPLADD, "NUMWEMM", buff);
5273 tpl_addVar(vars, TPLADD, "ERRLINE", numerrl);
5274
5275 return bret;
5276}
5277
5278static char *send_oscam_EMM_running(struct templatevars * vars, struct uriparams * params)
5279{
5280
5281 struct s_reader *rdr = NULL;
5282
5283 setActiveMenu(vars, MNU_READERS);
5284 tpl_addVar(vars, TPLADD, "READER", getParam(params, "label"));
5285 tpl_addVar(vars, TPLADD, "FNAME", getParam(params, "emmfile"));
5286
5287 rdr = get_reader_by_label(getParam(params, "label"));
5288 if(rdr)
5289 {
5290 int32_t tcaid = dyn_word_atob(getParam(params, "emmcaid"));
5291 uint16_t caid = (-1 != tcaid) ? (uint16_t)tcaid : 0;
5292 char buff[7] = "";
5293 struct s_cardsystem *cs = NULL;
5294 int32_t proxy = is_cascading_reader(rdr);
5295
5296 if((proxy || !rdr->csystem.active) && caid) // network reader (R_CAMD35 R_NEWCAMD R_CS378X R_CCCAM)
5297 {
5298 if(proxy && !rdr->ph.c_send_emm)
5299 {
5300 tpl_addMsg(vars, "The reader does not support EMMs!");
5301 return tpl_getTpl(vars, "EMM_RUNNING");
5302 }
5303
5304 cs = get_cardsystem_by_caid(caid);
5305 if(!cs)
5306 {
5307 rdr_debug_mask(rdr, D_EMM, "unable to find cardsystem for caid %04X", caid);
5308 caid = 0;
5309 }
5310 }
5311 else if(!proxy && rdr->csystem.active) // local active reader
5312 {
5313 cs = &rdr->csystem;
5314 caid = rdr->caid;
5315 }
5316
5317 if(cs)
5318 {
5319 tpl_addVar(vars, TPLADD, "SYSTEM", cs->desc);
5320 }
5321 else
5322 {
5323 tpl_addVar(vars, TPLADD, "SYSTEM", "unknown");
5324 }
5325 if(caid)
5326 {
5327 snprintf(buff, sizeof(buff), "0x%04X", caid);
5328 tpl_addVar(vars, TPLADD, "CAID", buff);
5329 }
5330 else
5331 {
5332 tpl_addVar(vars, TPLADD, "CAID", "unknown");
5333 }
5334
5335 process_single_emm(vars, rdr, caid, cs, getParam(params, "ep"));
5336 process_emm_file(vars, rdr, caid, cs, getParam(params, "emmfile"));
5337 }
5338 else
5339 {
5340 char sMessage[128] = {0};
5341 snprintf(sMessage, sizeof(sMessage), "READER \"%s\" not found!", getParam(params, "label"));
5342 tpl_addMsg(vars, sMessage);
5343 tpl_addVar(vars, TPLADD, "READER", "reader not found");
5344 }
5345
5346 return tpl_getTpl(vars, "EMM_RUNNING");
5347}
5348
5349static char *send_oscam_EMM(struct templatevars * vars, struct uriparams * params)
5350{
5351
5352 setActiveMenu(vars, MNU_READERS);
5353 tpl_addVar(vars, TPLADD, "READER", getParam(params, "label"));
5354
5355 struct s_reader *rdr = NULL;
5356 rdr = get_reader_by_label(getParam(params, "label"));
5357 if(rdr && rdr->caid)
5358 {
5359 char buff[5] = "";
5360 snprintf(buff, sizeof(buff), "%04X", rdr->caid);
5361 tpl_addVar(vars, TPLADD, "CAID", buff);
5362 if(!is_cascading_reader(rdr))
5363 {
5364 tpl_addVar(vars, TPLADD, "READONLY", "readonly=\"readonly\"");
5365 }
5366 }
5367
5368 return tpl_getTpl(vars, "ASKEMM");
5369}
5370
5371static char *send_oscam_api(struct templatevars * vars, FILE * f, struct uriparams * params, int8_t *keepalive, int8_t apicall, char *extraheader)
5372{
5373 if(strcmp(getParam(params, "part"), "status") == 0)
5374 {
5375 return send_oscam_status(vars, params, apicall);
5376 }
5377 else if(strcmp(getParam(params, "part"), "userstats") == 0)
5378 {
5379 return send_oscam_user_config(vars, params, apicall);
5380 }
5381 else if(strcmp(getParam(params, "part"), "failban") == 0)
5382 {
5383 return send_oscam_failban(vars, params, apicall);
5384 }
5385 else if(strcmp(getParam(params, "part"), "files") == 0)
5386 {
5387 return send_oscam_files(vars, params, apicall);
5388 }
5389 else if(strcmp(getParam(params, "part"), "readerlist") == 0)
5390 {
5391 return send_oscam_reader(vars, params, apicall);
5392 }
5393 else if(strcmp(getParam(params, "part"), "serverconfig") == 0)
5394 {
5395 //Send Errormessage
5396 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "serverconfig not yet avail");
5397 return tpl_getTpl(vars, "APIERROR");
5398 }
5399 else if(strcmp(getParam(params, "part"), "userconfig") == 0)
5400 {
5401 if(((strcmp(getParam(params, "action"), "Save") == 0) ||
5402 (strcmp(getParam(params, "action"), "Save As") == 0)) && cfg.http_readonly == 1)
5403 {
5404 //Send Errormessage
5405 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "API is in readonly mode");
5406 return tpl_getTpl(vars, "APIERROR");
5407 }
5408 else
5409 {
5410 struct s_auth *account = get_account_by_name(getParam(params, "user"));
5411 if(!account && strcmp(getParam(params, "action"), "Save"))
5412 {
5413 //Send Errormessage
5414 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "user not exist");
5415 return tpl_getTpl(vars, "APIERROR");
5416 }
5417 else
5418 {
5419 return send_oscam_user_config_edit(vars, params, apicall);
5420 }
5421 }
5422 }
5423 else if(strcmp(getParam(params, "part"), "entitlement") == 0)
5424 {
5425
5426 if(strcmp(getParam(params, "label"), ""))
5427 {
5428 struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
5429 if(rdr)
5430 {
5431 if(rdr->typ == R_CCCAM && rdr->enable == 1)
5432 {
5433 return send_oscam_entitlement(vars, params, apicall);
5434 }
5435 else
5436 {
5437 //Send Errormessage
5438 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "no cccam reader or disabled");
5439 return tpl_getTpl(vars, "APIERROR");
5440 }
5441 }
5442 else
5443 {
5444 //Send Errormessage
5445 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "reader not exist");
5446 return tpl_getTpl(vars, "APIERROR");
5447 }
5448 }
5449 else
5450 {
5451 //Send Errormessage
5452 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "no reader selected");
5453 return tpl_getTpl(vars, "APIERROR");
5454 }
5455 }
5456 else if(strcmp(getParam(params, "part"), "ecmhistory") == 0)
5457 {
5458 int32_t i;
5459 int32_t isec;
5460 int32_t shown;
5461 time_t now = time((time_t *)0);
5462 char *usr;
5463 struct s_client *cl;
5464 for(i = 0, cl = first_client; cl ; cl = cl->next, i++)
5465 {
5466 if(cl->wihidden != 1)
5467 {
5468 isec = now - cl->lastecm;
5469 usr = username(cl);
5470 shown = 0;
5471 if(strcmp(getParam(params, "label"), "") == 0)
5472 {
5473 if(strcmp(getParam(params, "type"), "servers") == 0)
5474 {
5475 if(cl->typ == 'p' || cl->typ == 'r')
5476 { shown = 1; }
5477 }
5478 else if(strcmp(getParam(params, "type"), "users") == 0)
5479 {
5480 if(cl->typ == 'c')
5481 { shown = 1; }
5482 }
5483 else
5484 {
5485 shown = 1;
5486 }
5487 }
5488 else if(strcmp(getParam(params, "label"), usr) == 0)
5489 {
5490 shown = 1;
5491 }
5492 if(shown == 1)
5493 {
5494 tpl_printf(vars, TPLADD, "CLIENTTYPE", "%c", cl->typ);
5495 tpl_addVar(vars, TPLADD, "CLIENTUSER", xml_encode(vars, usr));
5496 if(cl->typ == 'c')
5497 {
5498 tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", xml_encode(vars, (cl->account && cl->account->description) ? cl->account->description : ""));
5499 }
5500 else if(cl->typ == 'p' || cl->typ == 'r')
5501 {
5502 tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", xml_encode(vars, cl->reader->description ? cl->reader->description : ""));
5503 }
5504 tpl_printf(vars, TPLADD, "CLIENTLASTRESPONSETIME", "%d", cl->cwlastresptime ? cl->cwlastresptime : -1);
5505 tpl_printf(vars, TPLADD, "CLIENTIDLESECS", "%d", isec);
5506
5507 //load historical values from ringbuffer
5508 char *value = get_ecm_fullhistorystring(cl);
5509 tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIMEHIST", value);
5510 free_mk_t(value);
5511
5512 tpl_addVar(vars, TPLAPPEND, "APISTATUSBITS", tpl_getTpl(vars, "APISTATUSBIT"));
5513 }
5514 }
5515 }
5516 return tpl_getTpl(vars, "APISTATUS");
5517 }
5518 else if(strcmp(getParam(params, "part"), "readerstats") == 0)
5519 {
5520 if(strcmp(getParam(params, "label"), ""))
5521 {
5522 struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
5523 if(rdr)
5524 {
5525 return send_oscam_reader_stats(vars, params, apicall);
5526 }
5527 else
5528 {
5529 //Send Errormessage
5530 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "reader not exist");
5531 return tpl_getTpl(vars, "APIERROR");
5532 }
5533 }
5534 else
5535 {
5536 //Send Errormessage
5537 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "no reader selected");
5538 return tpl_getTpl(vars, "APIERROR");
5539 }
5540 }
5541 else if(strcmp(getParam(params, "part"), "shutdown") == 0)
5542 {
5543 if((strcmp(strtolower(getParam(params, "action")), "restart") == 0) ||
5544 (strcmp(strtolower(getParam(params, "action")), "shutdown") == 0))
5545 {
5546 if(!cfg.http_readonly)
5547 {
5548 return send_oscam_shutdown(vars, f, params, apicall, keepalive, extraheader);
5549 }
5550 else
5551 {
5552 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "webif readonly mode");
5553 return tpl_getTpl(vars, "APIERROR");
5554 }
5555 }
5556 else
5557 {
5558 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "missing parameter action");
5559 return tpl_getTpl(vars, "APIERROR");
5560 }
5561
5562 }
5563 else
5564 {
5565 tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "part not found");
5566 return tpl_getTpl(vars, "APIERROR");
5567 }
5568}
5569
5570static char *send_oscam_image(struct templatevars * vars, FILE * f, struct uriparams * params, char *image, time_t modifiedheader, uint32_t etagheader, char *extraheader)
5571{
5572 char *wanted;
5573 if(image == NULL) { wanted = getParam(params, "i"); }
5574 else { wanted = image; }
5575 if(strlen(wanted) > 3 && wanted[0] == 'I' && wanted[1] == 'C')
5576 {
5577 if(etagheader == 0)
5578 {
5579 int8_t disktpl = 0;
5580 if(cfg.http_tpl)
5581 {
5582 char path[255];
5583 if(strlen(tpl_getTplPath(wanted, cfg.http_tpl, path, 255)) > 0 && file_exists(path))
5584 {
5585 struct stat st;
5586 disktpl = 1;
5587 stat(path, &st);
5588 if((time_t)st.st_mtime < modifiedheader)
5589 {
5590 send_header304(f, extraheader);
5591 return "1";
5592 }
5593 }
5594 }
5595 if(disktpl == 0 && first_client->login < modifiedheader)
5596 {
5597 send_header304(f, extraheader);
5598 return "1";
5599 }
5600 }
5601 char *header = strstr(tpl_getTpl(vars, wanted), "data:");
5602 if(header != NULL)
5603 {
5604 char *ptr = header + 5;
5605 while(ptr[0] != ';' && ptr[0] != '\0') { ++ptr; }
5606 if(ptr[0] != '\0' && ptr[1] != '\0') { ptr[0] = '\0'; }
5607 else { return "0"; }
5608 ptr = strstr(ptr + 1, "base64,");
5609 if(ptr != NULL)
5610 {
5611 int32_t len = b64decode((uchar *)ptr + 7);
5612 if(len > 0)
5613 {
5614 if((uint32_t)crc32(0L, (uchar *)ptr + 7, len) == etagheader)
5615 {
5616 send_header304(f, extraheader);
5617 }
5618 else
5619 {
5620 send_headers(f, 200, "OK", extraheader, header + 5, 1, len, ptr + 7, 0);
5621 webif_write_raw(ptr + 7, f, len);
5622 }
5623 return "1";
5624 }
5625 }
5626 }
5627 }
5628 // Return file not found
5629 const char *not_found = "File not found.\n";
5630 send_headers(f, 404, "Not Found", extraheader, "text/plain", 0, strlen(not_found), (char *)not_found, 0);
5631 webif_write_raw((char *)not_found, f, strlen(not_found));
5632 return "1";
5633}
5634
5635static char *send_oscam_robots_txt(FILE * f)
5636{
5637 const char *content = "User-agent: *\nDisallow: /\n";
5638 send_headers(f, 200, "OK", NULL, "text/plain", 0, strlen(content), (char *)content, 0);
5639 webif_write_raw((char *)content, f, strlen(content));
5640 return "1";
5641}
5642
5643static char *send_oscam_graph(struct templatevars * vars)
5644{
5645 return tpl_getTpl(vars, "GRAPH");
5646}
5647
5648#ifdef CS_CACHEEX
5649static uint64_t get_cacheex_node(struct s_client * cl)
5650{
5651 uint64_t node = 0x00;
5652 struct s_module *module = (cl->reader ? &cl->reader->ph : get_module(cl));
5653#ifdef MODULE_CCCAM
5654 if(module->num == R_CCCAM && cl->cc)
5655 {
5656 struct cc_data *cc = cl->cc;
5657 memcpy(&node, cc->peer_node_id, 8);
5658 }
5659 else
5660#endif
5661#ifdef MODULE_CAMD35
5662 if(module->num == R_CAMD35)
5663 {
5664 memcpy(&node, cl->ncd_skey, 8);
5665 }
5666 else
5667#endif
5668#ifdef MODULE_CAMD35_TCP
5669 if(module->num == R_CS378X)
5670 {
5671 memcpy(&node, cl->ncd_skey, 8);
5672 }
5673 else
5674#endif
5675 {}
5676 return node;
5677}
5678
5679
5680static char *send_oscam_cacheex(struct templatevars * vars, struct uriparams * params, int8_t apicall)
5681{
5682
5683 if(!apicall) { setActiveMenu(vars, MNU_CACHEEX); }
5684
5685 if(strcmp(getParam(params, "x"), "x") == 0)
5686 {
5687 // avoid compilerwarning unused vars
5688 }
5689 if(cfg.http_refresh > 0)
5690 {
5691 tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", cfg.http_refresh);
5692 tpl_addVar(vars, TPLADD, "REFRESHURL", "cacheex.html");
5693 tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
5694 }
5695 char *level[] = {"NONE", "CACHE PULL", "CACHE PUSH", "REVERSE CACHE PUSH"};
5696 char *getting = "<IMG SRC=\"image?i=ICARRL\" ALT=\"Getting\">";
5697 char *pushing = "<IMG SRC=\"image?i=ICARRR\" ALT=\"Pushing\">";
5698 char *rowvariable = "";
5699
5700 int16_t i, written = 0;
5701 struct s_client *cl;
5702 time_t now = time((time_t *)0);
5703
5704 tpl_printf(vars, TPLADD, "OWN_CACHEEX_NODEID", "%" PRIu64 "X", cacheex_node_id(cacheex_peer_id));
5705
5706 for(i = 0, cl = first_client; cl ; cl = cl->next, i++)
5707 {
5708 if(cl->typ == 'c' && cl->account && cl->account->cacheex.mode)
5709 {
5710 tpl_addVar(vars, TPLADD, "TYPE", "Client");
5711 if(!apicall) { tpl_addVar(vars, TPLADD, "NAME", xml_encode(vars, cl->account->usr)); }
5712 else { tpl_addVar(vars, TPLADD, "NAME", cl->account->usr); }
5713 tpl_addVar(vars, TPLADD, "IP", cs_inet_ntoa(cl->ip));
5714 tpl_printf(vars, TPLADD, "NODE", "%" PRIu64 "X", get_cacheex_node(cl));
5715 tpl_addVar(vars, TPLADD, "LEVEL", level[cl->account->cacheex.mode]);
5716 tpl_printf(vars, TPLADD, "PUSH", "%d", cl->account->cwcacheexpush);
5717 tpl_printf(vars, TPLADD, "GOT", "%d", cl->account->cwcacheexgot);
5718 tpl_printf(vars, TPLADD, "HIT", "%d", cl->account->cwcacheexhit);
5719 tpl_printf(vars, TPLADD, "ERR", "%d", cl->account->cwcacheexerr);
5720 tpl_printf(vars, TPLADD, "ERRCW", "%d", cl->account->cwcacheexerrcw);
5721 tpl_addVar(vars, TPLADD, "DIRECTIONIMG", (cl->account->cacheex.mode == 3) ? getting : pushing);
5722 rowvariable = "TABLECLIENTROWS";
5723 written = 1;
5724 }
5725 else if((cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode))
5726 {
5727 tpl_addVar(vars, TPLADD, "TYPE", "Reader");
5728 if(!apicall) { tpl_addVar(vars, TPLADD, "NAME", xml_encode(vars, cl->reader->label)); }
5729 else { tpl_addVar(vars, TPLADD, "NAME", cl->reader->label); }
5730 tpl_addVar(vars, TPLADD, "IP", cs_inet_ntoa(cl->ip));
5731 tpl_printf(vars, TPLADD, "NODE", "%" PRIu64 "X", get_cacheex_node(cl));
5732 tpl_addVar(vars, TPLADD, "LEVEL", level[cl->reader->cacheex.mode]);
5733 tpl_printf(vars, TPLADD, "PUSH", "%d", cl->cwcacheexpush);
5734 tpl_printf(vars, TPLADD, "GOT", "%d", cl->cwcacheexgot);
5735 tpl_printf(vars, TPLADD, "HIT", "%d", cl->cwcacheexhit);
5736 tpl_printf(vars, TPLADD, "ERR", "%d", cl->cwcacheexerr);
5737 tpl_printf(vars, TPLADD, "ERRCW", "%d", cl->cwcacheexerrcw);
5738 tpl_addVar(vars, TPLADD, "DIRECTIONIMG", (cl->reader->cacheex.mode == 3) ? pushing : getting);
5739 rowvariable = "TABLEREADERROWS";
5740 written = 1;
5741 }
5742 else if(get_module(cl)->listenertype == LIS_CSPUDP)
5743 {
5744 tpl_addVar(vars, TPLADD, "TYPE", "csp");
5745 tpl_addVar(vars, TPLADD, "NAME", "csp");
5746 tpl_addVar(vars, TPLADD, "IP", cs_inet_ntoa(cl->ip));
5747 tpl_addVar(vars, TPLADD, "NODE", "csp");
5748 if(cl->cwcacheexping)
5749 {
5750 tpl_printf(vars, TPLADD, "LEVEL", "csp (%d ms)", cl->cwcacheexping);
5751 }
5752 else
5753 {
5754 tpl_addVar(vars, TPLADD, "LEVEL", "csp");
5755 }
5756 tpl_printf(vars, TPLADD, "PUSH", "%d", cl->cwcacheexpush);
5757 tpl_printf(vars, TPLADD, "GOT", "%d", cl->cwcacheexgot);
5758 tpl_printf(vars, TPLADD, "HIT", "%d", cl->cwcacheexhit);
5759 tpl_printf(vars, TPLADD, "ERR", "%d", cl->cwcacheexerr);
5760 tpl_printf(vars, TPLADD, "ERRCW", "%d", cl->cwcacheexerrcw);
5761 tpl_addVar(vars, TPLADD, "DIRECTIONIMG", getting);
5762 rowvariable = "TABLECLIENTROWS";
5763 written = 1;
5764 }
5765
5766 if(written)
5767 {
5768 tpl_addVar(vars, TPLAPPEND, rowvariable, tpl_getTpl(vars, "CACHEEXTABLEROW"));
5769
5770 if(cl->ll_cacheex_stats)
5771 {
5772 LL_ITER itr = ll_iter_create(cl->ll_cacheex_stats);
5773 S_CACHEEX_STAT_ENTRY *cacheex_stats_entry;
5774
5775 while((cacheex_stats_entry = ll_iter_next(&itr)))
5776 {
5777
5778 tpl_addVar(vars, TPLADD, "DIRECTIONIMG", "");
5779 if(now - cacheex_stats_entry->cache_last < 20)
5780 { tpl_addVar(vars, TPLADD, "TYPE", cacheex_stats_entry->cache_direction == 0 ? pushing : getting); }
5781 else
5782 { tpl_addVar(vars, TPLADD, "TYPE", ""); }
5783 tpl_printf(vars, TPLADD, "NAME", "%04X:%06X:%04X", cacheex_stats_entry->cache_caid,
5784 cacheex_stats_entry->cache_prid,
5785 cacheex_stats_entry->cache_srvid);
5786 if(cacheex_stats_entry->cache_direction == 0)
5787 {
5788 tpl_printf(vars, TPLADD, "PUSH", "%d", cacheex_stats_entry->cache_count);
5789 tpl_addVar(vars, TPLADD, "GOT", "");
5790 }
5791 else
5792 {
5793 tpl_printf(vars, TPLADD, "GOT", "%d", cacheex_stats_entry->cache_count);
5794 tpl_addVar(vars, TPLADD, "PUSH", "");
5795 }
5796 tpl_addVar(vars, TPLADD, "HIT", "");
5797 char channame[32];
5798 char *lastchan = xml_encode(vars, get_servicename(cl, cacheex_stats_entry->cache_srvid, cacheex_stats_entry->cache_caid, channame));
5799 tpl_addVar(vars, TPLADD, "LEVEL", lastchan);
5800 tpl_addVar(vars, TPLAPPEND, rowvariable, tpl_getTpl(vars, "CACHEEXTABLEROW"));
5801
5802 }
5803 }
5804 written = 0;
5805 }
5806 }
5807
5808 float cachesum = first_client ? first_client->cwcacheexgot : 1;
5809 if(cachesum < 1)
5810 {
5811 cachesum = 1;
5812 }
5813 tpl_printf(vars, TPLADD, "TOTAL_CACHEXPUSH", "%d", first_client ? first_client->cwcacheexpush : 0);
5814 tpl_addVar(vars, TPLADD, "TOTAL_CACHEXPUSH_IMG", pushing);
5815 tpl_printf(vars, TPLADD, "TOTAL_CACHEXGOT", "%d", first_client ? first_client->cwcacheexgot : 0);
5816 tpl_addVar(vars, TPLADD, "TOTAL_CACHEXGOT_IMG", getting);
5817 tpl_printf(vars, TPLADD, "TOTAL_CACHEXHIT", "%d", first_client ? first_client->cwcacheexhit : 0);
5818 tpl_printf(vars, TPLADD, "TOTAL_CACHESIZE", "%d", cache_size());
5819
5820 tpl_printf(vars, TPLADD, "REL_CACHEXHIT", "%.2f", (first_client ? first_client->cwcacheexhit : 0) * 100 / cachesum);
5821
5822 return tpl_getTpl(vars, "CACHEEXPAGE");
5823}
5824#endif
5825
5826#ifdef MODULE_GHTTP
5827static bool ghttp_autoconf(struct templatevars * vars, struct uriparams * params)
5828{
5829 int8_t i = 0;
5830 struct s_reader *rdr;
5831 char *name = getParam(params, "gacname");
5832 if(strlen(name) < 3)
5833 {
5834 tpl_addMsg(vars, "Invalid host name!");
5835 return false;
5836 }
5837
5838 LL_ITER itr = ll_iter_create(configured_readers);
5839 while((rdr = ll_iter_next(&itr)))
5840 if(rdr->ph.num == R_GHTTP) { i++; } // count existing ghttp readers
5841
5842 while(i < 3) // if less than 3, add more
5843 {
5844 char lbl[128];
5845 snprintf(lbl, sizeof(lbl), "%s%d", "ghttp", i + 1);
5846 cs_log("GHttp autoconf: adding reader %s", lbl);
5847 struct s_reader *newrdr;
5848 if(!cs_malloc(&newrdr, sizeof(struct s_reader)))
5849 {
5850 tpl_addMsg(vars, "Create reader failed!");
5851 return false;
5852 };
5853 newrdr->typ = R_GHTTP;
5854 cs_strncpy(newrdr->label, lbl, sizeof(newrdr->label));
5855 module_reader_set(newrdr);
5856 reader_set_defaults(newrdr);
5857 newrdr->enable = 0;
5858 newrdr->grp = 1;
5859 ll_append(configured_readers, newrdr);
5860 i++;
5861 }
5862
5863 uint16_t port = 0;
5864 char *str = strstr(name, ":");
5865 if(str)
5866 {
5867 port = atoi(str + 1);
5868 str[0] = '\0';
5869 }
5870
5871 i = 0;
5872 itr = ll_iter_create(configured_readers);
5873 while((rdr = ll_iter_next(&itr)))
5874 {
5875 if(rdr->ph.num == R_GHTTP)
5876 {
5877 if(i > 2) // remove superflous
5878 {
5879 cs_log("GHttp autoconf: removing reader %s", rdr->label);
5880 inactivate_reader(rdr);
5881 ll_iter_remove(&itr);
5882 free_reader(rdr);
5883 }
5884 else // reconfigure the 3 first ghttp readers
5885 {
5886 cs_log("GHttp autoconf: reconfiguring reader %s", rdr->label);
5887 snprintf(rdr->label, sizeof(rdr->label), "%s%d", "ghttp", i + 1);
5888 rdr->r_port = port;
5889 rdr->enable = 1;
5890 rdr->ghttp_use_ssl = 0;
5891#ifdef WITH_SSL
5892 rdr->ghttp_use_ssl = 1;
5893#endif
5894 if(rdr->grp < 1) { rdr->grp = 1; }
5895 cs_strncpy(rdr->r_usr, getParam(params, "gacuser"), sizeof(rdr->r_usr));
5896 cs_strncpy(rdr->r_pwd, getParam(params, "gacpasswd"), sizeof(rdr->r_pwd));
5897 if(i == 0) { cs_strncpy(rdr->device, name, sizeof(rdr->device)); }
5898 else
5899 {
5900 if(!strstr(name, "."))
5901 { snprintf(rdr->device, sizeof(rdr->device), "%s%d", name, i); } // name, name1, name2
5902 else { cs_strncpy(rdr->device, name, sizeof(rdr->device)); }
5903 // . in the name = assume full hostname = use same for all 3 readers
5904 }
5905 if(i == 2) { rdr->fallback = 1; }
5906 else { rdr->fallback = 0; }
5907 i++;
5908 }
5909 }
5910 }
5911 cs_log("GHttp autoconf: Saving %d readers", i);
5912 if(write_server() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
5913 itr = ll_iter_create(configured_readers);
5914 while((rdr = ll_iter_next(&itr)))
5915 {
5916 if(rdr->ph.num == R_GHTTP)
5917 { restart_cardreader(rdr, 1); }
5918 }
5919 return true;
5920}
5921
5922static char *send_oscam_ghttp(struct templatevars * vars, struct uriparams * params, int8_t apicall)
5923{
5924 if(strcmp(strtolower(getParam(params, "action")), "autoconf") == 0)
5925 {
5926 if(!apicall)
5927 {
5928 bool missing = false;
5929 if(strlen(getParam(params, "gacuser")) == 0)
5930 {
5931 tpl_addVar(vars, TPLADD, "USERREQ", "<font color='red'>(Required)</font>");
5932 missing = true;
5933 }
5934 else { tpl_addVar(vars, TPLADD, "GACUSER", getParam(params, "gacuser")); }
5935 if(strlen(getParam(params, "gacpasswd")) == 0)
5936 {
5937 tpl_addVar(vars, TPLADD, "PWDREQ", "<font color='red'>(Required)</font>");
5938 missing = true;
5939 }
5940 else { tpl_addVar(vars, TPLADD, "GACPASSWD", getParam(params, "gacpasswd")); }
5941 if(strlen(getParam(params, "gacname")) == 0)
5942 {
5943 tpl_addVar(vars, TPLADD, "NAMEREQ", "<font color='red'>(Required)</font>");
5944 missing = true;
5945 }
5946 else { tpl_addVar(vars, TPLADD, "GACNAME", getParam(params, "gacname")); }
5947 if(missing) { return tpl_getTpl(vars, "PREAUTOCONF"); }
5948 cs_log("GHttp autoconf requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
5949 }
5950 else
5951 {
5952 tpl_addVar(vars, TPLADD, "APICONFIRMMESSAGE", "autoconf");
5953 cs_log("GHttp autoconf requested by XMLApi from %s", cs_inet_ntoa(GET_IP()));
5954 }
5955
5956 if(ghttp_autoconf(vars, params))
5957 {
5958 tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", 3);
5959 tpl_addVar(vars, TPLADD, "REFRESHURL", "status.html");
5960 tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
5961 tpl_printf(vars, TPLADD, "SECONDS", "%d", 3);
5962 if(apicall) { return tpl_getTpl(vars, "APICONFIRMATION"); }
5963 else { return tpl_getTpl(vars, "AUTOCONF"); }
5964 }
5965 else { return tpl_getTpl(vars, "PREAUTOCONF"); } // something failed
5966
5967 }
5968 else
5969 {
5970 if(strlen(getParam(params, "token")) > 0) // parse autoconf token
5971 {
5972 char *token = getParam(params, "token");
5973 int32_t len = b64decode((uchar *)token);
5974 if(len > 0)
5975 {
5976 struct uriparams tokenprms;
5977 tokenprms.paramcount = 0;
5978 parseParams(&tokenprms, token);
5979 if(strlen(getParam(&tokenprms, "u")) > 0)
5980 {
5981 tpl_addVar(vars, TPLADD, "GACUSER", getParam(&tokenprms, "u"));
5982 tpl_addVar(vars, TPLADD, "USERRDONLY", "readonly");
5983 }
5984 if(strlen(getParam(&tokenprms, "p")) > 0)
5985 {
5986 tpl_addVar(vars, TPLADD, "GACPASSWD", getParam(&tokenprms, "p"));
5987 tpl_addVar(vars, TPLADD, "PWDRDONLY", "readonly");
5988 }
5989 if(strlen(getParam(&tokenprms, "n")) > 0)
5990 {
5991 tpl_addVar(vars, TPLADD, "GACNAME", getParam(&tokenprms, "n"));
5992 tpl_addVar(vars, TPLADD, "NAMERDONLY", "readonly");
5993 }
5994 }
5995 }
5996 return tpl_getTpl(vars, "PREAUTOCONF");
5997 }
5998}
5999#endif
6000
6001static int8_t check_httpip(IN_ADDR_T addr)
6002{
6003 int8_t i = 0;
6004 // check all previously dyndns resolved addresses
6005 for(i = 0; i < MAX_HTTP_DYNDNS; i++)
6006 {
6007 if(IP_ISSET(cfg.http_dynip[i]) && IP_EQUAL(cfg.http_dynip[i], addr))
6008 { return 1; }
6009 }
6010 return 0;
6011}
6012
6013static int8_t check_httpdyndns(IN_ADDR_T addr)
6014{
6015
6016 // check all previously dyndns resolved addresses
6017 if(check_httpip(addr))
6018 { return 1; }
6019
6020 // we are not ok, so resolve all dyndns entries into IP's - maybe outdated IP's
6021
6022 if(cfg.http_dyndns[0][0])
6023 {
6024 int8_t i = 0;
6025 for(i = 0; i < MAX_HTTP_DYNDNS; i++)
6026 {
6027 if(cfg.http_dyndns[i][0])
6028 {
6029 cs_resolve((const char *)cfg.http_dyndns[i], &cfg.http_dynip[i], NULL, NULL);
6030 cs_debug_mask(D_TRACE, "WebIf: httpdyndns [%d] resolved %s to %s ", i, (char *)cfg.http_dyndns[i], cs_inet_ntoa(cfg.http_dynip[i]));
6031 }
6032 }
6033 }
6034 else
6035 {
6036 cs_debug_mask(D_TRACE, "WebIf: No dyndns addresses found");
6037 return 0;
6038 }
6039
6040 // again check all dyndns resolved addresses
6041 if(check_httpip(addr))
6042 { return 1; }
6043
6044 return 0;
6045}
6046
6047static int8_t check_valid_origin(IN_ADDR_T addr)
6048{
6049
6050 // check whether requesting IP is in allowed IP ranges
6051 if(check_ip(cfg.http_allowed, addr))
6052 { return 1; }
6053
6054 // we havn't found the requesting IP in allowed range. So we check for allowed httpdyndns as last chance
6055 if(cfg.http_dyndns[0][0])
6056 {
6057 int8_t ok;
6058 ok = check_httpdyndns(addr);
6059 return ok;
6060 }
6061 return 0;
6062}
6063
6064static int8_t check_request(char *result, int32_t readen)
6065{
6066 if(readen < 50) { return 0; }
6067 result[readen] = '\0';
6068 int8_t method;
6069 if(strncmp(result, "POST", 4) == 0) { method = 1; }
6070 else { method = 0; }
6071 char *headerEnd = strstr(result, "\r\n\r\n");
6072 if(headerEnd == NULL) { return 0; }
6073 else if(method == 0) { return 1; }
6074 else
6075 {
6076 char *ptr = strstr(result, "Content-Length: ");
6077 if(ptr != NULL)
6078 {
6079 ptr += 16;
6080 if(ptr < result + readen)
6081 {
6082 uint32_t length = atoi(ptr);
6083 if(strlen(headerEnd + 4) >= length) { return 1; }
6084 }
6085 }
6086 }
6087 return 0;
6088}
6089
6090static int32_t readRequest(FILE * f, IN_ADDR_T in, char **result, int8_t forcePlain)
6091{
6092 int32_t n, bufsize = 0, errcount = 0;
6093 char buf2[1024];
6094 struct pollfd pfd2[1];
6095#ifdef WITH_SSL
6096 int8_t is_ssl = 0;
6097 if(ssl_active && !forcePlain)
6098 { is_ssl = 1; }
6099#endif
6100
6101 while(1)
6102 {
6103 errno = 0;
6104 if(forcePlain)
6105 { n = read(fileno(f), buf2, sizeof(buf2)); }
6106 else
6107 { n = webif_read(buf2, sizeof(buf2), f); }
6108 if(n <= 0)
6109 {
6110 if((errno == 0 || errno == EINTR))
6111 {
6112 if(errcount++ < 10)
6113 {
6114 cs_sleepms(5);
6115 continue;
6116 }
6117 else { return -1; }
6118 }
6119#ifdef WITH_SSL
6120 if(is_ssl)
6121 {
6122 if(errno != ECONNRESET)
6123 {
6124 int32_t errcode = ERR_peek_error();
6125 char errstring[128];
6126 ERR_error_string_n(errcode, errstring, sizeof(errstring) - 1);
6127 cs_debug_mask(D_TRACE, "WebIf: read error ret=%d (%d%s%s)", n, SSL_get_error(cur_ssl(), n), errcode ? " " : "", errcode ? errstring : "");
6128 }
6129 return -1;
6130 }
6131#else
6132 if(errno != ECONNRESET)
6133 { cs_debug_mask(D_TRACE, "WebIf: read error ret=%d (errno=%d %s)", n, errno, strerror(errno)); }
6134#endif
6135 return -1;
6136 }
6137 if(!cs_realloc(result, bufsize + n + 1))
6138 {
6139 send_error500(f);
6140 return -1;
6141 }
6142
6143 memcpy(*result + bufsize, buf2, n);
6144 bufsize += n;
6145
6146 //max request size 100kb
6147 if(bufsize > 102400)
6148 {
6149 cs_log("error: too much data received from %s", cs_inet_ntoa(in));
6150 free(*result);
6151 *result = NULL;
6152 return -1;
6153 }
6154
6155#ifdef WITH_SSL
6156 if(ssl_active && !forcePlain)
6157 {
6158 int32_t len = 0;
6159 len = SSL_pending((SSL *)f);
6160
6161 if(len > 0)
6162 { continue; }
6163
6164 pfd2[0].fd = SSL_get_fd((SSL *)f);
6165
6166 }
6167 else
6168#endif
6169 pfd2[0].fd = fileno(f);
6170
6171 pfd2[0].events = (POLLIN | POLLPRI);
6172
6173 int32_t rc = poll(pfd2, 1, 100);
6174 if(rc > 0 || !check_request(*result, bufsize))
6175 { continue; }
6176 else
6177 { break; }
6178 }
6179 return bufsize;
6180}
6181static int32_t process_request(FILE * f, IN_ADDR_T in)
6182{
6183 int32_t ok = 0;
6184 int8_t *keepalive = (int8_t *)pthread_getspecific(getkeepalive);
6185 IN_ADDR_T addr = GET_IP();
6186
6187 do
6188 {
6189#ifdef WITH_SSL
6190 if(!ssl_active && *keepalive) { fflush(f); }
6191#else
6192 if(*keepalive) { fflush(f); }
6193#endif
6194
6195 // at this point we do all checks related origin IP, ranges and dyndns stuff
6196 ok = check_valid_origin(addr);
6197 cs_debug_mask(D_TRACE, "WebIf: Origin checked. Result: access from %s => %s", cs_inet_ntoa(addr), (!ok) ? "forbidden" : "allowed");
6198
6199 // based on the failed origin checks we send a 403 to calling browser
6200 if(!ok)
6201 {
6202 send_error(f, 403, "Forbidden", NULL, "Access denied.", 0);
6203 cs_log("unauthorized access from %s", cs_inet_ntoa(addr));
6204 return 0;
6205 }
6206
6207 int32_t authok = 0;
6208 char expectednonce[(MD5_DIGEST_LENGTH * 2) + 1], opaque[(MD5_DIGEST_LENGTH * 2) + 1];
6209 char authheadertmp[sizeof(AUTHREALM) + sizeof(expectednonce) + sizeof(opaque) + 100];
6210
6211 char *method, *path, *protocol, *str1, *saveptr1 = NULL, *authheader = NULL, *extraheader = NULL, *filebuf = NULL;
6212 char *pch, *tmp, *buf, *nameInUrl, subdir[32];
6213 /* List of possible pages */
6214 char *pages[] =
6215 {
6216 "/config.html",
6217 "/readers.html",
6218 "/entitlements.html",
6219 "/status.html",
6220 "/userconfig.html",
6221 "/readerconfig.html",
6222 "/services.html",
6223 "/user_edit.html",
6224 "/site.css",
6225 "/services_edit.html",
6226 "/savetemplates.html",
6227 "/shutdown.html",
6228 "/script.html",
6229 "/scanusb.html",
6230 "/files.html",
6231 "/readerstats.html",
6232 "/failban.html",
6233 "/oscam.js",
6234 "/oscamapi.html",
6235 "/image",
6236 "/favicon.ico",
6237 "/graph.svg",
6238 "/oscamapi.xml",
6239 "/cacheex.html",
6240 "/oscamapi.json",
6241 "/emm.html",
6242 "/emm_running.html",
6243 "/robots.txt",
6244 "/ghttp.html",
6245 };
6246
6247 int32_t pagescnt = sizeof(pages) / sizeof(char *); // Calculate the amount of items in array
6248 int32_t i, bufsize, len, pgidx = -1;
6249 uint32_t etagheader = 0;
6250 struct uriparams params;
6251 params.paramcount = 0;
6252 time_t modifiedheader = 0;
6253
6254 bufsize = readRequest(f, in, &filebuf, 0);
6255
6256 if(!filebuf || bufsize < 1)
6257 {
6258 if(!*keepalive) { cs_debug_mask(D_CLIENT, "WebIf: No data received from client %s. Closing connection.", cs_inet_ntoa(addr)); }
6259 return -1;
6260 }
6261
6262 buf = filebuf;
6263
6264 if((method = strtok_r(buf, " ", &saveptr1)) != NULL)
6265 {
6266 if((path = strtok_r(NULL, " ", &saveptr1)) != NULL)
6267 {
6268 if((protocol = strtok_r(NULL, "\r", &saveptr1)) == NULL)
6269 {
6270 free(filebuf);
6271 return -1;
6272 }
6273 }
6274 else
6275 {
6276 free(filebuf);
6277 return -1;
6278 }
6279 }
6280 else
6281 {
6282 free(filebuf);
6283 return -1;
6284 }
6285 tmp = protocol + strlen(protocol) + 2;
6286
6287 pch = path;
6288 /* advance pointer to beginning of query string */
6289 while(pch[0] != '?' && pch[0] != '\0') { ++pch; }
6290 if(pch[0] == '?')
6291 {
6292 pch[0] = '\0';
6293 ++pch;
6294 }
6295
6296 nameInUrl = pch - 1;
6297 while(nameInUrl != path && nameInUrl[0] != '/') { --nameInUrl; }
6298
6299 /* allow only alphanumeric sub-folders */
6300 int32_t subdirLen = nameInUrl - path;
6301 subdir[0] = '\0';
6302 if(subdirLen > 0 && subdirLen < 32)
6303 {
6304 cs_strncpy(subdir, path + 1, subdirLen);
6305
6306 int32_t invalidSubdir = 0;
6307 for(i = 0; i < subdirLen - 1; i++)
6308 {
6309 if(!((subdir[i] >= '0' && subdir[i] <= '9')
6310 || (subdir[i] >= 'a' && subdir[i] <= 'z')
6311 || (subdir[i] >= 'A' && subdir[i] <= 'Z')))
6312 {
6313
6314 invalidSubdir = 1;
6315 subdir[0] = '\0';
6316 break;
6317 }
6318 }
6319
6320 if(!invalidSubdir)
6321 {
6322 subdir[subdirLen] = '\0';
6323#ifdef WIN32
6324 subdir[subdirLen - 1] = '\\';
6325#else
6326 subdir[subdirLen - 1] = '/';
6327#endif
6328 }
6329 }
6330
6331 /* Map page to our static page definitions */
6332 for(i = 0; i < pagescnt; i++)
6333 {
6334 if(!strcmp(nameInUrl, pages[i])) { pgidx = i; }
6335 }
6336
6337 parseParams(&params, pch);
6338
6339 if(!cfg.http_user || !cfg.http_pwd)
6340 { authok = 1; }
6341
6342 for(str1 = strtok_r(tmp, "\n", &saveptr1); str1; str1 = strtok_r(NULL, "\n", &saveptr1))
6343 {
6344 len = strlen(str1);
6345 if(str1[len - 1] == '\r')
6346 {
6347 str1[len - 1] = '\0';
6348 --len;
6349 }
6350 if(len == 0)
6351 {
6352 if(strcmp(method, "POST") == 0)
6353 {
6354 parseParams(&params, str1 + 2);
6355 }
6356 break;
6357 }
6358 if(!authok && len > 50 && strncasecmp(str1, "Authorization:", 14) == 0 && strstr(str1, "Digest") != NULL)
6359 {
6360 if(cs_dblevel & D_CLIENT)
6361 {
6362 if(cs_realloc(&authheader, len + 1))
6363 { cs_strncpy(authheader, str1, len); }
6364 }
6365 authok = check_auth(str1, method, path, addr, expectednonce, opaque);
6366 }
6367 else if(len > 40 && strncasecmp(str1, "If-Modified-Since:", 18) == 0)
6368 {
6369 modifiedheader = parse_modifiedsince(str1);
6370 }
6371 else if(len > 20 && strncasecmp(str1, "If-None-Match:", 14) == 0)
6372 {
6373 for(pch = str1 + 14; pch[0] != '"' && pch[0] != '\0'; ++pch) { ; }
6374 if(strlen(pch) > 5) { etagheader = (uint32_t)strtoul(++pch, NULL, 10); }
6375 }
6376 else if(len > 12 && strncasecmp(str1, "Connection: Keep-Alive", 22) == 0 && strcmp(method, "POST"))
6377 {
6378 *keepalive = 1;
6379 }
6380 }
6381
6382 if(cfg.http_user && cfg.http_pwd)
6383 {
6384 if(!authok || strlen(opaque) != MD5_DIGEST_LENGTH * 2) { calculate_opaque(addr, opaque); }
6385 if(authok != 2)
6386 {
6387 if(!authok)
6388 {
6389 if(authheader)
6390 {
6391 cs_debug_mask(D_CLIENT, "WebIf: Received wrong auth header from %s:", cs_inet_ntoa(addr));
6392 cs_debug_mask(D_CLIENT, "%s", authheader);
6393 }
6394 else
6395 { cs_debug_mask(D_CLIENT, "WebIf: Received no auth header from %s.", cs_inet_ntoa(addr)); }
6396 }
6397 calculate_nonce(NULL, expectednonce, opaque);
6398 }
6399 if(authok != 1)
6400 {
6401 snprintf(authheadertmp, sizeof(authheadertmp), "WWW-Authenticate: Digest algorithm=\"MD5\", realm=\"%s\", qop=\"auth\", opaque=\"%s\", nonce=\"%s\"", AUTHREALM, opaque, expectednonce);
6402 if(authok == 2) { strncat(authheadertmp, ", stale=true", sizeof(authheadertmp) - strlen(authheadertmp) - 1); }
6403 }
6404 else
6405 { snprintf(authheadertmp, sizeof(authheadertmp), "Authentication-Info: nextnonce=\"%s\"", expectednonce); }
6406 extraheader = authheadertmp;
6407 if(authok != 1)
6408 {
6409 char *msg = "Access denied.\n";
6410 send_headers(f, 401, "Unauthorized", extraheader, "text/html", 0, strlen(msg), msg, 0);
6411 webif_write(msg, f);
6412 NULLFREE(authheader);
6413 free(filebuf);
6414 if(*keepalive) { continue; }
6415 else { return 0; }
6416 }
6417 }
6418 else { NULLFREE(authheader); }
6419
6420 /*build page*/
6421 if(pgidx == 8)
6422 {
6423 send_file(f, "CSS", subdir, modifiedheader, etagheader, extraheader);
6424 }
6425 else if(pgidx == 17)
6426 {
6427 send_file(f, "JS", subdir, modifiedheader, etagheader, extraheader);
6428 }
6429 else
6430 {
6431 time_t t;
6432 struct templatevars *vars = tpl_create();
6433 if(vars == NULL)
6434 {
6435 send_error500(f);
6436 free(filebuf);
6437 return 0;
6438 }
6439
6440 tpl_addVar(vars, TPLADD, "SUBDIR", subdir);
6441
6442 struct tm lt, st;
6443 time(&t);
6444
6445 localtime_r(&t, &lt);
6446
6447 tpl_addVar(vars, TPLADD, "CS_VERSION", CS_VERSION);
6448 tpl_addVar(vars, TPLADD, "CS_SVN_VERSION", CS_SVN_VERSION);
6449 tpl_addVar(vars, TPLADD, "HTTP_CHARSET", cs_http_use_utf8 ? "UTF-8" : "ISO-8859-1");
6450 if(cfg.http_refresh > 0 && (pgidx == 3 || pgidx == -1))
6451 {
6452 tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", cfg.http_refresh);
6453 tpl_addVar(vars, TPLADD, "REFRESHURL", "status.html");
6454 tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
6455 }
6456
6457 tpl_printf(vars, TPLADD, "CURDATE", "%02d.%02d.%02d", lt.tm_mday, lt.tm_mon + 1, lt.tm_year % 100);
6458 tpl_printf(vars, TPLADD, "CURTIME", "%02d:%02d:%02d", lt.tm_hour, lt.tm_min, lt.tm_sec);
6459 localtime_r(&first_client->login, &st);
6460 tpl_printf(vars, TPLADD, "STARTDATE", "%02d.%02d.%02d", st.tm_mday, st.tm_mon + 1, st.tm_year % 100);
6461 tpl_printf(vars, TPLADD, "STARTTIME", "%02d:%02d:%02d", st.tm_hour, st.tm_min, st.tm_sec);
6462 tpl_printf(vars, TPLADD, "PROCESSID", "%d", getpid());
6463
6464 time_t now = time((time_t *)0);
6465 // XMLAPI
6466 if(pgidx == 18 || pgidx == 22 || pgidx == 24)
6467 {
6468 char tbuffer [30];
6469 strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &st);
6470 tpl_addVar(vars, TPLADD, "APISTARTTIME", tbuffer);
6471 tpl_printf(vars, TPLADD, "APIUPTIME", "%ld", now - first_client->login);
6472 tpl_printf(vars, TPLADD, "APIREADONLY", "%d", cfg.http_readonly);
6473 if(strcmp(getParam(&params, "callback"), ""))
6474 {
6475 tpl_addVar(vars, TPLADD, "CALLBACK", getParam(&params, "callback"));
6476 }
6477
6478 }
6479
6480 // language code in helplink
6481 tpl_addVar(vars, TPLADD, "LANGUAGE", cfg.http_help_lang);
6482 tpl_addVar(vars, TPLADD, "UPTIME", sec2timeformat(vars, (now - first_client->login)));
6483 tpl_addVar(vars, TPLADD, "CURIP", cs_inet_ntoa(addr));
6484 if(cfg.http_readonly)
6485 { tpl_addVar(vars, TPLAPPEND, "BTNDISABLED", "DISABLED"); }
6486
6487 i = ll_count(cfg.v_list);
6488 if(i > 0) { tpl_printf(vars, TPLADD, "FAILBANNOTIFIER", "<SPAN CLASS=\"span_notifier\">%d</SPAN>", i); }
6489
6490 char *result = NULL;
6491
6492 // WebIf allows modifying many things. Thus, all pages except images/css are excpected to be non-threadsafe!
6493 if(pgidx != 19 && pgidx != 20) { cs_writelock(&http_lock); }
6494 switch(pgidx)
6495 {
6496 case 0:
6497 result = send_oscam_config(vars, &params);
6498 break;
6499 case 1:
6500 result = send_oscam_reader(vars, &params, 0);
6501 break;
6502 case 2:
6503 result = send_oscam_entitlement(vars, &params, 0);
6504 break;
6505 case 3:
6506 result = send_oscam_status(vars, &params, 0);
6507 break;
6508 case 4:
6509 result = send_oscam_user_config(vars, &params, 0);
6510 break;
6511 case 5:
6512 result = send_oscam_reader_config(vars, &params);
6513 break;
6514 case 6:
6515 result = send_oscam_services(vars, &params);
6516 break;
6517 case 7:
6518 result = send_oscam_user_config_edit(vars, &params, 0);
6519 break;
6520 //case 8: css file
6521 case 9:
6522 result = send_oscam_services_edit(vars, &params);
6523 break;
6524 case 10:
6525 result = send_oscam_savetpls(vars);
6526 break;
6527 case 11:
6528 result = send_oscam_shutdown(vars, f, &params, 0, keepalive, extraheader);
6529 break;
6530 case 12:
6531 result = send_oscam_script(vars);
6532 break;
6533 case 13:
6534 result = send_oscam_scanusb(vars);
6535 break;
6536 case 14:
6537 result = send_oscam_files(vars, &params, 0);
6538 break;
6539 case 15:
6540 result = send_oscam_reader_stats(vars, &params, 0);
6541 break;
6542 case 16:
6543 result = send_oscam_failban(vars, &params, 0);
6544 break;
6545 //case 17: js file
6546 case 18:
6547 result = send_oscam_api(vars, f, &params, keepalive, 1, extraheader);
6548 break; //oscamapi.html
6549 case 19:
6550 result = send_oscam_image(vars, f, &params, NULL, modifiedheader, etagheader, extraheader);
6551 break;
6552 case 20:
6553 result = send_oscam_image(vars, f, &params, "ICMAI", modifiedheader, etagheader, extraheader);
6554 break;
6555 case 21:
6556 result = send_oscam_graph(vars);
6557 break;
6558 case 22:
6559 result = send_oscam_api(vars, f, &params, keepalive, 1, extraheader);
6560 break; //oscamapi.xml
6561#ifdef CS_CACHEEX
6562 case 23:
6563 result = send_oscam_cacheex(vars, &params, 0);
6564 break;
6565#endif
6566 case 24:
6567 result = send_oscam_api(vars, f, &params, keepalive, 2, extraheader);
6568 break; //oscamapi.json
6569 case 25:
6570 result = send_oscam_EMM(vars, &params);
6571 break; //emm.html
6572 case 26:
6573 result = send_oscam_EMM_running(vars, &params);
6574 break; //emm_running.html
6575 case 27:
6576 result = send_oscam_robots_txt(f);
6577 break; //robots.txt
6578#ifdef MODULE_GHTTP
6579 case 28:
6580 result = send_oscam_ghttp(vars, &params, 0);
6581 break;
6582#endif
6583 default:
6584 result = send_oscam_status(vars, &params, 0);
6585 break;
6586 }
6587 if(pgidx != 19 && pgidx != 20) { cs_writeunlock(&http_lock); }
6588
6589 if(result == NULL || !strcmp(result, "0") || strlen(result) == 0) { send_error500(f); }
6590 else if(strcmp(result, "1"))
6591 {
6592 //it doesn't make sense to check for modified etagheader here as standard template has timestamp in output and so site changes on every request
6593 if(pgidx == 18)
6594 { send_headers(f, 200, "OK", extraheader, "text/xml", 0, strlen(result), NULL, 0); }
6595 else if(pgidx == 21)
6596 { send_headers(f, 200, "OK", extraheader, "image/svg+xml", 0, strlen(result), NULL, 0); }
6597 else if(pgidx == 24)
6598 { send_headers(f, 200, "OK", extraheader, "text/javascript", 0, strlen(result), NULL, 0); }
6599 else
6600 { send_headers(f, 200, "OK", extraheader, "text/html", 0, strlen(result), NULL, 0); }
6601 webif_write(result, f);
6602 }
6603 tpl_clear(vars);
6604 }
6605 free(filebuf);
6606 }
6607 while(*keepalive == 1);
6608 return 0;
6609}
6610
6611static void *serve_process(void *conn)
6612{
6613 struct s_connection *myconn = (struct s_connection *)conn;
6614 int32_t s = myconn->socket;
6615 struct s_client *cl = myconn->cl;
6616 IN_ADDR_T in;
6617 IP_ASSIGN(in, myconn->remote);
6618
6619 set_thread_name(__func__);
6620
6621#ifdef WITH_SSL
6622 SSL *ssl = myconn->ssl;
6623 pthread_setspecific(getssl, ssl);
6624#endif
6625 free(myconn);
6626
6627 pthread_setspecific(getip, &in);
6628 pthread_setspecific(getclient, cl);
6629
6630 int8_t keepalive = 0;
6631 pthread_setspecific(getkeepalive, &keepalive);
6632
6633#ifdef WITH_SSL
6634 if(ssl_active)
6635 {
6636 if(SSL_set_fd(ssl, s))
6637 {
6638 int32_t ok = (SSL_accept(ssl) != -1);
6639 if(!ok)
6640 {
6641 int8_t tries = 100;
6642 while(!ok && tries--)
6643 {
6644 int32_t err = SSL_get_error(ssl, -1);
6645 if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
6646 { break; }
6647 else
6648 {
6649 struct pollfd pfd;
6650 pfd.fd = s;
6651 pfd.events = POLLIN | POLLPRI;
6652 int32_t rc = poll(&pfd, 1, -1);
6653 if(rc < 0)
6654 {
6655 if(errno == EINTR || errno == EAGAIN) { continue; }
6656 break;
6657 }
6658 if(rc == 1)
6659 { ok = (SSL_accept(ssl) != -1); }
6660 }
6661 }
6662 }
6663 if(ok)
6664 {
6665 process_request((FILE *)ssl, in);
6666 }
6667 else
6668 {
6669 FILE *f;
6670 f = fdopen(s, "r+");
6671 if(f != NULL)
6672 {
6673 char *ptr, *filebuf = NULL, *host = NULL;
6674 int32_t bufsize = readRequest(f, in, &filebuf, 1);
6675
6676 if(filebuf)
6677 {
6678 filebuf[bufsize] = '\0';
6679 host = strstr(filebuf, "Host: ");
6680 if(host)
6681 {
6682 host += 6;
6683 ptr = strchr(host, '\r');
6684 if(ptr) { ptr[0] = '\0'; }
6685 }
6686 }
6687 if(host)
6688 {
6689 char extra[strlen(host) + 20];
6690 snprintf(extra, sizeof(extra), "Location: https://%s", host);
6691 send_error(f, 301, "Moved Permanently", extra, "This web server is running in SSL mode.", 1);
6692 }
6693 else
6694 { send_error(f, 200, "Bad Request", NULL, "This web server is running in SSL mode.", 1); }
6695 fflush(f);
6696 fclose(f);
6697 }
6698 else
6699 {
6700 cs_debug_mask(D_TRACE, "WebIf: fdopen(%d) failed. (errno=%d %s)", s, errno, strerror(errno));
6701 }
6702 }
6703 }
6704 else { cs_log("WebIf: Error calling SSL_set_fd()."); }
6705 SSL_shutdown(ssl);
6706 close(s);
6707 SSL_free(ssl);
6708 }
6709 else
6710#endif
6711 {
6712 FILE *f;
6713 f = fdopen(s, "r+");
6714 if(f != NULL)
6715 {
6716 process_request(f, in);
6717 fflush(f);
6718 fclose(f);
6719 }
6720 else
6721 {
6722 cs_debug_mask(D_TRACE, "WebIf: fdopen(%d) failed. (errno=%d %s)", s, errno, strerror(errno));
6723 }
6724 shutdown(s, SHUT_WR);
6725 close(s);
6726 }
6727
6728 return NULL;
6729}
6730
6731/* Creates a random string with specified length. Note that dst must be one larger than size to hold the trailing \0*/
6732static void create_rand_str(char *dst, int32_t size)
6733{
6734 int32_t i;
6735 for(i = 0; i < size; ++i)
6736 {
6737 dst[i] = (rand() % 94) + 32;
6738 }
6739 dst[i] = '\0';
6740}
6741
6742static void *http_server(void *UNUSED(d))
6743{
6744 pthread_t workthread;
6745 pthread_attr_t attr;
6746 struct s_client *cl = create_client(first_client->ip);
6747 if(cl == NULL) { return NULL; }
6748 pthread_setspecific(getclient, cl);
6749 cl->typ = 'h';
6750 int32_t s, reuse = 1;
6751 struct s_connection *conn;
6752
6753 set_thread_name(__func__);
6754
6755 /* Create random string for nonce value generation */
6756 create_rand_str(noncekey, 32);
6757
6758 /* Prepare base64 decoding array */
6759 b64prepare();
6760 webif_tpls_prepare();
6761
6762 tpl_checkDiskRevisions();
6763
6764 cs_lock_create(&http_lock, 10, "http_lock");
6765 init_noncelocks();
6766
6767 if(pthread_key_create(&getip, NULL))
6768 {
6769 cs_log("Could not create getip");
6770 return NULL;
6771 }
6772 if(pthread_key_create(&getkeepalive, NULL))
6773 {
6774 cs_log("Could not create getkeepalive");
6775 return NULL;
6776 }
6777
6778 struct SOCKADDR sin;
6779 socklen_t len = 0;
6780 memset(&sin, 0, sizeof(sin));
6781
6782 bool do_ipv6 = config_enabled(IPV6SUPPORT);
6783#ifdef IPV6SUPPORT
6784 if(do_ipv6)
6785 {
6786 len = sizeof(struct sockaddr_in6);
6787 if((sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0)
6788 {
6789 cs_log("HTTP Server: ERROR: Creating IPv6 socket failed! (errno=%d %s)", errno, strerror(errno));
6790 cs_log("HTTP Server: Falling back to IPv4.");
6791 do_ipv6 = false;
6792 }
6793 else
6794 {
6795 struct sockaddr_in6 *ia = (struct sockaddr_in6 *)&sin;
6796 ia->sin6_family = AF_INET6;
6797 ia->sin6_addr = in6addr_any;
6798 ia->sin6_port = htons(cfg.http_port);
6799 }
6800 }
6801#endif
6802 if(!do_ipv6)
6803 {
6804 len = sizeof(struct sockaddr_in);
6805 if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
6806 {
6807 cs_log("HTTP Server: ERROR: Creating socket failed! (errno=%d %s)", errno, strerror(errno));
6808 return NULL;
6809 }
6810 SIN_GET_FAMILY(sin) = AF_INET;
6811 if(IP_ISSET(cfg.http_srvip))
6812 { IP_ASSIGN(SIN_GET_ADDR(sin), cfg.http_srvip); }
6813 else if(IP_ISSET(cfg.srvip))
6814 { IP_ASSIGN(SIN_GET_ADDR(sin), cfg.srvip); }
6815 // The default is INADDR_ANY (0)
6816 SIN_GET_PORT(sin) = htons(cfg.http_port);
6817 }
6818
6819 if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
6820 {
6821 cs_log("HTTP Server: Setting SO_REUSEADDR via setsockopt failed! (errno=%d %s)", errno, strerror(errno));
6822 }
6823
6824 if(bind(sock, (struct sockaddr *)&sin, len) < 0)
6825 {
6826 cs_log("HTTP Server couldn't bind on port %d (errno=%d %s). Not starting HTTP!", cfg.http_port, errno, strerror(errno));
6827 close(sock);
6828 return NULL;
6829 }
6830
6831 if(listen(sock, SOMAXCONN) < 0)
6832 {
6833 cs_log("HTTP Server: Call to listen() failed! (errno=%d %s)", errno, strerror(errno));
6834 close(sock);
6835 return NULL;
6836 }
6837
6838#ifdef WITH_SSL
6839 SSL_CTX *ctx = NULL;
6840 if(cfg.http_use_ssl)
6841 {
6842 ctx = SSL_Webif_Init();
6843 if(ctx == NULL)
6844 { cs_log("SSL could not be initialized. Starting WebIf in plain mode."); }
6845 else { ssl_active = 1; }
6846 }
6847 else { ssl_active = 0; }
6848 cs_log("HTTP Server running. ip=%s port=%d%s", cs_inet_ntoa(SIN_GET_ADDR(sin)), cfg.http_port, ssl_active ? " (SSL)" : "");
6849#else
6850 cs_log("HTTP Server running. ip=%s port=%d", cs_inet_ntoa(SIN_GET_ADDR(sin)), cfg.http_port);
6851#endif
6852
6853 struct SOCKADDR remote;
6854 memset(&remote, 0, sizeof(remote));
6855
6856 while(!exit_oscam)
6857 {
6858 if((s = accept(sock, (struct sockaddr *) &remote, &len)) < 0)
6859 {
6860 if(exit_oscam)
6861 { break; }
6862 if(errno != EAGAIN && errno != EINTR)
6863 {
6864 cs_log("HTTP Server: Error calling accept() (errno=%d %s)", errno, strerror(errno));
6865 cs_sleepms(100);
6866 }
6867 else { cs_sleepms(5); }
6868 continue;
6869 }
6870 else
6871 {
6872 getpeername(s, (struct sockaddr *) &remote, &len);
6873 if(!cs_malloc(&conn, sizeof(struct s_connection)))
6874 {
6875 close(s);
6876 continue;
6877 }
6878 setTCPTimeouts(s);
6879 cur_client()->last = time((time_t *)0); //reset last busy time
6880 conn->cl = cur_client();
6881#ifdef IPV6SUPPORT
6882 if(do_ipv6)
6883 {
6884 struct sockaddr_in6 *ra = (struct sockaddr_in6 *)&remote;
6885 memcpy(&conn->remote, &ra->sin6_addr, sizeof(struct in6_addr));
6886 }
6887 else
6888 {
6889 struct sockaddr_in *fba = (struct sockaddr_in *)&remote;
6890 struct in6_addr taddr;
6891 memset(&taddr, 0, sizeof(taddr));
6892 taddr.s6_addr32[3] = fba->sin_addr.s_addr;
6893 memcpy(&conn->remote, &taddr, sizeof(struct in6_addr));
6894 }
6895#else
6896 memcpy(&conn->remote, &remote.sin_addr, sizeof(struct in_addr));
6897#endif
6898 conn->socket = s;
6899#ifdef WITH_SSL
6900 conn->ssl = NULL;
6901 if(ssl_active)
6902 {
6903 conn->ssl = SSL_new(ctx);
6904 if(conn->ssl == NULL)
6905 {
6906 close(s);
6907 cs_log("WebIf: Error calling SSL_new().");
6908 continue;
6909 }
6910 }
6911#endif
6912 pthread_attr_init(&attr);
6913 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
6914 int32_t ret = pthread_create(&workthread, &attr, serve_process, (void *)conn);
6915 if(ret)
6916 {
6917 cs_log("ERROR: can't create thread for webif (errno=%d %s)", ret, strerror(ret));
6918 free(conn);
6919 }
6920 else
6921 { pthread_detach(workthread); }
6922 pthread_attr_destroy(&attr);
6923 }
6924 }
6925 // Wait a bit so that we don't close ressources while http threads are active
6926 cs_sleepms(300);
6927#ifdef WITH_SSL
6928 if(ssl_active)
6929 {
6930 SSL_CTX_free(ctx);
6931 CRYPTO_set_dynlock_create_callback(NULL);
6932 CRYPTO_set_dynlock_lock_callback(NULL);
6933 CRYPTO_set_dynlock_destroy_callback(NULL);
6934 CRYPTO_set_locking_callback(NULL);
6935 CRYPTO_set_id_callback(NULL);
6936 OPENSSL_free(lock_cs);
6937 lock_cs = NULL;
6938 }
6939#endif
6940 cs_log("HTTP Server stopped");
6941 free_client(cl);
6942 close(sock);
6943 return NULL;
6944}
6945
6946void webif_client_reset_lastresponsetime(struct s_client * cl)
6947{
6948 int32_t i;
6949 for(i = 0; i < CS_ECM_RINGBUFFER_MAX; i++)
6950 {
6951 cl->cwlastresptimes[i].duration = 0;
6952 cl->cwlastresptimes[i].timestamp = time((time_t *)0);
6953 cl->cwlastresptimes[i].rc = 0;
6954 }
6955 cl->cwlastresptimes_last = 0;
6956}
6957
6958void webif_client_add_lastresponsetime(struct s_client * cl, int32_t ltime, time_t timestamp, int32_t rc)
6959{
6960 int32_t last = cl->cwlastresptimes_last = (cl->cwlastresptimes_last + 1) & (CS_ECM_RINGBUFFER_MAX - 1);
6961 cl->cwlastresptimes[last].duration = ltime > 9999 ? 9999 : ltime;
6962 cl->cwlastresptimes[last].timestamp = timestamp;
6963 cl->cwlastresptimes[last].rc = rc;
6964}
6965
6966void webif_client_init_lastreader(struct s_client * client, ECM_REQUEST * er, struct s_reader * er_reader, const char *stxt[])
6967{
6968 if(er_reader)
6969 {
6970 if(er->rc == E_FOUND)
6971 { cs_strncpy(client->lastreader, er_reader->label, sizeof(client->lastreader)); }
6972 else if(er->rc == E_CACHEEX)
6973 { cs_strncpy(client->lastreader, "cache3", sizeof(client->lastreader)); }
6974 else if(er->rc < E_NOTFOUND)
6975 { snprintf(client->lastreader, sizeof(client->lastreader) - 1, "%s (cache)", er_reader->label); }
6976 else
6977 { cs_strncpy(client->lastreader, stxt[er->rc], sizeof(client->lastreader)); }
6978 }
6979 else
6980 {
6981 cs_strncpy(client->lastreader, stxt[er->rc], sizeof(client->lastreader));
6982 }
6983}
6984
6985void webif_init(void)
6986{
6987 if(cfg.http_port == 0)
6988 {
6989 cs_log("http disabled");
6990 return;
6991 }
6992 pthread_attr_t attr;
6993 pthread_attr_init(&attr);
6994 pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
6995 int32_t ret = pthread_create(&httpthread, &attr, http_server, NULL);
6996 if(ret)
6997 {
6998 cs_log("ERROR: Can't start http server (errno=%d %s)", ret, strerror(ret));
6999 pthread_attr_destroy(&attr);
7000 return;
7001 }
7002 pthread_attr_destroy(&attr);
7003}
7004
7005void webif_close(void)
7006{
7007 if(!sock)
7008 { return; }
7009 shutdown(sock, 2);
7010 close(sock);
7011 pthread_join(httpthread, NULL);
7012}
7013
7014#endif
Note: See TracBrowser for help on using the repository browser.