source: trunk/module-webif.c@ 8434

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

webif: Create and use private templates array.

This allows storing of additional information along with templates
data (which is const).

For now we store name hash but in the future the data that comes from
struct templates (in webif/pages.c) may need to be preprocessed
(uncompressed for example) and the abstraction in this commit makes
it easier to do such changes.

  • 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.