source: trunk/module-webif.c@ 9130

Last change on this file since 9130 was 9130, checked in by skyndas, 10 years ago

WebIf: Fix for the same behavior of button "debugselect = ALL" in status.html and files.html?file=logfile

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