source: trunk/module-webif.c @ 9562

Last change on this file since 9562 was 9562, checked in by Deas, 6 years ago

add patch series by gismo2004: reset_rdr_stats_v1 - for details see: ​http://www.streamboard.tv/wbb2/thread.php?postid=502478#post502478

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