source: trunk/module-webif.c@ 8437

Last change on this file since 8437 was 8437, checked in by gf, 9 years ago

Revert "webif: Simplify template loading and checking."

This reverts commit r8346. The subdir logic is used to have different
template directories for different paths comming from http request.

For more info see:

http://www.streamboard.tv/wbb2/thread.php?threadid=37378

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