source: trunk/module-webif.c @ 9568

Last change on this file since 9568 was 9568, checked in by blaky, 6 years ago

added Patch from pfanne
to get more feedback from other VG2 Card Owners
see: http://www.streamboard.tv/wbb2/thread.php?threadid=40471

-Added some info on entitlements page's
-Fix ins4c longer than 9 byte (like v14)
-Fix wrong order of some ins at boot
-Added possibility to send ins2e06 (like italian stb*)
-Added (experimental!) unlock parental control (it reads the pin from card and sends it with ins2e04, we don't need to write it in the config) set it on config>global

  • seems that the actual value for sky_it is BFFFFFFF

if your provider uses it, add ins2e06 = BFFFFFFF (or similar) in config or webif

  • Property svn:eol-style set to LF
File size: 219.8 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    // ins2e06
1734    if(rdr->ins2e06[0x04])
1735    {
1736        for(i = 0; i < 4 ; i++) { tpl_printf(vars, TPLAPPEND, "INS2E06", "%02X", rdr->ins2e06[i]); }
1737    }
1738
1739    // ATR
1740    if(rdr->atr[0])
1741        for(i = 0; i < rdr->atrlen / 2; i++)
1742            { tpl_printf(vars, TPLAPPEND, "ATR", "%02X", rdr->atr[i]); }
1743
1744    // ECM Whitelist
1745    value = mk_t_ecmwhitelist(rdr->ecmWhitelist);
1746    tpl_addVar(vars, TPLADD, "ECMWHITELIST", value);
1747    free_mk_t(value);
1748
1749    // ECM Header Whitelist
1750    value = mk_t_ecmheaderwhitelist(rdr->ecmHeaderwhitelist);
1751    tpl_addVar(vars, TPLADD, "ECMHEADERWHITELIST", value);
1752    free_mk_t(value);
1753
1754    // Deprecated
1755    if(!apicall)
1756    {
1757        tpl_addVar(vars, TPLADD, "DEPRECATEDCHECKED", (rdr->deprecated == 1) ? "checked" : "");
1758    }
1759    else
1760    {
1761        tpl_addVar(vars, TPLADD, "DEPRECATEDVALUE", (rdr->deprecated == 1) ? "1" : "0");
1762    }
1763
1764    // Smargopatch
1765    if(!apicall)
1766    {
1767        tpl_addVar(vars, TPLADD, "SMARGOPATCHCHECKED", (rdr->smargopatch == 1) ? "checked" : "");
1768    }
1769    else
1770    {
1771        tpl_addVar(vars, TPLADD, "SMARGOPATCHVALUE", (rdr->smargopatch == 1) ? "1" : "0");
1772    }
1773
1774    // Autospeed
1775    if(!apicall)
1776    {
1777        tpl_addVar(vars, TPLADD, "AUTOSPEEDCHECKED", (rdr->autospeed == 1) ? "checked" : "");
1778    }
1779    else
1780    {
1781        tpl_addVar(vars, TPLADD, "AUTOSPEEDVALUE", (rdr->autospeed == 1) ? "1" : "0");
1782    }
1783
1784    // sc8in1 dtrrts patch
1785    if(!apicall)
1786    {
1787        tpl_addVar(vars, TPLADD, "SC8IN1DTRRTSPATCHCHECKED", (rdr->sc8in1_dtrrts_patch == 1) ? "checked" : "");
1788    }
1789    else
1790    {
1791        tpl_addVar(vars, TPLADD, "SC8IN1DTRRTSPATCHVALUE", (rdr->sc8in1_dtrrts_patch == 1) ? "1" : "0");
1792    }
1793
1794    // Detect
1795    if(rdr->detect & 0x80)
1796        { tpl_printf(vars, TPLADD, "DETECT", "!%s", RDR_CD_TXT[rdr->detect & 0x7f]); }
1797    else
1798        { tpl_addVar(vars, TPLADD, "DETECT", RDR_CD_TXT[rdr->detect & 0x7f]); }
1799
1800    // Ratelimit
1801    if(rdr->ratelimitecm)
1802    {
1803        tpl_printf(vars, TPLADD, "RATELIMITECM", "%d", rdr->ratelimitecm);
1804        tpl_printf(vars, TPLADD, "RATELIMITTIME", "%d", rdr->ratelimittime);
1805        tpl_printf(vars, TPLADD, "SRVIDHOLDTIME", "%d", rdr->srvidholdtime);
1806        // ECMUNIQUE
1807        if(!apicall)
1808        {
1809            tpl_addVar(vars, TPLADD, "ECMUNIQUECHECKED", (rdr->ecmunique == 1) ? "checked" : "");
1810        }
1811        else
1812        {
1813            tpl_addVar(vars, TPLADD, "ECMUNIQUE", (rdr->ecmunique == 1) ? "1" : "0");
1814        }
1815    }
1816    // Cooldown
1817    if(rdr->cooldown[0] && rdr->cooldown[1])
1818    {
1819        tpl_printf(vars, TPLADD, "COOLDOWNDELAY", "%d", rdr->cooldown[0]);
1820        tpl_printf(vars, TPLADD, "COOLDOWNTIME", "%d", rdr->cooldown[1]);
1821    }
1822    // Frequencies
1823    tpl_printf(vars, TPLADD, "MHZ", "%d", rdr->mhz);
1824    tpl_printf(vars, TPLADD, "CARDMHZ", "%d", rdr->cardmhz);
1825
1826    // Device
1827    if(!apicall)
1828    {
1829        tpl_addVar(vars, TPLADD, "DEVICE", xml_encode(vars, rdr->device));
1830    }
1831    else
1832    {
1833        tpl_addVar(vars, TPLADD, "DEVICE", rdr->device);
1834    }
1835
1836    if(rdr->r_port)
1837        { tpl_printf(vars, TPLAPPEND, "DEVICE", ",%d", rdr->r_port); }
1838    if(rdr->l_port)
1839    {
1840        if(rdr->r_port)
1841            { tpl_printf(vars, TPLAPPEND, "DEVICE", ",%d", rdr->l_port); }
1842        else
1843            { tpl_printf(vars, TPLAPPEND, "DEVICE", ",,%d", rdr->l_port); }
1844    }
1845
1846    // Group
1847    value = mk_t_group(rdr->grp);
1848    tpl_addVar(vars, TPLADD, "GRP", value);
1849    free_mk_t(value);
1850
1851#ifdef WITH_LB
1852    if(rdr->lb_weight)
1853        { tpl_printf(vars, TPLADD, "LBWEIGHT", "%d", rdr->lb_weight); }
1854#endif
1855
1856    //services
1857    if(!apicall)
1858    {
1859        struct s_sidtab *sidtab = cfg.sidtab;
1860        //build matrix
1861        i = 0;
1862        while(sidtab != NULL)
1863        {
1864            tpl_addVar(vars, TPLADD, "SIDLABEL", xml_encode(vars, sidtab->label));
1865            if(rdr->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, "READERCONFIGSIDOKBIT"));
1868            if(rdr->sidtabs.no & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
1869            else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
1870            tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "READERCONFIGSIDNOBIT"));
1871            if(rdr->lb_sidtabs.ok & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
1872            else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
1873            tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "READERCONFIGSIDLBOKBIT"));
1874            sidtab = sidtab->next;
1875            i++;
1876        }
1877    }
1878    else
1879    {
1880        value = mk_t_service(&rdr->sidtabs);
1881        if(strlen(value) > 0)
1882            { tpl_addVar(vars, TPLADD, "SERVICES", value); }
1883        free_mk_t(value);
1884    }
1885
1886    // CAID
1887    value = mk_t_caidtab(&rdr->ctab);
1888    tpl_addVar(vars, TPLADD, "CAIDS", value);
1889    free_mk_t(value);
1890
1891    // AESkeys
1892    value = mk_t_aeskeys(rdr);
1893    tpl_addVar(vars, TPLADD, "AESKEYS", value);
1894    free_mk_t(value);
1895
1896    //ident
1897    value = mk_t_ftab(&rdr->ftab);
1898    tpl_addVar(vars, TPLADD, "IDENTS", value);
1899    free_mk_t(value);
1900
1901    //CHID
1902    value = mk_t_ftab(&rdr->fchid);
1903    tpl_addVar(vars, TPLADD, "CHIDS", value);
1904    free_mk_t(value);
1905
1906    //class
1907    value = mk_t_cltab(&rdr->cltab);
1908    tpl_addVar(vars, TPLADD, "CLASS", value);
1909    free_mk_t(value);
1910
1911    if(rdr->cachemm)
1912        { tpl_printf(vars, TPLADD, "EMMCACHE", "%d,%d,%d", rdr->cachemm, rdr->rewritemm, rdr->logemm); }
1913
1914    //savenano
1915    value = mk_t_nano(rdr->s_nano);
1916    tpl_addVar(vars, TPLADD, "SAVENANO", value);
1917    free_mk_t(value);
1918
1919    //blocknano
1920    value = mk_t_nano(rdr->b_nano);
1921    tpl_addVar(vars, TPLADD, "BLOCKNANO", value);
1922    free_mk_t(value);
1923
1924    // Blocke EMM
1925    if(!apicall)
1926    {
1927        tpl_addVar(vars, TPLADD, "BLOCKEMMUNKNOWNCHK", (rdr->blockemm & EMM_UNKNOWN) ? "checked" : "");
1928        tpl_addVar(vars, TPLADD, "BLOCKEMMUNIQCHK", (rdr->blockemm & EMM_UNIQUE) ? "checked" : "");
1929        tpl_addVar(vars, TPLADD, "BLOCKEMMSHAREDCHK", (rdr->blockemm & EMM_SHARED) ? "checked" : "");
1930        tpl_addVar(vars, TPLADD, "BLOCKEMMGLOBALCHK", (rdr->blockemm & EMM_GLOBAL) ? "checked" : "");
1931    }
1932    else
1933    {
1934        tpl_addVar(vars, TPLADD, "BLOCKEMMUNKNOWNVALUE", (rdr->blockemm & EMM_UNKNOWN) ? "1" : "0");
1935        tpl_addVar(vars, TPLADD, "BLOCKEMMUNIQVALUE", (rdr->blockemm & EMM_UNIQUE) ? "1" : "0");
1936        tpl_addVar(vars, TPLADD, "BLOCKEMMSHAREDVALUE", (rdr->blockemm & EMM_SHARED) ? "1" : "0");
1937        tpl_addVar(vars, TPLADD, "BLOCKEMMGLOBALVALUE", (rdr->blockemm & EMM_GLOBAL) ? "1" : "0");
1938    }
1939
1940    // Save EMM
1941    if(!apicall)
1942    {
1943        tpl_addVar(vars, TPLADD, "SAVEEMMUNKNOWNCHK", (rdr->saveemm & EMM_UNKNOWN) ? "checked" : "");
1944        tpl_addVar(vars, TPLADD, "SAVEEMMUNIQCHK", (rdr->saveemm & EMM_UNIQUE) ? "checked" : "");
1945        tpl_addVar(vars, TPLADD, "SAVEEMMSHAREDCHK", (rdr->saveemm & EMM_SHARED) ? "checked" : "");
1946        tpl_addVar(vars, TPLADD, "SAVEEMMGLOBALCHK", (rdr->saveemm & EMM_GLOBAL) ? "checked" : "");
1947    }
1948    else
1949    {
1950        tpl_addVar(vars, TPLADD, "SAVEEMMUNKNOWNVALUE", (rdr->saveemm & EMM_UNKNOWN) ? "1" : "0");
1951        tpl_addVar(vars, TPLADD, "SAVEEMMUNIQVALUE", (rdr->saveemm & EMM_UNIQUE) ? "1" : "0");
1952        tpl_addVar(vars, TPLADD, "SAVEEMMSHAREDVALUE", (rdr->saveemm & EMM_SHARED) ? "1" : "0");
1953        tpl_addVar(vars, TPLADD, "SAVEEMMGLOBALVALUE", (rdr->saveemm & EMM_GLOBAL) ? "1" : "0");
1954    }
1955
1956    value = mk_t_emmbylen(rdr);
1957    if(strlen(value) > 0)
1958        { tpl_addVar(vars, TPLADD, "BLOCKEMMBYLEN", value); }
1959    free_mk_t(value);
1960
1961#ifdef MODULE_CCCAM
1962    if(!strcmp(rdr->cc_version, "2.0.11"))
1963    {
1964        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED0", "selected");
1965    }
1966    else if(!strcmp(rdr->cc_version, "2.1.1"))
1967    {
1968        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED1", "selected");
1969    }
1970    else if(!strcmp(rdr->cc_version, "2.1.2"))
1971    {
1972        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED2", "selected");
1973    }
1974    else if(!strcmp(rdr->cc_version, "2.1.3"))
1975    {
1976        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED3", "selected");
1977    }
1978    else if(!strcmp(rdr->cc_version, "2.1.4"))
1979    {
1980        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED4", "selected");
1981    }
1982    else if(!strcmp(rdr->cc_version, "2.2.0"))
1983    {
1984        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED5", "selected");
1985    }
1986    else if(!strcmp(rdr->cc_version, "2.2.1"))
1987    {
1988        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED6", "selected");
1989    }
1990    else if(!strcmp(rdr->cc_version, "2.3.0"))
1991    {
1992        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED7", "selected");
1993    }
1994#endif
1995
1996    tpl_printf(vars, TPLADD, "TMP", "NDSVERSION%d", rdr->ndsversion);
1997    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1998
1999    tpl_printf(vars, TPLADD, "TMP", "NAGRAREAD%d", rdr->nagra_read);
2000    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2001
2002#ifdef MODULE_CCCAM
2003    tpl_printf(vars, TPLADD, "CCCMAXHOPS",   "%d", rdr->cc_maxhops);
2004    tpl_printf(vars, TPLADD, "CCCMINDOWN",   "%d", rdr->cc_mindown);
2005    tpl_printf(vars, TPLADD, "CCCRESHARE",   "%d", rdr->cc_reshare);
2006    tpl_printf(vars, TPLADD, "RESHARE",      "%d", cfg.cc_reshare);
2007    tpl_printf(vars, TPLADD, "CCCRECONNECT", "%d", rdr->cc_reconnect);
2008
2009    if(rdr->cc_want_emu)
2010        { tpl_addVar(vars, TPLADD, "CCCWANTEMUCHECKED", "checked"); }
2011    if(rdr->cc_keepalive)
2012        { tpl_addVar(vars, TPLADD, "KEEPALIVECHECKED", "checked"); }
2013#endif
2014
2015#ifdef MODULE_GBOX
2016    tpl_printf(vars, TPLADD, "GBOXMAXDISTANCE",   "%d", rdr->gbox_maxdist);
2017    tpl_printf(vars, TPLADD, "GBOXMAXECMSEND",   "%d", rdr->gbox_maxecmsend);
2018    tpl_printf(vars, TPLADD, "GBOXRESHARE",   "%d", rdr->gbox_reshare);
2019#endif
2020
2021    tpl_addVar(vars, TPLADD, "PROTOCOL", reader_get_type_desc(rdr, 0));
2022
2023    // Show only parameters which needed for the reader
2024    switch(rdr->typ)
2025    {
2026    case R_CONSTCW:
2027    case R_DB2COM1:
2028    case R_DB2COM2:
2029    case R_MOUSE :
2030    case R_MP35:
2031    case R_SC8in1 :
2032    case R_SMART :
2033    case R_INTERNAL:
2034    case R_SERIAL :
2035    case R_PCSC :
2036        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
2037        break;
2038    case R_CAMD35 :
2039        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCAMD35BIT"));
2040        break;
2041    case R_CS378X :
2042        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCS378XBIT"));
2043        break;
2044    case R_RADEGAST:
2045        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGRADEGASTBIT"));
2046        break;
2047    case R_GHTTP:
2048        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGGHTTPBIT"));
2049        break;
2050    case R_GBOX:
2051        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGGBOXBIT"));
2052        break;
2053    case R_NEWCAMD:
2054        if(rdr->ncd_proto == NCD_525)
2055        {
2056            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGNCD525BIT"));
2057        }
2058        else if(rdr->ncd_proto == NCD_524)
2059        {
2060            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGNCD524BIT"));
2061        }
2062        break;
2063#ifdef MODULE_CCCAM
2064    case R_CCCAM :
2065        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCCCAMBIT"));
2066        break;
2067#endif
2068    default :
2069        tpl_addMsg(vars, "Error: protocol not resolvable");
2070        tpl_addMsg(vars, tpl_printf(vars, TPLADD, "TMP", "Error: protocol number: %d readername: %s", rdr->typ, xml_encode(vars, rdr->label)));
2071        break;
2072
2073    }
2074
2075#ifdef MODULE_CCCAM
2076    if(rdr->typ != R_CCCAM)
2077    {
2078        tpl_printf(vars, TPLADD, "CCCHOP", "%d", rdr->cc_hop);
2079        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGHOPBIT"));
2080    }
2081#endif
2082
2083    return tpl_getTpl(vars, "READERCONFIG");
2084}
2085
2086static char *send_oscam_reader_stats(struct templatevars *vars, struct uriparams *params, int32_t apicall)
2087{
2088
2089    if(!apicall) { setActiveMenu(vars, MNU_READERS); }
2090
2091    int8_t error;
2092    struct s_client *cl = NULL;
2093    struct s_reader *rdr;
2094
2095    rdr = get_reader_by_label(getParam(params, "label"));
2096    error = (rdr ? 0 : 1);
2097
2098    if(!error && rdr)
2099    {
2100        cl = rdr->client;
2101        error = (cl ? 0 : 1);
2102    }
2103
2104    if(error)
2105    {
2106        tpl_addVar(vars, TPLAPPEND, "READERSTATSROW", tpl_getTpl(vars, "READERSTATSROWBIT"));
2107        if(!apicall)
2108            { return tpl_getTpl(vars, "READERSTATS"); }
2109        else
2110            { return tpl_getTpl(vars, "APIREADERSTATS"); }
2111    }
2112
2113#ifdef WITH_LB
2114    char *stxt[] = {"found", "cache1", "cache2", "cache3",
2115                    "not found", "timeout", "sleeping",
2116                    "fake", "invalid", "corrupt", "no card", "expdate",
2117                    "disabled", "stopped"
2118                   };
2119
2120    if(strcmp(getParam(params, "action"), "resetstat") == 0)
2121    {
2122        char *rcs = getParam(params, "rc");
2123        int32_t retval = 0;
2124        if(strlen(rcs) > 0)
2125        {
2126            int8_t rc;
2127            rc = atoi(rcs);
2128            retval = clean_stat_by_rc(rdr, rc, 0);
2129            cs_log("Reader %s stats %d %s entr%s deleted by WebIF from %s",
2130                   rdr->label, retval, stxt[rc],
2131                   retval == 1 ? "y" : "ies",
2132                   cs_inet_ntoa(GET_IP()));
2133        }
2134        else
2135        {
2136            clear_reader_stat(rdr);
2137            cs_log("Reader %s stats resetted by WebIF from %s", rdr->label, cs_inet_ntoa(GET_IP()));
2138        }
2139
2140    }
2141
2142    if(strcmp(getParam(params, "action"), "deleterecord") == 0)
2143    {
2144        char *record = getParam(params, "record");
2145        if(strlen(record) > 0)
2146        {
2147            int32_t retval = 0;
2148            uint32_t caid, provid, sid, cid, len;
2149            sscanf(record, "%4x:%6x:%4x:%4x:%4x", &caid, &provid, &sid, &cid, &len);
2150            retval = clean_stat_by_id(rdr, caid, provid, sid, cid, len);
2151            cs_log("Reader %s stats %d entr%s deleted by WebIF from %s",
2152                   rdr->label, retval,
2153                   retval == 1 ? "y" : "ies",
2154                   cs_inet_ntoa(GET_IP()));
2155        }
2156    }
2157
2158    if(strcmp(getParam(params, "action"), "updateecmlen") == 0)
2159    {
2160        update_ecmlen_from_stat(rdr);
2161        write_server();
2162    }
2163
2164#endif
2165
2166    tpl_addVar(vars, TPLADD, "READERNAME", xml_encode(vars, rdr->label));
2167    tpl_addVar(vars, TPLADD, "LABEL", xml_encode(vars, rdr->label));
2168    tpl_addVar(vars, TPLADD, "ENCODEDLABEL", urlencode(vars, rdr->label));
2169
2170    if(apicall)
2171    {
2172        int32_t i, emmcount = 0;
2173        char *ttxt[] = {"unknown", "unique", "shared", "global"};
2174
2175        for(i = 0; i < 4; i++)
2176        {
2177            tpl_addVar(vars, TPLADD, "EMMRESULT", "error");
2178            tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
2179            tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmerror[i]);
2180            tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
2181            emmcount += rdr->emmerror[i];
2182            tpl_printf(vars, TPLADD, "TOTALERROR", "%d", emmcount);
2183        }
2184        emmcount = 0;
2185        for(i = 0; i < 4; i++)
2186        {
2187            tpl_addVar(vars, TPLADD, "EMMRESULT", "written");
2188            tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
2189            tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmwritten[i]);
2190            tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
2191            emmcount += rdr->emmwritten[i];
2192            tpl_printf(vars, TPLADD, "TOTALWRITTEN", "%d", emmcount);
2193        }
2194        emmcount = 0;
2195        for(i = 0; i < 4; i++)
2196        {
2197            tpl_addVar(vars, TPLADD, "EMMRESULT", "skipped");
2198            tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
2199            tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmskipped[i]);
2200            tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
2201            emmcount += rdr->emmskipped[i];
2202            tpl_printf(vars, TPLADD, "TOTALSKIPPED", "%d", emmcount);
2203        }
2204        emmcount = 0;
2205        for(i = 0; i < 4; i++)
2206        {
2207            tpl_addVar(vars, TPLADD, "EMMRESULT", "blocked");
2208            tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
2209            tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmblocked[i]);
2210            tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
2211            emmcount += rdr->emmblocked[i];
2212            tpl_printf(vars, TPLADD, "TOTALBLOCKED", "%d", emmcount);
2213        }
2214    }
2215
2216    if(apicall)
2217    {
2218        char *txt = "UNDEF";
2219        switch(rdr->card_status)
2220        {
2221        case NO_CARD:
2222            txt = "OFF";
2223            break;
2224        case UNKNOWN:
2225            txt = "UNKNOWN";
2226            break;
2227        case CARD_NEED_INIT:
2228            txt = "NEEDINIT";
2229            break;
2230        case CARD_INSERTED:
2231            if(cl->typ == 'p')
2232                { txt = "CONNECTED"; }
2233            else
2234                { txt = "CARDOK"; }
2235            break;
2236        case CARD_FAILURE:
2237            txt = "ERROR";
2238            break;
2239        default:
2240            txt = "UNDEF";
2241        }
2242        tpl_addVar(vars, TPLADD, "READERSTATUS", txt);
2243        tpl_printf(vars, TPLADD, "READERCAID", "%04X", rdr->caid);
2244    }
2245
2246    int32_t rowcount = 0;
2247    uint64_t ecmcount = 0;
2248    time_t lastaccess = 0;
2249
2250#ifdef WITH_LB
2251    int32_t rc2hide = (-1);
2252    if(strlen(getParam(params, "hide")) > 0)
2253        { rc2hide = atoi(getParam(params, "hide")); }
2254
2255    if(rdr->lb_stat)
2256    {
2257        int32_t statsize;
2258        // @todo alno: sort by click, 0=ascending, 1=descending (maybe two buttons or reverse on second click)
2259        READER_STAT **statarray = get_sorted_stat_copy(rdr, 0, &statsize);
2260        char channame[32];
2261        for(; rowcount < statsize; ++rowcount)
2262        {
2263            READER_STAT *s = statarray[rowcount];
2264            if(!(s->rc == rc2hide))
2265            {
2266                struct tm lt;
2267                localtime_r(&s->last_received.time, &lt); // fixme we need walltime!
2268                ecmcount += s->ecm_count;
2269                if(!apicall)
2270                {
2271                    tpl_printf(vars, TPLADD, "CHANNEL", "%04X:%06X:%04X:%04X", s->caid, s->prid, s->srvid, s->chid);
2272                    tpl_addVar(vars, TPLADD, "CHANNELNAME", xml_encode(vars, get_servicename(cur_client(), s->srvid, s->caid, channame)));
2273                    tpl_printf(vars, TPLADD, "ECMLEN", "%04hX", s->ecmlen);
2274                    tpl_addVar(vars, TPLADD, "RC", stxt[s->rc]);
2275                    tpl_printf(vars, TPLADD, "TIME", "%dms", s->time_avg);
2276                    if(s->time_stat[s->time_idx])
2277                        { tpl_printf(vars, TPLADD, "TIMELAST", "%dms", s->time_stat[s->time_idx]); }
2278                    else
2279                        { tpl_addVar(vars, TPLADD, "TIMELAST", ""); }
2280                    tpl_printf(vars, TPLADD, "COUNT", "%d", s->ecm_count);
2281
2282                    if(s->last_received.time)
2283                    {
2284                        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);
2285
2286                    }
2287                    else
2288                    {
2289                        tpl_addVar(vars, TPLADD, "LAST", "never");
2290                    }
2291                }
2292                else
2293                {
2294                    tpl_printf(vars, TPLADD, "ECMCAID", "%04X", s->caid);
2295                    tpl_printf(vars, TPLADD, "ECMPROVID", "%06X", s->prid);
2296                    tpl_printf(vars, TPLADD, "ECMSRVID", "%04X", s->srvid);
2297                    tpl_printf(vars, TPLADD, "ECMLEN", "%04hX", s->ecmlen);
2298                    tpl_addVar(vars, TPLADD, "ECMCHANNELNAME", xml_encode(vars, get_servicename(cur_client(), s->srvid, s->caid, channame)));
2299                    tpl_printf(vars, TPLADD, "ECMTIME", "%d", s->time_avg);
2300                    tpl_printf(vars, TPLADD, "ECMTIMELAST", "%d", s->time_stat[s->time_idx]);
2301                    tpl_printf(vars, TPLADD, "ECMRC", "%d", s->rc);
2302                    tpl_addVar(vars, TPLADD, "ECMRCS", stxt[s->rc]);
2303                    if(s->last_received.time)
2304                    {
2305                        char tbuffer [30];
2306                        strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
2307                        tpl_addVar(vars, TPLADD, "ECMLAST", tbuffer);
2308                    }
2309                    else
2310                    {
2311                        tpl_addVar(vars, TPLADD, "ECMLAST", "");
2312                    }
2313                    tpl_printf(vars, TPLADD, "ECMCOUNT", "%d", s->ecm_count);
2314
2315                    if(s->last_received.time > lastaccess)
2316                        { lastaccess = s->last_received.time; }
2317                }
2318
2319                if(!apicall)
2320                {
2321                    if(s->rc == E_NOTFOUND)
2322                    {
2323                        tpl_addVar(vars, TPLAPPEND, "READERSTATSROWNOTFOUND", tpl_getTpl(vars, "READERSTATSBIT"));
2324                        tpl_addVar(vars, TPLADD, "RESETA", urlencode(vars, rdr->label));
2325                        tpl_addVar(vars, TPLADD, "READERSTATSNFHEADLINE", tpl_getTpl(vars, "READERSTATSROWNOTFOUNDBIT"));
2326                    }
2327                    else if(s->rc == E_TIMEOUT)
2328                    {
2329                        tpl_addVar(vars, TPLAPPEND, "READERSTATSROWTIMEOUT", tpl_getTpl(vars, "READERSTATSBIT"));
2330                        tpl_addVar(vars, TPLADD, "RESETB", urlencode(vars, rdr->label));
2331                        tpl_addVar(vars, TPLADD, "READERSTATSTOHEADLINE", tpl_getTpl(vars, "READERSTATSROWTIMEOUTBIT"));
2332                    }
2333                    else
2334                        { tpl_addVar(vars, TPLAPPEND, "READERSTATSROWFOUND", tpl_getTpl(vars, "READERSTATSBIT")); }
2335                }
2336                else
2337                {
2338
2339                    tpl_addVar(vars, TPLAPPEND, "ECMSTATS", tpl_getTpl(vars, "APIREADERSTATSECMBIT"));
2340                }
2341            }
2342        }
2343        NULLFREE(statarray);
2344    }
2345    else
2346#endif
2347        tpl_addVar(vars, TPLAPPEND, "READERSTATSROW", tpl_getTpl(vars, "READERSTATSNOSTATS"));
2348
2349    tpl_printf(vars, TPLADD, "ROWCOUNT", "%d", rowcount);
2350
2351    if(lastaccess > 0)
2352    {
2353        char tbuffer [30];
2354        struct tm lt;
2355        localtime_r(&lastaccess, &lt);
2356        strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
2357        tpl_addVar(vars, TPLADD, "LASTACCESS", tbuffer);
2358    }
2359    else
2360    {
2361        tpl_addVar(vars, TPLADD, "LASTACCESS", "");
2362    }
2363
2364    if(apicall)
2365    {
2366        if(cl)
2367        {
2368            char *value = get_ecm_historystring(cl);
2369            tpl_addVar(vars, TPLADD, "ECMHISTORY", value);
2370            free_mk_t(value);
2371        }
2372    }
2373
2374    tpl_printf(vars, TPLADD, "TOTALECM", "%" PRIu64, ecmcount);
2375
2376    if(!apicall)
2377        { return tpl_getTpl(vars, "READERSTATS"); }
2378    else
2379        { return tpl_getTpl(vars, "APIREADERSTATS"); }
2380}
2381
2382static char *send_oscam_user_config_edit(struct templatevars *vars, struct uriparams *params, int32_t apicall)
2383{
2384    struct s_auth *account, *ptr;
2385    char user[sizeof(first_client->account->usr)];
2386
2387    int32_t i;
2388
2389    if(!apicall) { setActiveMenu(vars, MNU_USERS); }
2390
2391    if(strcmp(getParam(params, "action"), "Save As") == 0) { cs_strncpy(user, getParam(params, "newuser"), sizeof(user) / sizeof(char)); }
2392    else { cs_strncpy(user, getParam(params, "user"), sizeof(user) / sizeof(char)); }
2393
2394    for(account = cfg.account; account != NULL && strcmp(user, account->usr) != 0; account = account->next) { ; }
2395
2396    // Create a new user if it doesn't yet
2397    if(account == NULL)
2398    {
2399        i = 1;
2400        while(strlen(user) < 1)
2401        {
2402            snprintf(user, sizeof(user) / sizeof(char) - 1, "NEWUSER%d", i);
2403            for(account = cfg.account; account != NULL && strcmp(user, account->usr) != 0; account = account->next) { ; }
2404            if(account != NULL) { user[0] = '\0'; }
2405            ++i;
2406        }
2407        if(!cs_malloc(&account, sizeof(struct s_auth))) { return "0"; }
2408        if(cfg.account == NULL) { cfg.account = account; }
2409        else
2410        {
2411            for(ptr = cfg.account; ptr != NULL && ptr->next != NULL; ptr = ptr->next) { ; }
2412            ptr->next = account;
2413        }
2414        account_set_defaults(account);
2415        account->disabled = 1;
2416        cs_strncpy((char *)account->usr, user, sizeof(account->usr));
2417        if(!account->grp)
2418            { account->grp = 1; }
2419        tpl_addMsg(vars, "New user has been added with default settings");
2420
2421        if(write_userdb() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
2422        // no need to refresh anything here as the account is disabled by default and there's no client with this new account anyway!
2423    }
2424
2425    if((strcmp(getParam(params, "action"), "Save") == 0) || (strcmp(getParam(params, "action"), "Save As") == 0))
2426    {
2427        char servicelabels[1024] = "";
2428
2429        for(i = 0; i < (*params).paramcount; i++)
2430        {
2431            if((strcmp((*params).params[i], "action")) &&
2432                    (strcmp((*params).params[i], "user")) &&
2433                    (strcmp((*params).params[i], "newuser")) &&
2434                    (strcmp((*params).params[i], "part")))
2435            {
2436
2437                if(!strcmp((*params).params[i], "services"))
2438                    { snprintf(servicelabels + strlen(servicelabels), sizeof(servicelabels) - strlen(servicelabels), "%s,", (*params).values[i]); }
2439                else
2440                    { chk_account((*params).params[i], (*params).values[i], account); }
2441            }
2442        }
2443        chk_account("services", servicelabels, account);
2444        tpl_addMsg(vars, "Account updated");
2445
2446        refresh_oscam(REFR_CLIENTS);
2447
2448        if(write_userdb() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
2449    }
2450
2451    tpl_addVar(vars, TPLADD, "USERNAME", xml_encode(vars, account->usr));
2452    tpl_addVar(vars, TPLADD, "PASSWORD", xml_encode(vars, account->pwd));
2453    tpl_addVar(vars, TPLADD, "DESCRIPTION", xml_encode(vars, account->description));
2454
2455    //Disabled
2456    if(!apicall)
2457    {
2458        if(account->disabled)
2459            { tpl_addVar(vars, TPLADD, "DISABLEDCHECKED", "checked"); }
2460    }
2461    else
2462    {
2463        tpl_printf(vars, TPLADD, "DISABLEDVALUE", "%d", account->disabled);
2464    }
2465
2466    //Expirationdate
2467    struct tm timeinfo;
2468    cs_gmtime_r(&account->expirationdate, &timeinfo);
2469    char buf [80];
2470    strftime(buf, 80, "%Y-%m-%d", &timeinfo);
2471    if(strcmp(buf, "1970-01-01")) { tpl_addVar(vars, TPLADD, "EXPDATE", buf); }
2472
2473    //Allowed TimeFrame
2474    if(account->allowedtimeframe[0] && account->allowedtimeframe[1])
2475    {
2476        tpl_printf(vars, TPLADD, "ALLOWEDTIMEFRAME", "%02d:%02d-%02d:%02d",
2477                   account->allowedtimeframe[0] / 60,
2478                   account->allowedtimeframe[0] % 60,
2479                   account->allowedtimeframe[1] / 60,
2480                   account->allowedtimeframe[1] % 60);
2481    }
2482
2483    //Group
2484    char *value = mk_t_group(account->grp);
2485    tpl_addVar(vars, TPLADD, "GROUPS", value);
2486    free_mk_t(value);
2487
2488    // allowed protocols
2489    value = mk_t_allowedprotocols(account);
2490    tpl_addVar(vars, TPLADD, "ALLOWEDPROTOCOLS", value);
2491    free_mk_t(value);
2492
2493    //Hostname
2494    tpl_addVar(vars, TPLADD, "DYNDNS", xml_encode(vars, account->dyndns));
2495
2496    //Uniq
2497    if(!apicall)
2498    {
2499        tpl_printf(vars, TPLADD, "TMP", "UNIQSELECTED%d", account->uniq);
2500        tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2501    }
2502    else
2503    {
2504        tpl_printf(vars, TPLADD, "UNIQVALUE", "%d", account->uniq);
2505    }
2506
2507    //Sleep
2508    if(!account->tosleep) { tpl_addVar(vars, TPLADD, "SLEEP", "0"); }
2509    else { tpl_printf(vars, TPLADD, "SLEEP", "%d", account->tosleep); }
2510
2511    //Monlevel selector
2512    if(!apicall)
2513    {
2514        tpl_printf(vars, TPLADD, "TMP", "MONSELECTED%d", account->monlvl);
2515        tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2516    }
2517    else
2518    {
2519        tpl_printf(vars, TPLADD, "MONVALUE", "%d", account->monlvl);
2520    }
2521
2522    //Au
2523    if(account->autoau == 1)
2524        { tpl_addVar(vars, TPLADD, "AUREADER", "1"); }
2525    else if(account->aureader_list)
2526    {
2527        value = mk_t_aureader(account);
2528        tpl_addVar(vars, TPLADD, "AUREADER", value);
2529        free_mk_t(value);
2530    }
2531
2532    if(!apicall)
2533    {
2534        /* SERVICES */
2535        struct s_sidtab *sidtab = cfg.sidtab;
2536        //build matrix
2537        i = 0;
2538        while(sidtab != NULL)
2539        {
2540            tpl_addVar(vars, TPLADD, "SIDLABEL", xml_encode(vars, sidtab->label));
2541            if(account->sidtabs.ok & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
2542            else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
2543            tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "USEREDITSIDOKBIT"));
2544            if(account->sidtabs.no & ((SIDTABBITS)1 << i)) { tpl_addVar(vars, TPLADD, "CHECKED", "checked"); }
2545            else { tpl_addVar(vars, TPLADD, "CHECKED", ""); }
2546            tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "USEREDITSIDNOBIT"));
2547            sidtab = sidtab->next;
2548            i++;
2549        }
2550    }
2551    else
2552    {
2553        value = mk_t_service(&account->sidtabs);
2554        if(strlen(value) > 0)
2555            { tpl_addVar(vars, TPLADD, "SERVICES", value); }
2556        free_mk_t(value);
2557    }
2558
2559    // CAID
2560    value = mk_t_caidtab(&account->ctab);
2561    tpl_addVar(vars, TPLADD, "CAIDS", value);
2562    free_mk_t(value);
2563
2564    //ident
2565    value = mk_t_ftab(&account->ftab);
2566    tpl_addVar(vars, TPLADD, "IDENTS", value);
2567    free_mk_t(value);
2568
2569    //CHID
2570    value = mk_t_ftab(&account->fchid);
2571    tpl_addVar(vars, TPLADD, "CHIDS",  value);
2572    free_mk_t(value);
2573
2574    //class
2575    value = mk_t_cltab(&account->cltab);
2576    tpl_addVar(vars, TPLADD, "CLASS", value);
2577    free_mk_t(value);
2578
2579    //Betatunnel
2580    value = mk_t_tuntab(&account->ttab);
2581    tpl_addVar(vars, TPLADD, "BETATUNNELS", value);
2582    free_mk_t(value);
2583
2584    //SUPPRESSCMD08
2585    if(!apicall)
2586    {
2587        if(account->c35_suppresscmd08)
2588            { tpl_addVar(vars, TPLADD, "SUPPRESSCMD08", "selected"); }
2589    }
2590    else
2591    {
2592        tpl_printf(vars, TPLADD, "SUPPRESSCMD08VALUE", "%d", account->c35_suppresscmd08);
2593    }
2594
2595    //Sleepsend
2596    tpl_printf(vars, TPLADD, "SLEEPSEND", "%u", account->c35_sleepsend);
2597
2598    //User Max Idle
2599    tpl_printf(vars, TPLADD, "UMAXIDLE", "%u", account->umaxidle);
2600
2601    //EMM Reassembly selector
2602    if(!apicall)
2603    {
2604        tpl_printf(vars, TPLADD, "TMP", "EMMRSELECTED%d", account->emm_reassembly);
2605        tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2606    }
2607    else
2608    {
2609        tpl_printf(vars, TPLADD, "EMMRVALUE", "%d", account->emm_reassembly);
2610    }
2611
2612#ifdef CS_CACHEEX
2613    // Cacheex
2614    if(!apicall)
2615    {
2616        tpl_printf(vars, TPLADD, "TMP", "CACHEEXSELECTED%d", account->cacheex.mode);
2617        tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2618
2619    }
2620    else
2621    {
2622        tpl_printf(vars, TPLADD, "CACHEEX", "%d", account->cacheex.mode);
2623    }
2624    tpl_printf(vars, TPLADD, "CACHEEX_MAXHOP", "%d", account->cacheex.maxhop);
2625
2626    value = mk_t_cacheex_hitvaluetab(&account->cacheex.filter_caidtab);
2627    //if (strlen(value) > 0)
2628    tpl_printf(vars, TPLADD, "CACHEEX_ECM_FILTER", "%s", value);
2629    free_mk_t(value);
2630
2631    tpl_addVar(vars, TPLADD, "DCCHECKED", (account->cacheex.drop_csp == 1) ? "checked" : "");
2632    tpl_addVar(vars, TPLADD, "ARCHECKED", (account->cacheex.allow_request == 1) ? "checked" : "");
2633    tpl_addVar(vars, TPLADD, "NWTCHECKED", (account->no_wait_time == 1) ? "checked" : "");
2634   
2635#endif
2636
2637    //Keepalive
2638    if(!apicall)
2639    {
2640        if(account->ncd_keepalive)
2641            { tpl_addVar(vars, TPLADD, "KEEPALIVE", "checked"); }
2642    }
2643    else
2644    {
2645        tpl_printf(vars, TPLADD, "KEEPALIVEVALUE", "%d", account->ncd_keepalive);
2646    }
2647
2648#ifdef CS_ANTICASC
2649    tpl_printf(vars, TPLADD, "AC_USERS", "%d", account->ac_users);
2650    tpl_printf(vars, TPLADD, "CFGNUMUSERS", "%d", cfg.ac_users);
2651    if(!apicall)
2652    {
2653        tpl_printf(vars, TPLADD, "TMP", "PENALTY%d", account->ac_penalty);
2654        tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2655        char *tmp = NULL;
2656        switch(cfg.ac_penalty)
2657        {
2658        case 0:
2659            tmp = "(0) Only write to log";
2660            break;
2661        case 1:
2662            tmp = "(1) Fake DW delayed";
2663            break;
2664        case 2:
2665            tmp = "(2) Ban";
2666            break;
2667        case 3:
2668            tmp = "(3) Real DW delayed";
2669            break;
2670        }
2671        tpl_addVar(vars, TPLADD, "CFGPENALTY", tmp);
2672    }
2673    else
2674    {
2675        tpl_printf(vars, TPLADD, "PENALTYVALUE", "%d", account->ac_penalty);
2676    }
2677#endif
2678
2679#ifdef MODULE_CCCAM
2680    tpl_printf(vars, TPLADD, "CCCMAXHOPS", "%d", account->cccmaxhops);
2681    tpl_printf(vars, TPLADD, "CCCRESHARE", "%d", account->cccreshare);
2682    tpl_printf(vars, TPLADD, "RESHARE",    "%d", cfg.cc_reshare);
2683
2684    //CCcam Ignore Reshare
2685    tpl_printf(vars, TPLADD, "TMP", "CCCIGNRSHRSELECTED%d", account->cccignorereshare);
2686    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2687    tpl_addVar(vars, TPLADD, "CFGIGNORERESHARE",
2688               cfg.cc_ignore_reshare == 0 ?
2689               "0 - use reshare level of Server" : "1 - use reshare level of Reader or User");
2690
2691    //CCcam Stealth Mode
2692    tpl_printf(vars, TPLADD, "TMP", "CCCSTEALTHSELECTED%d", account->cccstealth);
2693    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
2694
2695    tpl_addVar(vars, TPLADD, "STEALTH", cfg.cc_stealth ? "enable" : "disable");
2696#endif
2697
2698    //Failban
2699    tpl_printf(vars, TPLADD, "FAILBAN", "%d", account->failban);
2700
2701    if(!apicall)
2702        { return tpl_getTpl(vars, "USEREDIT"); }
2703    else
2704        { return tpl_getTpl(vars, "APIUSEREDIT"); }
2705
2706}
2707
2708static void webif_add_client_proto(struct templatevars *vars, struct s_client *cl, const char *proto, int8_t apicall)
2709{
2710    tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", "");
2711    tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", "");
2712    if(!cl) { return; }
2713#ifdef MODULE_NEWCAMD
2714    if(streq(proto, "newcamd") && cl->typ == 'c')
2715    {
2716        if(cfg.http_showpicons && !apicall)
2717        {
2718            char picon_name[32];
2719            snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%s_%s", (char *)proto, newcamd_get_client_name(cl->ncd_client_id));
2720            if(picon_exists(picon_name))
2721            {
2722                tpl_addVar(vars, TPLADD, "NCMDA", (char *)proto);
2723                tpl_addVar(vars, TPLADD, "NCMDB", (char *)newcamd_get_client_name(cl->ncd_client_id));
2724                tpl_addVar(vars, TPLADD, "CLIENTPROTO", tpl_getTpl(vars, "PROTONEWCAMDPIC"));
2725            }
2726            else
2727            {
2728                tpl_printf(vars, TPLADD, "CLIENTPROTO", "%s (%s)", proto, newcamd_get_client_name(cl->ncd_client_id));
2729                tpl_printf(vars, TPLADD, "CLIENTPROTOTITLE", "missing icon: IC_%s_%s.tpl", proto, newcamd_get_client_name(cl->ncd_client_id));
2730            }
2731        }
2732        else
2733        {
2734            tpl_printf(vars, TPLADD, "CLIENTPROTO", "%s (%s)", proto, newcamd_get_client_name(cl->ncd_client_id));
2735        }
2736        return;
2737    }
2738#endif
2739#ifdef MODULE_CCCAM
2740    if(strncmp(proto, "cccam", 5) == 0)
2741    {
2742        struct cc_data *cc = cl->cc;
2743        if(cc && cc->remote_version && cc->remote_build)
2744        {
2745            if(cfg.http_showpicons && !apicall)
2746            {
2747                char picon_name[32];
2748                snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%s_%s_%s", proto, cc->remote_version, cc->remote_build);
2749                if(picon_exists(picon_name))
2750                {
2751                    tpl_addVar(vars, TPLADD, "CCA", (char *)proto);
2752                    tpl_addVar(vars, TPLADD, "CCB", cc->remote_version);
2753                    tpl_addVar(vars, TPLADD, "CCC", cc->remote_build);
2754                    tpl_addVar(vars, TPLADD, "CCD", cc->extended_mode ? cc->remote_oscam : "");
2755                    tpl_addVar(vars, TPLADD, "CLIENTPROTO", tpl_getTpl(vars, "PROTOCCCAMPIC"));
2756                    tpl_addVar(vars, TPLADD, "CLIENTPROTOTITLE", cc->extended_mode ? cc->remote_oscam : "");
2757                }
2758                else
2759                {
2760                    tpl_printf(vars, TPLADD, "CLIENTPROTO", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
2761                    tpl_printf(vars, TPLADD, "CLIENTPROTOTITLE", "cccam extinfo: %s missing icon: IC_%s_%s_%s.tpl",
2762                    cc->extended_mode ? cc->remote_oscam : "", proto, cc->remote_version, cc->remote_build);
2763                }
2764            }
2765            else
2766            {
2767                tpl_printf(vars, TPLADDONCE, "CLIENTPROTO", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
2768                tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", cc->extended_mode ? cc->remote_oscam : "");
2769            }
2770        }
2771        return;
2772    }
2773#endif
2774    if(cfg.http_showpicons && !apicall)
2775    {
2776        char picon_name[32];
2777        snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%s", proto);
2778        if(picon_exists(picon_name))
2779        {
2780            tpl_addVar(vars, TPLADD, "OTHER", (char *)proto);
2781            tpl_addVar(vars, TPLADD, "CLIENTPROTO", tpl_getTpl(vars, "PROTOOTHERPIC"));
2782            tpl_addVar(vars, TPLADD, "CLIENTPROTOTITLE", "");
2783        }
2784        else
2785        {
2786            tpl_addVar(vars, TPLADD, "CLIENTPROTO", (char *)proto);
2787            tpl_printf(vars, TPLADD, "CLIENTPROTOTITLE", "missing icon: IC_%s.tpl", proto);
2788        }
2789    }
2790    else
2791    {
2792        tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", (char *)proto);
2793        tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", "");
2794    }
2795}
2796
2797static void clear_account_stats(struct s_auth *account)
2798{
2799    account->cwfound = 0;
2800    account->cwcache = 0;
2801    account->cwnot = 0;
2802    account->cwtun = 0;
2803    account->cwignored  = 0;
2804    account->cwtout = 0;
2805    account->emmok = 0;
2806    account->emmnok = 0;
2807#ifdef CW_CYCLE_CHECK
2808    account->cwcycledchecked = 0;
2809    account->cwcycledok = 0;
2810    account->cwcyclednok = 0;
2811    account->cwcycledign = 0;
2812#endif
2813    cacheex_clear_account_stats(account);
2814}
2815
2816static void clear_all_account_stats(void)
2817{
2818    struct s_auth *account = cfg.account;
2819    while(account)
2820    {
2821        clear_account_stats(account);
2822        account = account->next;
2823    }
2824}
2825
2826#ifdef CS_CACHEEX
2827static void cacheex_clear_all_stats(void)
2828{
2829    struct s_auth *account = cfg.account;
2830    while(account)
2831    {
2832        cacheex_clear_account_stats(account);
2833        account = account->next;
2834    }
2835    struct s_client *cl;
2836    for(cl = first_client->next; cl ; cl = cl->next)
2837    {
2838        cacheex_clear_client_stats(cl);
2839        ll_clear_data(cl->ll_cacheex_stats);
2840    }
2841    cacheex_clear_client_stats(first_client);
2842}
2843#endif
2844
2845static void clear_system_stats(void)
2846{
2847    first_client->cwfound = 0;
2848    first_client->cwcache = 0;
2849    first_client->cwnot = 0;
2850    first_client->cwtun = 0;
2851    first_client->cwignored  = 0;
2852    first_client->cwtout = 0;
2853    first_client->emmok = 0;
2854    first_client->emmnok = 0;
2855    cacheex_clear_client_stats(first_client);
2856}
2857
2858static void kill_account_thread(struct s_auth *account)
2859{
2860    struct s_client *cl;
2861    for(cl = first_client->next; cl ; cl = cl->next)
2862    {
2863        if(cl->account == account)
2864        {
2865            if(get_module(cl)->type & MOD_CONN_NET)
2866            {
2867                kill_thread(cl);
2868            }
2869            else
2870            {
2871                cl->account = first_client->account;
2872            }
2873        }
2874    }
2875}
2876
2877static char *send_oscam_user_config(struct templatevars *vars, struct uriparams *params, int32_t apicall)
2878{
2879    struct s_auth *account;
2880    struct s_client *cl;
2881    char *user = getParam(params, "user");
2882    int32_t found = 0;
2883
2884    if(!apicall)
2885    {
2886        setActiveMenu(vars, MNU_USERS);
2887        if(cfg.http_picon_size > 0)
2888        {
2889            tpl_printf(vars, TPLADD, "HTTPPICONSIZE", "img.readericon,img.protoicon,img.usericon {height:%dpx !important;}", cfg.http_picon_size);
2890        }
2891    }
2892    if(strcmp(getParam(params, "action"), "reinit") == 0)
2893    {
2894        if(!cfg.http_readonly)
2895            { refresh_oscam(REFR_ACCOUNTS); }
2896    }
2897    if(strcmp(getParam(params, "action"), "delete") == 0)
2898    {
2899        if(cfg.http_readonly)
2900        {
2901            tpl_addMsg(vars, "WebIf is in readonly mode. No deletion will be made!");
2902        }
2903        else
2904        {
2905            struct s_auth *account_prev = NULL;
2906
2907            for(account = cfg.account; (account); account = account->next)
2908            {
2909                if(strcmp(account->usr, user) == 0)
2910                {
2911                    if(account_prev == NULL)
2912                        { cfg.account = account->next; }
2913                    else
2914                        { account_prev->next = account->next; }
2915                    ll_clear(account->aureader_list);
2916                    kill_account_thread(account);
2917                    add_garbage(account);
2918                    found = 1;
2919                    break;
2920                }
2921                account_prev = account;
2922            }
2923            if(found > 0)
2924            {
2925                if(write_userdb() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
2926            }
2927            else { tpl_addMsg(vars, "Sorry but the specified user doesn't exist. No deletion will be made!"); }
2928        }
2929    }
2930
2931    if((strcmp(getParam(params, "action"), "disable") == 0) || (strcmp(getParam(params, "action"), "enable") == 0))
2932    {
2933        account = get_account_by_name(getParam(params, "user"));
2934        if(account)
2935        {
2936            if(strcmp(getParam(params, "action"), "disable") == 0)
2937            {
2938                account->disabled = 1;
2939                kill_account_thread(account);
2940            }
2941            else
2942                { account->disabled = 0; }
2943            if(write_userdb() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
2944        }
2945        else
2946        {
2947            tpl_addMsg(vars, "Sorry but the specified user doesn't exist. No deletion will be made!");
2948        }
2949    }
2950
2951    if(strcmp(getParam(params, "action"), "resetstats") == 0)
2952    {
2953        account = get_account_by_name(getParam(params, "user"));
2954        if(account) { clear_account_stats(account); }
2955    }
2956
2957    if(strcmp(getParam(params, "action"), "resetserverstats") == 0)
2958    {
2959        clear_system_stats();
2960    }
2961
2962    if(strcmp(getParam(params, "action"), "resetalluserstats") == 0)
2963    {
2964        clear_all_account_stats();
2965    }
2966
2967    if((strcmp(getParam(params, "part"), "adduser") == 0) && (!cfg.http_readonly))
2968    {
2969        tpl_addVar(vars, TPLAPPEND, "NEWUSERFORM", tpl_getTpl(vars, "ADDNEWUSER"));
2970    }
2971    else
2972    {
2973        if(cfg.http_refresh > 0)
2974        {
2975            tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", cfg.http_refresh);
2976            tpl_addVar(vars, TPLADD, "REFRESHURL", "userconfig.html");
2977            tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
2978        }
2979    }
2980
2981    /* List accounts*/
2982    char *status, *expired, *classname, *lastchan;
2983    time_t now = time((time_t *)0);
2984    int32_t isec = 0, chsec = 0;
2985
2986    char *filter = NULL;
2987    int32_t clientcount = 0;
2988    if(apicall)
2989    {
2990        filter = getParam(params, "label");
2991    }
2992    int8_t grp_set = 0;
2993    int8_t expdate_set = 0;
2994    int32_t total_users = 0;
2995    int32_t disabled_users = 0;
2996    int32_t expired_users = 0;
2997    int32_t active_users = 0;
2998    int32_t connected_users = 0;
2999    int32_t online_users = 0;
3000    int8_t isactive;
3001    int32_t casc_users = 0;
3002    int32_t casc_users2 = 0;
3003    int32_t n_request = 0;
3004   
3005    for(account = cfg.account; (account); account = account->next)
3006    {
3007        if(account->expirationdate){
3008            expdate_set = 1;
3009        }
3010       
3011        if(account->next){
3012            if(account->grp != account->next->grp){
3013                grp_set = 1;
3014            }
3015        }
3016        if(expdate_set && grp_set)
3017        break;
3018    }
3019   
3020    for(account = cfg.account; (account); account = account->next)
3021    {
3022        //clear for next client
3023        total_users++;
3024        isactive = 1;
3025
3026        status = "offline";
3027        expired = "";
3028        classname = "offline";
3029        isec = 0;
3030        chsec = 0;
3031
3032        //reset caid/srevid template variables
3033        tpl_addVar(vars, TPLADD, "CLIENTCAID", "");
3034        tpl_addVar(vars, TPLADD, "CLIENTSRVID", "");
3035        tpl_addVar(vars, TPLADD, "LASTCHANNEL", "");
3036
3037        if(account->expirationdate && account->expirationdate < now)
3038        {
3039            expired = " (expired)";
3040            classname = "expired";
3041            expired_users++;
3042            isactive = 0;
3043        }
3044        else
3045        {
3046            expired = "";
3047        }
3048
3049        if(account->disabled != 0)
3050        {
3051            expired = " (disabled)";
3052            classname = "disabled";
3053            tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICENA");
3054            tpl_addVar(vars, TPLADD, "SWITCHTITLE", "Enable this account");
3055            tpl_addVar(vars, TPLADD, "SWITCH", "enable");
3056            disabled_users++;
3057            isactive = 0;
3058        }
3059        else
3060        {
3061            tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICDIS");
3062            tpl_addVar(vars, TPLADD, "SWITCHTITLE", "Disable this account");
3063            tpl_addVar(vars, TPLADD, "SWITCH", "disable");
3064        }
3065
3066        if(isactive)
3067            { active_users++; }
3068
3069        int32_t lastresponsetm = 0, latestactivity = 0;
3070        const char *proto = "";
3071        double cwrate = 0.0, cwrate2 = 0.0;
3072
3073        //search account in active clients
3074        isactive = 0;
3075        int16_t nrclients = 0;
3076        struct s_client *latestclient = NULL;
3077        for(cl = first_client->next; cl ; cl = cl->next)
3078        {
3079            if(cl->account && !strcmp(cl->account->usr, account->usr))
3080            {
3081                if(cl->lastecm > latestactivity || cl->login > latestactivity)
3082                {
3083                    if(cl->lastecm > cl->login) { latestactivity = cl->lastecm; }
3084                    else { latestactivity = cl->login; }
3085                    latestclient = cl;
3086                }
3087                nrclients++;
3088            }
3089        }
3090        if(account->cwfound + account->cwnot + account->cwcache > 0)
3091        {
3092            cwrate = now - account->firstlogin;
3093            cwrate /= (account->cwfound + account->cwnot + account->cwcache);
3094        }
3095
3096        casc_users = 0;
3097        casc_users2 = 0;
3098        int8_t conn = 0;
3099        if(latestclient != NULL)
3100        {
3101            char channame[32];
3102            status = (!apicall) ? "<B>connected</B>" : "connected";
3103            if(account->expirationdate && account->expirationdate < now) { classname = "expired"; }
3104            else { classname = "connected";conn = 1; }
3105
3106            proto = client_get_proto(latestclient);
3107            int clientcaid = latestclient->last_caid;
3108            int clientsrvid = latestclient->last_srvid;
3109            tpl_printf(vars, TPLADD, "CLIENTCAID", "%04X", clientcaid);
3110            tpl_printf(vars, TPLADD, "CLIENTSRVID", "%04X", clientsrvid);
3111
3112            if(clientsrvid != NO_SRVID_VALUE || clientcaid != NO_CAID_VALUE)
3113            {
3114                lastchan = xml_encode(vars, get_servicename(latestclient, clientsrvid, clientcaid, channame));
3115            }
3116            else
3117            {
3118                lastchan = "";
3119            }
3120
3121            if(cfg.http_showpicons && !apicall)
3122            {
3123                char picon_name[32];
3124                snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%04X_%04X", clientcaid, clientsrvid);
3125                int8_t picon_ok = picon_exists(picon_name);
3126                if(!picon_ok)
3127                {
3128                    snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "0000_%04X", clientsrvid);
3129                    picon_ok = picon_exists(picon_name);
3130                }
3131                if(picon_ok)
3132                {
3133                    tpl_addVar(vars, TPLADDONCE, "LCA", picon_name);
3134                    tpl_addVar(vars, TPLADDONCE, "LCB", lastchan);
3135                    tpl_addVar(vars, TPLADDONCE, "LASTCHANNELTITLE", lastchan);
3136                    tpl_addVar(vars, TPLADDONCE, "LASTCHANNEL", tpl_getTpl(vars, "USERCONFIGLASTCHANEL"));
3137                }
3138                else
3139                {
3140                    tpl_addVar(vars, TPLADDONCE, "LASTCHANNEL", lastchan);
3141                    tpl_printf(vars, TPLADDONCE, "LASTCHANNELTITLE", "missing icon: IC_%s.tpl", picon_name);
3142                }
3143            }
3144            else
3145            {
3146                tpl_addVar(vars, TPLADDONCE, "LASTCHANNEL", lastchan);
3147                tpl_addVar(vars, TPLADDONCE, "LASTCHANNELTITLE", lastchan);
3148            }
3149
3150            lastresponsetm = latestclient->cwlastresptime;
3151            tpl_addVar(vars, TPLADDONCE, "CLIENTIP", cs_inet_ntoa(latestclient->ip));
3152            connected_users++;
3153            casc_users = ll_count(latestclient->cascadeusers);
3154            LL_ITER it = ll_iter_create(latestclient->cascadeusers);
3155            struct s_cascadeuser *cu;
3156            while((cu = ll_iter_next(&it)))
3157            {
3158                if(cu->cwrate > 0)
3159                    { casc_users2++; }
3160            }
3161            if(latestactivity > 0)
3162            {
3163                isec = now - latestactivity;
3164                chsec = latestclient->lastswitch ? now - latestclient->lastswitch : 0;
3165                if(isec < cfg.hideclient_to)
3166                {
3167                    isactive = 1;
3168                    status = (!apicall) ? "<B>online</B>" : "online";
3169                    if(account->expirationdate && account->expirationdate < now) { classname = "expired"; }
3170                    else { classname = "online"; }
3171                    if(latestclient->cwfound + latestclient->cwnot + latestclient->cwcache > 0)
3172                    {
3173                        cwrate2 = now - latestclient->login;
3174                        cwrate2 /= (latestclient->cwfound + latestclient->cwnot + latestclient->cwcache);
3175                        tpl_printf(vars, TPLADDONCE, "CWRATE2", " (%.2f)", cwrate2);
3176                        online_users++;
3177                    }
3178                }
3179            }
3180        }
3181
3182        n_request = 0;
3183        if(latestclient != NULL){
3184            n_request = latestclient->n_request[0];
3185        }
3186
3187        tpl_addVar(vars, TPLADD, "EXPIREVIEW", expdate_set ? "" : "exp");
3188        tpl_addVar(vars, TPLADD, "GRPVIEW", grp_set ? "" : "grp");
3189#ifdef CS_ANTICASC
3190        tpl_addVar(vars, TPLADD, "ANTICASCVIEW", cfg.ac_enabled ? "" : "acasc");
3191#endif
3192        tpl_printf(vars, TPLADD, "CWOK", "%d", account->cwfound);
3193        tpl_printf(vars, TPLADD, "CWNOK", "%d", account->cwnot);
3194        tpl_printf(vars, TPLADD, "CWIGN", "%d", account->cwignored);
3195        tpl_printf(vars, TPLADD, "CWTOUT", "%d", account->cwtout);
3196#ifdef CW_CYCLE_CHECK
3197        tpl_addVar(vars, TPLADD, "CWCCYCVIEW", cfg.cwcycle_check_enable ? "" : "cwc");
3198        tpl_printf(vars, TPLADD, "CWCYCLECHECKED", "%d", account->cwcycledchecked);
3199        tpl_printf(vars, TPLADD, "CWCYCLEOK", "%d", account->cwcycledok);
3200        tpl_printf(vars, TPLADD, "CWCYCLENOK", "%d", account->cwcyclednok);
3201        tpl_printf(vars, TPLADD, "CWCYCLEIGN", "%d", account->cwcycledign);
3202#endif
3203        tpl_printf(vars, TPLADD, "CWCACHE", "%d", account->cwcache);
3204        tpl_printf(vars, TPLADD, "CWTUN", "%d", account->cwtun);
3205        tpl_printf(vars, TPLADD, "EMMOK", "%d", account->emmok);
3206        tpl_printf(vars, TPLADD, "EMMNOK", "%d", account->emmnok);
3207        tpl_printf(vars, TPLADD, "CWRATE", "%.2f", cwrate);
3208        tpl_printf(vars, TPLADD, "CASCUSERS", "%d", casc_users);
3209        tpl_printf(vars, TPLADD, "CASCUSERS2", "%d", casc_users2);
3210        tpl_printf(vars, TPLADD, "CASCUSERSCOMB", "%d/%d", casc_users, casc_users2);
3211        tpl_printf(vars, TPLADD, "N_REQUEST_MIN", "%d", n_request);
3212
3213        if(isactive > 0 || !cfg.http_hide_idle_clients)
3214        {
3215
3216            tpl_printf(vars, TPLADDONCE, "CWLASTRESPONSET", "%d", lastresponsetm);
3217            tpl_addVar(vars, TPLADDONCE, "IDLESECS", sec2timeformat(vars, isec));
3218
3219            if(isactive > 0)
3220            {
3221                tpl_printf(vars, TPLADDONCE, "CLIENTTIMEONCHANNELAPI", "%d", chsec);
3222                tpl_addVar(vars, TPLADDONCE, "CLIENTTIMEONCHANNEL", sec2timeformat(vars, chsec));
3223                if(account->tosleep)
3224                {
3225                    tpl_printf(vars, TPLADDONCE, "CLIENTTIMETOSLEEP", "Sleeping in %d minutes", account->tosleep - (chsec / 60));
3226                    tpl_printf(vars, TPLADDONCE, "CLIENTTIMETOSLEEPAPI", "%d", account->tosleep - (chsec / 60));
3227                }
3228                else
3229                {
3230                    tpl_addVar(vars, TPLADDONCE, "CLIENTTIMETOSLEEP", "No sleep defined");
3231                    tpl_addVar(vars, TPLADDONCE, "CLIENTTIMETOSLEEPAPI", "undefined");
3232                }
3233            }
3234            else
3235            {
3236                if (conn > 0)
3237                {
3238                    tpl_addVar(vars, TPLADDONCE, "IDLESECS", sec2timeformat(vars, isec));
3239                }
3240                else
3241                {
3242                    tpl_addVar(vars, TPLADDONCE, "IDLESECS", "");
3243                }
3244                tpl_addVar(vars, TPLADDONCE, "CLIENTTIMEONCHANNELAPI", "");
3245                tpl_addVar(vars, TPLADDONCE, "CLIENTTIMEONCHANNEL", "");
3246                tpl_addVar(vars, TPLADDONCE, "CLIENTTIMETOSLEEP", "");
3247                tpl_addVar(vars, TPLADDONCE, "CLIENTTIMETOSLEEPAPI", "");
3248            }
3249
3250            webif_add_client_proto(vars, latestclient, proto, apicall);
3251        }
3252        else
3253        {
3254            if (conn > 0)
3255            {
3256                tpl_addVar(vars, TPLADDONCE, "IDLESECS", sec2timeformat(vars, isec));
3257            }
3258            else
3259            {
3260                tpl_addVar(vars, TPLADDONCE, "IDLESECS", "");
3261            }
3262            tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", "");
3263        }
3264
3265        tpl_addVar(vars, TPLADD, "CLASSNAME", classname);
3266        tpl_addVar(vars, TPLADD, "USERNAME", xml_encode(vars, account->usr));
3267        tpl_addVar(vars, TPLADD, "USERNAMEENC", urlencode(vars, account->usr));
3268
3269        static const char *user_tpl_name = "USERLABEL";
3270        if(cfg.http_showpicons && !apicall)
3271            user_tpl_name = picon_exists(xml_encode(vars, account->usr)) ? "USERICON" : "USERNOICON";
3272        tpl_addVar(vars, TPLADD, "USERBIT", tpl_getTpl(vars, user_tpl_name));
3273
3274        char *value = mk_t_group(account->grp);
3275        tpl_addVar(vars, TPLADD, "GROUPS", value);
3276        free_mk_t(value);
3277        tpl_addVar(vars, TPLADD, "DESCRIPTION", xml_encode(vars, account->description ? account->description : ""));
3278        tpl_addVar(vars, TPLADD, "STATUS", status);
3279        tpl_addVar(vars, TPLAPPEND, "STATUS", expired);
3280
3281        if(nrclients > 1)
3282        {
3283            tpl_printf(vars, TPLADD, "UNOTIFY", "%d", nrclients);
3284            tpl_addVar(vars, TPLADDONCE, "CLIENTCOUNTNOTIFIER", tpl_getTpl(vars, "CLIENTCOUNTNOTIFIERBIT"));
3285        }
3286
3287        //Expirationdate
3288        struct tm timeinfo;
3289        cs_gmtime_r(&account->expirationdate, &timeinfo);
3290        char buf [80];
3291        strftime(buf, 80, "%Y-%m-%d", &timeinfo);
3292        if(strcmp(buf, "1970-01-01")) { tpl_addVar(vars, TPLADD, "EXPDATE", buf); }
3293        else { tpl_addVar(vars, TPLADD, "EXPDATE", ""); }
3294
3295        // append row to table template
3296        if(!apicall)
3297            { tpl_addVar(vars, TPLAPPEND, "USERCONFIGS", tpl_getTpl(vars, "USERCONFIGLISTBIT")); }
3298        else if(!filter || strcmp(filter, account->usr) == 0 || strcmp(filter, "all") == 0 || strlen(filter) == 0)
3299        {
3300            tpl_addVar(vars, TPLAPPEND, "APIUSERCONFIGS", tpl_getTpl(vars, "APIUSERCONFIGLISTBIT"));
3301            ++clientcount;
3302        }
3303    }
3304
3305    tpl_printf(vars, TPLADD, "TOTAL_USERS", "%d", total_users);
3306    tpl_printf(vars, TPLADD, "TOTAL_DISABLED", "%d", disabled_users);
3307    tpl_printf(vars, TPLADD, "TOTAL_EXPIRED", "%d", expired_users);
3308    tpl_printf(vars, TPLADD, "TOTAL_ACTIVE", "%d", active_users);
3309    tpl_printf(vars, TPLADD, "TOTAL_CONNECTED", "%d", connected_users);
3310    tpl_printf(vars, TPLADD, "TOTAL_ONLINE", "%d", online_users);
3311
3312
3313    float ecmsum = first_client->cwfound + first_client->cwnot + first_client->cwtout + first_client->cwcache; //dont count TUN its included
3314    if(ecmsum < 1)  ecmsum = 1;
3315    float ecmpos = first_client->cwfound + first_client->cwcache; // dont count TUN its included
3316    if(ecmpos < 1) ecmpos = 1;
3317    float ecmneg = first_client->cwnot + first_client->cwignored + first_client->cwtout;
3318    if(ecmneg < 1) ecmneg = 1;
3319
3320    //if one of the stats overloaded, reset all stats!
3321    if(first_client->cwfound<0
3322      || first_client->cwnot<0
3323      || first_client->cwignored<0
3324      || first_client->cwtout<0
3325      || first_client->cwcache<0
3326      || first_client->cwtun<0
3327      || first_client->emmok<0
3328      || first_client->emmnok<0
3329#ifdef CS_CACHEEX
3330      || first_client->cwcacheexgot<0
3331      || first_client->cwcacheexpush<0
3332      || first_client->cwcacheexhit<0
3333#endif
3334      || (first_client->cwfound * 100 / ecmsum)<0
3335      || (first_client->cwnot * 100 / ecmsum)<0
3336      || (first_client->cwignored * 100 / ecmsum)<0
3337      || (first_client->cwtout * 100 / ecmsum)<0
3338      || (first_client->cwcache * 100 / ecmsum)<0
3339      || (first_client->cwtun * 100 / ecmsum)<0
3340      || ((first_client->cwfound + first_client->cwcache) * 100 / ecmsum)<0
3341      || ((first_client->cwnot + first_client->cwignored + first_client->cwtout) * 100 / ecmsum)<0
3342      || (first_client->cwfound * 100 / ecmpos)<0
3343      || (first_client->cwcache * 100 / ecmpos)<0
3344      || (first_client->cwnot * 100 / ecmneg)<0
3345      || (first_client->cwignored * 100 / ecmneg)<0
3346      || (first_client->cwtout * 100 / ecmneg)<0
3347    ){
3348        clear_system_stats();
3349        ecmsum = 1;
3350        ecmpos = 1;
3351        ecmneg = 1;
3352    }
3353    //end reset stats
3354
3355    tpl_printf(vars, TPLADD, "TOTAL_ECM_MIN", "%d", first_client->n_request[0]);
3356    tpl_printf(vars, TPLADD, "TOTAL_CW", "%d", (int)ecmsum);
3357    tpl_printf(vars, TPLADD, "TOTAL_CWOK", "%d", first_client->cwfound);
3358    tpl_printf(vars, TPLADD, "TOTAL_CWNOK", "%d", first_client->cwnot);
3359    tpl_printf(vars, TPLADD, "TOTAL_CWIGN", "%d", first_client->cwignored);
3360    tpl_printf(vars, TPLADD, "TOTAL_CWTOUT", "%d", first_client->cwtout);
3361    tpl_printf(vars, TPLADD, "TOTAL_CWCACHE", "%d", first_client->cwcache);
3362    tpl_printf(vars, TPLADD, "TOTAL_CWTUN", "%d", first_client->cwtun);
3363    tpl_printf(vars, TPLADD, "TOTAL_CWPOS", "%d", first_client->cwfound + first_client->cwcache);
3364    tpl_printf(vars, TPLADD, "TOTAL_CWNEG", "%d", first_client->cwnot + first_client->cwtout);
3365
3366    tpl_printf(vars, TPLADD, "REL_CWOK", "%.2f", first_client->cwfound * 100 / ecmsum);
3367    tpl_printf(vars, TPLADD, "REL_CWNOK", "%.2f", first_client->cwnot * 100 / ecmsum);
3368    tpl_printf(vars, TPLADD, "REL_CWIGN", "%.2f", first_client->cwignored * 100 / ecmsum);
3369    tpl_printf(vars, TPLADD, "REL_CWTOUT", "%.2f", first_client->cwtout * 100 / ecmsum);
3370    tpl_printf(vars, TPLADD, "REL_CWCACHE", "%.2f", first_client->cwcache * 100 / ecmsum);
3371    tpl_printf(vars, TPLADD, "REL_CWTUN", "%.2f", first_client->cwtun * 100 / ecmsum);
3372    tpl_printf(vars, TPLADD, "REL_CWPOS", "%.2f", (first_client->cwfound + first_client->cwcache) * 100 / ecmsum);
3373    tpl_printf(vars, TPLADD, "REL_CWNEG", "%.2f", (first_client->cwnot + first_client->cwtout) * 100 / ecmsum);
3374    tpl_printf(vars, TPLADD, "REL_CWPOSOK", "%.2f", first_client->cwfound * 100 / ecmpos);
3375    tpl_printf(vars, TPLADD, "REL_CWPOSCACHE", "%.2f", first_client->cwcache * 100 / ecmpos);
3376    tpl_printf(vars, TPLADD, "REL_CWNEGNOK", "%.2f", first_client->cwnot * 100 / ecmneg);
3377    tpl_printf(vars, TPLADD, "REL_CWNEGIGN", "%.2f", first_client->cwignored * 100 / ecmneg);
3378    tpl_printf(vars, TPLADD, "REL_CWNEGTOUT", "%.2f", first_client->cwtout * 100 / ecmneg);
3379
3380    if(!apicall)
3381        { return tpl_getTpl(vars, "USERCONFIGLIST"); }
3382    else
3383    {
3384        if(!filter || clientcount > 0)
3385        {
3386            return tpl_getTpl(vars, "APIUSERCONFIGLIST");
3387        }
3388        else
3389        {
3390            tpl_printf(vars, TPLADD, "APIERRORMESSAGE", "Invalid client %s", xml_encode(vars, filter));
3391            return tpl_getTpl(vars, "APIERROR");
3392        }
3393    }
3394
3395}
3396
3397#define ENTITLEMENT_PAGE_SIZE 500
3398
3399#ifdef MODULE_CCCSHARE
3400static char *get_cardsystem_desc_by_caid(uint16_t caid)
3401{
3402    if(caid >= 0x0100 && caid <= 0x01FF) { return "seca"; }
3403    if(caid >= 0x0500 && caid <= 0x05FF) { return "viaccess"; }
3404    if(caid >= 0x0600 && caid <= 0x06FF) { return "irdeto"; }
3405    if(caid >= 0x0900 && caid <= 0x09FF) { return "videoguard"; }
3406    if(caid >= 0x0B00 && caid <= 0x0BFF) { return "conax"; }
3407    if(caid >= 0x0D00 && caid <= 0x0DFF) { return "cryptoworks"; }
3408    if(caid >= 0x1700 && caid <= 0x17FF) { return "betacrypt"; }
3409    if(caid >= 0x1800 && caid <= 0x18FF) { return "nagra"; }
3410    if(caid >= 0x4B00 && caid <= 0x4BFF) { return "tongfang"; }
3411    if(caid >= 0x4AE0 && caid <= 0x4AE1) { return "drecrypt"; }
3412    if(caid == 0x5581 || caid == 0x4AEE) { return "bulcrypt"; }
3413    if(caid == 0x5501 || caid == 0x5504 || caid == 0x5511) { return "griffin"; }
3414    if(caid == 0x4ABF) { return "dgcrypt"; }
3415    return "???";
3416}
3417
3418static void print_cards(struct templatevars *vars, struct uriparams *params, struct cc_card **cardarray, int32_t cardsize,
3419                        int8_t show_global_list, struct s_reader *rdr, int32_t offset, int32_t apicall)
3420{
3421    if(cardarray)
3422    {
3423        uint8_t serbuf[8];
3424        int32_t i, count = 0;
3425        char provname[83];
3426        struct cc_card *card;
3427        int32_t cardcount = 0;
3428        int32_t providercount = 0;
3429        int32_t nodecount = 0;
3430
3431        char *provider = "";
3432
3433        // @todo alno: sort by click, 0=ascending, 1=descending (maybe two buttons or reverse on second click)
3434        for(i = offset; i < cardsize; ++i)
3435        {
3436            card = cardarray[i];
3437            if(count == ENTITLEMENT_PAGE_SIZE)
3438                { break; }
3439            count++;
3440
3441            if(!apicall)
3442            {
3443                if(show_global_list)
3444                    { rdr = card->origin_reader; }
3445                if(rdr)
3446                    { tpl_printf(vars, TPLADD, "HOST", "%s:%d", xml_encode(vars, rdr->device), rdr->r_port); }
3447                tpl_printf(vars, TPLADD, "CAID", "%04X", card->caid);
3448                tpl_printf(vars, TPLADD, "CARDTYPE", "%02X", card->card_type);
3449            }
3450            else
3451            {
3452                tpl_printf(vars, TPLADD, "APICARDNUMBER", "%d", cardcount);
3453                tpl_printf(vars, TPLADD, "APICAID", "%04X", card->caid);
3454                tpl_printf(vars, TPLADD, "APICARDTYPE", "%02X", card->card_type);
3455            }
3456
3457            if(cc_UA_valid(card->hexserial))    //Add UA:
3458            {
3459                cc_UA_cccam2oscam(card->hexserial, serbuf, card->caid);
3460                char tmp[20];
3461                tpl_printf(vars, TPLAPPEND, "HOST", "<BR>\nUA_Oscam:%s", cs_hexdump(0, serbuf, 8, tmp, 20));
3462                tpl_printf(vars, TPLAPPEND, "HOST", "<BR>\nUA_CCcam:%s", cs_hexdump(0, card->hexserial, 8, tmp, 20));
3463            }
3464            if(!apicall)
3465            {
3466                int32_t n;
3467                LL_ITER its = ll_iter_create(card->goodsids);
3468                struct cc_srvid *srv;
3469                n = 0;
3470                tpl_addVar(vars, TPLADD, "SERVICESGOOD", "");
3471                while((srv = ll_iter_next(&its)))
3472                {
3473                    tpl_printf(vars, TPLAPPEND, "SERVICESGOOD", "%04X%s", srv->sid, ++n % 10 == 0 ? "<BR>\n" : " ");
3474                }
3475
3476                its = ll_iter_create(card->badsids);
3477                n = 0;
3478                tpl_addVar(vars, TPLADD, "SERVICESBAD", "");
3479                while((srv = ll_iter_next(&its)))
3480                {
3481                    tpl_printf(vars, TPLAPPEND, "SERVICESBAD", "%04X%s", srv->sid, ++n % 10 == 0 ? "<BR>\n" : " ");
3482                }
3483            }
3484
3485            tpl_addVar(vars, TPLADD, "SYSTEM", get_cardsystem_desc_by_caid(card->caid));
3486
3487            tpl_printf(vars, TPLADD, "SHAREID", "%08X", card->id);
3488            tpl_printf(vars, TPLADD, "REMOTEID", "%08X", card->remote_id);
3489            tpl_printf(vars, TPLADD, "UPHOPS", "%d", card->hop);
3490            tpl_printf(vars, TPLADD, "MAXDOWN", "%d", card->reshare);
3491
3492            LL_ITER pit = ll_iter_create(card->providers);
3493            struct cc_provider *prov;
3494
3495            providercount = 0;
3496
3497            if(!apicall)
3498                { tpl_addVar(vars, TPLADD, "PROVIDERS", ""); }
3499            else
3500                { tpl_addVar(vars, TPLADD, "PROVIDERLIST", ""); }
3501
3502            while((prov = ll_iter_next(&pit)))
3503            {
3504                provider = xml_encode(vars, get_provider(card->caid, prov->prov, provname, sizeof(provname)));
3505
3506                if(!apicall)
3507                {
3508                    if(prov->sa[0] || prov->sa[1] || prov->sa[2] || prov->sa[3])
3509                    {
3510                        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]);
3511                    }
3512                    else
3513                    {
3514                        tpl_printf(vars, TPLAPPEND, "PROVIDERS", "%s<BR>\n", provider);
3515                    }
3516                }
3517                else
3518                {
3519                    if(prov->sa[0] || prov->sa[1] || prov->sa[2] || prov->sa[3])
3520                        { tpl_printf(vars, TPLADD, "APIPROVIDERSA", "%02X%02X%02X%02X", prov->sa[0], prov->sa[1], prov->sa[2], prov->sa[3]); }
3521                    else
3522                        { tpl_addVar(vars, TPLADD, "APIPROVIDERSA", ""); }
3523                    tpl_printf(vars, TPLADD, "APIPROVIDERCAID", "%04X", card->caid);
3524                    tpl_printf(vars, TPLADD, "APIPROVIDERPROVID", "%06X", prov->prov);
3525                    tpl_printf(vars, TPLADD, "APIPROVIDERNUMBER", "%d", providercount);
3526                    tpl_addVar(vars, TPLADD, "APIPROVIDERNAME", xml_encode(vars, provider));
3527                    tpl_addVar(vars, TPLAPPEND, "PROVIDERLIST", tpl_getTpl(vars, "APICCCAMCARDPROVIDERBIT"));
3528
3529                }
3530                providercount++;
3531                tpl_printf(vars, TPLADD, "APITOTALPROVIDERS", "%d", providercount);
3532            }
3533
3534            LL_ITER nit = ll_iter_create(card->remote_nodes);
3535            uint8_t *node;
3536
3537            nodecount = 0;
3538            if(!apicall) { tpl_addVar(vars, TPLADD, "NODES", ""); }
3539            else { tpl_addVar(vars, TPLADD, "NODELIST", ""); }
3540
3541            while((node = ll_iter_next(&nit)))
3542            {
3543
3544                if(!apicall)
3545                {
3546                    tpl_printf(vars, TPLAPPEND, "NODES", "%02X%02X%02X%02X%02X%02X%02X%02X<BR>\n",
3547                               node[0], node[1], node[2], node[3], node[4], node[5], node[6], node[7]);
3548                }
3549                else
3550                {
3551                    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]);
3552                    tpl_printf(vars, TPLADD, "APINODENUMBER", "%d", nodecount);
3553                    tpl_addVar(vars, TPLAPPEND, "NODELIST", tpl_getTpl(vars, "APICCCAMCARDNODEBIT"));
3554                }
3555                nodecount++;
3556                tpl_printf(vars, TPLADD, "APITOTALNODES", "%d", nodecount);
3557            }
3558
3559            if(!apicall)
3560                { tpl_addVar(vars, TPLAPPEND, "CCCAMSTATSENTRY", tpl_getTpl(vars, "ENTITLEMENTCCCAMENTRYBIT")); }
3561            else
3562                { tpl_addVar(vars, TPLAPPEND, "CARDLIST", tpl_getTpl(vars, "APICCCAMCARDBIT")); }
3563
3564            cardcount++;
3565        }
3566        // set previous Link if needed
3567        if(offset >= ENTITLEMENT_PAGE_SIZE)
3568        {
3569            tpl_printf(vars, TPLAPPEND, "CONTROLS", "<A HREF=\"entitlements.html?offset=%d&globallist=%s&amp;label=%s\"> << PREVIOUS < </A>",
3570                       offset - ENTITLEMENT_PAGE_SIZE,
3571                       getParam(params, "globallist"),
3572                       urlencode(vars, getParam(params, "label")));
3573        }
3574
3575        // set next link if needed
3576        if(cardsize > count && offset < cardsize)
3577        {
3578            tpl_printf(vars, TPLAPPEND, "CONTROLS", "<A HREF=\"entitlements.html?offset=%d&globallist=%s&amp;label=%s\"> > NEXT >> </A>",
3579                       offset + ENTITLEMENT_PAGE_SIZE,
3580                       getParam(params, "globallist"),
3581                       urlencode(vars, getParam(params, "label")));
3582        }
3583
3584        if(!apicall)
3585        {
3586            tpl_printf(vars, TPLADD, "TOTALS", "card count=%d", cardsize);
3587            tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTCCCAMBIT"));
3588        }
3589        else
3590        {
3591            tpl_printf(vars, TPLADD, "APITOTALCARDS", "%d", cardsize);
3592        }
3593
3594    }
3595    else
3596    {
3597        if(!apicall)
3598        {
3599            tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTGENERICBIT"));
3600            tpl_addVar(vars, TPLADD, "LOGHISTORY", "no cards found<BR>\n");
3601        }
3602        else
3603        {
3604            tpl_printf(vars, TPLADD, "APITOTALCARDS", "%d", 0);
3605        }
3606    }
3607
3608}
3609#endif
3610
3611static char *send_oscam_entitlement(struct templatevars *vars, struct uriparams *params, int32_t apicall)
3612{
3613    if(!apicall) { setActiveMenu(vars, MNU_READERS); }
3614    char *reader_ = getParam(params, "label");
3615#ifdef MODULE_CCCAM
3616    char *sharelist_ = getParam(params, "globallist");
3617    int32_t show_global_list = sharelist_ && sharelist_[0] == '1';
3618
3619    struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
3620    if(show_global_list || strlen(reader_) || (rdr && rdr->typ == R_CCCAM))
3621    {
3622
3623        if(show_global_list || (rdr && rdr->typ == R_CCCAM && rdr->enable))
3624        {
3625
3626            if(show_global_list)
3627            {
3628                tpl_addVar(vars, TPLADD, "READERNAME", "GLOBAL");
3629                tpl_addVar(vars, TPLADD, "APIHOST", "GLOBAL");
3630                tpl_addVar(vars, TPLADD, "APIHOSTPORT", "GLOBAL");
3631            }
3632            else
3633            {
3634                tpl_addVar(vars, TPLADD, "READERNAME", xml_encode(vars, rdr->label));
3635                tpl_addVar(vars, TPLADD, "APIHOST", xml_encode(vars, rdr->device));
3636                tpl_printf(vars, TPLADD, "APIHOSTPORT", "%d", rdr->r_port);
3637            }
3638
3639#ifdef MODULE_CCCSHARE
3640            int32_t offset = atoi(getParam(params, "offset")); //should be 0 if parameter is missed on very first call
3641            int32_t cardsize;
3642            if(show_global_list)
3643            {
3644                int32_t i;
3645                LLIST **sharelist = get_and_lock_sharelist();
3646                LLIST *sharelist2 = ll_create("web-sharelist");
3647                for(i = 0; i < CAID_KEY; i++)
3648                {
3649                    if(sharelist[i])
3650                        { ll_putall(sharelist2, sharelist[i]); }
3651                }
3652                unlock_sharelist();
3653                struct cc_card **cardarray = get_sorted_card_copy(sharelist2, 0, &cardsize);
3654                ll_destroy(sharelist2);
3655                print_cards(vars, params, cardarray, cardsize, 1, NULL, offset, apicall);
3656                NULLFREE(cardarray);
3657            }
3658            else
3659            {
3660                struct s_client *rc = rdr->client;
3661                struct cc_data *rcc = (rc) ? rc->cc : NULL;
3662                if(rcc && rcc->cards)
3663                {
3664                    struct cc_card **cardarray = get_sorted_card_copy(rcc->cards, 0, &cardsize);
3665                    print_cards(vars, params, cardarray, cardsize, 0, rdr, offset, apicall);
3666                    NULLFREE(cardarray);
3667                }
3668            }
3669#endif
3670
3671        }
3672        else
3673        {
3674#else
3675    if(strlen(reader_))
3676    {
3677        {
3678            struct s_reader *rdr;
3679#endif
3680            tpl_addVar(vars, TPLADD, "LOGHISTORY", "->");
3681            // normal non-cccam reader
3682
3683            rdr = get_reader_by_label(reader_);
3684
3685            if(rdr)
3686            {
3687                struct s_client *cl = rdr->client;
3688                if(rdr->ll_entitlements)
3689                {
3690
3691                    time_t now = time((time_t *)0);
3692
3693                    struct tm start_t, end_t;
3694                    LL_ITER itr = ll_iter_create(rdr->ll_entitlements);
3695                    S_ENTITLEMENT *item;
3696
3697                    tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", "<BR><BR>New Structure:<BR>");
3698                    char tbuffer[83];
3699                    while((item = ll_iter_next(&itr)))
3700                    {
3701
3702                        localtime_r(&item->start, &start_t);
3703                        localtime_r(&item->end, &end_t);
3704
3705                        if(!apicall)
3706                            { strftime(tbuffer, 30, "%Y-%m-%d", &start_t); }
3707                        else
3708                            { strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &start_t); }
3709                        tpl_addVar(vars, TPLADD, "ENTSTARTDATE", tbuffer);
3710
3711                        if(!apicall)
3712                            { strftime(tbuffer, 30, "%Y-%m-%d", &end_t); }
3713                        else
3714                            { strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &end_t); }
3715                        tpl_addVar(vars, TPLADD, "ENTENDDATE", tbuffer);
3716
3717                        tpl_addVar(vars, TPLADD, "ENTEXPIERED", item->end > now ? "e_valid" : "e_expired");
3718                        tpl_printf(vars, TPLADD, "ENTCAID", "%04X", item->caid);
3719                        tpl_printf(vars, TPLADD, "ENTPROVID", "%06X", item->provid);
3720                        tpl_printf(vars, TPLADD, "ENTID", "%08X%08X", (uint32_t)(item->id >> 32), (uint32_t)item->id);
3721                        tpl_printf(vars, TPLADD, "ENTCLASS", "%08X", item->class);
3722                        tpl_addVar(vars, TPLADD, "ENTTYPE", entitlement_type[item->type]);
3723
3724                        char *entresname;
3725                        entresname = xml_encode(vars, get_tiername((uint16_t)(item->id & 0xFFFF), item->caid, tbuffer));
3726                        if(!tbuffer[0])
3727                            { entresname = xml_encode(vars, get_provider(item->caid, item->provid, tbuffer, sizeof(tbuffer))); }
3728                        tpl_addVar(vars, TPLADD, "ENTRESNAME", entresname);
3729
3730                        if((strcmp(getParam(params, "hideexpired"), "1") != 0) || (item->end > now))
3731                            { tpl_addVar(vars, TPLAPPEND, "READERENTENTRY", tpl_getTpl(vars, "ENTITLEMENTITEMBIT")); }
3732
3733                    }
3734                }
3735
3736                if(cl && cl->typ)
3737                    { tpl_printf(vars, TPLADD, "READERTYPE", "%c", cl->typ); }
3738                else
3739                    { tpl_addVar(vars, TPLADD, "READERTYPE", "null"); }
3740                tpl_addVar(vars, TPLADD, "READERNAME", xml_encode(vars, rdr->label));
3741
3742                int8_t i, j;
3743                for(i = 0; i < 15; i++) { tpl_printf(vars, TPLAPPEND, "READERROM", "%c", rdr->rom[i]); }
3744                if(rdr->hexserial[0] || rdr->hexserial[1]) { i = 0; }
3745                else { i = 2; }
3746                if(rdr->hexserial[6] || rdr->hexserial[7]) { j = 8; }
3747                else { j = 6; }
3748                for(; i < j; i++)   { tpl_printf(vars, TPLAPPEND, "READERSERIAL", "%02X%s", rdr->hexserial[i], i < j - 1 ? " " : ""); }
3749                for(i = 0; i < rdr->nprov; i++)
3750                {
3751                    for(j = 0; j < 4; j++)  { tpl_printf(vars, TPLAPPEND, "READERPROVIDS", "%02X ", rdr->prid[i][j]); }
3752                    tpl_addVar(vars, TPLAPPEND, "READERPROVIDS", i == 0 ? "(sysid)<BR>\n" : "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>\n");
3753                }
3754
3755                //regional code for Vg card
3756                if(rdr->VgRegionC[0])
3757                {
3758                    for(i = 0; i < 8; i++) { tpl_printf(vars, TPLAPPEND, "READER_RCODE", "%c", rdr->VgRegionC[i]); }
3759                }
3760                else
3761                {
3762                    tpl_addVar(vars, TPLADD, "READER_RCODE", "n/a");
3763                }
3764
3765                //Pin Vg card
3766                if(rdr->VgPin)
3767                {
3768                    tpl_printf(vars, TPLAPPEND, "READERPIN", "%04i", rdr->VgPin);
3769                }
3770                else
3771                {
3772                    tpl_addVar(vars, TPLADD, "READERPIN", "n/a");
3773                }
3774
3775                //credit on Vg card
3776                if(rdr->VgCredit)
3777                {
3778                    tpl_printf(vars, TPLAPPEND, "READERCREDIT", "%i", rdr->VgCredit);
3779                }
3780                else
3781                {
3782                    tpl_addVar(vars, TPLADD, "READERCREDIT", "n/a");
3783                }
3784
3785                if(rdr->card_valid_to)
3786                {
3787                    struct tm vto_t;
3788                    char vtobuffer[30];
3789                    localtime_r(&rdr->card_valid_to, &vto_t);
3790                    strftime(vtobuffer, 30, "%Y-%m-%d", &vto_t);
3791                    tpl_addVar(vars, TPLADD, "READERCARDVALIDTO", vtobuffer);
3792                }
3793                else
3794                {
3795                    tpl_addVar(vars, TPLADD, "READERCARDVALIDTO", "n/a");
3796                }
3797
3798                if(rdr->irdId[0])
3799                {
3800                    for(i = 0; i < 4; i++)  { tpl_printf(vars, TPLAPPEND, "READERIRDID", "%02X ", rdr->irdId[i]); }
3801                }
3802                else
3803                {
3804                    tpl_addVar(vars, TPLADD, "READERIRDID", "n/a");
3805                }
3806
3807                if(rdr->card_atr_length)
3808                    for(i = 0; i < rdr->card_atr_length; i++) { tpl_printf(vars, TPLAPPEND, "READERATR", "%02X ", rdr->card_atr[i]); }
3809
3810                tpl_addVar(vars, TPLADD, "READERCSYSTEM", rdr->csystem.desc);
3811
3812                tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTBIT"));
3813
3814            }
3815            else
3816            {
3817                tpl_addMsg(vars, "Reader does not exist or is not started!");
3818            }
3819        }
3820
3821    }
3822    else
3823    {
3824        tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTGENERICBIT"));
3825    }
3826
3827    if(!apicall)
3828        { return tpl_getTpl(vars, "ENTITLEMENTS"); }
3829    else
3830        { return tpl_getTpl(vars, "APICCCAMCARDLIST"); }
3831}
3832
3833static char *send_oscam_status(struct templatevars * vars, struct uriparams * params, int32_t apicall)
3834{
3835    int32_t i;
3836    char *usr;
3837    int32_t lsec, isec, chsec, con, cau = 0;
3838    time_t now = time((time_t *)0);
3839    struct tm lt;
3840
3841    if(!apicall)
3842    {
3843        setActiveMenu(vars, MNU_STATUS);
3844        if(cfg.http_picon_size > 0)
3845        {
3846            tpl_printf(vars, TPLADD, "HTTPPICONSIZE", "img.readericon,img.protoicon,img.statususericon {height:%dpx !important;}", cfg.http_picon_size);
3847        }
3848    }
3849    char picon_name[32];
3850    snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "LOGO");
3851    if(picon_exists(picon_name))
3852    {
3853        tpl_addVar(vars, TPLADD, "LOGO", tpl_getTpl(vars, "LOGOBIT"));
3854    }
3855    else
3856    {
3857        tpl_addVar(vars, TPLADD, "LOGO", "");
3858    }
3859    if(strcmp(getParam(params, "action"), "kill") == 0)
3860    {
3861        char *cptr = getParam(params, "threadid");
3862        struct s_client *cl = NULL;
3863        if(strlen(cptr) > 1)
3864            { sscanf(cptr, "%p", (void **)(void *)&cl); }
3865
3866        if(cl && is_valid_client(cl))
3867        {
3868#ifdef HAVE_DVBAPI
3869            if(streq(cl->account->usr, cfg.dvbapi_usr))
3870            {
3871                cs_log("WebIF from %s requests to kill dvbapi client %s -> ignoring!",  cs_inet_ntoa(GET_IP()), cl->account->usr);
3872            }
3873            else
3874            {
3875                kill_thread(cl);
3876                cs_log("Client %s killed by WebIF from %s", cl->account->usr, cs_inet_ntoa(GET_IP()));
3877            }
3878        }
3879#else
3880            kill_thread(cl);
3881            cs_log("Client %s killed by WebIF from %s", cl->account->usr, cs_inet_ntoa(GET_IP()));
3882        }
3883#endif
3884    }
3885
3886    if(strcmp(getParam(params, "action"), "resetserverstats") == 0)
3887    {
3888        clear_system_stats();
3889    }
3890    if(strcmp(getParam(params, "action"), "restart") == 0)
3891    {
3892        struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
3893        if(rdr)
3894        {
3895            add_job(rdr->client, ACTION_READER_RESTART, NULL, 0);
3896            cs_log("Reader %s restarted by WebIF from %s", rdr->label, cs_inet_ntoa(GET_IP()));
3897        }
3898    }
3899
3900    char *debuglvl = getParam(params, "debug");
3901    if(strlen(debuglvl) > 0)
3902    {
3903#ifndef WITH_DEBUG
3904        cs_log("*** Warning: Debug Support not compiled in ***");
3905#else
3906        int32_t dblvl = atoi(debuglvl);
3907        if(dblvl >= 0 && dblvl <= 65535) { cs_dblevel = dblvl; }
3908        cs_log("%s debug_level=%d", "all", cs_dblevel);
3909#endif
3910    }
3911
3912    char *hide = getParam(params, "hide");
3913    if(strlen(hide) > 0)
3914    {
3915        struct s_client *hideidx = NULL;
3916        sscanf(hide, "%p", (void **)(void *)&hideidx);
3917
3918        if(hideidx && is_valid_client(hideidx))
3919            { hideidx->wihidden = 1; }
3920    }
3921
3922    char *hideidle = getParam(params, "hideidle");
3923    if(strlen(hideidle) > 0)
3924    {
3925        if(atoi(hideidle) == 2)
3926        {
3927            struct s_client *cl;
3928            for(cl = first_client; cl ; cl = cl->next)
3929                { cl->wihidden = 0; }
3930        }
3931        else if(atoi(hideidle) == 3)
3932        {
3933            struct s_client *cl;
3934            for(cl = first_client; cl ; cl = cl->next)
3935            {
3936                if(cl->typ == 'r'){
3937                    cl->wihidden = 0;
3938                }
3939            }
3940        }
3941        else if(atoi(hideidle) == 4)
3942        {
3943            struct s_client *cl;
3944            for(cl = first_client; cl ; cl = cl->next)
3945            {
3946                if(cl->typ == 'p'){
3947                    cl->wihidden = 0;
3948                }
3949            }
3950        }
3951        else if(atoi(hideidle) == 5)
3952        {
3953            struct s_client *cl;
3954            for(cl = first_client; cl ; cl = cl->next)
3955            {
3956                if(cl->typ == 'c'){
3957                    cl->wihidden = 0;
3958                }
3959            }
3960        }
3961        else
3962        {
3963            int32_t oldval = cfg.http_hide_idle_clients;
3964            config_set("webif", "httphideidleclients", hideidle);
3965            if(oldval != cfg.http_hide_idle_clients)
3966            {
3967                refresh_oscam(REFR_SERVER);
3968            }
3969        }
3970    }
3971
3972    if(cfg.http_hide_idle_clients > 0) { tpl_addVar(vars, TPLADD, "HIDEIDLECLIENTSSELECTED1", "selected"); }
3973    else { tpl_addVar(vars, TPLADD, "HIDEIDLECLIENTSSELECTED0", "selected"); }
3974
3975    int32_t user_count_all = 0, user_count_shown = 0, user_count_active = 0;
3976    int32_t reader_count_all = 0, reader_count_conn = 0;
3977    int32_t proxy_count_all = 0, proxy_count_conn = 0;
3978    int32_t shown;
3979
3980    struct s_client *cl;
3981    int8_t filtered;
3982
3983    cs_readlock(&readerlist_lock);
3984    cs_readlock(&clientlist_lock);
3985    for(i = 0, cl = first_client; cl ; cl = cl->next, i++)
3986    {
3987        if(cl->kill) { continue; }
3988#ifdef CS_CACHEEX
3989        if(get_module(cl)->listenertype != LIS_CSPUDP)
3990        {
3991#endif
3992
3993            // Reset template variables
3994            tpl_addVar(vars, TPLADD, "CLIENTLBVALUE", "");
3995            tpl_addVar(vars, TPLADD, "LASTREADER", "");
3996            tpl_addVar(vars, TPLADD, "CLIENTPROTO", "");
3997            tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", "");
3998            tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIME", "");
3999            tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIMEHIST", "");
4000            tpl_addVar(vars, TPLADD, "JSONARRAYDELIMITER", cl->next ? "," : "");
4001
4002            if(cl->typ == 'c')
4003                { user_count_all++; }
4004            else if(cl->typ == 'p')
4005                { proxy_count_all++; }
4006            else if(cl->typ == 'r')
4007                { reader_count_all++; }
4008
4009            shown = 0;
4010            if(cl->wihidden != 1)
4011            {
4012                filtered = !(cfg.http_hide_idle_clients != 1 || cl->typ != 'c' || (now - cl->lastecm) <= cfg.hideclient_to);
4013                if(!filtered && cfg.http_hide_type)
4014                {
4015                    char *p = cfg.http_hide_type;
4016                    while(*p && !filtered)
4017                    {
4018                        char type = *p++;
4019#ifdef CS_CACHEEX
4020                        filtered = (type == cl->typ) || (type == 'x' && (cl->typ == 'p' || cl->typ == 'r') && (cl->reader && cl->reader->cacheex.mode));
4021#else
4022                        filtered = (type == cl->typ);
4023#endif
4024                    }
4025                }
4026
4027                if(!filtered)
4028                {
4029                    if(cl->typ == 'c')
4030                    {
4031                        user_count_shown++;
4032                        if(cfg.http_hide_idle_clients != 1 && cfg.hideclient_to > 0 && (now - cl->lastecm) <= cfg.hideclient_to)
4033                        {
4034                            user_count_active++;
4035                            tpl_addVar(vars, TPLADD, "CLIENTTYPE", "a");
4036                        }
4037                        else { tpl_addVar(vars, TPLADD, "CLIENTTYPE", "c"); }
4038                    }
4039                    else
4040                    {
4041                        if(cl->typ == 'r' && cl->reader->card_status == CARD_INSERTED)
4042                            { reader_count_conn++; }
4043                        else if(cl->typ == 'p' && (cl->reader->card_status == CARD_INSERTED || cl->reader->tcp_connected))
4044                            { proxy_count_conn++; }
4045                        tpl_printf(vars, TPLADD, "CLIENTTYPE", "%c", cl->typ);
4046                    }
4047                    if(cl->typ == 'c' || cl->typ == 'r' || cl->typ == 'p')
4048                    {
4049                        if(cl->lastecm >= cl->login && cl->lastecm >= cl->logout) { isec = now - cl->lastecm; }
4050                        else if(cl->logout >= cl->login) { isec = now - cl->logout; }
4051                        else { isec = now - cl->login; }
4052                    }
4053                    else { isec = now - cl->last; }
4054
4055                    shown = 1;
4056                    lsec = now - cl->login;
4057                    chsec = now - cl->lastswitch;
4058                    usr = username(cl);
4059
4060                    if((cl->typ == 'r') || (cl->typ == 'p')) { usr = cl->reader->label; }
4061
4062                    if(cl->dup) { con = 2; }
4063                    else if((cl->tosleep) && (now - cl->lastswitch > cl->tosleep)) { con = 1; }
4064                    else { con = 0; }
4065
4066                    // no AU reader == 0 / AU ok == 1 / Last EMM > aulow == -1
4067                    if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r')
4068                    {
4069                        if((cl->typ == 'c' && ll_count(cl->aureader_list) == 0) || ((cl->typ == 'p' || cl->typ == 'r') && cl->reader->audisabled)) { cau = 0; }
4070                        else if((now - cl->lastemm) / 60 > cfg.aulow) { cau = -1; }
4071                        else { cau = 1; }
4072
4073                        if(!apicall)
4074                        {
4075                            if(cau == 0)
4076                            {
4077                                tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "OFF");
4078                            }
4079                            else
4080                            {
4081                                if(cau == -1)
4082                                    { tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "<A HREF=\"#\" CLASS=\"tooltip\">ON"); }
4083                                else
4084                                    { tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "<A HREF=\"#\" CLASS=\"tooltip\">ACTIVE"); }
4085                                tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", "<SPAN>");
4086                                if(cl->typ == 'c')
4087                                {
4088                                    struct s_reader *rdr;
4089                                    LL_ITER itr = ll_iter_create(cl->aureader_list);
4090                                    while((rdr = ll_iter_next(&itr)))
4091                                    {
4092                                        if(rdr->audisabled)
4093                                            { tpl_printf(vars, TPLAPPEND, "CLIENTCAUHTTP", "(%s)<BR>", xml_encode(vars, rdr->label)); }
4094                                        else
4095                                            { tpl_printf(vars, TPLAPPEND, "CLIENTCAUHTTP", "%s<BR>", xml_encode(vars, rdr->label)); }
4096                                    }
4097                                }
4098                                else { tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", xml_encode(vars, cl->reader->label)); }
4099                                tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", "</SPAN></A>");
4100                            }
4101                        }
4102                    }
4103                    else
4104                    {
4105                        cau = 0;
4106                        tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "");
4107                    }
4108                    localtime_r(&cl->login, &lt);
4109
4110                    if(!apicall)
4111                    {
4112                        if(cl->typ == 'c')
4113                        {
4114                            tpl_addVar(vars, TPLADD, "TARGET", "User");
4115                            tpl_addVar(vars, TPLADD, "LBL", xml_encode(vars, usr));
4116                            tpl_printf(vars, TPLADD, "CID", "%p", cl);
4117                            tpl_addVar(vars, TPLADD, "HIDEIDX", tpl_getTpl(vars, "STATUSHBUTTON"));
4118                            tpl_addVar(vars, TPLADD, "CSIDX", tpl_getTpl(vars, "STATUSKBUTTON"));
4119                        }
4120                        else if(cl->typ == 'p')
4121                        {
4122                            tpl_addVar(vars, TPLADD, "TARGET", "Proxy");
4123                            tpl_addVar(vars, TPLADD, "LBL", xml_encode(vars, usr));
4124                            tpl_addVar(vars, TPLADD, "LBLENC", urlencode(vars, usr));
4125                            tpl_printf(vars, TPLADD, "CID", "%p", cl);
4126                            tpl_addVar(vars, TPLADD, "HIDEIDX", tpl_getTpl(vars, "STATUSHBUTTON"));
4127                            tpl_addVar(vars, TPLADD, "CSIDX", tpl_getTpl(vars, "STATUSRBUTTON"));
4128                        }
4129                        else if(cl->typ == 'r')
4130                        {
4131                            tpl_addVar(vars, TPLADD, "TARGET", "Reader");
4132                            tpl_addVar(vars, TPLADD, "LBL", xml_encode(vars, usr));
4133                            tpl_addVar(vars, TPLADD, "LBLENC", urlencode(vars, usr));
4134                            tpl_printf(vars, TPLADD, "CID", "%p", cl);
4135                            tpl_addVar(vars, TPLADD, "HIDEIDX", tpl_getTpl(vars, "STATUSHBUTTON"));
4136                            tpl_addVar(vars, TPLADD, "CSIDX", tpl_getTpl(vars, "STATUSRBUTTON"));
4137                        }
4138                        else if (cl->typ == 'h' || cl->typ == 's' || cl->typ == 'm')
4139                        {
4140                            tpl_addVar(vars, TPLADD, "TARGET", "Reader");
4141                            tpl_addVar(vars, TPLADD, "LBL", xml_encode(vars, usr));
4142                            tpl_printf(vars, TPLADD, "CID", "%p", cl);
4143                            tpl_addVar(vars, TPLADD, "HIDEIDX", tpl_getTpl(vars, "STATUSHBUTTON"));
4144                            tpl_printf(vars, TPLADD, "CSIDX", "%p", cl);
4145                        }
4146                    }
4147                    else
4148                    {
4149                        tpl_printf(vars, TPLADD, "HIDEIDX", "%p", cl);
4150                        tpl_printf(vars, TPLADD, "CSIDX", "%p", cl);
4151                    }
4152                    tpl_printf(vars, TPLADD, "CLIENTTYPE", "%c", cl->typ);
4153                    tpl_printf(vars, TPLADD, "CLIENTCNR", "%d", get_threadnum(cl));
4154                    tpl_addVar(vars, TPLADD, "CLIENTUSER", xml_encode(vars, usr));
4155                    if(cl->typ == 'c')
4156                    {
4157                        tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", xml_encode(vars, (cl->account && cl->account->description) ? cl->account->description : ""));
4158                    }
4159                    else if(cl->typ == 'p' || cl->typ == 'r')
4160                    {
4161                        tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", xml_encode(vars, cl->reader->description ? cl->reader->description : ""));
4162                    }
4163
4164                    tpl_addVar(vars, TPLADD, "STATUSUSERICON", xml_encode(vars, usr));
4165                    if (cl->typ == 'c') {
4166                        tpl_addVar(vars, TPLADD, "USERNAME", xml_encode(vars, usr));
4167                        tpl_addVar(vars, TPLADD, "USERENC", urlencode(vars, usr));
4168                    } else if (cl->typ == 'p' || cl->typ == 'r') {
4169                        tpl_addVar(vars, TPLADD, "READERNAME", xml_encode(vars, usr));
4170                        tpl_addVar(vars, TPLADD, "READERNAMEENC", urlencode(vars, usr));
4171                    }
4172
4173                    if(!apicall)
4174                    {
4175                        bool picon_shown = false;
4176                        const char *status_user_icon_tpl = NULL;
4177
4178                        if(cfg.http_showpicons && !apicall)
4179                        {
4180                            if(picon_exists(xml_encode(vars, usr)))
4181                            {
4182                                switch (cl->typ) {
4183                                case 'c': status_user_icon_tpl = "SUSERICON"; picon_shown = true; break;
4184                                case 'p': // Fall through
4185                                case 'r': status_user_icon_tpl = "SREADERICON"; picon_shown = true; break;
4186                                }
4187                            }
4188                            else
4189                            {
4190                                tpl_printf(vars, TPLADD, "UPICMISSING", "missing icon: IC_%s.tpl", xml_encode(vars, usr));
4191                            }
4192                        }
4193
4194                        if (!picon_shown) {
4195                            switch (cl->typ) {
4196                            case 'c': status_user_icon_tpl = "SUSER"; break;
4197                            case 'p': // Fall through
4198                            case 'r': status_user_icon_tpl = "SREADER"; break;
4199                            }
4200                        }
4201
4202                        if (status_user_icon_tpl)
4203                            tpl_addVar(vars, TPLADD, "STATUSUSERICON", tpl_getTpl(vars, status_user_icon_tpl));
4204                    }
4205
4206                    tpl_printf(vars, TPLADD, "CLIENTCAU", "%d", cau);
4207                    if(!apicall)
4208                    {
4209                        if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r')
4210                        {
4211                            if(cl->crypted) { tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", "ON"); }
4212                            else { tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", "OFF"); }
4213                        }
4214                        else { tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", ""); }
4215                    }
4216                    else { tpl_printf(vars, TPLADD, "CLIENTCRYPTED", "%d", cl->crypted); }
4217                    tpl_addVar(vars, TPLADD, "CLIENTIP", cs_inet_ntoa(cl->ip));
4218                    tpl_printf(vars, TPLADD, "CLIENTPORT", "%d", cl->port);
4219                    const char *proto = client_get_proto(cl);
4220                    webif_add_client_proto(vars, cl, proto, apicall);
4221
4222                    if(!apicall)
4223                    {
4224                        if((cl->typ != 'p' && cl->typ != 'r') || cl->reader->card_status == CARD_INSERTED)
4225                        {
4226                            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);
4227                            tpl_addVar(vars, TPLADD, "CLIENTLOGINSECS", sec2timeformat(vars, lsec));
4228                        }
4229                        else
4230                        {
4231                            tpl_addVar(vars, TPLADD, "CLIENTLOGINDATE", "");
4232                            tpl_addVar(vars, TPLADD, "CLIENTLOGINSECS", "");
4233                        }
4234                    }
4235                    else
4236                    {
4237                        char tbuffer [30];
4238                        strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
4239                        tpl_addVar(vars, TPLADD, "CLIENTLOGINDATE", tbuffer);
4240                        tpl_printf(vars, TPLADD, "CLIENTLOGINSECS", "%d", lsec);
4241                    }
4242
4243                    //load historical values from ringbuffer
4244                    char *value = get_ecm_historystring(cl);
4245                    tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIMEHIST", value);
4246                    free_mk_t(value);
4247
4248                    if((isec < cfg.hideclient_to || cfg.hideclient_to == 0) && (cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r'))
4249                    {
4250                        if(((cl->typ != 'r') || (cl->typ != 'p')) && (cl->lastreader[0]))
4251                        {
4252                            if(apicall)
4253                            {
4254                                tpl_addVar(vars, TPLADD, "LASTREADER", cl->lastreader);
4255                            }
4256                            else
4257                            {
4258                                tpl_addVar(vars, TPLADD, "LBLVALUE", xml_encode(vars, cl->lastreader));
4259                                tpl_addVar(vars, TPLADD, "LBLVALUEENC", urlencode(vars, cl->lastreader));
4260                                tpl_printf(vars, TPLADD, "MSVALUE", "%d", cl->cwlastresptime);
4261#ifdef WITH_LB
4262                                tpl_addVar(vars, TPLAPPEND, "CLIENTLBVALUE", tpl_getTpl(vars, "CLIENTLBLVALUEBIT"));
4263#else
4264                                tpl_printf(vars, TPLAPPEND, "CLIENTLBVALUE", "%s (%dms)", xml_encode(vars, cl->lastreader), cl->cwlastresptime);
4265#endif
4266                            }
4267                        }
4268                        if(cl->last_caid != NO_CAID_VALUE && cl->last_srvid != NO_SRVID_VALUE)
4269                        {
4270                            tpl_printf(vars, TPLADD, "CLIENTCAID", "%04X", cl->last_caid);
4271                            tpl_printf(vars, TPLADD, "CLIENTSRVID", "%04X", cl->last_srvid);
4272                            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 ? ": " : "");
4273                            tpl_addVar(vars, TPLADD, "CLIENTSRVNAME", cl->last_srvidptr && cl->last_srvidptr->name ? xml_encode(vars, cl->last_srvidptr->name) : "");
4274                            tpl_printf(vars, TPLADD, "CLIENTLASTRESPONSETIME", "%d", cl->cwlastresptime ? cl->cwlastresptime : 1);
4275                            tpl_addVar(vars, TPLADD, "CLIENTSRVTYPE", cl->last_srvidptr && cl->last_srvidptr->type ? xml_encode(vars, cl->last_srvidptr->type) : "");
4276                            tpl_addVar(vars, TPLADD, "CLIENTSRVDESCRIPTION", cl->last_srvidptr && cl->last_srvidptr->desc ? xml_encode(vars, cl->last_srvidptr->desc) : "");
4277                            tpl_addVar(vars, TPLADD, "CLIENTTIMEONCHANNEL", sec2timeformat(vars, chsec));
4278                            if(cfg.http_showpicons && !apicall)
4279                            {
4280                                snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "%04X_%04X", cl->last_caid, cl->last_srvid);
4281                                tpl_addVar(vars, TPLADD, "PICONNAME", picon_name);
4282                                int8_t picon_ok = picon_exists(picon_name);
4283                                if(!picon_ok)
4284                                {
4285                                    snprintf(picon_name, sizeof(picon_name) / sizeof(char) - 1, "0000_%04X", cl->last_srvid);
4286                                    picon_ok = picon_exists(picon_name);
4287                                    if(picon_ok) tpl_addVar(vars, TPLADD, "PICONNAME", picon_name);
4288                                }
4289                                if(picon_ok)
4290                                {                                   
4291                                    tpl_addVar(vars, TPLADDONCE, "CURRENTPICON", tpl_getTpl(vars, "CLIENTCURRENTCHANNELPIC"));
4292                                }
4293                                else
4294                                {
4295                                    tpl_addVar(vars, TPLADDONCE, "CURRENTPICON", tpl_getTpl(vars, "CLIENTCURRENTCHANNEL"));
4296                                }
4297                            }
4298                            else
4299                            {
4300                                tpl_addVar(vars, TPLADDONCE, "CURRENTPICON", tpl_getTpl(vars, "CLIENTCURRENTCHANNELBIT"));
4301                            }
4302                        }
4303                        else
4304                        {
4305                            tpl_addVar(vars, TPLADD, "CLIENTCAID", "0000");
4306                            tpl_printf(vars, TPLADD, "CLIENTSRVID", "0000");
4307                        }
4308                    }
4309                    else
4310                    {
4311                        tpl_addVar(vars, TPLADD, "CLIENTCAID", "0000");
4312                        tpl_addVar(vars, TPLADD, "CLIENTSRVID", "0000");
4313                        tpl_addVar(vars, TPLADD, "CLIENTCURRENTPICON", "");
4314                        tpl_addVar(vars, TPLADD, "CLIENTSRVPROVIDER", "");
4315                        tpl_addVar(vars, TPLADD, "CLIENTSRVNAME", "");
4316                        tpl_addVar(vars, TPLADD, "CLIENTSRVTYPE", "");
4317                        tpl_addVar(vars, TPLADD, "CLIENTSRVDESCRIPTION", "");
4318                        tpl_addVar(vars, TPLADD, "CLIENTLBVALUE", "");
4319                        tpl_addVar(vars, TPLADD, "CLIENTTIMEONCHANNEL", "");
4320                    }
4321
4322                    if(!apicall)
4323                    {
4324                        tpl_addVar(vars, TPLADD, "CLIENTIDLESECS", sec2timeformat(vars, isec));
4325
4326                        if((cl->typ != 'p' && cl->typ != 'r') || cl->reader->card_status == CARD_INSERTED)
4327                            { tpl_addVar(vars, TPLADD, "CLIENTIDLESECSCLASS", "idlesec_normal"); }
4328                        else
4329                            { tpl_addVar(vars, TPLADD, "CLIENTIDLESECSCLASS", "idlesec_alert"); }
4330                    }
4331                    else
4332                    {
4333                        tpl_printf(vars, TPLADD, "CLIENTIDLESECS", "%d", isec);
4334                    }
4335
4336                    if(con == 2) { tpl_addVar(vars, TPLADD, "CLIENTCON", "Duplicate"); }
4337                    else if(con == 1) { tpl_addVar(vars, TPLADD, "CLIENTCON", "Sleep"); }
4338                    else
4339                    {
4340                        struct s_reader *rdr = cl->reader;
4341                        char *txt = "OK";
4342                        if(!rdr && (cl->typ == 'r' || cl->typ == 'p')) { txt = "UNKNOWN"; }
4343                        else if(cl->typ == 'r' || cl->typ == 'p')  //reader or proxy
4344                        {
4345                            if(rdr->lbvalue)
4346                            {
4347                                tpl_addVar(vars, TPLADD, "LBLRPVALUE", rdr->label);
4348                                tpl_addVar(vars, TPLADD, "LBLRPVALUEENC", urlencode(vars, rdr->label));
4349                                tpl_printf(vars, TPLADD, "LBLRPSTRVALUE", "%d", rdr->lbvalue);
4350#ifdef WITH_LB
4351                                tpl_addVar(vars, TPLADD, "CLIENTLBVALUE", tpl_getTpl(vars, "CLIENTLBLVALUERP"));
4352#else
4353                                tpl_printf(vars, TPLADD, "CLIENTLBVALUE", "%d", rdr->lbvalue);
4354#endif
4355
4356                            }
4357                            else
4358                            {
4359                                tpl_addVar(vars, TPLADD, "LBLRPVALUE", rdr->label);
4360                                tpl_addVar(vars, TPLADD, "LBLRPVALUEENC", urlencode(vars, rdr->label));
4361                                tpl_addVar(vars, TPLADD, "LBLRPSTRVALUE", "no data");
4362#ifdef WITH_LB
4363                                tpl_addVar(vars, TPLADD, "CLIENTLBVALUE", tpl_getTpl(vars, "CLIENTLBLVALUERP"));
4364#else
4365                                tpl_addVar(vars, TPLADD, "CLIENTLBVALUE", "no data");
4366#endif
4367                            }
4368                            switch(rdr->card_status)
4369                            {
4370                            case NO_CARD:
4371                                txt = "OFF";
4372                                break;
4373                            case UNKNOWN:
4374                                txt = "UNKNOWN";
4375                                break;
4376                            case CARD_NEED_INIT:
4377#ifdef CS_CACHEEX
4378                                if (cl->reader->cacheex.mode > 0)
4379                                {
4380                                    txt = "CCcam CacheEX";
4381                                }
4382                                else
4383                                {
4384#endif
4385                                    txt = "NEEDINIT";
4386#ifdef CS_CACHEEX
4387                                }
4388#endif
4389                                break;
4390                            case CARD_INSERTED:
4391                                if(cl->typ == 'p')
4392                                    { txt = "CONNECTED"; }
4393                                else
4394                                    { txt = "CARDOK"; }
4395                                break;
4396                            case CARD_FAILURE:
4397                                txt = "ERROR";
4398                                break;
4399                            default:
4400                                txt = "UNDEF";
4401                            }
4402                        }
4403                        tpl_addVar(vars, TPLADD, "CLIENTCON", txt);
4404                        if(rdr && (cl->typ == 'r') && (!apicall))  //reader
4405                        {
4406                            if(rdr->ll_entitlements)
4407                            {
4408                                LL_ITER itr = ll_iter_create(rdr->ll_entitlements);
4409                                S_ENTITLEMENT *ent;
4410                                uint16_t total_ent = 0;
4411                                uint16_t active_ent = 0;
4412                                struct tm end_t;
4413                                tpl_addVar(vars, TPLADD, "TMPSPAN", "<SPAN>");
4414                                while((ent = ll_iter_next(&itr)))
4415                                {
4416                                    total_ent++;
4417                                    if((ent->end > now) && (ent->type != 7))
4418                                    {
4419                                        if(active_ent) { tpl_addVar(vars, TPLAPPEND, "TMPSPAN", "<BR><BR>"); }
4420                                        active_ent++;
4421                                        localtime_r(&ent->end, &end_t);
4422                                        tpl_printf(vars, TPLAPPEND, "TMPSPAN", "%04X:%06X<BR>exp:%04d/%02d/%02d",
4423                                                   ent->caid, ent->provid,
4424                                                   end_t.tm_year + 1900, end_t.tm_mon + 1, end_t.tm_mday);
4425                                    }
4426                                }
4427                                if(((total_ent) && (active_ent == 0)) || (total_ent == 0))
4428                                {
4429                                    tpl_addVar(vars, TPLAPPEND, "TMPSPAN", "No active entitlements found");
4430                                }
4431                                tpl_addVar(vars, TPLAPPEND, "TMPSPAN", "</SPAN>");
4432                                if(active_ent)
4433                                {
4434                                    tpl_printf(vars, TPLADD, "TMP", "(%d entitlement%s)", active_ent, (active_ent != 1) ? "s" : "");
4435                                }
4436                                else
4437                                {
4438                                    tpl_addVar(vars, TPLADD, "TMP", "(no entitlements)");
4439                                }
4440                                tpl_addVar(vars, TPLADD, "ENTLABEL", urlencode(vars, cl->reader->label));
4441                                tpl_addVar(vars, TPLADD, "ENTVALUE", active_ent > 0 ? "" : "1");
4442                                tpl_addVar(vars, TPLAPPEND, "CLIENTCON", tpl_getTpl(vars, "FOUNDENTITLEMENTS"));
4443                            }
4444                            else
4445                            {
4446                                tpl_addVar(vars, TPLADD, "ENTLABEL",  urlencode(vars, cl->reader->label));
4447                                tpl_addVar(vars, TPLAPPEND, "CLIENTCON", tpl_getTpl(vars, "NOENTITLEMENTS"));
4448                            }
4449                        }
4450#ifdef MODULE_CCCAM
4451                        if(!apicall)
4452                        {
4453                            if(rdr && (cl->typ == 'r' || cl->typ == 'p') && strncmp(proto, "cccam", 5) == 0 && rdr->tcp_connected && rdr->card_status != CARD_FAILURE)
4454                            {
4455                                struct cc_data *rcc = cl->cc;
4456                                if(rcc)
4457                                {
4458                                    LLIST *cards = rcc->cards;
4459                                    if(cards)
4460                                    {
4461                                        int32_t cnt = ll_count(cards);
4462                                        int32_t locals = rcc->num_hop1;
4463                                        tpl_printf(vars, TPLADD, "TMP", "(%d of %d card%s)", locals, cnt, (cnt > 1) ? "s" : "");
4464                                        tpl_printf(vars, TPLADD, "CCCOUNT", "%d", cnt);
4465                                        tpl_printf(vars, TPLADD, "CCCHOP1", "%d", rcc->num_hop1);
4466                                        tpl_printf(vars, TPLADD, "CCCHOP2", "%d", rcc->num_hop2);
4467                                        tpl_printf(vars, TPLADD, "CCCHOPX", "%d", rcc->num_hopx);
4468                                        tpl_printf(vars, TPLADD, "CCCCURR", "%d", cl->reader->currenthops);
4469                                        tpl_printf(vars, TPLADD, "CCCRES0", "%d", rcc->num_reshare0);
4470                                        tpl_printf(vars, TPLADD, "CCCRES1", "%d", rcc->num_reshare1);
4471                                        tpl_printf(vars, TPLADD, "CCCRES2", "%d", rcc->num_reshare2);
4472                                        tpl_printf(vars, TPLADD, "CCCRESX", "%d", rcc->num_resharex);
4473                                        tpl_addVar(vars, TPLADD, "TMPSPAN", tpl_getTpl(vars, "CCENTITLEMENTS"));
4474                                        tpl_addVar(vars, TPLADD, "CCCLABEL", urlencode(vars, cl->reader->label));
4475                                        tpl_addVar(vars, TPLADD, "CCCRESHARE", rcc->num_reshare0 > 0 ? "1" : "");
4476                                        tpl_addVar(vars, TPLADD, "CCCTMP", tpl_getVar(vars, "TMP"));
4477                                        tpl_addVar(vars, TPLADD, "CCCTMPSPAN", tpl_getVar(vars, "TMPSPAN"));
4478                                        tpl_addVar(vars, TPLAPPEND, "CLIENTCON", tpl_getTpl(vars, "CCENTITLETOOLTIP"));
4479                                    }
4480                                }
4481                            }
4482                        }
4483#endif
4484                    }
4485                }
4486            }
4487            if(!apicall)
4488            {
4489                // select right suborder
4490                if(cl->typ == 'c')
4491                {
4492                    if(shown) { tpl_addVar(vars, TPLAPPEND, "CLIENTSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT")); }
4493                    if(cfg.http_hide_idle_clients == 1 || cfg.hideclient_to < 1)
4494                    {
4495                        tpl_printf(vars, TPLADD, "UCS", "%d", user_count_shown);
4496                        tpl_printf(vars, TPLADD, "UCA", "%d", user_count_all);
4497                        tpl_addVar(vars, TPLADD, "CLIENTHEADLINE", tpl_getTpl(vars, "CLIENTHEADLINEBIT"));
4498                    }
4499                    else
4500                    {
4501                        tpl_printf(vars, TPLADD, "UCS", "%d", user_count_shown);
4502                        tpl_printf(vars, TPLADD, "UCA", "%d", user_count_all);
4503                        tpl_printf(vars, TPLADD, "UCAC", "%d", user_count_active);
4504                        tpl_printf(vars, TPLADD, "CFGH", "%d", cfg.hideclient_to);
4505                        tpl_addVar(vars, TPLADD, "CLIENTHEADLINE", tpl_getTpl(vars, "CLIENTHEADLINEWITH"));
4506                    }
4507                }
4508                else if(cl->typ == 'r')
4509                {
4510                    if(shown)
4511                    {
4512                        tpl_addVar(vars, TPLAPPEND, "READERSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT"));
4513                    }
4514                        tpl_printf(vars, TPLADD, "RCC", "%d", reader_count_conn);
4515                        tpl_printf(vars, TPLADD, "RCA", "%d", reader_count_all);
4516                        tpl_addVar(vars, TPLADD, "READERHEADLINE", tpl_getTpl(vars, "CLIENTRHEADLINE"));
4517                }
4518                else if(cl->typ == 'p')
4519                {
4520                    if(shown)
4521                    {
4522                        tpl_addVar(vars, TPLAPPEND, "PROXYSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT"));
4523                    }
4524                        tpl_printf(vars, TPLADD, "PCC", "%d", proxy_count_conn);
4525                        tpl_printf(vars, TPLADD, "PCA", "%d", proxy_count_all);
4526                        tpl_addVar(vars, TPLADD, "PROXYHEADLINE", tpl_getTpl(vars, "CLIENTPHEADLINE"));
4527                }
4528                else if(shown)
4529                {
4530                    if(cl->typ == 'm')
4531                    {
4532                        tpl_addVar(vars, TPLAPPEND, "SERVERSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT"));
4533                    }
4534                    if(cl->typ == 's')
4535                    {
4536                        usr = username(cl);
4537                    }
4538                }
4539            }
4540            else
4541            {
4542                if(shown)
4543                {
4544                    if(apicall == 1)
4545                        { tpl_addVar(vars, TPLAPPEND, "APISTATUSBITS", tpl_getTpl(vars, "APISTATUSBIT")); }
4546                    if(apicall == 2)
4547                        { tpl_addVar(vars, TPLAPPEND, "JSONSTATUSBITS", tpl_getTpl(vars, "JSONSTATUSBIT")); }
4548                }
4549            }
4550
4551#ifdef CS_CACHEEX
4552        }
4553#endif
4554
4555    }
4556    cs_readunlock(&clientlist_lock);
4557    cs_readunlock(&readerlist_lock);
4558
4559    if(cfg.loghistorysize)
4560    {
4561        char *t_loghistptr = loghistptr, *ptr1 = NULL;
4562        if(loghistptr >= loghist + (cfg.loghistorysize) - 1)
4563            { t_loghistptr = loghist; }
4564        int32_t d = 0, l1 = strlen(t_loghistptr + 1) + 2;
4565        char *lastpos = loghist + (cfg.loghistorysize) - 1;
4566
4567        for(ptr1 = t_loghistptr + l1, i = 0; i < 200; i++, ptr1 = ptr1 + l1)
4568        {
4569            l1 = strlen(ptr1) + 1;
4570            if(!d && ((ptr1 >= lastpos) || (l1 < 2)))
4571            {
4572                ptr1 = loghist;
4573                l1 = strlen(ptr1) + 1;
4574                d++;
4575            }
4576
4577            if(d && ((ptr1 >= t_loghistptr) || (l1 < 2)))
4578                { break; }
4579
4580            char p_usr[32];
4581            size_t pos1 = strcspn(ptr1, "\t") + 1;
4582            cs_strncpy(p_usr, ptr1 , pos1 > sizeof(p_usr) ? sizeof(p_usr) : pos1);
4583
4584            char *p_txt = ptr1 + pos1;
4585
4586            if(!apicall)
4587            {
4588                if(p_txt[0])
4589                    tpl_printf(vars, TPLAPPEND, "LOGHISTORY",
4590                               "\t\t<SPAN CLASS=\"%s\">%s\t\t</SPAN><BR>\n", xml_encode(vars, p_usr), xml_encode(vars, p_txt));
4591            }
4592            else
4593            {
4594                if(apicall == 1)
4595                    if(strcmp(getParam(params, "appendlog"), "1") == 0)
4596                        { tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", p_txt); }
4597            }
4598        }
4599    }
4600    else
4601    {
4602        tpl_addVar(vars, TPLADD, "LOGHISTORY", "loghistorysize is set to 0 in your configuration<BR>\n");
4603    }
4604
4605#ifdef CS_CACHEEX
4606    char *getting = "<IMG SRC=\"image?i=ICARRL\" ALT=\"Getting\">";
4607    char *pushing = "<IMG SRC=\"image?i=ICARRR\" ALT=\"Pushing\">";
4608
4609    float cachesum = first_client ? first_client->cwcacheexgot : 1;
4610    if(cachesum < 1)
4611    {
4612        cachesum = 1;
4613    }
4614    tpl_printf(vars, TPLADD, "TOTAL_CACHEXPUSH", "%d", first_client ? first_client->cwcacheexpush : 0);
4615    tpl_addVar(vars, TPLADD, "TOTAL_CACHEXPUSH_IMG", pushing);
4616    tpl_printf(vars, TPLADD, "TOTAL_CACHEXGOT", "%d", first_client ? first_client->cwcacheexgot : 0);
4617    tpl_addVar(vars, TPLADD, "TOTAL_CACHEXGOT_IMG", getting);
4618    tpl_printf(vars, TPLADD, "TOTAL_CACHEXHIT", "%d", first_client ? first_client->cwcacheexhit : 0);
4619    tpl_printf(vars, TPLADD, "TOTAL_CACHESIZE", "%d", cache_size());
4620    tpl_printf(vars, TPLADD, "REL_CACHEXHIT", "%.2f", (first_client ? first_client->cwcacheexhit : 0) * 100 / cachesum);
4621    tpl_addVar(vars, TPLADD, "CACHEEXSTATS", tpl_getTpl(vars, "STATUSCACHEX"));
4622#endif
4623    //User info
4624    struct s_auth *account;
4625    int32_t total_users = 0;
4626    int32_t disabled_users = 0;
4627    int32_t expired_users = 0;
4628    for(account = cfg.account; (account); account = account->next)
4629    {
4630        total_users++;
4631        if(account->expirationdate && account->expirationdate < now)
4632        {
4633            expired_users++;
4634        }
4635        if(account->disabled != 0)
4636        {
4637            disabled_users++;
4638        }
4639    }
4640    tpl_printf(vars, TPLADD, "TOTAL_USERS", "%d", total_users);
4641    tpl_printf(vars, TPLADD, "TOTAL_ACTIVE", "%d", total_users - expired_users - disabled_users);
4642    tpl_printf(vars, TPLADD, "TOTAL_EXPIRED", "%d", expired_users);
4643    tpl_printf(vars, TPLADD, "TOTAL_DISABLED", "%d", disabled_users);
4644    tpl_printf(vars, TPLADD, "TOTAL_ONLINE", "%d", cfg.http_hide_idle_clients ? user_count_shown : user_count_active);
4645    tpl_printf(vars, TPLADD, "TOTAL_CONNECTED", "%d", user_count_all);
4646
4647    //CW info
4648    float ecmsum = first_client->cwfound + first_client->cwnot + first_client->cwtout + first_client->cwcache; //dont count TUN its included
4649    if(ecmsum < 1){ecmsum = 1;}
4650    tpl_printf(vars, TPLADD, "TOTAL_ECM_MIN", "%d", first_client->n_request[0]);
4651    tpl_printf(vars, TPLADD, "TOTAL_CW", "%d", (int)ecmsum);
4652    tpl_printf(vars, TPLADD, "TOTAL_CWOK", "%d", first_client->cwfound);
4653    tpl_printf(vars, TPLADD, "TOTAL_CWNOK", "%d", first_client->cwnot);
4654    tpl_printf(vars, TPLADD, "TOTAL_CWIGN", "%d", first_client->cwignored);
4655    tpl_printf(vars, TPLADD, "TOTAL_CWTOUT", "%d", first_client->cwtout);
4656    tpl_printf(vars, TPLADD, "TOTAL_CWCACHE", "%d", first_client->cwcache);
4657    tpl_printf(vars, TPLADD, "TOTAL_CWTUN", "%d", first_client->cwtun);
4658    tpl_printf(vars, TPLADD, "TOTAL_CWPOS", "%d", first_client->cwfound + first_client->cwcache);
4659    tpl_printf(vars, TPLADD, "TOTAL_CWNEG", "%d", first_client->cwnot + first_client->cwtout);
4660    tpl_printf(vars, TPLADD, "REL_CWOK", "%.2f", first_client->cwfound * 100 / ecmsum);
4661    tpl_printf(vars, TPLADD, "REL_CWNOK", "%.2f", first_client->cwnot * 100 / ecmsum);
4662    tpl_printf(vars, TPLADD, "REL_CWIGN", "%.2f", first_client->cwignored * 100 / ecmsum);
4663    tpl_printf(vars, TPLADD, "REL_CWTOUT", "%.2f", first_client->cwtout * 100 / ecmsum);
4664    tpl_printf(vars, TPLADD, "REL_CWCACHE", "%.2f", first_client->cwcache * 100 / ecmsum);
4665    tpl_printf(vars, TPLADD, "REL_CWTUN", "%.2f", first_client->cwtun * 100 / ecmsum);
4666    tpl_printf(vars, TPLADD, "REL_CWPOS", "%.2f", (first_client->cwfound + first_client->cwcache) * 100 / ecmsum);
4667    tpl_printf(vars, TPLADD, "REL_CWNEG", "%.2f", (first_client->cwnot + first_client->cwtout) * 100 / ecmsum);
4668
4669    //copy struct to p_stat_old for cpu_usage calculation
4670    p_stat_old = p_stat_cur;
4671
4672    //Memory-CPU Info for linux based systems
4673#if defined(__linux__)
4674    //get actual stats
4675    if(!get_stats_linux(getpid(),&p_stat_cur)){
4676        if(p_stat_old.cpu_total_time != 0){
4677            calc_cpu_usage_pct(&p_stat_cur, &p_stat_old);
4678        }
4679    }
4680    else{
4681        //something went wrong, so fill with "N/A"
4682        p_stat_cur.check_available = 65535;
4683    }
4684#else // if not linux, fill with "N/A" but probably in future gets filled also for other platforms
4685    p_stat_cur.check_available = 65535;
4686#endif
4687    set_status_info(vars, p_stat_cur);
4688
4689    if(cfg.http_showmeminfo || cfg.http_showuserinfo || cfg.http_showloadinfo || cfg.http_showecminfo || (cfg.http_showcacheexinfo  && config_enabled(CS_CACHEEX))){
4690        tpl_addVar(vars, TPLADD, "FOOTER", "footerwidth");
4691        tpl_addVar(vars, TPLADD, "DISPLAYINFO", "visible");
4692    }
4693    else{
4694        tpl_addVar(vars, TPLADD, "DISPLAYINFO", "hidden");
4695    }
4696
4697    tpl_addVar(vars, TPLADD, "DISPLAYSYSINFO", cfg.http_showmeminfo ? "visible" : "hidden");
4698    tpl_addVar(vars, TPLADD, "DISPLAYUSERINFO", cfg.http_showuserinfo ? "visible" : "hidden");
4699    tpl_addVar(vars, TPLADD, "DISPLAYLOADINFO", cfg.http_showloadinfo ?"visible" : "hidden");
4700    tpl_addVar(vars, TPLADD, "DISPLAYECMINFO", cfg.http_showecminfo ? "visible" : "hidden");
4701
4702    if(cfg.http_showcacheexinfo == 1 && config_enabled(CS_CACHEEX)){
4703        tpl_addVar(vars, TPLADD, "DISPLAYCACHEEXINFO", "visible");
4704        tpl_addVar(vars, TPLADDONCE, "CACHEEX_INFO", tpl_getTpl(vars, "CACHEEXINFOBIT"));
4705    }
4706
4707    tpl_addVar(vars, TPLADDONCE, "SYSTEM_INFO", tpl_getTpl(vars, "SYSTEMINFOBIT"));
4708    tpl_addVar(vars, TPLADDONCE, "USER_INFO", tpl_getTpl(vars, "USERINFOBIT"));
4709
4710#ifdef WITH_DEBUG
4711    // Debuglevel Selector
4712    int32_t lvl;
4713    for(i = 0; i < MAX_DEBUG_LEVELS; i++)
4714    {
4715        lvl = 1 << i;
4716        tpl_printf(vars, TPLADD, "TMPC", "DCLASS%d", lvl);
4717        tpl_printf(vars, TPLADD, "TMPV", "DEBUGVAL%d", lvl);
4718        if(cs_dblevel & lvl)
4719        {
4720            tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugls");
4721            tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel - lvl);
4722        }
4723        else
4724        {
4725            tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugl");
4726            tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel + lvl);
4727        }
4728    }
4729
4730    if(cs_dblevel == D_ALL_DUMP)
4731        { tpl_addVar(vars, TPLADD, "DCLASS65535", "debugls"); }
4732    else
4733        { tpl_addVar(vars, TPLADD, "DCLASS65535", "debugl"); }
4734
4735    tpl_addVar(vars, TPLADD, "NEXTPAGE", "status.html");
4736    tpl_addVar(vars, TPLADD, "DCLASS", "debugl"); //default
4737    tpl_printf(vars, TPLADD, "ACTDEBUG", "%d", cs_dblevel);
4738    tpl_addVar(vars, TPLADD, "SDEBUG", tpl_getTpl(vars, "DEBUGSELECT"));
4739#endif
4740
4741    if(apicall)
4742    {
4743        if(apicall == 1)
4744            { return tpl_getTpl(vars, "APISTATUS"); }
4745        if(apicall == 2)
4746            { return tpl_getTpl(vars, "JSONSTATUS"); }
4747    }
4748
4749    if(config_enabled(TOUCH) && streq(tpl_getVar(vars, "SUBDIR"), TOUCH_SUBDIR))
4750        { return tpl_getTpl(vars, "TOUCH_STATUS"); }
4751    else
4752        { return tpl_getTpl(vars, "STATUS"); }
4753}
4754
4755static char *send_oscam_services_edit(struct templatevars * vars, struct uriparams * params)
4756{
4757    struct s_sidtab *sidtab, *ptr;
4758    char label[sizeof(cfg.sidtab->label)];
4759    int32_t i;
4760
4761    setActiveMenu(vars, MNU_SERVICES);
4762
4763    cs_strncpy(label, strtolower(getParam(params, "service")), sizeof(label));
4764    ++cfg_sidtab_generation;
4765    for(sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab = sidtab->next) { ; }
4766
4767    if(sidtab == NULL)
4768    {
4769        i = 1;
4770        while(strlen(label) < 1)
4771        {
4772            snprintf(label, sizeof(label) / sizeof(char) - 1, "newservice%d", i);
4773            for(sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab = sidtab->next) { ; }
4774            if(sidtab != NULL) { label[0] = '\0'; }
4775            ++i;
4776        }
4777        if(!cs_malloc(&sidtab, sizeof(struct s_sidtab))) { return "0"; }
4778
4779        if(cfg.sidtab == NULL) { cfg.sidtab = sidtab; }
4780        else
4781        {
4782            for(ptr = cfg.sidtab; ptr != NULL && ptr->next != NULL; ptr = ptr->next) { ; }
4783            ptr->next = sidtab;
4784        }
4785        cs_strncpy((char *)sidtab->label, label, sizeof(sidtab->label));
4786        ++cfg_sidtab_generation;
4787        tpl_addMsg(vars, "New service has been added");
4788        // Adding is uncritical as the new service is appended to sidtabs.ok/sidtabs.no and accounts/clients/readers have zeros there
4789        if(write_services() != 0) { tpl_addMsg(vars, "Writing services to disk failed!"); }
4790    }
4791
4792    if(strcmp(getParam(params, "action"), "Save") == 0)
4793    {
4794        for(i = 0; i < (*params).paramcount; i++)
4795        {
4796            if((strcmp((*params).params[i], "action")) && (strcmp((*params).params[i], "service")))
4797            {
4798                chk_sidtab((*params).params[i], (*params).values[i], sidtab);
4799            }
4800        }
4801        ++cfg_sidtab_generation;
4802        tpl_addMsg(vars, "Services updated");
4803        // We don't need any refresh here as accounts/clients/readers sidtabs.ok/sidtabs.no are unaffected!
4804        if(write_services() != 0) { tpl_addMsg(vars, "Write Config failed!"); }
4805
4806        for(sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab = sidtab->next) { ; }
4807    }
4808
4809    tpl_addVar(vars, TPLADD, "LABEL", xml_encode(vars, sidtab->label));
4810    tpl_addVar(vars, TPLADD, "LABELENC", urlencode(vars, sidtab->label));
4811
4812    if(sidtab)
4813    {
4814        for(i = 0; i < sidtab->num_caid; i++)
4815        {
4816            if(i == 0) { tpl_printf(vars, TPLADD, "CAIDS", "%04X", sidtab->caid[i]); }
4817            else { tpl_printf(vars, TPLAPPEND, "CAIDS", ",%04X", sidtab->caid[i]); }
4818        }
4819        for(i = 0; i < sidtab->num_provid; i++)
4820        {
4821            if(i == 0) { tpl_printf(vars, TPLADD, "PROVIDS", "%06X", sidtab->provid[i]); }
4822            else { tpl_printf(vars, TPLAPPEND, "PROVIDS", ",%06X", sidtab->provid[i]); }
4823        }
4824        for(i = 0; i < sidtab->num_srvid; i++)
4825        {
4826            if(i == 0) { tpl_printf(vars, TPLADD, "SRVIDS", "%04X", sidtab->srvid[i]); }
4827            else { tpl_printf(vars, TPLAPPEND, "SRVIDS", ",%04X", sidtab->srvid[i]); }
4828        }
4829    }
4830    return tpl_getTpl(vars, "SERVICEEDIT");
4831}
4832
4833static void delete_from_SIDTABBITS(SIDTABBITS * orgsidtab, int32_t position, int32_t sidtablength)
4834{
4835    if(*orgsidtab)
4836    {
4837        int32_t i;
4838        SIDTABBITS newsidtab = 0;
4839        for(i = 0; i < position; ++i)
4840        {
4841            if(*orgsidtab & ((SIDTABBITS)1 << i))
4842                { newsidtab |= ((SIDTABBITS)1 << i); }
4843        }
4844        for(; i < sidtablength; ++i)
4845        {
4846            if(*orgsidtab & ((SIDTABBITS)1 << (i + 1)))
4847                { newsidtab |= ((SIDTABBITS)1 << i); }
4848        }
4849        *orgsidtab = newsidtab;
4850    }
4851}
4852
4853static char *send_oscam_services(struct templatevars * vars, struct uriparams * params)
4854{
4855    struct s_sidtab *sidtab;
4856    char *service = getParam(params, "service");
4857    char channame[32];
4858    int32_t i, counter = 0;
4859
4860    setActiveMenu(vars, MNU_SERVICES);
4861
4862    if(strcmp(getParam(params, "action"), "delete") == 0)
4863    {
4864        if(cfg.http_readonly)
4865        {
4866            tpl_addMsg(vars, "Sorry, Webif is in readonly mode. No deletion will be made!");
4867        }
4868        else
4869        {
4870            struct s_sidtab *sidtab_prev = NULL;
4871            int32_t sidtablength = -1;
4872            int32_t position = 0;
4873
4874            // Calculate sidtablength before deletion so that updating sidtabs is faster
4875            for(sidtab = cfg.sidtab; sidtab; sidtab = sidtab->next)
4876                { ++sidtablength; }
4877
4878            for(sidtab = cfg.sidtab; sidtab; sidtab = sidtab->next)
4879            {
4880                if(strcmp(sidtab->label, service) == 0)
4881                {
4882                    struct s_auth *account;
4883                    struct s_client *cl;
4884                    struct s_reader *rdr;
4885
4886                    if(!sidtab_prev)
4887                        { cfg.sidtab = sidtab->next; }
4888                    else
4889                        { sidtab_prev->next = sidtab->next; }
4890
4891                    for(account = cfg.account; (account