source: trunk/oscam-http.c @ 5375

Last change on this file since 5375 was 5370, checked in by Admin, 8 years ago

Cleanup memory in pipe on client exit. Fix some possible segfault sources. Fix wrong display of au parameter on WebIf status page if config includes an empty au line.

File size: 130.5 KB
Line 
1#include "globals.h"
2#ifdef WEBIF
3//
4// OSCam HTTP server module
5//
6
7#include <stdio.h>
8#include <string.h>
9#include <time.h>
10#include <sys/stat.h>
11#include <dirent.h>
12#include <sys/socket.h>
13#include "oscam-http-helpers.c"
14#include "module-cccam.h"
15#include "module-cccshare.h"
16
17extern void restart_cardreader(struct s_reader *rdr, int32_t restart);
18
19static int8_t running = 1;
20static pthread_t httpthread;
21pthread_mutex_t http_lock;
22
23pthread_key_t getip;
24
25#ifdef CS_ANTICASC
26static void kill_ac_client(void)
27{
28        struct s_client *cl;
29        for (cl=first_client->next; cl ; cl=cl->next)
30        if (cl->typ=='a') {
31             cs_accounts_chk();
32            break;
33        }
34}
35#endif
36
37void refresh_oscam(enum refreshtypes refreshtype) {
38
39    switch (refreshtype) {
40        case REFR_ACCOUNTS:
41        cs_log("Refresh Accounts requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
42
43        cs_accounts_chk();
44        break;
45
46        case REFR_READERS:
47        cs_card_info();
48        cs_log("Refresh Reader/Tiers requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
49        break;
50
51        case REFR_SERVER:
52        cs_log("Refresh Server requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
53        //kill(first_client->pid, SIGHUP);
54        //todo how I can refresh the server after global settings
55        break;
56
57        case REFR_SERVICES:
58        cs_log("Refresh Services requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
59        //init_sidtab();
60        cs_accounts_chk();
61        break;
62
63#ifdef CS_ANTICASC
64        case REFR_ANTICASC:
65        cs_log("Refresh Anticascading requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
66        kill_ac_client();
67#endif
68        default:
69            break;
70    }
71}
72
73char *send_oscam_config_global(struct templatevars *vars, struct uriparams *params) {
74    int32_t i;
75
76    if (strcmp(getParam(params, "action"), "execute") == 0) {
77        for(i = 0; i < (*params).paramcount; ++i) {
78            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
79                //tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
80                //we use the same function as used for parsing the config tokens
81
82                chk_t_global((*params).params[i], (*params).values[i]);
83            }
84        }
85        if(cfg.usrfile == NULL) cfg.disableuserfile = 1;
86        if(cfg.mailfile == NULL) cfg.disablemail = 1;
87        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration Global done. You should restart OSCam now.</B><BR><BR>");
88        if(write_config()==0) refresh_oscam(REFR_SERVER);
89        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
90    }
91    if (cfg.srvip != 0)
92    tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.srvip));
93    tpl_printf(vars, TPLADD, "NICE", "%d", cfg.nice);
94    tpl_printf(vars, TPLADD, "BINDWAIT", "%d", cfg.bindwait);
95    tpl_printf(vars, TPLADD, "NETPRIO", "%ld", cfg.netprio);
96
97
98    if (cfg.usrfile != NULL) tpl_addVar(vars, TPLADD, "USERFILE", cfg.usrfile);
99    if (cfg.disableuserfile == 1) tpl_addVar(vars, TPLADD, "DISABLEUSERFILECHECKED", "selected");
100    if(cfg.usrfileflag == 1) tpl_addVar(vars, TPLADD, "USERFILEFLAGCHECKED", "selected");
101    if (cfg.mailfile != NULL) tpl_addVar(vars, TPLADD, "MAILFILE", cfg.mailfile);
102    if (cfg.disablemail == 1) tpl_addVar(vars, TPLADD, "DISABLEMAILCHECKED", "selected");
103
104    char *value = mk_t_logfile();
105    tpl_addVar(vars, TPLADD, "LOGFILE", value);
106    free_mk_t(value);
107    if(cfg.disablelog == 1) tpl_addVar(vars, TPLADD, "DISABLELOGCHECKED", "selected");
108    tpl_printf(vars, TPLADD, "MAXLOGSIZE", "%d", cfg.max_log_size);
109
110    if (cfg.cwlogdir != NULL) tpl_addVar(vars, TPLADD, "CWLOGDIR", cfg.cwlogdir);
111    if (cfg.emmlogdir != NULL) tpl_addVar(vars, TPLADD, "EMMLOGDIR", cfg.emmlogdir);
112    if (cfg.saveinithistory == 1)   tpl_addVar(vars, TPLADD, "SAVEINITHISTORYCHECKED", "selected");
113    tpl_printf(vars, TPLADD, "LOGHISTORYSIZE", "%u", cfg.loghistorysize);
114
115    tpl_printf(vars, TPLADD, "CLIENTTIMEOUT", "%u", cfg.ctimeout);
116    tpl_printf(vars, TPLADD, "FALLBACKTIMEOUT", "%u", cfg.ftimeout);
117    tpl_printf(vars, TPLADD, "CLIENTMAXIDLE", "%u", cfg.cmaxidle);
118    tpl_printf(vars, TPLADD, "CACHEDELAY", "%u", cfg.delay);
119
120    tpl_printf(vars, TPLADD, "SLEEP", "%d", cfg.tosleep);
121    if (cfg.ulparent == 1) tpl_addVar(vars, TPLADD, "UNLOCKPARENTALCHECKED", "selected");
122
123    tpl_printf(vars, TPLADD, "SERIALTIMEOUT", "%d", cfg.srtimeout);
124
125
126    if (cfg.waitforcards == 1)  tpl_addVar(vars, TPLADD, "WAITFORCARDSCHECKED", "selected");
127    tpl_printf(vars, TPLADD, "EXTRADELAY", "%d", cfg.waitforcards_extra_delay);
128    if (cfg.preferlocalcards == 1)  tpl_addVar(vars, TPLADD, "PREFERLOCALCARDSCHECKED", "selected");
129
130    if (cfg.c35_suppresscmd08)
131        tpl_addVar(vars, TPLADD, "SUPPRESSCMD08", "checked");
132
133    if (cfg.reader_restart_seconds)
134        tpl_printf(vars, TPLADD, "READERRESTARTSECONDS", "%d", cfg.reader_restart_seconds);
135
136    if (cfg.dropdups)
137        tpl_addVar(vars, TPLADD, "DROPDUPSCHECKED", "selected");
138
139    if (cfg.resolve_gethostbyname == 1)
140        tpl_addVar(vars, TPLADD, "RESOLVER1", "selected");
141    else
142        tpl_addVar(vars, TPLADD, "RESOLVER0", "selected");
143
144    tpl_printf(vars, TPLADD, "FAILBANTIME", "%d", cfg.failbantime);
145    tpl_printf(vars, TPLADD, "FAILBANCOUNT", "%d", cfg.failbancount);
146
147#ifdef CS_WITH_DOUBLECHECK
148    if(cfg.double_check == 1)
149        tpl_addVar(vars, TPLADD, "DCHECKCSELECTED", "selected");
150#endif
151
152    return tpl_getTpl(vars, "CONFIGGLOBAL");
153}
154
155#ifdef WITH_LB
156char *send_oscam_config_loadbalancer(struct templatevars *vars, struct uriparams *params) {
157    int32_t i;
158
159    if (strcmp(getParam(params, "button"), "Load Stats") == 0) {
160        clear_all_stat();
161        load_stat_from_file();
162        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Stats loades from file</B><BR><BR>");
163    }
164
165    if (strcmp(getParam(params, "button"), "Save Stats") == 0) {
166        save_stat_to_file(1);
167        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Stats saved to file</B><BR><BR>");
168    }
169
170    if (strcmp(getParam(params, "button"), "Clear Stats") == 0) {
171        clear_all_stat();
172        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Stats cleared completly</B><BR><BR>");
173    }
174
175    if (strcmp(getParam(params, "action"),"execute") == 0) {
176        for(i = 0; i < (*params).paramcount; ++i) {
177            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
178                //tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
179                //we use the same function as used for parsing the config tokens
180                chk_t_global((*params).params[i], (*params).values[i]);
181            }
182        }
183        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration Loadbalancer done.</B><BR><BR>");
184        if(write_config()==0) refresh_oscam(REFR_SERVER);
185        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
186    }
187
188    tpl_printf(vars, TPLADD, "TMP", "LBMODE%d", cfg.lb_mode);
189    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
190
191    tpl_printf(vars, TPLADD, "LBSAVE", "%d",cfg.lb_save);
192    tpl_printf(vars, TPLADD, "LBSAVEPATH", cfg.lb_savepath?cfg.lb_savepath:"");
193
194    tpl_printf(vars, TPLADD, "LBNBESTREADERS", "%d",cfg.lb_nbest_readers);
195    char *value = mk_t_caidvaluetab(&cfg.lb_nbest_readers_tab);
196    tpl_printf(vars, TPLADD, "LBNBESTPERCAID", value);
197    free_mk_t(value);
198    tpl_printf(vars, TPLADD, "LBNFBREADERS", "%d",cfg.lb_nfb_readers);
199    tpl_printf(vars, TPLADD, "LBMAXREADERS", "%d",cfg.lb_max_readers);
200    tpl_printf(vars, TPLADD, "LBMINECMCOUNT", "%d",cfg.lb_min_ecmcount);
201    tpl_printf(vars, TPLADD, "LBMAXECEMCOUNT", "%d",cfg.lb_max_ecmcount);
202    tpl_printf(vars, TPLADD, "LBRETRYLIMIT", "%d",cfg.lb_retrylimit);
203
204    value = mk_t_caidvaluetab(&cfg.lb_retrylimittab);
205    tpl_printf(vars, TPLADD, "LBRETRYLIMITS", value);
206    free_mk_t(value);
207
208    tpl_printf(vars, TPLADD, "LBREOPENSECONDS", "%d",cfg.lb_reopen_seconds);
209    tpl_printf(vars, TPLADD, "LBCLEANUP", "%d",cfg.lb_stat_cleanup);
210    if (cfg.lb_use_locking) tpl_addVar(vars, TPLADD, "USELOCKINGCHECKED", "selected");
211    if (cfg.lb_reopen_mode) tpl_addVar(vars, TPLADD, "REOPENMODE", "selected");
212
213    value = mk_t_caidtab(&cfg.lb_noproviderforcaid);
214    tpl_addVar(vars, TPLADD, "LBNOPROVIDERFORCAID", value);
215    free_mk_t(value);
216
217    if (cfg.lb_auto_betatunnel) tpl_addVar(vars, TPLADD, "LBAUTOBETATUNNEL", "selected");
218
219    return tpl_getTpl(vars, "CONFIGLOADBALANCER");
220}
221#endif
222
223char *send_oscam_config_camd33(struct templatevars *vars, struct uriparams *params) {
224    int32_t i;
225
226    if (strcmp(getParam(params, "action"), "execute") == 0) {
227        for(i = 0; i < (*params).paramcount; ++i) {
228            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
229                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
230                //we use the same function as used for parsing the config tokens
231                chk_t_camd33((*params).params[i], (*params).values[i]);
232            }
233        }
234        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration camd33 done. You should restart OSCam now.</B><BR><BR>");
235        if(write_config()==0) refresh_oscam(REFR_SERVER);
236        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
237    }
238
239    if (cfg.c33_port) {
240        tpl_printf(vars, TPLADD, "PORT", "%d", cfg.c33_port);
241        if (cfg.c33_srvip != 0)     tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.c33_srvip));
242        if (cfg.c33_passive == 1)       tpl_addVar(vars, TPLADD, "PASSIVECHECKED", "selected");
243
244        for (i = 0; i < (int) sizeof(cfg.c33_key); ++i) tpl_printf(vars, TPLAPPEND, "KEY", "%02X",cfg.c33_key[i]);
245        char *value = mk_t_iprange(cfg.c33_plain);
246        tpl_addVar(vars, TPLADD, "NOCRYPT", value);
247        free_mk_t(value);
248    }
249
250    return tpl_getTpl(vars, "CONFIGCAMD33");
251}
252
253char *send_oscam_config_camd35(struct templatevars *vars, struct uriparams *params) {
254    int32_t i;
255    if ((strcmp(getParam(params, "action"),"execute") == 0) && (getParam(params, "port"))[0]) {
256        for(i = 0; i < (*params).paramcount; ++i) {
257            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
258                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
259                //we use the same function as used for parsing the config tokens
260                chk_t_camd35((*params).params[i], (*params).values[i]);
261            }
262        }
263        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration camd35 done. You should restart OSCam now.</B><BR><BR>");
264        if(write_config()==0) refresh_oscam(REFR_SERVER);
265        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
266    }
267
268    if (cfg.c35_port) {
269        tpl_printf(vars, TPLADD, "PORT", "%d", cfg.c35_port);
270        if (cfg.c35_srvip != 0)
271            tpl_addVar(vars, TPLAPPEND, "SERVERIP", cs_inet_ntoa(cfg.c35_srvip));
272
273        if (cfg.c35_udp_suppresscmd08)
274            tpl_addVar(vars, TPLADD, "SUPPRESSCMD08UDP", "checked");
275
276    }
277    return tpl_getTpl(vars, "CONFIGCAMD35");
278}
279
280char *send_oscam_config_camd35tcp(struct templatevars *vars, struct uriparams *params) {
281    int32_t i;
282    if ((strcmp(getParam(params, "action"),"execute") == 0) && (getParam(params, "port"))[0]) {
283        for(i = 0; i < (*params).paramcount; ++i) {
284            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
285                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
286                //we use the same function as used for parsing the config tokens
287                chk_t_camd35_tcp((*params).params[i], (*params).values[i]);
288            }
289        }
290        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration camd35 TCP done. You should restart OSCam now.</B><BR><BR>");
291        if(write_config()==0) refresh_oscam(REFR_SERVER);
292        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
293    }
294
295    if ((cfg.c35_tcp_ptab.nports > 0) && (cfg.c35_tcp_ptab.ports[0].s_port > 0)) {
296
297        char *value = mk_t_camd35tcp_port();
298        tpl_addVar(vars, TPLADD, "PORT", value);
299        free_mk_t(value);
300
301        if (cfg.c35_tcp_srvip != 0)
302            tpl_addVar(vars, TPLAPPEND, "SERVERIP", cs_inet_ntoa(cfg.c35_tcp_srvip));
303
304        if (cfg.c35_tcp_suppresscmd08)
305            tpl_addVar(vars, TPLADD, "SUPPRESSCMD08TCP", "checked");
306    }
307    return tpl_getTpl(vars, "CONFIGCAMD35TCP");
308}
309
310char *send_oscam_config_newcamd(struct templatevars *vars, struct uriparams *params) {
311    int32_t i;
312    if (strcmp(getParam(params, "action"),"execute") == 0) {
313        for(i = 0; i < (*params).paramcount; ++i) {
314            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
315                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
316                //we use the same function as used for parsing the config tokens
317                chk_t_newcamd((*params).params[i], (*params).values[i]);
318            }
319        }
320        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration Newcamd done. You should restart OSCam now.</B><BR><BR>");
321        if(write_config()==0) refresh_oscam(REFR_SERVER);
322        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
323    }
324
325    if ((cfg.ncd_ptab.nports > 0) && (cfg.ncd_ptab.ports[0].s_port > 0)) {
326
327        char *value = mk_t_newcamd_port();
328        tpl_addVar(vars, TPLADD, "PORT", value);
329        free_mk_t(value);
330
331        if (cfg.ncd_srvip != 0)
332            tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.ncd_srvip));
333
334        for (i = 0; i < 14; i++) tpl_printf(vars, TPLAPPEND, "KEY", "%02X", cfg.ncd_key[i]);
335
336        value = mk_t_iprange(cfg.ncd_allowed);
337        tpl_addVar(vars, TPLADD, "ALLOWED", value);
338        free_mk_t(value);
339
340        if (cfg.ncd_keepalive)
341            tpl_addVar(vars, TPLADD, "KEEPALIVE", "checked");
342        if (cfg.ncd_mgclient)
343            tpl_addVar(vars, TPLADD, "MGCLIENTCHK", "checked");
344    }
345    return tpl_getTpl(vars, "CONFIGNEWCAMD");
346}
347
348char *send_oscam_config_radegast(struct templatevars *vars, struct uriparams *params) {
349    int32_t i;
350    if (strcmp(getParam(params, "action"),"execute") == 0) {
351        for(i = 0; i < (*params).paramcount; ++i) {
352            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
353                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
354                //we use the same function as used for parsing the config tokens
355                chk_t_radegast((*params).params[i], (*params).values[i]);
356            }
357        }
358        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration Radegast done. You should restart OSCam now.</B><BR><BR>");
359        if(write_config()==0) refresh_oscam(REFR_SERVER);
360        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
361    }
362    tpl_printf(vars, TPLADD, "PORT", "%d", cfg.rad_port);
363    if (cfg.rad_srvip != 0)
364    tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.rad_srvip));
365    tpl_addVar(vars, TPLADD, "USER", cfg.rad_usr);
366
367    char *value = mk_t_iprange(cfg.rad_allowed);
368    tpl_addVar(vars, TPLADD, "ALLOWED", value);
369    free_mk_t(value);
370
371    return tpl_getTpl(vars, "CONFIGRADEGAST");
372}
373
374#ifdef MODULE_CCCAM
375char *send_oscam_config_cccam(struct templatevars *vars, struct uriparams *params) {
376
377    if (strcmp(getParam(params, "button"), "Refresh global list") == 0) {
378        cs_debug_mask(D_TRACE, "Entitlements: Refresh Shares start");
379        refresh_shares();
380        cs_debug_mask(D_TRACE, "Entitlements: Refresh Shares finished");
381        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Refresh Shares started</B><BR><BR>");
382    }
383
384    int32_t i;
385    if (strcmp(getParam(params, "action"),"execute") == 0) {
386        for(i = 0; i < (*params).paramcount; ++i) {
387            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
388                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
389                //we use the same function as used for parsing the config tokens
390                chk_t_cccam((*params).params[i], (*params).values[i]);
391            }
392        }
393        if(write_config()==0) refresh_oscam(REFR_SERVER);
394        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
395        cc_update_nodeid();
396    }
397
398    char *value = mk_t_cccam_port();
399    tpl_addVar(vars, TPLAPPEND, "PORT", value);
400    free_mk_t(value);
401   
402    tpl_printf(vars, TPLADD, "RESHARE", "%d", cfg.cc_reshare);
403
404    if (!strcmp((char*)cfg.cc_version,"2.0.11")) {
405        tpl_addVar(vars, TPLADD, "VERSIONSELECTED0", "selected");
406    } else if (!strcmp((char*)cfg.cc_version,"2.1.1")) {
407        tpl_addVar(vars, TPLADD, "VERSIONSELECTED1", "selected");
408    } else if (!strcmp((char*)cfg.cc_version,"2.1.2")) {
409        tpl_addVar(vars, TPLADD, "VERSIONSELECTED2", "selected");
410    } else if (!strcmp((char*)cfg.cc_version,"2.1.3")) {
411        tpl_addVar(vars, TPLADD, "VERSIONSELECTED3", "selected");
412    } else if (!strcmp((char*)cfg.cc_version,"2.1.4")) {
413        tpl_addVar(vars, TPLADD, "VERSIONSELECTED4", "selected");
414    } else if (!strcmp((char*)cfg.cc_version,"2.2.0")) {
415        tpl_addVar(vars, TPLADD, "VERSIONSELECTED5", "selected");
416    } else if (!strcmp((char*)cfg.cc_version,"2.2.1")) {
417        tpl_addVar(vars, TPLADD, "VERSIONSELECTED6", "selected");
418    }
419
420    tpl_printf(vars, TPLADD, "UPDATEINTERVAL", "%d", cfg.cc_update_interval);
421    if (cfg.cc_stealth)
422        tpl_printf(vars, TPLADD, "STEALTH", "selected");
423       
424    tpl_printf(vars, TPLADD, "NODEID", "%02X%02X%02X%02X%02X%02X%02X%02X",
425        cfg.cc_fixed_nodeid[0], cfg.cc_fixed_nodeid[1], cfg.cc_fixed_nodeid[2], cfg.cc_fixed_nodeid[3],
426        cfg.cc_fixed_nodeid[4], cfg.cc_fixed_nodeid[5], cfg.cc_fixed_nodeid[6], cfg.cc_fixed_nodeid[7]);
427
428    tpl_printf(vars, TPLADD, "TMP", "MINIMIZECARDSELECTED%d", cfg.cc_minimize_cards);
429    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
430
431    tpl_printf(vars, TPLADD, "TMP", "RESHAREMODE%d", cfg.cc_reshare_services);
432    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
433
434    if (cfg.cc_ignore_reshare)
435        tpl_printf(vars, TPLADD, "IGNORERESHARE", "selected");
436
437    if (cfg.cc_forward_origin_card)
438        tpl_printf(vars, TPLADD, "FORWARDORIGINCARD", "selected");
439
440    if (cfg.cc_keep_connected)
441        tpl_printf(vars, TPLADD, "KEEPCONNECTED", "selected");
442
443
444    return tpl_getTpl(vars, "CONFIGCCCAM");
445}
446#endif
447
448char *send_oscam_config_monitor(struct templatevars *vars, struct uriparams *params) {
449    int32_t i;
450    if (strcmp(getParam(params, "action"),"execute") == 0) {
451        for(i = 0; i < (*params).paramcount; ++i) {
452            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
453                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
454
455                //we use the same function as used for parsing the config tokens
456                if (strstr((*params).params[i], "http")) {
457                    chk_t_webif((*params).params[i], (*params).values[i]);
458                }
459#ifdef LCDSUPPORT
460                else if (strstr((*params).params[i], "lcd")) {
461                    chk_t_lcd((*params).params[i], (*params).values[i]);
462                }
463#endif
464                else {
465                    chk_t_monitor((*params).params[i], (*params).values[i]);
466                }
467            }
468        }
469        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration Monitor done. You should restart OSCam now.</B><BR><BR>");
470        if(write_config()==0) refresh_oscam(REFR_SERVER);
471        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
472    }
473    tpl_printf(vars, TPLADD, "MONPORT", "%d", cfg.mon_port);
474    if (cfg.mon_srvip != 0)
475    tpl_addVar(vars, TPLADD, "SERVERIP", cs_inet_ntoa(cfg.mon_srvip));
476    tpl_printf(vars, TPLADD, "AULOW", "%d", cfg.mon_aulow);
477    tpl_printf(vars, TPLADD, "HIDECLIENTTO", "%d", cfg.mon_hideclient_to);
478    if(cfg.mon_appendchaninfo)
479        tpl_addVar(vars, TPLADD, "APPENDCHANINFO", "checked");
480
481#ifdef WITH_SSL
482    if(cfg.http_use_ssl)
483        tpl_printf(vars, TPLADD, "HTTPPORT", "+%d", cfg.http_port);
484    else
485        tpl_printf(vars, TPLADD, "HTTPPORT", "%d", cfg.http_port);
486#else
487    tpl_printf(vars, TPLADD, "HTTPPORT", "%d", cfg.http_port);
488#endif
489
490    tpl_addVar(vars, TPLADD, "HTTPUSER", cfg.http_user);
491    tpl_addVar(vars, TPLADD, "HTTPPASSWORD", cfg.http_pwd);
492
493    // css style selector
494    if(strlen(cfg.http_css) == 0) {
495        tpl_addVar(vars, TPLADD, "CSSOPTIONS", "\t\t\t\t\t\t<option value=\"\" selected>embedded</option>\n");
496    } else {
497        tpl_addVar(vars, TPLADD, "CSSOPTIONS", "\t\t\t\t\t\t<option value=\"\">embedded</option>\n");
498    }
499
500    DIR *hdir;
501    struct dirent *entry;
502    hdir = opendir(cs_confdir);
503    do {
504        entry = readdir(hdir);
505        if ((entry) && (strstr(entry->d_name, ".css"))) {
506            if (strstr(cfg.http_css, entry->d_name)) {
507                tpl_printf(vars, TPLAPPEND, "CSSOPTIONS", "\t\t\t\t\t\t<option value=\"%s%s\" selected>%s%s</option>\n",cs_confdir,entry->d_name,cs_confdir,entry->d_name);
508            } else {
509                tpl_printf(vars, TPLAPPEND, "CSSOPTIONS", "\t\t\t\t\t\t<option value=\"%s%s\">%s%s</option>\n",cs_confdir,entry->d_name,cs_confdir,entry->d_name);
510            }
511        }
512    } while (entry);
513    closedir(hdir);
514
515    if (cfg.http_help_lang[0])
516        tpl_addVar(vars, TPLADD, "HTTPHELPLANG", cfg.http_help_lang);
517    else
518        tpl_addVar(vars, TPLADD, "HTTPHELPLANG", "en");
519
520    tpl_printf(vars, TPLADD, "HTTPREFRESH", "%d", cfg.http_refresh);
521    tpl_addVar(vars, TPLADD, "HTTPTPL", cfg.http_tpl);
522    tpl_addVar(vars, TPLADD, "HTTPSCRIPT", cfg.http_script);
523    tpl_addVar(vars, TPLADD, "HTTPJSCRIPT", cfg.http_jscript);
524
525    if (cfg.http_hide_idle_clients > 0) tpl_addVar(vars, TPLADD, "CHECKED", "checked");
526
527    char *value = mk_t_iprange(cfg.mon_allowed);
528    tpl_addVar(vars, TPLADD, "NOCRYPT", value);
529    free_mk_t(value);
530   
531    value = mk_t_iprange(cfg.http_allowed);
532    tpl_addVar(vars, TPLADD, "HTTPALLOW", value);
533    free_mk_t(value);
534
535    tpl_addVar(vars, TPLADD, "HTTPDYNDNS", (char*)cfg.http_dyndns);
536
537    //Monlevel selector
538    tpl_printf(vars, TPLADD, "TMP", "MONSELECTED%d", cfg.mon_level);
539    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
540
541    if (cfg.http_full_cfg)
542        tpl_addVar(vars, TPLADD, "HTTPSAVEFULLSELECT", "selected");
543
544#ifdef LCDSUPPORT
545    if (cfg.lcd_output_path != NULL)
546        tpl_addVar(vars, TPLADD, "LCDOUTPUTPATH", cfg.lcd_output_path);
547    if (cfg.lcd_hide_idle)
548        tpl_addVar(vars, TPLADD, "LCDHIDEIDLE", "selected");
549    tpl_printf(vars, TPLADD, "LCDREFRESHINTERVAL", "%d", cfg.lcd_write_intervall);
550#endif
551
552    return tpl_getTpl(vars, "CONFIGMONITOR");
553}
554
555char *send_oscam_config_serial(struct templatevars *vars, struct uriparams *params) {
556    int32_t i;
557    char *saveptr1 = NULL;
558    if (strcmp(getParam(params, "action"),"execute") == 0) {
559        for(i = 0; i < (*params).paramcount; ++i) {
560            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
561                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
562                //we use the same function as used for parsing the config tokens
563                chk_t_serial((*params).params[i], (*params).values[i]);
564            }
565        }
566        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration Serial done. You should restart OSCam now.</B><BR><BR>");
567        if(write_config()==0) refresh_oscam(REFR_SERVER);
568        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
569    }
570
571    if (cfg.ser_device[0]){
572        char sdevice[512];
573        cs_strncpy(sdevice, cfg.ser_device, sizeof(sdevice));
574        char *ptr;
575        char delimiter[2]; delimiter[0] = 1; delimiter[1] = '\0';
576        for(ptr = strtok_r(sdevice, delimiter, &saveptr1); ptr; ptr = strtok_r(NULL, delimiter, &saveptr1)){
577            tpl_addVar(vars, TPLADD, "SERIALDEVICE", ptr);
578            tpl_addVar(vars, TPLAPPEND, "DEVICES", tpl_getTpl(vars, "CONFIGSERIALDEVICEBIT"));
579        }
580    }
581
582    tpl_addVar(vars, TPLADD, "SERIALDEVICE", "");
583    tpl_addVar(vars, TPLAPPEND, "DEVICES", tpl_getTpl(vars, "CONFIGSERIALDEVICEBIT"));
584
585    return tpl_getTpl(vars, "CONFIGSERIAL");
586}
587
588#ifdef HAVE_DVBAPI
589char *send_oscam_config_dvbapi(struct templatevars *vars, struct uriparams *params) {
590    int32_t i;
591    if (strcmp(getParam(params, "action"),"execute") == 0) {
592        for(i = 0; i < (*params).paramcount; ++i) {
593            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
594                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
595                //we use the same function as used for parsing the config tokens
596                chk_t_dvbapi((*params).params[i], (*params).values[i]);
597            }
598        }
599        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration DVB Api done. You should restart OSCam now.</B><BR><BR>");
600        if(write_config()==0) refresh_oscam(REFR_SERVER);
601        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
602    }
603
604    if (cfg.dvbapi_enabled > 0)
605        tpl_addVar(vars, TPLADD, "ENABLEDCHECKED", "checked");
606
607    if (cfg.dvbapi_au > 0)
608        tpl_addVar(vars, TPLADD, "AUCHECKED", "checked");
609
610    tpl_printf(vars, TPLADD, "BOXTYPE", "<option value=\"\"%s>None</option>\n", cfg.dvbapi_boxtype == 0 ? " selected" : "");
611    for (i=1; i<=BOXTYPES; i++) {
612        tpl_printf(vars, TPLAPPEND, "BOXTYPE", "<option%s>%s</option>\n", cfg.dvbapi_boxtype == i ? " selected" : "", boxdesc[i]);
613    }
614
615    if(cfg.dvbapi_usr[0])
616        tpl_addVar(vars, TPLADD, "USER", cfg.dvbapi_usr);
617
618    //PMT Mode
619    tpl_printf(vars, TPLADD, "TMP", "PMTMODESELECTED%d", cfg.dvbapi_pmtmode);
620    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
621
622    //Request Mode
623    tpl_printf(vars, TPLADD, "TMP", "REQMODESELECTED%d", cfg.dvbapi_requestmode);
624    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
625
626    return tpl_getTpl(vars, "CONFIGDVBAPI");
627}
628#endif
629
630#ifdef CS_ANTICASC
631char *send_oscam_config_anticasc(struct templatevars *vars, struct uriparams *params) {
632    int32_t i;
633    if (strcmp(getParam(params, "action"),"execute") == 0) {
634        for(i = 0; i < (*params).paramcount; ++i) {
635            if ((strcmp((*params).params[i], "part")) && (strcmp((*params).params[i], "action"))) {
636                tpl_printf(vars, TPLAPPEND, "MESSAGE", "Parameter: %s set to Value: %s<BR>\n", (*params).params[i], (*params).values[i]);
637                //we use the same function as used for parsing the config tokens
638                chk_t_ac((*params).params[i], (*params).values[i]);
639            }
640        }
641        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<BR><BR><B>Configuration Anticascading done. You should restart OSCam now.</B><BR><BR>");
642        refresh_oscam(REFR_ANTICASC);
643        if(write_config()==0) refresh_oscam(REFR_SERVER);
644        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
645    }
646    if (cfg.ac_enabled > 0) tpl_addVar(vars, TPLADD, "CHECKED", "checked");
647    tpl_printf(vars, TPLADD, "NUMUSERS", "%d", cfg.ac_users);
648    tpl_printf(vars, TPLADD, "SAMPLETIME", "%d", cfg.ac_stime);
649    tpl_printf(vars, TPLADD, "SAMPLES", "%d", cfg.ac_samples);
650
651    tpl_printf(vars, TPLADD, "TMP", "PENALTY%d", cfg.ac_penalty);
652    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
653
654    tpl_addVar(vars, TPLADD, "ACLOGFILE", cfg.ac_logfile);
655    tpl_printf(vars, TPLADD, "FAKEDELAY", "%d", cfg.ac_fakedelay);
656    tpl_printf(vars, TPLADD, "DENYSAMPLES", "%d", cfg.ac_denysamples);
657    return tpl_getTpl(vars, "CONFIGANTICASC");
658}
659#endif
660
661char *send_oscam_config(struct templatevars *vars, struct uriparams *params) {
662    char *part = getParam(params, "part");
663    if (!strcmp(part,"camd33")) return send_oscam_config_camd33(vars, params);
664    else if (!strcmp(part,"camd35")) return send_oscam_config_camd35(vars, params);
665    else if (!strcmp(part,"camd35tcp")) return send_oscam_config_camd35tcp(vars, params);
666    else if (!strcmp(part,"newcamd")) return send_oscam_config_newcamd(vars, params);
667    else if (!strcmp(part,"radegast")) return send_oscam_config_radegast(vars, params);
668#ifdef MODULE_CCCAM
669    else if (!strcmp(part,"cccam")) return send_oscam_config_cccam(vars, params);
670#endif
671#ifdef HAVE_DVBAPI
672    else if (!strcmp(part,"dvbapi")) return send_oscam_config_dvbapi(vars, params);
673#endif
674#ifdef CS_ANTICASC
675    else if (!strcmp(part,"anticasc")) return send_oscam_config_anticasc(vars, params);
676#endif
677    else if (!strcmp(part,"monitor")) return send_oscam_config_monitor(vars, params);
678    else if (!strcmp(part,"serial")) return send_oscam_config_serial(vars, params);
679#ifdef WITH_LB
680    else if (!strcmp(part,"loadbalancer")) return send_oscam_config_loadbalancer(vars, params);
681#endif
682    else return send_oscam_config_global(vars, params);
683}
684
685void inactivate_reader(struct s_reader *rdr)
686{
687    remove_reader_from_active(rdr);
688    if (rdr->client)
689        kill_thread(rdr->client);
690}
691
692char *send_oscam_reader(struct templatevars *vars, struct uriparams *params) {
693    struct s_reader *rdr;
694    int32_t i;
695
696    if ((strcmp(getParam(params, "action"), "disable") == 0) || (strcmp(getParam(params, "action"), "enable") == 0)) {
697        if(cfg.http_readonly) {
698            tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Webif is in readonly mode. Enabling or disabling readers is not possible!</b><BR>");
699        } else {
700            rdr = get_reader_by_label(getParam(params, "label"));
701            if (rdr) {
702                if (strcmp(getParam(params, "action"), "enable") == 0) {
703                    if (!rdr->enable) {
704                        add_reader_to_active(rdr);
705                        rdr->enable = 1;
706                        restart_cardreader(rdr, 1);
707                    }
708                } else {
709                    if (rdr->enable) {
710                        rdr->enable = 0;
711                        inactivate_reader(rdr);
712                    }
713                }
714                if(write_server() != 0)
715                    tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
716            }
717        }
718    }
719
720    if (strcmp(getParam(params, "action"), "delete") == 0) {
721        if(cfg.http_readonly) {
722            tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Webif is in readonly mode. No deletion will be made!</b><BR>");
723        } else {
724            rdr = get_reader_by_label(getParam(params, "label"));
725            if (rdr) {
726                inactivate_reader(rdr);
727                ll_remove(configured_readers, rdr);
728               
729                free_reader(rdr);
730
731                if(write_server()==0) refresh_oscam(REFR_READERS);
732                else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
733            }
734        }
735    }
736
737    if (strcmp(getParam(params, "action"), "reread") == 0) {
738        rdr = get_reader_by_label(getParam(params, "label"));
739        if (rdr) {
740            //reset the counters
741            for (i = 0; i < 4; i++) {
742                rdr->emmerror[i] = 0;
743                rdr->emmwritten[i] = 0;
744                rdr->emmskipped[i] = 0;
745                rdr->emmblocked[i] = 0;
746            }
747            /*
748            if( rdr->enable == 1 && rdr->client->typ == 'r' && rdr->client->fd_m2c ) {
749                uchar dummy[1]={0x00};
750                write_to_pipe(rdr->client->fd_m2c, PIP_ID_CIN, dummy, 1);
751            }*/
752
753            refresh_oscam(REFR_READERS); // refresh all reader because  write pipe seams not work from here
754        }
755    }
756
757    LL_ITER itr = ll_iter_create(configured_readers);
758    for (i = 0, rdr = ll_iter_next(&itr); rdr && rdr->label[0]; rdr = ll_iter_next(&itr), i++);
759    tpl_printf(vars, TPLADD, "NEXTREADER", "Reader-%d", i); //Next Readername
760
761    ll_iter_reset(&itr); //going to iterate all configured readers
762    while ((rdr = ll_iter_next(&itr))) {
763
764        if(rdr->label[0] && rdr->typ) {
765
766            if (rdr->enable)
767                tpl_addVar(vars, TPLADD, "READERCLASS", "enabledreader");
768            else
769                tpl_addVar(vars, TPLADD, "READERCLASS", "disabledreader");
770
771            tpl_addVar(vars, TPLADD, "READERNAME", xml_encode(vars, rdr->label));
772            tpl_addVar(vars, TPLADD, "READERNAMEENC", urlencode(vars, rdr->label));
773            tpl_printf(vars, TPLADD, "EMMERRORUK", "%d", rdr->emmerror[UNKNOWN]);
774            tpl_printf(vars, TPLADD, "EMMERRORG", "%d", rdr->emmerror[GLOBAL]);
775            tpl_printf(vars, TPLADD, "EMMERRORS", "%d", rdr->emmerror[SHARED]);
776            tpl_printf(vars, TPLADD, "EMMERRORUQ", "%d", rdr->emmerror[UNIQUE]);
777
778            tpl_printf(vars, TPLADD, "EMMWRITTENUK", "%d", rdr->emmwritten[UNKNOWN]);
779            tpl_printf(vars, TPLADD, "EMMWRITTENG", "%d", rdr->emmwritten[GLOBAL]);
780            tpl_printf(vars, TPLADD, "EMMWRITTENS", "%d", rdr->emmwritten[SHARED]);
781            tpl_printf(vars, TPLADD, "EMMWRITTENUQ", "%d", rdr->emmwritten[UNIQUE]);
782
783            tpl_printf(vars, TPLADD, "EMMSKIPPEDUK", "%d", rdr->emmskipped[UNKNOWN]);
784            tpl_printf(vars, TPLADD, "EMMSKIPPEDG", "%d", rdr->emmskipped[GLOBAL]);
785            tpl_printf(vars, TPLADD, "EMMSKIPPEDS", "%d", rdr->emmskipped[SHARED]);
786            tpl_printf(vars, TPLADD, "EMMSKIPPEDUQ", "%d", rdr->emmskipped[UNIQUE]);
787
788            tpl_printf(vars, TPLADD, "EMMBLOCKEDUK", "%d", rdr->emmblocked[UNKNOWN]);
789            tpl_printf(vars, TPLADD, "EMMBLOCKEDG", "%d", rdr->emmblocked[GLOBAL]);
790            tpl_printf(vars, TPLADD, "EMMBLOCKEDS", "%d", rdr->emmblocked[SHARED]);
791            tpl_printf(vars, TPLADD, "EMMBLOCKEDUQ", "%d", rdr->emmblocked[UNIQUE]);
792
793            if (!(rdr->typ & R_IS_NETWORK)) { //reader is physical
794                tpl_addVar(vars, TPLADD, "REFRICO", "image?i=ICREF");
795                tpl_addVar(vars, TPLADD, "READERREFRESH", tpl_getTpl(vars, "READERREFRESHBIT"));
796                tpl_addVar(vars, TPLADD, "ENTICO", "image?i=ICENT");
797                tpl_addVar(vars, TPLADD, "ENTITLEMENT", tpl_getTpl(vars, "READERENTITLEBIT"));
798            } else {
799                tpl_addVar(vars, TPLADD, "READERREFRESH","");
800                if (rdr->typ == R_CCCAM) {
801                    tpl_addVar(vars, TPLADD, "ENTICO", "image?i=ICENT");
802                    tpl_addVar(vars, TPLADD, "ENTITLEMENT", tpl_getTpl(vars, "READERENTITLEBIT"));
803                } else {
804                    tpl_addVar(vars, TPLADD, "ENTITLEMENT","");
805                }
806            }
807
808            if(rdr->enable == 0) {
809                tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICENA");
810                tpl_addVar(vars, TPLADD, "SWITCHTITLE", "enable this reader");
811                tpl_addVar(vars, TPLADD, "SWITCH", "enable");
812            } else {
813                tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICDIS");
814                tpl_addVar(vars, TPLADD, "SWITCHTITLE", "disable this reader");
815                tpl_addVar(vars, TPLADD, "SWITCH", "disable");
816            }
817
818            tpl_addVar(vars, TPLADD, "CTYP", reader_get_type_desc(rdr, 0));
819
820            tpl_addVar(vars, TPLAPPEND, "READERLIST", tpl_getTpl(vars, "READERSBIT"));
821        }
822    }
823
824#ifdef HAVE_PCSC
825    tpl_addVar(vars, TPLAPPEND, "ADDPROTOCOL", "<option>pcsc</option>\n");
826#endif
827
828    for (i=0; i<CS_MAX_MOD; i++) {
829        if (cardreader[i].desc[0]!=0)
830            tpl_printf(vars, TPLAPPEND, "ADDPROTOCOL", "<option>%s</option>\n", cardreader[i].desc);
831    }
832
833    return tpl_getTpl(vars, "READERS");
834}
835
836char *send_oscam_reader_config(struct templatevars *vars, struct uriparams *params) {
837    int32_t i;
838    char *reader_ = getParam(params, "label");
839    char *value;
840
841    struct s_reader *rdr;
842
843    if(strcmp(getParam(params, "action"), "Add") == 0) {
844        // Add new reader
845        struct s_reader *newrdr;
846        if(!cs_malloc(&newrdr,sizeof(struct s_reader), -1)) return "0";
847        memset(newrdr, 0, sizeof(struct s_reader));
848        newrdr->next = NULL; // terminate list
849        newrdr->enable = 0; // do not start the reader because must configured before
850        ll_append(configured_readers, newrdr);
851        cs_strncpy(newrdr->pincode, "none", sizeof(newrdr->pincode));
852        for (i = 1; i < CS_MAXCAIDTAB; newrdr->ctab.mask[i++] = 0xffff);
853        for (i = 0; i < (*params).paramcount; ++i) {
854            if (strcmp((*params).params[i], "action"))
855                chk_reader((*params).params[i], (*params).values[i], newrdr);
856        }
857        if (newrdr->typ & R_IS_CASCADING) {
858            for (i=0; i<CS_MAX_MOD; i++) {
859                if (ph[i].num && newrdr->typ==ph[i].num) {
860                    newrdr->ph=ph[i];
861                    newrdr->ph.active=1;
862                }
863            }
864        }
865        reader_ = newrdr->label;
866    } else if(strcmp(getParam(params, "action"), "Save") == 0) {
867
868        rdr = get_reader_by_label(getParam(params, "label"));
869        if (rdr->typ & R_IS_NETWORK)
870            inactivate_reader(rdr); //Stop reader before reinitialization
871        char servicelabels[1024]="";
872
873        for(i = 0; i < (*params).paramcount; ++i) {
874            if ((strcmp((*params).params[i], "reader")) && (strcmp((*params).params[i], "action"))) {
875                if (!strcmp((*params).params[i], "services"))
876                    snprintf(servicelabels + strlen(servicelabels), sizeof(servicelabels) - strlen(servicelabels), "%s,", (*params).values[i]);
877                else
878                    /*if(strlen((*params).values[i]) > 0)*/
879                        chk_reader((*params).params[i], (*params).values[i], rdr);
880            }
881            //printf("param %s value %s\n",(*params).params[i], (*params).values[i]);
882        }
883        chk_reader("services", servicelabels, rdr);
884
885        if(write_server()==0) {
886            refresh_oscam(REFR_READERS);
887            // fixme: restart_cardreader causes segfaults sometimes
888            if (rdr->typ & R_IS_NETWORK)
889                restart_cardreader(rdr, 1); //physical readers make trouble if re-started
890        }
891        else
892            tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
893    }
894
895    rdr = get_reader_by_label(reader_);
896
897    tpl_addVar(vars, TPLADD, "READERNAME", rdr->label);
898
899    if(rdr->enable)
900        tpl_addVar(vars, TPLADD, "ENABLED", "checked");
901
902    tpl_addVar(vars, TPLADD, "ACCOUNT", rdr->r_usr);
903    tpl_addVar(vars, TPLADD, "PASSWORD", rdr->r_pwd);
904
905    for (i=0; i<14; i++)
906        tpl_printf(vars, TPLAPPEND, "NCD_KEY", "%02X", rdr->ncd_key[i]);
907
908    tpl_addVar(vars, TPLADD, "PINCODE", rdr->pincode);
909    if (rdr->emmfile) tpl_addVar(vars, TPLADD, "EMMFILE", (char *)rdr->emmfile);
910    tpl_printf(vars, TPLADD, "INACTIVITYTIMEOUT", "%d", rdr->tcp_ito);
911    tpl_printf(vars, TPLADD, "RECEIVETIMEOUT", "%d", rdr->tcp_rto);
912    if(rdr->ncd_disable_server_filt)
913        tpl_addVar(vars, TPLADD, "DISABLESERVERFILTERCHECKED", "checked");
914
915    if(rdr->fallback)
916        tpl_addVar(vars, TPLADD, "FALLBACKCHECKED", "checked");
917
918    tpl_printf(vars, TPLADD, "LOGPORT", "%d", rdr->log_port);
919
920    if(rdr->boxid)
921        tpl_printf(vars, TPLADD, "BOXID", "%08X", rdr->boxid);
922
923    if(rdr->fix_9993)
924        tpl_addVar(vars, TPLADD, "FIX9993CHECKED", "checked");
925
926    tpl_addVar(vars, TPLADD, "USER", rdr->r_usr);
927    tpl_addVar(vars, TPLADD, "PASS", rdr->r_pwd);
928
929    if(rdr->audisabled)
930        tpl_addVar(vars, TPLADD, "AUDISABLED", "checked");
931
932    if(rdr->auprovid)
933        tpl_printf(vars, TPLADD, "AUPROVID", "%06lX", rdr->auprovid);
934
935    if(rdr->force_irdeto)
936        tpl_addVar(vars, TPLADD, "FORCEIRDETOCHECKED", "checked");
937
938    int32_t len = check_filled(rdr->rsa_mod, 120);
939    if(len > 0) {
940        if(len > 64) len = 120;
941        else len = 64;
942        for (i = 0; i < len; i++) tpl_printf(vars, TPLAPPEND, "RSAKEY", "%02X", rdr->rsa_mod[i]);
943    }
944
945    len = check_filled(rdr->nagra_boxkey, 8);
946    if(len > 0) {
947        for (i = 0; i < 8 ; i++) tpl_printf(vars, TPLAPPEND, "BOXKEY", "%02X", rdr->nagra_boxkey[i]);
948    }
949
950    if ( rdr->atr[0])
951        for (i = 0; i < rdr->atrlen/2; i++)
952            tpl_printf(vars, TPLAPPEND, "ATR", "%02X", rdr->atr[i]);
953           
954    value = mk_t_ecmwhitelist(rdr->ecmWhitelist);
955    tpl_addVar(vars, TPLADD, "ECMWHITELIST", value);
956    free_mk_t(value);
957
958    if(rdr->smargopatch)
959        tpl_addVar(vars, TPLADD, "SMARGOPATCHCHECKED", "checked");
960
961    if (rdr->detect&0x80)
962        tpl_printf(vars, TPLADD, "DETECT", "!%s", RDR_CD_TXT[rdr->detect&0x7f]);
963    else
964        tpl_addVar(vars, TPLADD, "DETECT", RDR_CD_TXT[rdr->detect&0x7f]);
965
966    tpl_printf(vars, TPLADD, "MHZ", "%d", rdr->mhz);
967    tpl_printf(vars, TPLADD, "CARDMHZ", "%d", rdr->cardmhz);
968
969    tpl_addVar(vars, TPLADD, "DEVICE", rdr->device);
970    if(rdr->r_port)
971        tpl_printf(vars, TPLAPPEND, "DEVICE", ",%d", rdr->r_port);
972    if(rdr->l_port) {
973        if(rdr->r_port)
974            tpl_printf(vars, TPLAPPEND, "DEVICE", ",%d", rdr->l_port);
975        else
976            tpl_printf(vars, TPLAPPEND, "DEVICE", ",,%d", rdr->l_port);
977    }
978
979    //group
980    value = mk_t_group(rdr->grp);
981    tpl_addVar(vars, TPLADD, "GRP", value);
982    free_mk_t(value);
983
984#ifdef WITH_LB
985    if(rdr->lb_weight)
986        tpl_printf(vars, TPLADD, "LBWEIGHT", "%d", rdr->lb_weight);
987#endif
988
989    //services
990    struct s_sidtab *sidtab = cfg.sidtab;
991    //build matrix
992    i = 0;
993    while(sidtab != NULL) {
994        tpl_addVar(vars, TPLADD, "SIDLABEL", sidtab->label);
995        if(rdr->sidtabok&((SIDTABBITS)1<<i)) tpl_addVar(vars, TPLADD, "CHECKED", "checked");
996        else tpl_addVar(vars, TPLADD, "CHECKED", "");
997        tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "READERCONFIGSIDOKBIT"));
998        if(rdr->sidtabno&((SIDTABBITS)1<<i)) tpl_addVar(vars, TPLADD, "CHECKED", "checked");
999        else tpl_addVar(vars, TPLADD, "CHECKED", "");
1000        tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "READERCONFIGSIDNOBIT"));
1001        sidtab=sidtab->next;
1002        i++;
1003    }
1004
1005    // CAID
1006    value = mk_t_caidtab(&rdr->ctab);
1007    tpl_addVar(vars, TPLADD, "CAIDS", value);
1008    free_mk_t(value);
1009
1010    // AESkeys
1011    value = mk_t_aeskeys(rdr);
1012    tpl_addVar(vars, TPLADD, "AESKEYS", value);
1013    free_mk_t(value);
1014
1015    //ident
1016    value = mk_t_ftab(&rdr->ftab);
1017    tpl_addVar(vars, TPLADD, "IDENTS", value);
1018    free_mk_t(value);
1019
1020    //CHID
1021    value = mk_t_ftab(&rdr->fchid);
1022    tpl_addVar(vars, TPLADD, "CHIDS", value);
1023    free_mk_t(value);
1024
1025    //class
1026    value = mk_t_cltab(&rdr->cltab);
1027    tpl_addVar(vars, TPLADD, "CLASS", value);
1028    free_mk_t(value);
1029
1030    if (rdr->show_cls)
1031        tpl_printf(vars, TPLADD, "SHOWCLS", "%d", rdr->show_cls);
1032
1033    if(rdr->cachemm)
1034        tpl_printf(vars, TPLADD, "EMMCACHE", "%d,%d,%d", rdr->cachemm, rdr->rewritemm, rdr->logemm);
1035
1036    //savenano
1037    value = mk_t_nano(rdr, 0x02);
1038    tpl_addVar(vars, TPLADD, "SAVENANO", value);
1039    free_mk_t(value);
1040
1041    //blocknano
1042    value = mk_t_nano(rdr, 0x01);
1043    tpl_addVar(vars, TPLADD, "BLOCKNANO", value);
1044    free_mk_t(value);
1045
1046    if (rdr->blockemm & EMM_UNKNOWN)
1047        tpl_addVar(vars, TPLADD, "BLOCKEMMUNKNOWNCHK", "checked");
1048    if (rdr->blockemm & EMM_UNIQUE)
1049        tpl_addVar(vars, TPLADD, "BLOCKEMMUNIQCHK", "checked");
1050    if (rdr->blockemm & EMM_SHARED)
1051        tpl_addVar(vars, TPLADD, "BLOCKEMMSHAREDCHK", "checked");
1052    if (rdr->blockemm & EMM_GLOBAL)
1053        tpl_addVar(vars, TPLADD, "BLOCKEMMGLOBALCHK", "checked");
1054
1055    if (rdr->deprecated)
1056        tpl_addVar(vars, TPLADD, "DEPRECATEDCHCHECKED", "checked");
1057
1058#ifdef MODULE_CCCAM
1059    if (!strcmp(rdr->cc_version, "2.0.11")) {
1060        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED0", "selected");
1061    } else if (!strcmp(rdr->cc_version, "2.1.1")) {
1062        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED1", "selected");
1063    } else if (!strcmp(rdr->cc_version, "2.1.2")) {
1064        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED2", "selected");
1065    } else if (!strcmp(rdr->cc_version, "2.1.3")) {
1066        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED3", "selected");
1067    } else if (!strcmp(rdr->cc_version, "2.1.4")) {
1068        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED4", "selected");
1069    } else if (!strcmp(rdr->cc_version, "2.2.0")) {
1070        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED5", "selected");
1071    } else if (!strcmp(rdr->cc_version, "2.2.1")) {
1072        tpl_addVar(vars, TPLADD, "CCCVERSIONSELECTED6", "selected");
1073    }
1074#endif
1075
1076#ifdef LIBUSB
1077    tpl_addVar(vars, TPLADD, "DEVICEEP", tpl_getTpl(vars, "READERCONFIGDEVICEEPBIT"));
1078
1079    if(!rdr->device_endpoint) {
1080        tpl_addVar(vars, TPLADD, "DEVICEOUTEP0", "selected");
1081    } else if (rdr->device_endpoint == 0x82) {
1082        tpl_addVar(vars, TPLADD, "DEVICEOUTEP1", "selected");
1083    } else if (rdr->device_endpoint == 0x81) {
1084        tpl_addVar(vars, TPLADD, "DEVICEOUTEP2", "selected");
1085    }
1086#else
1087    tpl_addVar(vars, TPLADD, "DEVICEEP", "not avail LIBUSB");
1088#endif
1089
1090    tpl_printf(vars, TPLADD, "TMP", "NDSVERSION%d", rdr->ndsversion);
1091    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1092
1093    tpl_printf(vars, TPLADD, "TMP", "NAGRAREAD%d", rdr->nagra_read);
1094    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1095
1096#ifdef MODULE_CCCAM
1097    tpl_printf(vars, TPLADD, "CCCMAXHOP", "%d", rdr->cc_maxhop);
1098    tpl_printf(vars, TPLADD, "CCCMINDOWN", "%d", rdr->cc_mindown);
1099    tpl_printf(vars, TPLADD, "CCCRESHARE", "%d", (rdr->cc_reshare==-1)?cfg.cc_reshare:rdr->cc_reshare);
1100    if(rdr->cc_want_emu)
1101        tpl_addVar(vars, TPLADD, "CCCWANTEMUCHECKED", "checked");
1102    if(rdr->cc_keepalive)
1103        tpl_addVar(vars, TPLADD, "KEEPALIVECHECKED", "selected");
1104#endif
1105
1106    // Show only parameters which needed for the reader
1107    switch (rdr->typ) {
1108        case R_CONSTCW:
1109            tpl_addVar(vars, TPLADD, "PROTOCOL", "constcw");
1110            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1111            break;
1112        case R_DB2COM1:
1113        case R_DB2COM2:
1114        case R_MOUSE :
1115            tpl_addVar(vars, TPLADD, "PROTOCOL", "mouse");
1116            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1117            break;
1118        case R_MP35:
1119            tpl_addVar(vars, TPLADD, "PROTOCOL", "mp35");
1120            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1121            break;
1122        case R_SC8in1 :
1123            tpl_addVar(vars, TPLADD, "PROTOCOL", "sc8in1");
1124            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1125            break;
1126        case R_SMART :
1127            tpl_addVar(vars, TPLADD, "PROTOCOL", "smartreader");
1128            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1129            break;
1130        case R_INTERNAL:
1131            tpl_addVar(vars, TPLADD, "PROTOCOL", "internal");
1132            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1133            break;
1134        case R_SERIAL :
1135            tpl_addVar(vars, TPLADD, "PROTOCOL", "serial");
1136            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1137            break;
1138        case R_CAMD35 :
1139            tpl_addVar(vars, TPLADD, "PROTOCOL", "camd35");
1140            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCAMD35BIT"));
1141            break;
1142        case R_CS378X :
1143            tpl_addVar(vars, TPLADD, "PROTOCOL", "cs378x");
1144            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCS378XBIT"));
1145            break;
1146        case R_RADEGAST:
1147            tpl_addVar(vars, TPLADD, "PROTOCOL", "radegast");
1148            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGRADEGASTBIT"));
1149            break;
1150        case R_NEWCAMD :
1151            if ( rdr->ncd_proto == NCD_525 ){
1152                tpl_addVar(vars, TPLADD, "PROTOCOL", "newcamd525");
1153                tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGNCD525BIT"));
1154            } else if ( rdr->ncd_proto == NCD_524 ) {
1155                tpl_addVar(vars, TPLADD, "PROTOCOL", "newcamd524");
1156                tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGNCD524BIT"));
1157            }
1158            break;
1159#ifdef MODULE_CCCAM
1160        case R_CCCAM :
1161            tpl_addVar(vars, TPLADD, "PROTOCOL", "cccam");
1162            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGCCCAMBIT"));
1163            break;
1164#endif
1165#ifdef HAVE_PCSC
1166        case R_PCSC :
1167            tpl_addVar(vars, TPLADD, "PROTOCOL", "pcsc");
1168            tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGSTDHWREADERBIT"));
1169            break;
1170#endif
1171        default :
1172            tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Error: protocol not resolvable</b><BR>");
1173            tpl_printf(vars, TPLAPPEND, "MESSAGE", "<b>Error: protocol number: %d readername: %s</b><BR>", rdr->typ, rdr->label);
1174            break;
1175
1176    }
1177
1178#ifdef MODULE_CCCAM
1179    if(rdr->typ != R_CCCAM){
1180        tpl_printf(vars, TPLADD, "CCCHOP", "%d", rdr->cc_hop);
1181        tpl_addVar(vars, TPLAPPEND, "READERDEPENDINGCONFIG", tpl_getTpl(vars, "READERCONFIGHOPBIT"));
1182    }
1183#endif
1184
1185    return tpl_getTpl(vars, "READERCONFIG");
1186}
1187
1188#ifdef WITH_LB
1189char *send_oscam_reader_stats(struct templatevars *vars, struct uriparams *params, int32_t apicall) {
1190    struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
1191    if(!rdr) return "0";
1192
1193    if (strcmp(getParam(params, "action"), "resetstat") == 0) {
1194        if(rdr) {
1195            clear_reader_stat(rdr);
1196            cs_log("Reader %s stats resetted by WebIF from %s", rdr->label, cs_inet_ntoa(GET_IP()));
1197        }
1198    }
1199
1200    if (!apicall){
1201        tpl_addVar(vars, TPLADD, "LABEL", rdr->label);
1202        tpl_addVar(vars, TPLADD, "ENCODEDLABEL", urlencode(vars, rdr->label));
1203    } else {
1204        tpl_addVar(vars, TPLADD, "READERNAME", rdr->label);
1205    }
1206
1207    char *stxt[]={"found", "cache1", "cache2", "emu",
1208            "not found", "timeout", "sleeping",
1209            "fake", "invalid", "corrupt", "no card", "expdate",
1210            "disabled", "stopped"};
1211
1212    if (apicall) {
1213        int32_t i, emmcount = 0;
1214        char *ttxt[]={"unknown", "unique", "shared", "global"};
1215
1216        for (i=0; i<4; i++) {
1217            tpl_addVar(vars, TPLADD, "EMMRESULT", "error");
1218            tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
1219            tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmerror[i]);
1220            tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
1221            emmcount += rdr->emmerror[i];
1222            tpl_printf(vars, TPLADD, "TOTALERROR", "%d", emmcount);
1223        }
1224        emmcount = 0;
1225        for (i=0; i<4; i++) {
1226            tpl_addVar(vars, TPLADD, "EMMRESULT", "written");
1227            tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
1228            tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmwritten[i]);
1229            tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
1230            emmcount += rdr->emmwritten[i];
1231            tpl_printf(vars, TPLADD, "TOTALWRITTEN", "%d", emmcount);
1232        }
1233        emmcount = 0;
1234        for (i=0; i<4; i++) {
1235            tpl_addVar(vars, TPLADD, "EMMRESULT", "skipped");
1236            tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
1237            tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmskipped[i]);
1238            tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
1239            emmcount += rdr->emmskipped[i];
1240            tpl_printf(vars, TPLADD, "TOTALSKIPPED", "%d", emmcount);
1241        }
1242        emmcount = 0;
1243        for (i=0; i<4; i++) {
1244            tpl_addVar(vars, TPLADD, "EMMRESULT", "blocked");
1245            tpl_addVar(vars, TPLADD, "EMMTYPE", ttxt[i]);
1246            tpl_printf(vars, TPLADD, "EMMCOUNT", "%d", rdr->emmblocked[i]);
1247            tpl_addVar(vars, TPLAPPEND, "EMMSTATS", tpl_getTpl(vars, "APIREADERSTATSEMMBIT"));
1248            emmcount += rdr->emmblocked[i];
1249            tpl_printf(vars, TPLADD, "TOTALBLOCKED", "%d", emmcount);
1250        }
1251    }
1252
1253    int32_t rc2hide = (-1);
1254    if (strlen(getParam(params, "hide")) > 0)
1255            rc2hide = atoi(getParam(params, "hide"));
1256
1257    int32_t rowcount = 0;
1258    uint64_t ecmcount = 0;
1259    time_t lastaccess = 0;
1260
1261    if (rdr->lb_stat) {
1262   
1263        // @todo alno: sort by click, 0=ascending, 1=descending (maybe two buttons or reverse on second click)
1264        sort_stat(rdr, 0);
1265       
1266        LL_ITER it = ll_iter_create(rdr->lb_stat);
1267        READER_STAT *stat = ll_iter_next(&it);
1268        char channame[32];
1269        while (stat) {
1270
1271            if (!(stat->rc == rc2hide)) {
1272                struct tm lt;
1273                localtime_r(&stat->last_received, &lt);
1274                ecmcount += stat->ecm_count;
1275                if (!apicall) {
1276                    tpl_printf(vars, TPLADD, "CHANNEL", "%04X:%06lX:%04X", stat->caid, stat->prid, stat->srvid);
1277                    tpl_addVar(vars, TPLADD, "CHANNELNAME", xml_encode(vars, get_servicename(cur_client(), stat->srvid, stat->caid, channame)));
1278                    tpl_printf(vars, TPLADD, "ECMLEN","%04hX", stat->ecmlen);
1279                    tpl_addVar(vars, TPLADD, "RC", stxt[stat->rc]);
1280                    tpl_printf(vars, TPLADD, "TIME", "%dms", stat->time_avg);
1281                    if (stat->time_stat[stat->time_idx])
1282                        tpl_printf(vars, TPLADD, "TIMELAST", "%dms", stat->time_stat[stat->time_idx]);
1283                    else
1284                        tpl_printf(vars, TPLADD, "TIMELAST", "");
1285                    tpl_printf(vars, TPLADD, "COUNT", "%d", stat->ecm_count);
1286
1287                    if(stat->last_received) {
1288                        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);
1289
1290                    } else {
1291                        tpl_addVar(vars, TPLADD, "LAST","never");
1292                    }
1293                } else {
1294                    tpl_printf(vars, TPLADD, "ECMCAID", "%04X", stat->caid);
1295                    tpl_printf(vars, TPLADD, "ECMPROVID", "%06lX", stat->prid);
1296                    tpl_printf(vars, TPLADD, "ECMSRVID", "%04X", stat->srvid);
1297                    tpl_printf(vars, TPLADD, "ECMLEN", "%04hX", stat->ecmlen);
1298                    tpl_addVar(vars, TPLADD, "ECMCHANNELNAME", xml_encode(vars, get_servicename(cur_client(), stat->srvid, stat->caid, channame)));
1299                    tpl_printf(vars, TPLADD, "ECMTIME", "%d", stat->time_avg);
1300                    tpl_printf(vars, TPLADD, "ECMTIMELAST", "%d", stat->time_stat[stat->time_idx]);
1301                    tpl_printf(vars, TPLADD, "ECMRC", "%d", stat->rc);
1302                    tpl_addVar(vars, TPLADD, "ECMRCS", stxt[stat->rc]);
1303                    if(stat->last_received) {
1304                        char tbuffer [30];
1305                        strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
1306                        tpl_addVar(vars, TPLADD, "ECMLAST", tbuffer);
1307                    } else {
1308                        tpl_addVar(vars, TPLADD, "ECMLAST", "");
1309                    }
1310                    tpl_printf(vars, TPLADD, "ECMCOUNT", "%d", stat->ecm_count);
1311
1312                    if (stat->last_received > lastaccess)
1313                        lastaccess = stat->last_received;
1314                }
1315
1316                if (!apicall) {
1317                    if (stat->rc == 4) {
1318                        tpl_addVar(vars, TPLAPPEND, "READERSTATSROWNOTFOUND", tpl_getTpl(vars, "READERSTATSBIT"));
1319                        tpl_addVar(vars, TPLADD, "READERSTATSNFHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"7\">Not found</TD></TR>\n");
1320                    }
1321                    else
1322                        tpl_addVar(vars, TPLAPPEND, "READERSTATSROWFOUND", tpl_getTpl(vars, "READERSTATSBIT"));
1323                } else {
1324
1325                    tpl_addVar(vars, TPLAPPEND, "ECMSTATS", tpl_getTpl(vars, "APIREADERSTATSECMBIT"));
1326                }
1327            }
1328
1329        stat = ll_iter_next(&it);
1330        rowcount++;
1331        }
1332
1333    } else {
1334        tpl_addVar(vars, TPLAPPEND, "READERSTATSROW","<TR><TD colspan=\"6\"> No statistics found </TD></TR>");
1335    }
1336
1337    tpl_printf(vars, TPLADD, "ROWCOUNT", "%d", rowcount);
1338
1339    if (lastaccess > 0){
1340        char tbuffer [30];
1341        struct tm lt;
1342        localtime_r(&lastaccess, &lt);
1343        strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
1344        tpl_addVar(vars, TPLADD, "LASTACCESS", tbuffer);
1345    } else {
1346        tpl_addVar(vars, TPLADD, "LASTACCESS", "");
1347    }
1348
1349    tpl_printf(vars, TPLADD, "TOTALECM", "%llu", ecmcount);
1350
1351    if(!apicall)
1352        return tpl_getTpl(vars, "READERSTATS");
1353    else
1354        return tpl_getTpl(vars, "APIREADERSTATS");
1355}
1356#endif
1357
1358char *send_oscam_user_config_edit(struct templatevars *vars, struct uriparams *params) {
1359    struct s_auth *account, *ptr;
1360    char user[sizeof(first_client->account->usr)];
1361
1362    if (strcmp(getParam(params, "action"), "Save As") == 0) cs_strncpy(user, getParam(params, "newuser"), sizeof(user)/sizeof(char));
1363    else cs_strncpy(user, getParam(params, "user"), sizeof(user)/sizeof(char));
1364
1365    int32_t i;
1366
1367    for (account = cfg.account; account != NULL && strcmp(user, account->usr) != 0; account = account->next);
1368
1369    // Create a new user if it doesn't yet
1370    if (account == NULL) {
1371        i = 1;
1372        while(strlen(user) < 1) {
1373            snprintf(user, sizeof(user)/sizeof(char) - 1, "NEWUSER%d", i);
1374            for (account = cfg.account; account != NULL && strcmp(user, account->usr) != 0; account = account->next);
1375            if(account != NULL) user[0] = '\0';
1376            ++i;
1377        }
1378        if (!cs_malloc(&account, sizeof(struct s_auth), -1)) return "0";
1379        if(cfg.account == NULL) cfg.account = account;
1380        else {
1381            for (ptr = cfg.account; ptr != NULL && ptr->next != NULL; ptr = ptr->next);
1382            ptr->next = account;
1383        }
1384        memset(account, 0, sizeof(struct s_auth));
1385        cs_strncpy((char *)account->usr, user, sizeof(account->usr));
1386        account->monlvl=cfg.mon_level;
1387        account->tosleep=cfg.tosleep;
1388        for (i=1; i<CS_MAXCAIDTAB; account->ctab.mask[i++]=0xffff);
1389        for (i=1; i<CS_MAXTUNTAB; account->ttab.bt_srvid[i++]=0x0000);
1390        account->expirationdate=(time_t)NULL;
1391#ifdef CS_ANTICASC
1392        account->ac_users=cfg.ac_users;
1393        account->ac_penalty=cfg.ac_penalty;
1394#endif
1395        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>New user has been added with default settings</b><BR>");
1396
1397        if (write_userdb(cfg.account)==0)
1398            refresh_oscam(REFR_ACCOUNTS);
1399        else
1400            tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
1401        // need to reget account as writing to disk changes account!
1402        for (account = cfg.account; account != NULL && strcmp(user, account->usr) != 0; account = account->next);
1403    }
1404
1405    if((strcmp(getParam(params, "action"), "Save") == 0) || (strcmp(getParam(params, "action"), "Save As") == 0)) {
1406        char servicelabels[1024]="";
1407
1408        for(i=0;i<(*params).paramcount;i++) {
1409            if ((strcmp((*params).params[i], "action")) && (strcmp((*params).params[i], "user")) && (strcmp((*params).params[i], "newuser"))) {
1410                if (!strcmp((*params).params[i], "services"))
1411                    snprintf(servicelabels + strlen(servicelabels), sizeof(servicelabels) - strlen(servicelabels), "%s,", (*params).values[i]);
1412                else
1413                    chk_account((*params).params[i], (*params).values[i], account);
1414            }
1415        }
1416        chk_account("services", servicelabels, account);
1417        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Settings updated</B><BR><BR>");
1418
1419        if (write_userdb(cfg.account)==0)
1420            refresh_oscam(REFR_ACCOUNTS);
1421        else
1422            tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
1423
1424        // need to reget account as writing to disk changes account!
1425        for (account = cfg.account; account != NULL && strcmp(user, account->usr) != 0; account = account->next);
1426    }
1427
1428    tpl_addVar(vars, TPLADD, "USERNAME", account->usr);
1429    tpl_addVar(vars, TPLADD, "PASSWORD", account->pwd);
1430    tpl_addVar(vars, TPLADD, "DESCRIPTION", account->description);
1431
1432    //Disabled
1433    if(account->disabled)
1434        tpl_addVar(vars, TPLADD, "DISABLEDCHECKED", "selected");
1435
1436    //Expirationdate
1437    struct tm timeinfo;
1438    localtime_r (&account->expirationdate, &timeinfo);
1439    char buf [80];
1440    strftime (buf,80,"%Y-%m-%d",&timeinfo);
1441    if(strcmp(buf,"1970-01-01")) tpl_addVar(vars, TPLADD, "EXPDATE", buf);
1442
1443    if(account->allowedtimeframe[0] && account->allowedtimeframe[1]) {
1444        tpl_printf(vars, TPLADD, "ALLOWEDTIMEFRAME", "%02d:%02d-%02d:%02d",
1445                account->allowedtimeframe[0]/60,
1446                account->allowedtimeframe[0]%60,
1447                account->allowedtimeframe[1]/60,
1448                account->allowedtimeframe[1]%60 );
1449    }
1450
1451    //Group
1452    char *value = mk_t_group(account->grp);
1453    tpl_addVar(vars, TPLADD, "GROUPS", value);
1454    free_mk_t(value);
1455
1456    //Hostname
1457    tpl_addVar(vars, TPLADD, "DYNDNS", (char *)account->dyndns);
1458
1459    //Uniq
1460    tpl_printf(vars, TPLADD, "TMP", "UNIQSELECTED%d", account->uniq);
1461    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1462
1463    //Sleep
1464    if(!account->tosleep) tpl_addVar(vars, TPLADD, "SLEEP", "0");
1465    else tpl_printf(vars, TPLADD, "SLEEP", "%d", account->tosleep);
1466    //Monlevel selector
1467    tpl_printf(vars, TPLADD, "TMP", "MONSELECTED%d", account->monlvl);
1468    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1469
1470    //Au
1471    if (account->autoau == 1)
1472        tpl_addVar(vars, TPLADD, "AUREADER", "1");
1473    else if (account->aureader_list) {
1474        value = mk_t_aureader(account);
1475        tpl_addVar(vars, TPLADD, "AUREADER", value);
1476        free_mk_t(value);
1477    }
1478
1479    /* SERVICES */
1480    struct s_sidtab *sidtab = cfg.sidtab;
1481    //build matrix
1482    i=0;
1483    while(sidtab != NULL) {
1484        tpl_addVar(vars, TPLADD, "SIDLABEL", sidtab->label);
1485        if(account->sidtabok&((SIDTABBITS)1<<i)) tpl_addVar(vars, TPLADD, "CHECKED", "checked");
1486        else tpl_addVar(vars, TPLADD, "CHECKED", "");
1487        tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "USEREDITSIDOKBIT"));
1488        if(account->sidtabno&((SIDTABBITS)1<<i)) tpl_addVar(vars, TPLADD, "CHECKED", "checked");
1489        else tpl_addVar(vars, TPLADD, "CHECKED", "");
1490        tpl_addVar(vars, TPLAPPEND, "SIDS", tpl_getTpl(vars, "USEREDITSIDNOBIT"));
1491        sidtab=sidtab->next;
1492        i++;
1493    }
1494
1495    // CAID
1496    value = mk_t_caidtab(&account->ctab);
1497    tpl_addVar(vars, TPLADD, "CAIDS", value);
1498    free_mk_t(value);
1499
1500    //ident
1501    value = mk_t_ftab(&account->ftab);
1502    tpl_addVar(vars, TPLADD, "IDENTS", value);
1503    free_mk_t(value);
1504
1505    //CHID
1506    value = mk_t_ftab(&account->fchid);
1507    tpl_addVar(vars, TPLADD, "CHIDS",  value);
1508    free_mk_t(value);
1509   
1510    //class
1511    value = mk_t_cltab(&account->cltab);
1512    tpl_addVar(vars, TPLADD, "CLASS", value);
1513    free_mk_t(value);
1514
1515    //Betatunnel
1516    value = mk_t_tuntab(&account->ttab);
1517    tpl_addVar(vars, TPLADD, "BETATUNNELS", value);
1518    free_mk_t(value);
1519
1520    //SUPPRESSCMD08
1521    if (account->c35_suppresscmd08)
1522        tpl_addVar(vars, TPLADD, "SUPPRESSCMD08", "selected");
1523
1524    //Sleepsend
1525    tpl_printf(vars, TPLADD, "SLEEPSEND", "%u", account->c35_sleepsend);
1526
1527    //Keepalive
1528    if (account->ncd_keepalive)
1529        tpl_addVar(vars, TPLADD, "KEEPALIVE", "selected");
1530
1531#ifdef CS_ANTICASC
1532    tpl_printf(vars, TPLADD, "AC_USERS", "%d", account->ac_users);
1533    tpl_printf(vars, TPLADD, "TMP", "PENALTY%d", account->ac_penalty);
1534    tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMP"), "selected");
1535#endif
1536
1537#ifdef MODULE_CCCAM
1538    tpl_printf(vars, TPLADD, "CCCMAXHOPS", "%d", account->cccmaxhops);
1539    tpl_printf(vars, TPLADD, "CCCRESHARE", "%d", (account->cccreshare==-1)?cfg.cc_reshare:account->cccreshare);
1540    if ((account->cccignorereshare==-1)?cfg.cc_ignore_reshare:account->cccignorereshare)
1541        tpl_printf(vars, TPLADD, "CCCIGNORERESHARE", "selected");
1542    if ((account->cccstealth==-1)?cfg.cc_stealth:account->cccstealth)
1543        tpl_printf(vars, TPLADD, "CCCSTEALTH", "selected");
1544#endif
1545
1546    //Failban
1547    tpl_printf(vars, TPLADD, "FAILBAN", "%d", account->failban);
1548
1549    return tpl_getTpl(vars, "USEREDIT");
1550}
1551
1552char *send_oscam_user_config(struct templatevars *vars, struct uriparams *params, int32_t apicall) {
1553    struct s_auth *account, *account2;
1554    char *user = getParam(params, "user");
1555    int32_t found = 0, hideclient = 10;
1556
1557    if (cfg.mon_hideclient_to > 10)
1558    hideclient = cfg.mon_hideclient_to;
1559
1560    if (!apicall) {
1561        if (strcmp(getParam(params, "action"), "reinit") == 0) {
1562            if(!cfg.http_readonly)
1563                refresh_oscam(REFR_ACCOUNTS);
1564        }
1565
1566        if (strcmp(getParam(params, "action"), "delete") == 0) {
1567            if(cfg.http_readonly) {
1568                tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Webif is in readonly mode. No deletion will be made!</b><BR>");
1569            } else {
1570                account = cfg.account;
1571                if(strcmp(account->usr, user) == 0) {
1572                    cfg.account = account->next;
1573                    ll_clear(account->aureader_list);
1574                    add_garbage(account);
1575                    found = 1;
1576                } else if (account->next != NULL) {
1577                    do {
1578                        if(strcmp(account->next->usr, user) == 0) {
1579                            account2 = account->next;
1580                            account->next = account2->next;
1581                            ll_clear(account2->aureader_list);
1582                            add_garbage(account2);
1583                            found = 1;
1584                            break;
1585                        }
1586                    } while ((account = account->next) && (account->next != NULL));
1587                }
1588
1589                if (found > 0) {
1590                    if (write_userdb(cfg.account)==0)
1591                        refresh_oscam(REFR_ACCOUNTS);
1592                    else
1593                        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
1594
1595                } else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Sorry but the specified user doesn't exist. No deletion will be made!</b><BR>");
1596            }
1597        }
1598
1599        if ((strcmp(getParam(params, "action"), "disable") == 0) || (strcmp(getParam(params, "action"), "enable") == 0)) {
1600            account = get_account_by_name(getParam(params, "user"));
1601            if (account) {
1602                if(strcmp(getParam(params, "action"), "disable") == 0)
1603                    account->disabled = 1;
1604                else
1605                    account->disabled = 0;
1606                if (write_userdb(cfg.account) == 0)
1607                    refresh_oscam(REFR_ACCOUNTS);
1608            } else {
1609                tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Sorry but the specified user doesn't exist. No deletion will be made!</b><BR>");
1610            }
1611        }
1612
1613        if (strcmp(getParam(params, "action"), "resetstats") == 0) {
1614            account = get_account_by_name(getParam(params, "user"));
1615            if (account) clear_account_stats(account);
1616        }
1617
1618        if (strcmp(getParam(params, "action"), "resetserverstats") == 0) {
1619            clear_system_stats();
1620        }
1621
1622        if (strcmp(getParam(params, "action"), "resetalluserstats") == 0) {
1623            clear_all_account_stats();
1624        }
1625
1626        if ((strcmp(getParam(params, "part"), "adduser") == 0) && (!cfg.http_readonly)) {
1627            tpl_addVar(vars, TPLAPPEND, "NEWUSERFORM", tpl_getTpl(vars, "ADDNEWUSER"));
1628        } else {
1629            if(cfg.http_refresh > 0) {
1630                tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", cfg.http_refresh);
1631                tpl_addVar(vars, TPLADD, "REFRESHURL", "userconfig.html");
1632                tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
1633            }
1634        }
1635    }
1636
1637    /* List accounts*/
1638    char *status, *expired, *classname, *lastchan;
1639    time_t now = time((time_t)0);
1640    int32_t isec = 0;
1641
1642    char *filter = NULL;
1643    int32_t clientcount = 0;
1644    if (apicall) {
1645        filter = getParam(params, "label");
1646    }
1647
1648    for (account=cfg.account; (account); account=account->next) {
1649        //clear for next client
1650        status = "offline"; lastchan = "&nbsp;", expired = ""; classname = "offline";
1651        isec = 0;
1652
1653        if(account->expirationdate && account->expirationdate < time(NULL)) {
1654            expired = " (expired)";
1655            classname = "expired";
1656        } else {
1657            expired = "";
1658        }
1659
1660        if(account->disabled != 0) {
1661            expired = " (disabled)"; classname = "disabled";
1662            tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICENA");
1663            tpl_addVar(vars, TPLADD, "SWITCHTITLE", "enable this account");
1664            tpl_addVar(vars, TPLADD, "SWITCH", "enable");
1665        } else {
1666            tpl_addVar(vars, TPLADD, "SWITCHICO", "image?i=ICDIS");
1667            tpl_addVar(vars, TPLADD, "SWITCHTITLE", "disable this account");
1668            tpl_addVar(vars, TPLADD, "SWITCH", "disable");
1669        }
1670
1671        int32_t lastresponsetm = 0, latestactivity=0;
1672        char *proto = "";
1673        double cwrate = 0.0, cwrate2 = 0.0;
1674
1675        //search account in active clients
1676        int32_t isactive = 0;
1677        struct s_client *cl, *latestclient=NULL;
1678        for (cl=first_client; cl ; cl=cl->next) {
1679            if (cl->account && !strcmp(cl->account->usr, account->usr)) {
1680                if(cl->lastecm > latestactivity || cl->login > latestactivity){
1681                    if(cl->lastecm > cl->login) latestactivity = cl->lastecm;
1682                    else latestactivity = cl->login;
1683                    latestclient = cl;
1684                }
1685            }
1686        }
1687        if (account->cwfound + account->cwnot + account->cwcache > 0) {
1688            cwrate = now - account->firstlogin;
1689            cwrate /= (account->cwfound + account->cwnot + account->cwcache);
1690        }
1691        if(latestclient != NULL) {
1692            char channame[32];
1693            status = "<b>connected</b>";
1694            classname = "connected";
1695            proto = monitor_get_proto(latestclient);
1696            lastchan = xml_encode(vars, get_servicename(latestclient, latestclient->last_srvid, latestclient->last_caid, channame));
1697            lastresponsetm = latestclient->cwlastresptime;
1698            tpl_addVar(vars, TPLADDONCE, "CLIENTIP", cs_inet_ntoa(latestclient->ip));
1699        }
1700        if(latestactivity > 0){
1701            isec = now - latestactivity;
1702            if(isec < cfg.mon_hideclient_to) {
1703                isactive = 1;
1704                status = "<b>online</b>";
1705                classname = "online";
1706                if (latestclient->cwfound + latestclient->cwnot + latestclient->cwcache > 0) {
1707                    cwrate2 = now - latestclient->login;
1708                    cwrate2 /= (latestclient->cwfound + latestclient->cwnot + latestclient->cwcache);
1709                    tpl_printf(vars, TPLADDONCE, "CWRATE2", " (%.2f)", cwrate2);
1710                }
1711            }
1712        }
1713
1714        tpl_printf(vars, TPLADD, "CWOK", "%d", account->cwfound);
1715        tpl_printf(vars, TPLADD, "CWNOK", "%d", account->cwnot);
1716        tpl_printf(vars, TPLADD, "CWIGN", "%d", account->cwignored);
1717        tpl_printf(vars, TPLADD, "CWTOUT", "%d", account->cwtout);
1718        tpl_printf(vars, TPLADD, "CWCACHE", "%d", account->cwcache);
1719        tpl_printf(vars, TPLADD, "CWTUN", "%d", account->cwtun);
1720        tpl_printf(vars, TPLADD, "EMMOK", "%d", account->emmok);
1721        tpl_printf(vars, TPLADD, "EMMNOK", "%d", account->emmnok);
1722        tpl_printf(vars, TPLADD, "CWRATE", "%.2f", cwrate);
1723
1724        if ( isactive > 0 || !cfg.http_hide_idle_clients) {
1725            tpl_addVar(vars, TPLADDONCE, "LASTCHANNEL", lastchan);
1726            tpl_printf(vars, TPLADDONCE, "CWLASTRESPONSET", "%d", lastresponsetm);
1727            tpl_addVar(vars, TPLADDONCE, "IDLESECS", sec2timeformat(vars, isec));
1728
1729            if ((strcmp(proto,"newcamd") == 0) && (latestclient->typ == 'c'))
1730                tpl_printf(vars, TPLADDONCE, "CLIENTPROTO","%s (%s)", proto, get_ncd_client_name(latestclient->ncd_client_id));
1731#ifdef MODULE_CCCAM
1732            else if ((strncmp(proto,"cccam", 5) == 0)) {
1733                struct cc_data *cc = latestclient->cc;
1734                if(cc && cc->remote_version && cc->remote_build) {
1735                    tpl_printf(vars, TPLADDONCE, "CLIENTPROTO", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
1736                    if(cc->extended_mode)
1737                        tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", cc->remote_oscam);
1738                    else
1739                        tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", ""); //unset tpl var
1740                }
1741                else
1742                {
1743                    tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", proto);
1744                    tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", "");
1745                }
1746            }
1747#endif
1748            else {
1749                tpl_addVar(vars, TPLADDONCE, "CLIENTPROTO", proto);
1750                tpl_addVar(vars, TPLADDONCE, "CLIENTPROTOTITLE", "");
1751            }
1752        }
1753
1754        tpl_addVar(vars, TPLADD, "CLASSNAME", classname);
1755        tpl_addVar(vars, TPLADD, "USER", xml_encode(vars, account->usr));
1756        tpl_addVar(vars, TPLADD, "USERENC", urlencode(vars, account->usr));
1757        tpl_addVar(vars, TPLADD, "DESCRIPTION", xml_encode(vars, account->description));
1758        tpl_addVar(vars, TPLADD, "STATUS", status);
1759        tpl_addVar(vars, TPLAPPEND, "STATUS", expired);
1760        // append row to table template
1761        if (!apicall)
1762            tpl_addVar(vars, TPLAPPEND, "USERCONFIGS", tpl_getTpl(vars, "USERCONFIGLISTBIT"));
1763        else
1764            if (!filter || strcmp(filter, account->usr) == 0 || strcmp(filter, "all") == 0 || strlen(filter) == 0) {
1765                tpl_addVar(vars, TPLAPPEND, "APIUSERCONFIGS", tpl_getTpl(vars, "APIUSERCONFIGLISTBIT"));
1766                ++clientcount;
1767            }
1768    }
1769
1770    tpl_printf(vars, TPLADD, "TOTAL_CWOK", "%ld", first_client->cwfound);
1771    tpl_printf(vars, TPLADD, "TOTAL_CWNOK", "%ld", first_client->cwnot);
1772    tpl_printf(vars, TPLADD, "TOTAL_CWIGN", "%ld", first_client->cwignored);
1773    tpl_printf(vars, TPLADD, "TOTAL_CWTOUT", "%ld", first_client->cwtout);
1774    tpl_printf(vars, TPLADD, "TOTAL_CWCACHE", "%ld", first_client->cwcache);
1775    tpl_printf(vars, TPLADD, "TOTAL_CWTUN", "%ld", first_client->cwtun);
1776
1777    if (!apicall)
1778        return tpl_getTpl(vars, "USERCONFIGLIST");
1779    else {
1780        if (!filter || clientcount > 0) {
1781            return tpl_getTpl(vars, "APIUSERCONFIGLIST");
1782        } else {
1783            tpl_printf(vars, TPLADD, "APIERRORMESSAGE", "Invalid client %s", filter);
1784            return tpl_getTpl(vars, "APIERROR");
1785        }
1786    }
1787
1788}
1789
1790#define ENTITLEMENT_PAGE_SIZE 500
1791
1792char *send_oscam_entitlement(struct templatevars *vars, struct uriparams *params, int32_t apicall) {
1793
1794    //just to stop the guys open tedious tickets for warnings related to unused variables xD
1795    tpl_printf(vars, TPLADD, "ISAPICALL", "%d", apicall);
1796    //**************
1797
1798    /* build entitlements from reader init history */
1799    char *reader_ = getParam(params, "label");
1800#ifdef MODULE_CCCAM
1801    char *sharelist_ = getParam(params, "globallist");
1802    int32_t show_global_list = sharelist_ && sharelist_[0]=='1';
1803
1804    int32_t offset = atoi(getParam(params, "offset")); //should be 0 if parameter is missed on very first call
1805   
1806    struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
1807    if (show_global_list || (cfg.saveinithistory && strlen(reader_) > 0) || rdr->typ == R_CCCAM) {
1808
1809        if (show_global_list || (rdr->typ == R_CCCAM && rdr->enable)) {
1810
1811            if (show_global_list) {
1812                    tpl_addVar(vars, TPLADD, "READERNAME", "GLOBAL");
1813                    tpl_addVar(vars, TPLADD, "APIHOST", "GLOBAL");
1814                    tpl_printf(vars, TPLADD, "APIHOSTPORT", "GLOBAL");
1815            } else {
1816                    tpl_addVar(vars, TPLADD, "READERNAME", rdr->label);
1817                    tpl_addVar(vars, TPLADD, "APIHOST", rdr->device);
1818                    tpl_printf(vars, TPLADD, "APIHOSTPORT", "%d", rdr->r_port);
1819            }
1820
1821            int32_t cardcount = 0;
1822            int32_t providercount = 0;
1823            int32_t nodecount = 0;
1824
1825            char *provider = "";
1826
1827            struct cc_card *card;
1828
1829            LLIST *cards = NULL;
1830            pthread_mutex_t *lock = NULL;
1831
1832            if (show_global_list) {
1833                    cards = get_and_lock_sharelist();
1834            } else {
1835                    struct s_client *rc = rdr->client;
1836                    struct cc_data *rcc = (rc)?rc->cc:NULL;
1837
1838                    if (rcc && rcc->cards) {
1839                            cards = rcc->cards;
1840                            lock = &rcc->cards_busy;
1841                            cs_lock(lock);
1842                    }
1843            }
1844
1845            if (cards) {
1846
1847                uint8_t serbuf[8];
1848                char provname[83];
1849
1850                // @todo alno: sort by click, 0=ascending, 1=descending (maybe two buttons or reverse on second click)
1851                sort_cards_by_hop(cards, 0);
1852               
1853                LL_ITER it = ll_iter_create(cards);
1854                int32_t offset2 = offset+1;
1855                int32_t count = 0;
1856                while ((card = ll_iter_move(&it, offset2))) {
1857                    offset2 = 1;
1858                    if (count == ENTITLEMENT_PAGE_SIZE)
1859                        break;
1860                    count++;
1861                   
1862                    if (!apicall) {
1863                        if (show_global_list)
1864                            rdr = card->origin_reader;
1865                        if (rdr)
1866                            tpl_printf(vars, TPLADD, "HOST", "%s:%d", rdr->device, rdr->r_port);
1867                        tpl_printf(vars, TPLADD, "CAID", "%04X", card->caid);
1868                        tpl_printf(vars, TPLADD, "CARDTYPE", "%02X", card->card_type);
1869                    } else {
1870                        tpl_printf(vars, TPLADD, "APICARDNUMBER", "%d", cardcount);
1871                        tpl_printf(vars, TPLADD, "APICAID", "%04X", card->caid);
1872                        tpl_printf(vars, TPLADD, "APICARDTYPE", "%02X", card->card_type);
1873                    }
1874
1875                    if (cc_UA_valid(card->hexserial)) { //Add UA:
1876                        cc_UA_cccam2oscam(card->hexserial, serbuf, card->caid);
1877                        char tmp[20];
1878                        tpl_printf(vars, TPLAPPEND, "HOST", "<BR>\nUA_Oscam:%s", cs_hexdump_buf(0, serbuf, 8, tmp, 20));
1879                        tpl_printf(vars, TPLAPPEND, "HOST", "<BR>\nUA_CCcam:%s", cs_hexdump_buf(0, card->hexserial, 8, tmp, 20));
1880                    }
1881                    if (!apicall) {
1882                                int32_t n;
1883                                LL_ITER its = ll_iter_create(card->goodsids);
1884                                struct cc_srvid *srv;
1885                                n=0;
1886                                tpl_printf(vars, TPLADD, "SERVICESGOOD", "");
1887                                while ((srv=ll_iter_next(&its))) {
1888                                        tpl_printf(vars, TPLAPPEND, "SERVICESGOOD", "%04X%s", srv->sid, ++n%10==0?"<BR>\n":" ");
1889                                }
1890
1891                                its = ll_iter_create(card->badsids);
1892                                n=0;
1893                                tpl_printf(vars, TPLADD, "SERVICESBAD", "");
1894                                while ((srv=ll_iter_next(&its))) {
1895                                        tpl_printf(vars, TPLAPPEND, "SERVICESBAD", "%04X%s", srv->sid, ++n%10==0?"<BR>\n":" ");
1896                                }
1897                    }
1898
1899                    struct s_cardsystem *cs = get_cardsystem_by_caid(card->caid);
1900
1901                    if (cs)
1902                        tpl_addVar(vars, TPLADD, "SYSTEM", cs->desc ? cs->desc : "");
1903                    else
1904                        tpl_addVar(vars, TPLADD, "SYSTEM", "???");
1905
1906                    tpl_printf(vars, TPLADD, "SHAREID", "%08X", card->id);
1907                    tpl_printf(vars, TPLADD, "REMOTEID", "%08X", card->remote_id);
1908                    tpl_printf(vars, TPLADD, "UPHOPS", "%d", card->hop);
1909                    tpl_printf(vars, TPLADD, "MAXDOWN", "%d", card->reshare);
1910
1911                    LL_ITER pit = ll_iter_create(card->providers);
1912                    struct cc_provider *prov;
1913
1914                    providercount = 0;
1915
1916                    if (!apicall)
1917                        tpl_addVar(vars, TPLADD, "PROVIDERS", "");
1918                    else
1919                        tpl_addVar(vars, TPLADD, "PROVIDERLIST", "");
1920
1921                    while ((prov = ll_iter_next(&pit))) {
1922                        provider = xml_encode(vars, get_provider(card->caid, prov->prov, provname));
1923
1924                        if (!apicall) {
1925                            if (prov->sa[0] || prov->sa[1] || prov->sa[2] || prov->sa[3]) {
1926                                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]);
1927                            } else {
1928                                tpl_printf(vars, TPLAPPEND, "PROVIDERS", "%s<BR>\n", provider);
1929                            }
1930                        } else {
1931                            if (prov->sa[0] || prov->sa[1] || prov->sa[2] || prov->sa[3])
1932                                tpl_printf(vars, TPLADD, "APIPROVIDERSA", "%02X%02X%02X%02X", prov->sa[0], prov->sa[1], prov->sa[2], prov->sa[3]);
1933                            else
1934                                tpl_addVar(vars, TPLADD, "APIPROVIDERSA","");
1935                            tpl_printf(vars, TPLADD, "APIPROVIDERCAID", "%04X", card->caid);
1936                            tpl_printf(vars, TPLADD, "APIPROVIDERPROVID", "%06X", prov->prov);
1937                            tpl_printf(vars, TPLADD, "APIPROVIDERNUMBER", "%d", providercount);
1938                            tpl_addVar(vars, TPLADD, "APIPROVIDERNAME", xml_encode(vars, provider));
1939                            tpl_addVar(vars, TPLAPPEND, "PROVIDERLIST", tpl_getTpl(vars, "APICCCAMCARDPROVIDERBIT"));
1940                        }
1941                        providercount++;
1942                        tpl_printf(vars, TPLADD, "APITOTALPROVIDERS", "%d", providercount);
1943                    }
1944
1945                    LL_ITER nit = ll_iter_create(card->remote_nodes);
1946                    uint8_t *node;
1947
1948                    nodecount = 0;
1949                    if (!apicall) tpl_addVar(vars, TPLADD, "NODES", "");
1950                    else tpl_addVar(vars, TPLADD, "NODELIST", "");
1951
1952                    while ((node = ll_iter_next(&nit))) {
1953
1954                        if (!apicall) {
1955                            tpl_printf(vars, TPLAPPEND, "NODES", "%02X%02X%02X%02X%02X%02X%02X%02X<BR>\n",
1956                                    node[0], node[1], node[2], node[3], node[4], node[5], node[6], node[7]);
1957                        } else {
1958                            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]);
1959                            tpl_printf(vars, TPLADD, "APINODENUMBER", "%d", nodecount);
1960                            tpl_addVar(vars, TPLAPPEND, "NODELIST", tpl_getTpl(vars, "APICCCAMCARDNODEBIT"));
1961                        }
1962                        nodecount++;
1963                        tpl_printf(vars, TPLADD, "APITOTALNODES", "%d", nodecount);
1964                    }
1965
1966                    if (!apicall)
1967                        tpl_addVar(vars, TPLAPPEND, "CCCAMSTATSENTRY", tpl_getTpl(vars, "ENTITLEMENTCCCAMENTRYBIT"));
1968                    else
1969                        tpl_addVar(vars, TPLAPPEND, "CARDLIST", tpl_getTpl(vars, "APICCCAMCARDBIT"));
1970
1971                    cardcount++;
1972                }
1973               
1974                // set previous Link if needed
1975                if (offset >= ENTITLEMENT_PAGE_SIZE) {
1976                    tpl_printf(vars, TPLAPPEND, "CONTROLS", "<A HREF=\"entitlements.html?offset=%d&globallist=%s&amp;label=%s\"> << PREVIOUS < </A>",
1977                            offset - ENTITLEMENT_PAGE_SIZE,
1978                            getParam(params, "globallist"),
1979                            getParam(params, "label"));
1980                }
1981
1982                // set next link if needed
1983                if (card) {
1984                    tpl_printf(vars, TPLAPPEND, "CONTROLS", "<A HREF=\"entitlements.html?offset=%d&globallist=%s&amp;label=%s\"> > NEXT >> </A>",
1985                            offset + ENTITLEMENT_PAGE_SIZE,
1986                            getParam(params, "globallist"),
1987                            getParam(params, "label"));
1988                }
1989
1990                if (!apicall) {
1991                    tpl_printf(vars, TPLADD, "TOTALS", "card count=%d", cardcount);
1992                    tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTCCCAMBIT"));
1993                } else {
1994                    tpl_printf(vars, TPLADD, "APITOTALCARDS", "%d", cardcount);
1995                }
1996
1997            } else {
1998                if (!apicall) {
1999                    tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTGENERICBIT"));
2000                    tpl_addVar(vars, TPLADD, "LOGHISTORY", "no cards found<BR>\n");
2001                } else {
2002                    tpl_printf(vars, TPLADD, "APITOTALCARDS", "%d", cardcount);
2003                }
2004            }
2005
2006            if (show_global_list)
2007                    unlock_sharelist();
2008            else if (lock)
2009                    cs_unlock(lock);
2010
2011        } else {
2012#else
2013    if (cfg.saveinithistory && strlen(reader_) > 0) {
2014        {
2015            struct s_reader *rdr;
2016#endif
2017            tpl_addVar(vars, TPLADD, "LOGHISTORY", "->");
2018            // normal non-cccam reader
2019
2020            rdr = get_reader_by_label(reader_);
2021
2022            if (rdr->init_history) {
2023                char *ptr, *saveptr1 = NULL;
2024                for (ptr=strtok_r(rdr->init_history, "\n", &saveptr1); ptr; ptr=strtok_r(NULL, "\n", &saveptr1)) {
2025                    tpl_printf(vars, TPLAPPEND, "LOGHISTORY", "%s<BR />", ptr);
2026                    saveptr1[-1]='\n';
2027                }
2028            }
2029
2030            tpl_addVar(vars, TPLADD, "READERNAME", rdr->label);
2031            tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTGENERICBIT"));
2032        }
2033
2034    } else {
2035        tpl_addVar(vars, TPLADD, "LOGHISTORY",
2036                "You have to set saveinithistory=1 in your config to see Entitlements!<BR>\n");
2037        tpl_addVar(vars, TPLADD, "ENTITLEMENTCONTENT", tpl_getTpl(vars, "ENTITLEMENTGENERICBIT"));
2038    }
2039
2040    if (!apicall)
2041        return tpl_getTpl(vars, "ENTITLEMENTS");
2042    else
2043        return tpl_getTpl(vars, "APICCCAMCARDLIST");
2044}
2045
2046char *send_oscam_status(struct templatevars *vars, struct uriparams *params, int32_t apicall) {
2047    int32_t i;
2048    char *usr;
2049    int32_t lsec, isec, con, cau = 0;
2050    time_t now = time((time_t)0);
2051    struct tm lt;
2052
2053    if (strcmp(getParam(params, "action"), "kill") == 0) {
2054        struct s_client *cl = get_client_by_tid(atol(getParam(params, "threadid")));
2055        if (cl) {
2056            kill_thread(cl);
2057            cs_log("Client %s killed by WebIF from %s", cl->account->usr, cs_inet_ntoa(GET_IP()));
2058        }
2059    }
2060
2061    if (strcmp(getParam(params, "action"), "restart") == 0) {
2062        struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
2063        if(rdr) {
2064            restart_cardreader(rdr, 1);
2065            cs_log("Reader %s restarted by WebIF from %s", rdr->label, cs_inet_ntoa(GET_IP()));
2066        }
2067    }
2068
2069    char *debuglvl = getParam(params, "debug");
2070    if(strlen(debuglvl) > 0) {
2071#ifndef WITH_DEBUG
2072        cs_log("*** Warning: Debug Support not compiled in ***");
2073#else
2074        int32_t dblvl = atoi(debuglvl);
2075        if(dblvl >= 0 && dblvl <= 255) cs_dblevel = dblvl;
2076        cs_log("%s debug_level=%d", "all", cs_dblevel);
2077#endif
2078    }
2079
2080    char *hide = getParam(params, "hide");
2081    if(strlen(hide) > 0) {
2082        uint32_t clidx;
2083        clidx = atol(hide);
2084        struct s_client *hideidx = get_client_by_tid(clidx);
2085        if(hideidx)
2086            hideidx->wihidden = 1;
2087    }
2088
2089    char *hideidle = getParam(params, "hideidle");
2090    if(strlen(hideidle) > 0) {
2091        if (atoi(hideidle) == 2) {
2092            struct s_client *cl;
2093            for (cl=first_client; cl ; cl=cl->next)
2094                cl->wihidden = 0;
2095        }
2096        else {
2097            int32_t oldval = cfg.http_hide_idle_clients;
2098            chk_t_webif("httphideidleclients", hideidle);
2099            if(oldval != cfg.http_hide_idle_clients) {
2100                refresh_oscam(REFR_SERVER);
2101            }
2102        }
2103    }
2104
2105    if(cfg.http_hide_idle_clients > 0) tpl_addVar(vars, TPLADD, "HIDEIDLECLIENTSSELECTED1", "selected");
2106    else tpl_addVar(vars, TPLADD, "HIDEIDLECLIENTSSELECTED0", "selected");
2107
2108    int32_t user_count_all = 0, user_count_shown = 0, user_count_active = 0;
2109    int32_t reader_count_all = 0, reader_count_conn = 0;
2110    int32_t proxy_count_all = 0, proxy_count_conn = 0;
2111    int32_t shown;
2112
2113    struct s_client *cl;
2114    for (i=0, cl=first_client; cl ; cl=cl->next, i++) {
2115
2116        // Reset template variables
2117        tpl_addVar(vars, TPLADD, "CLIENTLBVALUE","");
2118        tpl_addVar(vars, TPLADD, "LASTREADER", "");
2119        tpl_addVar(vars, TPLADD, "CLIENTPROTO", "");
2120        tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", "");
2121        tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIME", "");
2122        tpl_addVar(vars, TPLADD, "CLIENTLASTRESPONSETIMEHIST", "");
2123
2124        if (cl->typ=='c')
2125            user_count_all++;
2126        else if (cl->typ=='p')
2127            proxy_count_all++;
2128        else if (cl->typ=='r')
2129            reader_count_all++;
2130
2131        shown = 0;
2132        if (cl->wihidden != 1) {
2133
2134            if((cfg.http_hide_idle_clients != 1) || (cl->typ != 'c') || ((now - cl->lastecm) <= cfg.mon_hideclient_to)) {
2135
2136                if (cl->typ=='c'){
2137                    user_count_shown++;
2138                    if (cfg.http_hide_idle_clients != 1 && cfg.mon_hideclient_to > 0 && (now - cl->lastecm) <= cfg.mon_hideclient_to){
2139                        user_count_active++;
2140                        tpl_addVar(vars, TPLADD, "CLIENTTYPE", "a");
2141                    } else tpl_addVar(vars, TPLADD, "CLIENTTYPE", "c");
2142                    if(cl->lastecm > cl->login) isec = now - cl->lastecm;
2143                    else isec = now - cl->login;
2144                } else {
2145                    if (cl->typ=='r' && cl->reader->card_status==CARD_INSERTED)
2146                        reader_count_conn++;
2147                    else if (cl->typ=='p' && (cl->reader->card_status==CARD_INSERTED ||cl->reader->tcp_connected))
2148                        proxy_count_conn++;
2149                    tpl_printf(vars, TPLADD, "CLIENTTYPE", "%c", cl->typ);
2150                    isec = now - cl->last;
2151                }
2152
2153                shown = 1;
2154                lsec=now-cl->login;
2155                usr=username(cl);
2156
2157                if ((cl->typ=='r') || (cl->typ=='p')) usr=cl->reader->label;
2158
2159                if (cl->dup) con=2;
2160                else if ((cl->tosleep) && (now-cl->lastswitch>cl->tosleep)) con=1;
2161                else con=0;
2162
2163                // no AU reader == 0 / AU ok == 1 / Last EMM > aulow == -1
2164                if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r'){
2165                    if ((cl->typ == 'c' && ll_count(cl->aureader_list) == 0) || ((cl->typ == 'p' || cl->typ == 'r') && cl->reader->audisabled)) cau = 0;
2166                    else if ((now-cl->lastemm)/60 > cfg.mon_aulow) cau = -1;
2167                    else cau = 1;
2168
2169                    if (!apicall){
2170                        if (cau == 0) {
2171                            tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "OFF");
2172                        } else {
2173                            if (cau == -1) tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "<a href=\"#\" class=\"tooltip\">ON");
2174                            else tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "<a href=\"#\" class=\"tooltip\">ACTIVE");
2175                            tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", "<span>");
2176                            if (cl->typ == 'c'){
2177                                struct s_reader *rdr;
2178                                LL_ITER itr = ll_iter_create(cl->aureader_list);
2179                                while ((rdr = ll_iter_next(&itr))) {
2180                                    if(rdr->audisabled) tpl_printf(vars, TPLAPPEND, "CLIENTCAUHTTP", "(%s)<br>", rdr->label);
2181                                    else tpl_printf(vars, TPLAPPEND, "CLIENTCAUHTTP", "%s<br>", rdr->label);
2182                                }
2183                            } else tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", cl->reader->label);
2184                            tpl_addVar(vars, TPLAPPEND, "CLIENTCAUHTTP", "</span></a>");
2185                        }
2186                    }
2187                } else {
2188                    cau = 0;
2189                    tpl_addVar(vars, TPLADD, "CLIENTCAUHTTP", "");
2190                }
2191
2192                localtime_r(&cl->login, &lt);
2193
2194                tpl_printf(vars, TPLADD, "HIDEIDX", "%ld", cl->thread);
2195
2196                if(cl->typ == 'c' && !cfg.http_readonly) {
2197                    tpl_printf(vars, TPLADD, "CSIDX", "<A HREF=\"status.html?action=kill&threadid=%ld\" TITLE=\"Kill this client\"><IMG HEIGHT=\"16\" WIDTH=\"16\" SRC=\"image?i=ICKIL\" ALT=\"Kill\"></A>", cl->thread);
2198                }
2199                else if((cl->typ == 'p') && !cfg.http_readonly) {
2200                    tpl_printf(vars, TPLADD, "CSIDX", "<A HREF=\"status.html?action=restart&amp;label=%s\" TITLE=\"Restart this reader/ proxy\"><IMG HEIGHT=\"16\" WIDTH=\"16\" SRC=\"image?i=ICKIL\" ALT=\"Restart\"></A>", urlencode(vars, cl->reader->label));
2201                }
2202                else {
2203                    tpl_printf(vars, TPLADD, "CSIDX", "%8X&nbsp;", cl->thread);
2204                }
2205
2206                tpl_printf(vars, TPLADD, "CLIENTTYPE", "%c", cl->typ);
2207                tpl_printf(vars, TPLADD, "CLIENTCNR", "%d", get_threadnum(cl));
2208                tpl_addVar(vars, TPLADD, "CLIENTUSER", xml_encode(vars, usr));
2209                if (cl->typ == 'c')
2210                    tpl_addVar(vars, TPLADD, "CLIENTDESCRIPTION", xml_encode(vars, cl->account?cl->account->description:""));
2211                tpl_printf(vars, TPLADD, "CLIENTCAU", "%d", cau);
2212                if(!apicall){
2213                    if(cl->typ == 'c' || cl->typ == 'p' || cl->typ == 'r'){
2214                        if(cl->crypted) tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", "ON");
2215                        else tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", "OFF");
2216                    } else tpl_addVar(vars, TPLADD, "CLIENTCRYPTED", "");
2217                } else tpl_printf(vars, TPLADD, "CLIENTCRYPTED", "%d", cl->crypted);
2218                tpl_addVar(vars, TPLADD, "CLIENTIP", cs_inet_ntoa(cl->ip));
2219                tpl_printf(vars, TPLADD, "CLIENTPORT", "%d", cl->port);
2220                char *proto = monitor_get_proto(cl);
2221
2222                if ((strcmp(proto,"newcamd") == 0) && (cl->typ == 'c'))
2223                    tpl_printf(vars, TPLADD, "CLIENTPROTO","%s (%s)", proto, get_ncd_client_name(cl->ncd_client_id));
2224#ifdef MODULE_CCCAM
2225                else if ((strncmp(proto,"cccam", 5) == 0)) {
2226                    struct cc_data *cc = cl->cc;
2227                    if(cc && cc->remote_version && cc->remote_build) {
2228                        tpl_printf(vars, TPLADD, "CLIENTPROTO", "%s (%s-%s)", proto, cc->remote_version, cc->remote_build);
2229                        if(cc->extended_mode)
2230                            tpl_addVar(vars, TPLADD, "CLIENTPROTOTITLE", cc->remote_oscam);
2231                        else
2232                            tpl_addVar(vars, TPLADD, "CLIENTPROTOTITLE", ""); //unset tpl var
2233                    }
2234                    else
2235                    {
2236                        tpl_addVar(vars, TPLADD, "CLIENTPROTO", proto);
2237                        tpl_addVar(vars, TPLADD, "CLIENTPROTOTITLE", "");
2238                    }
2239                }
2240#endif
2241                else {
2242                    tpl_addVar(vars, TPLADD, "CLIENTPROTO", proto);
2243                    tpl_addVar(vars, TPLADD, "CLIENTPROTOTITLE", "");
2244                }
2245
2246                if (!apicall) {
2247                    tpl_printf(vars, TPLADD, "CLIENTLOGINDATE", "%02d.%02d.%02d", lt.tm_mday, lt.tm_mon+1, lt.tm_year%100);
2248                    tpl_printf(vars, TPLAPPEND, "CLIENTLOGINDATE", " %02d:%02d:%02d", lt.tm_hour, lt.tm_min, lt.tm_sec);
2249                    tpl_addVar(vars, TPLADD, "CLIENTLOGINSECS", sec2timeformat(vars, lsec));
2250                } else {
2251                    char tbuffer [30];
2252                    strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &lt);
2253                    tpl_addVar(vars, TPLADD, "CLIENTLOGINDATE", tbuffer);
2254                    tpl_printf(vars, TPLADD, "CLIENTLOGINSECS", "%d", lsec);
2255                }
2256
2257                if (isec < cfg.mon_hideclient_to || cfg.mon_hideclient_to == 0) {
2258
2259                    if (((cl->typ!='r') || (cl->typ!='p')) && (cl->lastreader[0])) {
2260                        tpl_printf(vars, TPLADD, "CLIENTLBVALUE", "by %s", cl->lastreader);
2261                        tpl_printf(vars, TPLAPPEND, "CLIENTLBVALUE", "&nbsp;(%dms)", cl->cwlastresptime);
2262                        if (apicall)
2263                            tpl_addVar(vars, TPLADD, "LASTREADER", cl->lastreader);
2264                    }
2265
2266                    tpl_printf(vars, TPLADD, "CLIENTCAID", "%04X", cl->last_caid);
2267                    tpl_printf(vars, TPLADD, "CLIENTSRVID", "%04X", cl->last_srvid);
2268                    tpl_printf(vars, TPLADD, "CLIENTLASTRESPONSETIME", "%d", cl->cwlastresptime?cl->cwlastresptime:1);
2269
2270                    int32_t k;
2271                    char *dot = "";
2272
2273                    if(cl->cwlastresptimes_last == CS_ECM_RINGBUFFER_MAX - 1){
2274                        for(k = 0; k < CS_ECM_RINGBUFFER_MAX ; k++){
2275                            tpl_printf(vars, TPLAPPEND, "CLIENTLASTRESPONSETIMEHIST", "%s%d", dot, cl->cwlastresptimes[k]);
2276                            dot=",";
2277                        }
2278                    } else {
2279                        for(k = cl->cwlastresptimes_last + 1; k < CS_ECM_RINGBUFFER_MAX; k++){
2280                            tpl_printf(vars, TPLAPPEND, "CLIENTLASTRESPONSETIMEHIST", "%s%d", dot, cl->cwlastresptimes[k]);
2281                            dot=",";
2282                        }
2283
2284                        for(k = 0; k < cl->cwlastresptimes_last + 1 ; k++){
2285                            tpl_printf(vars, TPLAPPEND, "CLIENTLASTRESPONSETIMEHIST", "%s%d", dot, cl->cwlastresptimes[k]);
2286                            dot=",";
2287                        }
2288                    }
2289
2290                    if(!cfg.mon_appendchaninfo){
2291                        char channame[32];
2292                        get_servicename(cl, cl->last_srvid, cl->last_caid, channame);
2293                    }
2294
2295                    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 ? ": " : "");
2296                    tpl_addVar(vars, TPLADD, "CLIENTSRVNAME", cl->last_srvidptr && cl->last_srvidptr->name ? xml_encode(vars, cl->last_srvidptr->name) : "");
2297                    tpl_addVar(vars, TPLADD, "CLIENTSRVTYPE", cl->last_srvidptr && cl->last_srvidptr->type ? xml_encode(vars, cl->last_srvidptr->type) : "");
2298                    tpl_addVar(vars, TPLADD, "CLIENTSRVDESCRIPTION", cl->last_srvidptr && cl->last_srvidptr->desc ? xml_encode(vars, cl->last_srvidptr->desc) : "");
2299                } else {
2300                    tpl_addVar(vars, TPLADD, "CLIENTCAID", "0000");
2301                    tpl_addVar(vars, TPLADD, "CLIENTSRVID", "0000");
2302                    tpl_addVar(vars, TPLADD, "CLIENTSRVPROVIDER","");
2303                    tpl_addVar(vars, TPLADD, "CLIENTSRVNAME","");
2304                    tpl_addVar(vars, TPLADD, "CLIENTSRVTYPE","");
2305                    tpl_addVar(vars, TPLADD, "CLIENTSRVDESCRIPTION","");
2306                    tpl_addVar(vars, TPLADD, "CLIENTLBVALUE","");
2307
2308                }
2309
2310                if (!apicall) {
2311                    tpl_addVar(vars, TPLADD, "CLIENTIDLESECS", sec2timeformat(vars, isec));
2312                } else {
2313                    tpl_printf(vars, TPLADD, "CLIENTIDLESECS", "%d", isec);
2314                }
2315
2316
2317                if(con == 2) tpl_addVar(vars, TPLADD, "CLIENTCON", "Duplicate");
2318                else if (con == 1) tpl_addVar(vars, TPLADD, "CLIENTCON", "Sleep");
2319                else
2320                {
2321                    char *txt = "OK";
2322                    if (cl->typ == 'r' || cl->typ == 'p') //reader or proxy
2323                    {
2324                        struct s_reader *rdr = cl->reader;
2325                                if (rdr->lbvalue)
2326                                    tpl_printf(vars, TPLADD, "CLIENTLBVALUE", "<A HREF=\"readerstats.html?label=%s&amp;hide=4\" TITLE=\"Show statistics for this reader/ proxy\">%d</A>", urlencode(vars, rdr->label), rdr->lbvalue);
2327                                else
2328                                    tpl_printf(vars, TPLADD, "CLIENTLBVALUE", "<A HREF=\"readerstats.html?label=%s&amp;hide=4\" TITLE=\"Show statistics for this reader/ proxy\">%s</A>", urlencode(vars, rdr->label), "no data");
2329
2330                                switch(rdr->card_status)
2331                                {
2332                                case NO_CARD: txt = "OFF"; break;
2333                                case UNKNOWN: txt = "UNKNOWN"; break;
2334                                case CARD_NEED_INIT: txt = "NEEDINIT"; break;
2335                                case CARD_INSERTED:
2336                                    if (cl->typ=='p')
2337                                        txt = "CONNECTED";
2338                                    else
2339                                        txt = "CARDOK";
2340                                    break;
2341                                case CARD_FAILURE: txt = "ERROR"; break;
2342                                default: txt = "UNDEF";
2343                                }
2344                    }
2345                    tpl_addVar(vars, TPLADD, "CLIENTCON", txt);
2346
2347#ifdef MODULE_CCCAM
2348                    if (!apicall) {
2349                        if((cl->typ == 'r' || cl->typ == 'p') && strncmp(proto,"cccam", 5) == 0){
2350                            struct cc_data *rcc = cl->cc;
2351                            if(rcc){
2352                                LLIST *cards = rcc->cards;
2353                                if (cards) {
2354                                    int32_t cnt = ll_count(cards);
2355                                    int32_t locals = rcc->num_hop1;
2356                                    tpl_printf(vars, TPLADD, "TMP", "(%d of %d card%s)", locals, cnt, (cnt > 1)? "s": "");
2357                                    tpl_printf(vars, TPLADD, "TMPSPAN","<SPAN>card count=%d<BR>hop1=%d<BR>hop2=%d<BR>hopx=%d<BR>currenthops=%d<BR><BR>reshare0=%d<BR>reshare1=%d<BR>reshare2=%d<BR>resharex=%d</SPAN>",
2358                                            cnt,
2359                                            rcc->num_hop1,
2360                                            rcc->num_hop2,
2361                                            rcc->num_hopx,
2362                                            cl->reader->cc_currenthops,
2363                                            rcc->num_reshare0,
2364                                            rcc->num_reshare1,
2365                                            rcc->num_reshare2,
2366                                            rcc->num_resharex);
2367
2368                                    tpl_printf(vars, TPLAPPEND, "CLIENTCON", " <A HREF=\"entitlements.html?label=%s\" class=\"tooltip%s\">%s%s</A>",
2369                                                                urlencode(vars, cl->reader->label),
2370                                                                rcc->num_reshare0 > 0 ? "1": "",
2371                                                                tpl_getVar(vars, "TMP"),
2372                                                                tpl_getVar(vars, "TMPSPAN"));
2373                                }
2374                            }
2375                        }
2376                    }
2377#endif
2378                }
2379            }
2380        }
2381
2382        if (!apicall) {
2383            // select right suborder
2384            if (cl->typ == 'c') {
2385                if (shown) tpl_addVar(vars, TPLAPPEND, "CLIENTSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT"));
2386                if(cfg.http_hide_idle_clients == 1 || cfg.mon_hideclient_to < 1) tpl_printf(vars, TPLADD, "CLIENTHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"17\">Clients %d/%d</TD></TR>\n",
2387                        user_count_shown, user_count_all);
2388                else tpl_printf(vars, TPLADD, "CLIENTHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"17\">Clients %d/%d (%d with ECM within last %d seconds)</TD></TR>\n",
2389                        user_count_shown, user_count_all, user_count_active, cfg.mon_hideclient_to);
2390            }
2391            else if (cl->typ == 'r') {
2392                if (shown) tpl_addVar(vars, TPLAPPEND, "READERSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT"));
2393                tpl_printf(vars, TPLADD, "READERHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"17\">Readers %d/%d</TD></TR>\n",
2394                        reader_count_conn, reader_count_all);
2395            }
2396            else if (cl->typ == 'p') {
2397                if (shown) tpl_addVar(vars, TPLAPPEND, "PROXYSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT"));
2398                tpl_printf(vars, TPLADD, "PROXYHEADLINE", "\t\t<TR><TD CLASS=\"subheadline\" colspan=\"17\">Proxies %d/%d</TD></TR>\n",
2399                        proxy_count_conn, proxy_count_all);
2400            }
2401            else
2402                if (shown) tpl_addVar(vars, TPLAPPEND, "SERVERSTATUS", tpl_getTpl(vars, "CLIENTSTATUSBIT"));
2403
2404        } else {
2405            if (shown) tpl_addVar(vars, TPLAPPEND, "APISTATUSBITS", tpl_getTpl(vars, "APISTATUSBIT"));
2406        }
2407    }
2408
2409    if (loghist) {
2410        char *t_loghistptr = loghistptr, *ptr1 = NULL;
2411        int32_t d = 0, l1 = strlen(t_loghistptr+1) + 2;
2412        char *lastpos = loghist + (cfg.loghistorysize)-1;
2413
2414        for (ptr1 = t_loghistptr + l1, i=0; i<200; i++, ptr1 = ptr1+l1) {
2415            l1 = strlen(ptr1)+1;
2416            if (!d && ((ptr1 >= lastpos) || (l1 < 2))) {
2417                ptr1 = loghist;
2418                l1 = strlen(ptr1)+1;
2419                d++;
2420            }
2421       
2422            if (d && ((ptr1 >= t_loghistptr) || (l1 < 2)))
2423                break;
2424
2425            char p_usr[32];
2426            size_t pos1 = strcspn (ptr1, "\t")+1;
2427            cs_strncpy(p_usr, ptr1 , pos1 > sizeof(p_usr) ? sizeof(p_usr) : pos1);
2428
2429            char *p_txt = ptr1 + pos1;
2430
2431            if (!apicall) {
2432                if (p_txt[0]) tpl_printf(vars, TPLAPPEND, "LOGHISTORY", "\t\t<span class=\"%s\">%s\t\t</span><br>\n", p_usr, p_txt);
2433            } else {
2434                if (strcmp(getParam(params, "appendlog"), "1") == 0)
2435                    tpl_addVar(vars, TPLAPPEND, "LOGHISTORY", p_txt);
2436            }
2437        }
2438    } else {
2439        tpl_addVar(vars, TPLADD, "LOGHISTORY", "loghistorysize is set to 0 in your configuration<BR>\n");
2440    }
2441
2442#ifdef WITH_DEBUG
2443    // Debuglevel Selector
2444    int32_t lvl;
2445    for (i = 0; i < 8; i++) {
2446        lvl = 1 << i;
2447        tpl_printf(vars, TPLADD, "TMPC", "DCLASS%d", lvl);
2448        tpl_printf(vars, TPLADD, "TMPV", "DEBUGVAL%d", lvl);
2449        if (cs_dblevel & lvl) {
2450            tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugls");
2451            tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel - lvl);
2452        } else {
2453            tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugl");
2454            tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel + lvl);
2455        }
2456    }
2457
2458    if (cs_dblevel == 255)
2459        tpl_addVar(vars, TPLADD, "DCLASS255", "debugls");
2460    else
2461        tpl_addVar(vars, TPLADD, "DCLASS255", "debugl");
2462
2463    tpl_addVar(vars, TPLADD, "NEXTPAGE", "status.html");
2464    tpl_addVar(vars, TPLADD, "DCLASS", "debugl"); //default
2465    tpl_printf(vars, TPLADD, "ACTDEBUG", "%d", cs_dblevel);
2466    tpl_addVar(vars, TPLADD, "SDEBUG", tpl_getTpl(vars, "DEBUGSELECT"));
2467#endif
2468
2469    if(!apicall)
2470        return tpl_getTpl(vars, "STATUS");
2471    else
2472        return tpl_getTpl(vars, "APISTATUS");
2473
2474}
2475
2476char *send_oscam_services_edit(struct templatevars *vars, struct uriparams *params) {
2477    struct s_sidtab *sidtab,*ptr;
2478    char label[sizeof(cfg.sidtab->label)];
2479    int32_t i;
2480
2481    cs_strncpy(label, strtolower(getParam(params, "service")), sizeof(label));
2482
2483    for (sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab=sidtab->next);
2484
2485    if (sidtab == NULL) {
2486        i = 1;
2487        while(strlen(label) < 1) {
2488            snprintf(label, sizeof(label)/sizeof(char) - 1, "newservice%d", i);
2489            for (sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab = sidtab->next);
2490            if(sidtab != NULL) label[0] = '\0';
2491            ++i;
2492        }
2493        if (!cs_malloc(&sidtab, sizeof(struct s_sidtab), -1)) return "0";
2494
2495        if(cfg.sidtab == NULL) cfg.sidtab = sidtab;
2496        else {
2497            for (ptr = cfg.sidtab; ptr != NULL && ptr->next != NULL; ptr = ptr->next);
2498            ptr->next = sidtab;
2499        }
2500        memset(sidtab, 0, sizeof(struct s_sidtab));
2501        cs_strncpy((char *)sidtab->label, label, sizeof(sidtab->label));
2502
2503        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>New service has been added</b><BR>");
2504        if (write_services()==0) refresh_oscam(REFR_SERVICES);
2505        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Writing services to disk failed!</b><BR>");
2506
2507        for (sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab=sidtab->next);
2508    }
2509
2510    if (strcmp(getParam(params, "action"), "Save") == 0) {
2511        for(i=0;i<(*params).paramcount;i++) {
2512            if ((strcmp((*params).params[i], "action")) && (strcmp((*params).params[i], "service"))) {
2513                chk_sidtab((*params).params[i], (*params).values[i], sidtab);
2514            }
2515        }
2516        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Services updated</B><BR><BR>");
2517        if (write_services()==0) refresh_oscam(REFR_SERVICES);
2518        else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<B>Write Config failed</B><BR><BR>");
2519
2520        for (sidtab = cfg.sidtab; sidtab != NULL && strcmp(label, sidtab->label) != 0; sidtab=sidtab->next);
2521    }
2522
2523    tpl_addVar(vars, TPLADD, "LABEL", sidtab->label);
2524    tpl_addVar(vars, TPLADD, "LABELENC", urlencode(vars, sidtab->label));
2525
2526
2527    for (i=0; i<sidtab->num_caid; i++) {
2528        if (i==0) tpl_printf(vars, TPLADD, "CAIDS", "%04X", sidtab->caid[i]);
2529        else tpl_printf(vars, TPLAPPEND, "CAIDS", ",%04X", sidtab->caid[i]);
2530    }
2531    for (i=0; i<sidtab->num_provid; i++) {
2532        if (i==0) tpl_printf(vars, TPLADD, "PROVIDS", "%06lX", sidtab->provid[i]);
2533        else tpl_printf(vars, TPLAPPEND, "PROVIDS", ",%06lX", sidtab->provid[i]);
2534    }
2535    for (i=0; i<sidtab->num_srvid; i++) {
2536        if (i==0) tpl_printf(vars, TPLADD, "SRVIDS", "%04X", sidtab->srvid[i]);
2537        else tpl_printf(vars, TPLAPPEND, "SRVIDS", ",%04X", sidtab->srvid[i]);
2538    }
2539    return tpl_getTpl(vars, "SERVICEEDIT");
2540}
2541
2542char *send_oscam_services(struct templatevars *vars, struct uriparams *params) {
2543    struct s_sidtab *sidtab, *sidtab2;
2544    char *service = getParam(params, "service");
2545    char channame[32];
2546    int32_t i, found = 0;
2547
2548    if (strcmp(getParam(params, "action"), "delete") == 0) {
2549        if(cfg.http_readonly) {
2550            tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Sorry, Webif is in readonly mode. No deletion will be made!</b><BR>");
2551        } else {
2552            sidtab=cfg.sidtab;
2553            if(strcmp(sidtab->label, service) == 0) {
2554                cfg.sidtab = sidtab->next;
2555                free_sidtab(sidtab);
2556                found = 1;
2557            } else if (sidtab->next != NULL) {
2558                do {
2559                    if(strcmp(sidtab->next->label, service) == 0) {
2560                        sidtab2 = sidtab->next;
2561                        sidtab->next = sidtab2->next;
2562                        free_sidtab(sidtab2);
2563                        found = 1;
2564                        break;
2565                    }
2566                } while ((sidtab = sidtab->next) && (sidtab->next != NULL));
2567            }
2568            if (found > 0) {
2569                tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Service has been deleted!</b><BR>");
2570                if (write_services() == 0) refresh_oscam(REFR_SERVICES);
2571                else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Writing services to disk failed!</b><BR>");
2572            } else tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Sorry but the specified service doesn't exist. No deletion will be made!</b><BR>");
2573        }
2574    }
2575
2576    sidtab = cfg.sidtab;
2577    // Show List
2578    while(sidtab != NULL) {
2579        tpl_printf(vars, TPLADD, "SID","");
2580        if ((strcmp(getParam(params, "service"), sidtab->label) == 0) && (strcmp(getParam(params, "action"), "list") == 0) ) {
2581            tpl_printf(vars, TPLADD, "SIDCLASS","sidlist");
2582            tpl_printf(vars, TPLAPPEND, "SID", "<div style=\"float:right;background-color:red;color:white\"><A HREF=\"services.html\" style=\"color:white;text-decoration:none\">X</A></div>");
2583            for (i=0; i<sidtab->num_srvid; i++) {
2584                tpl_printf(vars, TPLAPPEND, "SID", "%04X : %s<BR>", sidtab->srvid[i], xml_encode(vars, get_servicename(cur_client(), sidtab->srvid[i], sidtab->caid[0], channame)));
2585            }
2586        } else {
2587            tpl_printf(vars, TPLADD, "SIDCLASS","");
2588            tpl_printf(vars, TPLADD, "SID","<A HREF=\"services.html?service=%s&amp;action=list\">Show Services</A>", urlencode(vars, sidtab->label));
2589        }
2590        tpl_addVar(vars, TPLADD, "LABELENC", urlencode(vars, sidtab->label));
2591        tpl_addVar(vars, TPLADD, "LABEL", xml_encode(vars, sidtab->label));
2592        tpl_addVar(vars, TPLADD, "SIDLIST", tpl_getTpl(vars, "SERVICECONFIGSIDBIT"));
2593
2594        tpl_addVar(vars, TPLAPPEND, "SERVICETABS", tpl_getTpl(vars, "SERVICECONFIGLISTBIT"));
2595        sidtab=sidtab->next;
2596    }
2597    return tpl_getTpl(vars, "SERVICECONFIGLIST");
2598}
2599
2600char *send_oscam_savetpls(struct templatevars *vars) {
2601    if(strlen(cfg.http_tpl) > 0) {
2602        tpl_printf(vars, TPLADD, "CNT", "%d", tpl_saveIncludedTpls(cfg.http_tpl));
2603        tpl_addVar(vars, TPLADD, "PATH", cfg.http_tpl);
2604    } else tpl_addVar(vars, TPLADD, "CNT", "0");
2605    return tpl_getTpl(vars, "SAVETEMPLATES");
2606}
2607
2608char *send_oscam_shutdown(struct templatevars *vars, FILE *f, struct uriparams *params, int32_t apicall, int8_t *keepalive) {
2609    if (strcmp(strtolower(getParam(params, "action")), "shutdown") == 0) {
2610        *keepalive = 0;
2611        if(!apicall){
2612            tpl_addVar(vars, TPLADD, "STYLESHEET", CSS);
2613            tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", SHUTDOWNREFRESH);
2614            tpl_addVar(vars, TPLADD, "REFRESHURL", "status.html");
2615            tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
2616            tpl_printf(vars, TPLADD, "SECONDS", "%d", SHUTDOWNREFRESH);
2617            char *result = tpl_getTpl(vars, "SHUTDOWN");
2618            send_headers(f, 200, "OK", NULL, "text/html", 0, strlen(result), NULL, 0);
2619            webif_write(result, f);
2620            cs_log("Shutdown requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
2621        } else {
2622            tpl_addVar(vars, TPLADD, "APICONFIRMMESSAGE", "shutdown");
2623            cs_log("Shutdown requested by XMLApi from %s", cs_inet_ntoa(GET_IP()));
2624        }
2625        running = 0;
2626        pthread_kill(httpthread, SIGPIPE);      // send signal to master thread to wake up from accept()
2627        cs_exit_oscam();
2628
2629        if(!apicall)
2630            return "1";
2631        else
2632            return tpl_getTpl(vars, "APICONFIRMATION");
2633
2634    }
2635    else if (strcmp(strtolower(getParam(params, "action")), "restart") == 0) {
2636        *keepalive = 0;
2637        if(!apicall){
2638            tpl_addVar(vars, TPLADD, "STYLESHEET", CSS);
2639            tpl_addVar(vars, TPLADD, "REFRESHTIME", "5");
2640            tpl_addVar(vars, TPLADD, "REFRESHURL", "status.html");
2641            tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
2642            tpl_addVar(vars, TPLADD, "SECONDS", "5");
2643            char *result = tpl_getTpl(vars, "SHUTDOWN");
2644            send_headers(f, 200, "OK", NULL, "text/html", 0,strlen(result), NULL, 0);
2645            webif_write(result, f);
2646            cs_log("Restart requested by WebIF from %s", cs_inet_ntoa(GET_IP()));
2647        } else {
2648            tpl_addVar(vars, TPLADD, "APICONFIRMMESSAGE", "restart");
2649            cs_log("Restart requested by XMLApi from %s", cs_inet_ntoa(GET_IP()));
2650        }
2651        running = 0;
2652        pthread_kill(httpthread, SIGPIPE);      // send signal to master thread to wake up from accept()
2653        cs_restart_oscam();
2654
2655        if(!apicall)
2656            return "1";
2657        else
2658            return tpl_getTpl(vars, "APICONFIRMATION");
2659
2660    } else {
2661        return tpl_getTpl(vars, "PRESHUTDOWN");
2662    }
2663}
2664
2665char *send_oscam_script(struct templatevars *vars) {
2666
2667    char *result = "not found";
2668    int32_t rc = 0;
2669    if(!cfg.http_readonly) {
2670        if(cfg.http_script[0]) {
2671            tpl_addVar(vars, TPLADD, "SCRIPTNAME",cfg.http_script);
2672            rc = system(cfg.http_script);
2673            if(rc == -1) {
2674                result = "done";
2675            } else {
2676                result = "failed";
2677            }
2678        } else {
2679            tpl_addVar(vars, TPLADD, "SCRIPTNAME", "no script defined");
2680        }
2681        tpl_addVar(vars, TPLADD, "SCRIPTRESULT", result);
2682        tpl_printf(vars, TPLADD, "CODE", "%d", rc);
2683    } else {
2684        tpl_addVar(vars, TPLAPPEND, "MESSAGE", "<b>Sorry, Webif is in readonly mode. No script execution possible!</b><BR>");
2685    }
2686    return tpl_getTpl(vars, "SCRIPT");
2687
2688}
2689
2690char *send_oscam_scanusb(struct templatevars *vars) {
2691
2692#ifndef OS_CYGWIN32
2693    FILE *fp;
2694    int32_t err=0;
2695    char path[1035];
2696
2697    fp = popen("lsusb -v | egrep '^Bus|^ *iSerial|^ *iProduct'", "r");
2698    if (fp == NULL) {
2699        tpl_addVar(vars, TPLADD, "USBENTRY", "Failed to run lusb");
2700        tpl_addVar(vars, TPLADD, "USBENTRY", path);
2701        tpl_addVar(vars, TPLAPPEND, "USBBIT", tpl_getTpl(vars, "SCANUSBBIT"));
2702        err = 1;
2703    }
2704
2705    if(!err) {
2706        while (fgets(path, sizeof(path)-1, fp) != NULL) {
2707            tpl_addVar(vars, TPLADD, "USBENTRYCLASS", "");
2708            if (strstr(path,"Bus ")) {
2709                tpl_addVar(vars, TPLADD, "USBENTRY", path);
2710                tpl_addVar(vars, TPLADD, "USBENTRYCLASS", "CLASS=\"scanusbsubhead\"");
2711            } else {
2712                tpl_printf(vars, TPLADD, "USBENTRY", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%s", path);
2713            }
2714            tpl_addVar(vars, TPLAPPEND, "USBBIT", tpl_getTpl(vars, "SCANUSBBIT"));
2715        }
2716    }
2717    pclose(fp);
2718#else
2719    tpl_addVar(vars, TPLADD, "MESSAGE", "Function not supported in CYGWIN environment");
2720#endif
2721    return tpl_getTpl(vars, "SCANUSB");
2722}
2723
2724char *send_oscam_files(struct templatevars *vars, struct uriparams *params) {
2725
2726    int32_t writable=0;
2727
2728    char *stoplog = getParam(params, "stoplog");
2729    if(strlen(stoplog) > 0)
2730        cfg.disablelog = atoi(stoplog);
2731
2732    char *stopusrlog = getParam(params, "stopusrlog");
2733    if(strlen(stopusrlog) > 0)
2734        cfg.disableuserfile = atoi(stopusrlog);
2735
2736    char *debuglvl = getParam(params, "debug");
2737    if(strlen(debuglvl) > 0) {
2738#ifndef WITH_DEBUG
2739        cs_log("*** Warning: Debug Support not compiled in ***");
2740#else
2741        int32_t dblvl = atoi(debuglvl);
2742        if(dblvl >= 0 && dblvl <= 255) cs_dblevel = dblvl;
2743        cs_log("%s debug_level=%d", "all", cs_dblevel);
2744#endif
2745    }
2746
2747    char targetfile[256];
2748
2749    if (strcmp(getParam(params, "part"), "conf") == 0) {
2750        snprintf(targetfile, 255,"%s%s", cs_confdir, "oscam.conf");
2751        writable = 1;
2752    }
2753    else if (strcmp(getParam(params, "part"), "version") == 0)
2754        snprintf(targetfile, 255,"%s%s", get_tmp_dir(), "/oscam.version");
2755    else if (strcmp(getParam(params, "part"), "user") == 0) {
2756        snprintf(targetfile, 255,"%s%s", cs_confdir, "oscam.user");
2757        writable = 1;
2758    }
2759    else if (strcmp(getParam(params, "part"), "server") == 0) {
2760        snprintf(targetfile, 255,"%s%s", cs_confdir, "oscam.server");
2761        writable = 1;
2762    }
2763    else if (strcmp(getParam(params, "part"), "services") == 0) {
2764        snprintf(targetfile, 255,"%s%s", cs_confdir, "oscam.services");
2765        writable = 1;
2766    }
2767    else if (strcmp(getParam(params, "part"), "srvid") == 0) {
2768        snprintf(targetfile, 255,"%s%s", cs_confdir, "oscam.srvid");
2769        writable = 1;
2770    }
2771    else if (strcmp(getParam(params, "part"), "provid") == 0) {
2772        snprintf(targetfile, 255,"%s%s", cs_confdir, "oscam.provid");
2773        writable = 1;
2774    }
2775    else if (strcmp(getParam(params, "part"), "tiers") == 0) {
2776        snprintf(targetfile, 255,"%s%s", cs_confdir, "oscam.tiers");
2777        writable = 1;
2778    }
2779    else if (strcmp(getParam(params, "part"), "logfile") == 0) {
2780        snprintf(targetfile, 255,"%s", cfg.logfile);
2781
2782        if (strcmp(getParam(params, "clear"), "logfile") == 0) {
2783            if(strlen(targetfile) > 0) {
2784                FILE *file = fopen(targetfile,"w");
2785                fclose(file);
2786            }
2787        }
2788
2789#ifdef WITH_DEBUG
2790        // Debuglevel Selector
2791        int32_t i, lvl;
2792        for (i = 0; i < 8; i++) {
2793            lvl = 1 << i;
2794            tpl_printf(vars, TPLADD, "TMPC", "DCLASS%d", lvl);
2795            tpl_printf(vars, TPLADD, "TMPV", "DEBUGVAL%d", lvl);
2796            if (cs_dblevel & lvl) {
2797                tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugls");
2798                tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel - lvl);
2799            } else {
2800                tpl_addVar(vars, TPLADD, tpl_getVar(vars, "TMPC"), "debugl");
2801                tpl_printf(vars, TPLADD, tpl_getVar(vars, "TMPV"), "%d", cs_dblevel + lvl);
2802            }
2803        }
2804
2805        if (cs_dblevel == 255)
2806            tpl_addVar(vars, TPLADD, "DCLASS255", "debugls");
2807        else
2808            tpl_addVar(vars, TPLADD, "DCLASS255", "debugl");
2809
2810        tpl_addVar(vars, TPLADD, "CUSTOMPARAM", "&part=logfile");
2811        tpl_printf(vars, TPLADD, "ACTDEBUG", "%d", cs_dblevel);
2812        tpl_addVar(vars, TPLADD, "SDEBUG", tpl_getTpl(vars, "DEBUGSELECT"));
2813        tpl_addVar(vars, TPLADD, "NEXTPAGE", "files.html");
2814#endif
2815
2816        if(!cfg.disablelog)
2817            tpl_printf(vars, TPLADD, "SLOG", "<BR><A CLASS=\"debugl\" HREF=\"files.html?part=logfile&amp;stoplog=%d\">%s</A><SPAN CLASS=\"debugt\">&nbsp;&nbsp;|&nbsp;&nbsp;</SPAN>\n", 1, "Stop Log");
2818        else
2819            tpl_printf(vars, TPLADD, "SLOG", "<BR><A CLASS=\"debugl\" HREF=\"files.html?part=logfile&amp;stoplog=%d\">%s</A><SPAN CLASS=\"debugt\">&nbsp;&nbsp;|&nbsp;&nbsp;</SPAN>\n", 0, "Start Log");
2820
2821        tpl_printf(vars, TPLADD, "SCLEAR", "<A CLASS=\"debugl\" HREF=\"files.html?part=logfile&amp;clear=logfile\">%s</A><BR><BR>\n", "Clear Log");
2822    }
2823    else if (strcmp(getParam(params, "part"), "userfile") == 0) {
2824        snprintf(targetfile, 255,"%s", cfg.usrfile);
2825        if (strcmp(getParam(params, "clear"), "usrfile") == 0) {
2826            if(strlen(targetfile) > 0) {
2827                FILE *file = fopen(targetfile,"w");
2828                fclose(file);
2829            }
2830        }
2831
2832        if(!cfg.disableuserfile)
2833            tpl_printf(vars, TPLADD, "SLOG", "<A HREF=\"files.html?part=userfile&amp;stopusrlog=%d\">%s</A>&nbsp;&nbsp;|&nbsp;&nbsp;\n", 1, "Stop Log");
2834        else
2835            tpl_printf(vars, TPLADD, "SLOG", "<A HREF=\"files.html?part=userfile&amp;stopusrlog=%d\">%s</A>&nbsp;&nbsp;|&nbsp;&nbsp;\n", 0, "Start Log");
2836
2837        tpl_printf(vars, TPLADD, "SCLEAR", "<A HREF=\"files.html?part=userfile&amp;clear=usrfile\">%s</A><BR><BR>\n", "Clear Log");
2838        tpl_addVar(vars, TPLADD, "FILTER", "<FORM ACTION=\"files.html\" method=\"get\">\n");
2839        tpl_addVar(vars, TPLAPPEND, "FILTER", "<INPUT name=\"part\" type=\"hidden\" value=\"userfile\">\n");
2840        tpl_addVar(vars, TPLAPPEND, "FILTER", "<SELECT name=\"filter\">\n");
2841        tpl_printf(vars, TPLAPPEND, "FILTER", "<OPTION value=\"%s\">%s</OPTION>\n", "all", "all");
2842
2843        struct s_auth *account;
2844        for (account = cfg.account; (account); account = account->next) {
2845            tpl_printf(vars, TPLAPPEND, "FILTER", "<OPTION value=\"%s\" %s>%s</OPTION>\n", account->usr, strcmp(getParam(params, "filter"), account->usr) ? "":"selected", account->usr);
2846        }
2847        tpl_addVar(vars, TPLAPPEND, "FILTER", "</SELECT><input type=\"submit\" name=\"action\" value=\"Filter\" title=\"Filter for a specific user\"></FORM>\n");
2848
2849    }
2850#ifdef CS_ANTICASC
2851    else if (strcmp(getParam(params, "part"), "anticasc") == 0)
2852        snprintf(targetfile, 255,"%s", cfg.ac_logfile);
2853#endif
2854
2855#ifdef HAVE_DVBAPI
2856    else if (strcmp(getParam(params, "part"), "dvbapi") == 0) {
2857        snprintf(targetfile, 255, "%s%s", cs_confdir, "oscam.dvbapi");
2858        writable = 1;
2859    }
2860#endif
2861    else targetfile[0] = '\0';
2862
2863    if (!strstr(targetfile, "/dev/")) {
2864
2865        if (strcmp(getParam(params, "action"), "Save") == 0) {
2866            if((strlen(targetfile) > 0) /*&& (file_exists(targetfile) == 1)*/) {
2867                FILE *fpsave;
2868                char *fcontent = getParam(params, "filecontent");
2869
2870                if((fpsave = fopen(targetfile,"w"))){
2871                    fprintf(fpsave,"%s",fcontent);
2872                    fclose(fpsave);
2873
2874                    if (strcmp(getParam(params, "part"), "srvid") == 0)
2875                        init_srvid();
2876
2877                    if (strcmp(getParam(params, "part"), "user") == 0)
2878                        cs_accounts_chk();
2879
2880#ifdef HAVE_DVBAPI
2881                    if (strcmp(getParam(params, "part"), "dvbapi") == 0)
2882                        dvbapi_read_priority();
2883#endif
2884                }
2885            }
2886        }
2887
2888        if((strlen(targetfile) > 0) && (file_exists(targetfile) == 1)) {
2889            FILE *fp;
2890            char buffer[256];
2891
2892            if((fp = fopen(targetfile,"r")) == NULL) return "0";
2893            while (fgets(buffer, sizeof(buffer), fp) != NULL)
2894                if (!strcmp(getParam(params, "filter"), "all"))
2895                    tpl_addVar(vars, TPLAPPEND, "FILECONTENT", buffer);
2896                else
2897                    if(strstr(buffer,getParam(params, "filter")))
2898                        tpl_addVar(vars, TPLAPPEND, "FILECONTENT", buffer);
2899            fclose (fp);
2900        } else {
2901            tpl_addVar(vars, TPLAPPEND, "FILECONTENT", "File does not exist or no file selected!");
2902        }
2903    } else {
2904        tpl_addVar(vars, TPLAPPEND, "FILECONTENT", "File not valid!");
2905    }
2906
2907    tpl_addVar(vars, TPLADD, "PART", getParam(params, "part"));
2908
2909    if (!writable) {
2910        tpl_addVar(vars, TPLADD, "WRITEPROTECTION", "You cannot change the content of this file!");
2911        tpl_addVar(vars, TPLADD, "BTNDISABLED", "DISABLED");
2912    }
2913
2914    return tpl_getTpl(vars, "FILE");
2915}
2916
2917char *send_oscam_failban(struct templatevars *vars, struct uriparams *params) {
2918
2919    uint32_t ip2delete = 0;
2920    LL_ITER itr = ll_iter_create(cfg.v_list);
2921    V_BAN *v_ban_entry;
2922
2923    if (strcmp(getParam(params, "action"), "delete") == 0) {
2924
2925        if(strcmp(getParam(params, "intip"), "all") == 0){
2926            // clear whole list
2927            while ((v_ban_entry=ll_iter_next(&itr))) {
2928                ll_iter_remove_data(&itr);
2929            }
2930
2931        } else {
2932            //we have a single IP
2933            sscanf(getParam(params, "intip"), "%u", &ip2delete);
2934            while ((v_ban_entry=ll_iter_next(&itr))) {
2935                if (v_ban_entry->v_ip == ip2delete) {
2936                    ll_iter_remove_data(&itr);
2937                    break;
2938                }
2939            }
2940        }
2941    }
2942    ll_iter_reset(&itr);
2943
2944    time_t now = time((time_t)0);
2945
2946    while ((v_ban_entry=ll_iter_next(&itr))) {
2947
2948        tpl_addVar(vars, TPLADD, "IPADDRESS", cs_inet_ntoa(v_ban_entry->v_ip));
2949
2950        struct tm st ;
2951        localtime_r(&v_ban_entry->v_time, &st);
2952
2953        tpl_printf(vars, TPLADD, "VIOLATIONDATE", "%02d.%02d.%02d %02d:%02d:%02d",
2954                st.tm_mday, st.tm_mon+1,
2955                st.tm_year%100, st.tm_hour,
2956                st.tm_min, st.tm_sec);
2957
2958        tpl_printf(vars, TPLADD, "VIOLATIONCOUNT", "%d", v_ban_entry->v_count);
2959        tpl_addVar(vars, TPLADD, "LEFTTIME", sec2timeformat(vars, (cfg.failbantime * 60) - (now - v_ban_entry->v_time)));
2960        tpl_printf(vars, TPLADD, "INTIP", "%u", v_ban_entry->v_ip);
2961        tpl_addVar(vars, TPLAPPEND, "FAILBANROW", tpl_getTpl(vars, "FAILBANBIT"));
2962    }
2963    return tpl_getTpl(vars, "FAILBAN");
2964}
2965
2966char *send_oscam_api(struct templatevars *vars, FILE *f, struct uriparams *params, int8_t *keepalive) {
2967    if (strcmp(getParam(params, "part"), "status") == 0) {
2968        return send_oscam_status(vars, params, 1);
2969    }
2970    else if (strcmp(getParam(params, "part"), "userstats") == 0) {
2971        return send_oscam_user_config(vars, params, 1);
2972    }
2973    else if (strcmp(getParam(params, "part"), "entitlement") == 0) {
2974
2975        if (strcmp(getParam(params, "label"),"")) {
2976            struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
2977            if (rdr) {
2978                if (rdr->typ == R_CCCAM && rdr->enable == 1) {
2979                    return send_oscam_entitlement(vars, params, 1);
2980                } else {
2981                    //Send Errormessage
2982                    tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "no cccam reader or disabled");
2983                    return tpl_getTpl(vars, "APIERROR");
2984                }
2985            } else {
2986                //Send Errormessage
2987                tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "reader not exist");
2988                return tpl_getTpl(vars, "APIERROR");
2989            }
2990        } else {
2991            //Send Errormessage
2992            tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "no reader selected");
2993            return tpl_getTpl(vars, "APIERROR");
2994        }
2995#ifdef WITH_LB
2996    } else if (strcmp(getParam(params, "part"), "readerstats") == 0) {
2997        if (strcmp(getParam(params, "label"),"")) {
2998            struct s_reader *rdr = get_reader_by_label(getParam(params, "label"));
2999            if (rdr) {
3000                return send_oscam_reader_stats(vars, params, 1);
3001            } else {
3002                //Send Errormessage
3003                tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "reader not exist");
3004                return tpl_getTpl(vars, "APIERROR");
3005            }
3006        } else {
3007            //Send Errormessage
3008            tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "no reader selected");
3009            return tpl_getTpl(vars, "APIERROR");
3010        }
3011#endif
3012    } else if (strcmp(getParam(params, "part"), "shutdown") == 0) {
3013        if ((strcmp(strtolower(getParam(params, "action")), "restart") == 0) ||
3014                (strcmp(strtolower(getParam(params, "action")), "shutdown") == 0)){
3015            if(!cfg.http_readonly) {
3016                return send_oscam_shutdown(vars, f, params, 1, keepalive);
3017            } else {
3018                tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "webif readonly mode");
3019                return tpl_getTpl(vars, "APIERROR");
3020            }
3021        } else {
3022            tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "missing parameter action");
3023            return tpl_getTpl(vars, "APIERROR");
3024        }
3025
3026    }
3027    else {
3028        tpl_addVar(vars, TPLADD, "APIERRORMESSAGE", "part not found");
3029        return tpl_getTpl(vars, "APIERROR");
3030    }
3031}
3032
3033char *send_oscam_image(struct templatevars *vars, FILE *f, struct uriparams *params, char *image, time_t modifiedheader, uint32_t etagheader) {
3034    char *wanted;
3035    if(image == NULL) wanted = getParam(params, "i");
3036    else wanted = image;
3037    if(strlen(wanted) > 3 && wanted[0] == 'I' && wanted[1] == 'C'){
3038        if(etagheader == 0){
3039            int8_t disktpl = 0;
3040            if(strlen(cfg.http_tpl) > 0){
3041            char path[255];
3042            if(strlen(tpl_getTplPath(wanted, cfg.http_tpl, path, 255)) > 0 && file_exists(path)){
3043                struct stat st;
3044                disktpl = 1;       
3045                    stat(path, &st);
3046                    if(st.st_mtime < modifiedheader){
3047                        send_header304(f);
3048                        return "1";
3049                    }
3050            }
3051        }
3052        if(disktpl == 0 && first_client->login < modifiedheader){
3053                send_header304(f);
3054                return "1";
3055            }
3056        }
3057        char *header = strstr(tpl_getTpl(vars, wanted), "data:");
3058        if(header != NULL){
3059            char *ptr = header + 5;
3060            while (ptr[0] != ';' && ptr[0] != '\0') ++ptr;
3061            if(ptr[0] != '\0' && ptr[1] != '\0') ptr[0] = '\0';
3062            else return "0";
3063            ptr = strstr(ptr + 1, "base64,");
3064            if(ptr != NULL){
3065                int32_t len = b64decode((uchar *)ptr + 7);
3066                if(len > 0){
3067                    if((uint32_t)crc32(0L, (uchar *)ptr + 7, len) == etagheader){
3068                        send_header304(f);
3069                    } else {
3070                        send_headers(f, 200, "OK", NULL, header + 5, 1, len, ptr + 7, 0);
3071                        webif_write_raw(ptr + 7, f, len);
3072                    }
3073                    return "1";
3074                }
3075            }
3076        }
3077    }
3078    return "0";
3079}
3080
3081int8_t check_request(char *result, int32_t read){
3082    if(read < 50) return 0;
3083    result[read]='\0';
3084    int8_t method;
3085    if (strncmp(result, "POST", 4) == 0) method = 1;
3086    else method = 0;
3087    char *headerEnd = strstr(result, "\r\n\r\n");
3088    if(headerEnd == NULL) return 0;
3089    else if(method == 0) return 1;
3090    else {
3091        char *ptr = strstr(result, "Content-Length: ");
3092        if(ptr != NULL){
3093            ptr += 16;
3094            if(ptr < result + read){
3095                uint32_t length = atoi(ptr);
3096                if(strlen(headerEnd+4) >= length) return 1;
3097            }
3098        }
3099    }
3100    return 0;
3101}
3102
3103int32_t readRequest(FILE *f, struct in_addr in, char **result, int8_t forcePlain){
3104    int32_t n, bufsize=0, errcount = 0, is_ssl = 0;
3105    char buf2[1024];
3106    struct pollfd pfd2[1];
3107#ifdef WITH_SSL
3108    if (ssl_active && !forcePlain)
3109        is_ssl = 1;
3110#endif
3111
3112    while (1) {
3113        errno = 0;
3114        if(forcePlain)
3115            n=read(fileno(f), buf2, sizeof(buf2));
3116        else
3117            n=webif_read(buf2, sizeof(buf2), f);
3118        if (n <= 0) {
3119            if ((!is_ssl) && (errno == 0 || errno == EINTR || errno == EAGAIN)){
3120                if(errcount++ < 10){
3121                    cs_sleepms(5);
3122                    continue;
3123                } else return -1;
3124            }
3125#ifdef WITH_SSL
3126            if (is_ssl){
3127                int32_t errcode = ERR_peek_error();
3128                char errstring[128];
3129                ERR_error_string_n(errcode, errstring, sizeof(errstring) - 1);
3130                cs_debug_mask(D_CLIENT, "WebIf: read error ret=%d (%d%s%s)", n, SSL_get_error(cur_ssl(), n), errcode?" ":"", errcode?errstring:"");
3131                return -1;
3132            }
3133#else
3134            cs_debug_mask(D_CLIENT, "WebIf: read error ret=%d (errno=%d %s)", n, errno, strerror(errno));
3135#endif
3136            return -1;
3137        }
3138        if(!cs_realloc(result, bufsize+n+1, -1)){
3139            send_error500(f);
3140            return -1;
3141        }
3142
3143        memcpy(*result+bufsize, buf2, n);
3144        bufsize+=n;
3145
3146        //max request size 100kb
3147        if (bufsize>102400) {
3148            cs_log("error: too much data received from %s", inet_ntoa(in));
3149            free(*result);
3150            return -1;
3151        }
3152
3153#ifdef WITH_SSL
3154        if (ssl_active && !forcePlain) {
3155            int32_t len = 0;
3156            len = SSL_pending((SSL*)f);
3157
3158            if (len>0)
3159                continue;
3160
3161            pfd2[0].fd = SSL_get_fd((SSL*)f);
3162
3163        } else
3164#endif
3165            pfd2[0].fd = fileno(f);
3166
3167        pfd2[0].events = (POLLIN | POLLPRI);
3168
3169        int32_t rc = poll(pfd2, 1, 100);
3170        if (rc>0 || !check_request(*result, bufsize))
3171            continue;
3172        else
3173            break;
3174    }
3175    return bufsize;
3176}
3177
3178int32_t process_request(FILE *f, struct in_addr in) {   
3179    int32_t ok=0,v=cv();
3180    int8_t *keepalive = (int8_t *)pthread_getspecific(getkeepalive);
3181    in_addr_t addr = GET_IP();
3182   
3183    do {
3184#ifdef WITH_SSL
3185        if (!ssl_active && *keepalive) fflush(f);
3186#else
3187        if (*keepalive) fflush(f);
3188#endif
3189        ok = check_ip(cfg.http_allowed, addr) ? v : 0;
3190   
3191        if (!ok && cfg.http_dyndns[0]) {
3192            cs_debug_mask(D_TRACE, "WebIf: IP not found in allowed range - test dyndns");
3193   
3194            if(cfg.http_dynip && cfg.http_dynip == addr) {
3195                ok = v;
3196                cs_debug_mask(D_TRACE, "WebIf: dyndns address previously resolved and ok");
3197   
3198            } else {
3199   
3200                if (cfg.resolve_gethostbyname) {
3201                    cs_debug_mask(D_TRACE, "WebIf: try resolving IP with 'gethostbyname'");
3202                    cs_lock(&gethostbyname_lock);
3203                    struct hostent *rht;
3204                    struct sockaddr_in udp_sa;
3205   
3206                    rht = gethostbyname((const char *) cfg.http_dyndns);
3207                    if (rht) {
3208                        memcpy(&udp_sa.sin_addr, rht->h_addr, sizeof(udp_sa.sin_addr));
3209                        cfg.http_dynip = udp_sa.sin_addr.s_addr;
3210                        cs_debug_mask(D_TRACE, "WebIf: dynip resolved %s access from %s",
3211                                cs_inet_ntoa(cfg.http_dynip),
3212                                cs_inet_ntoa(addr));
3213                        if (cfg.http_dynip == addr)
3214                            ok = v;
3215                    } else {
3216                        cs_log("can't resolve %s", cfg.http_dyndns); }
3217                    cs_unlock(&gethostbyname_lock);
3218   
3219                } else {
3220                    cs_debug_mask(D_TRACE, "WebIf: try resolving IP with 'getaddrinfo'");
3221                    struct addrinfo hints, *res = NULL;
3222                    memset(&hints, 0, sizeof(hints));
3223                    hints.ai_socktype = SOCK_STREAM;
3224                    hints.ai_family = AF_INET;
3225                    hints.ai_protocol = IPPROTO_TCP;
3226   
3227                    int32_t err = getaddrinfo((const char*)cfg.http_dyndns, NULL, &hints, &res);
3228                    if (err != 0 || !res || !res->ai_addr) {
3229                        cs_log("can't resolve %s, error: %s", cfg.http_dyndns, err ? gai_strerror(err) : "unknown");
3230                    }
3231                    else {
3232                        cfg.http_dynip = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr;
3233                        cs_debug_mask(D_TRACE, "WebIf: dynip resolved %s access from %s",
3234                                cs_inet_ntoa(cfg.http_dynip),
3235                                cs_inet_ntoa(addr));
3236                        if (cfg.http_dynip == addr)
3237                            ok = v;
3238                    }
3239                    if (res) freeaddrinfo(res);
3240   
3241                }
3242            }
3243        } else {
3244            if (cfg.http_dyndns[0])
3245                cs_debug_mask(D_TRACE, "WebIf: IP found in allowed range - bypass dyndns");
3246        }
3247   
3248        if (!ok) {
3249            send_error(f, 403, "Forbidden", NULL, "Access denied.", 0);
3250            cs_log("unauthorized access from %s flag %d", cs_inet_ntoa(addr), v);
3251            return 0;
3252        }
3253   
3254        int32_t authok = 0;
3255        char expectednonce[(MD5_DIGEST_LENGTH * 2) + 1];
3256   
3257        char *method, *path, *protocol, *str1, *saveptr1=NULL, *authheader = NULL, *filebuf = NULL;
3258        char *pch, *tmp, *buf;
3259        /* List of possible pages */
3260        char *pages[]= {
3261            "/config.html",
3262            "/readers.html",
3263            "/entitlements.html",
3264            "/status.html",
3265            "/userconfig.html",
3266            "/readerconfig.html",
3267            "/services.html",
3268            "/user_edit.html",
3269            "/site.css",
3270            "/services_edit.html",
3271            "/savetemplates.html",
3272            "/shutdown.html",
3273            "/script.html",
3274            "/scanusb.html",
3275            "/files.html",
3276            "/readerstats.html",
3277            "/failban.html",
3278            "/oscam.js",
3279            "/oscamapi.html",
3280            "/image",
3281            "/favicon.ico"};
3282   
3283        int32_t pagescnt = sizeof(pages)/sizeof(char *); // Calculate the amount of items in array
3284        int32_t i, bufsize, len, pgidx = -1;
3285        uint32_t etagheader = 0;
3286        struct uriparams params;
3287        params.paramcount = 0;
3288        time_t modifiedheader = 0;
3289       
3290        bufsize = readRequest(f, in, &filebuf, 0);
3291   
3292        if (!filebuf || bufsize < 1) {
3293            if(!*keepalive) cs_debug_mask(D_CLIENT, "WebIf: No data received from client %s. Closing connection.", cs_inet_ntoa(addr));
3294            return -1;
3295        }
3296   
3297        buf=filebuf;
3298   
3299        if((method = strtok_r(buf, " ", &saveptr1)) != NULL){
3300            if((path = strtok_r(NULL, " ", &saveptr1)) != NULL){
3301                if((protocol = strtok_r(NULL, "\r", &saveptr1)) == NULL){
3302                    free(filebuf);
3303                    return -1;
3304                }
3305            } else {
3306                free(filebuf);
3307                return -1;
3308            }
3309        } else {
3310            free(filebuf);
3311            return -1;
3312        }
3313        tmp=protocol+strlen(protocol)+2;
3314   
3315        pch=path;
3316        /* advance pointer to beginning of query string */
3317        while(pch[0] != '?' && pch[0] != '\0') ++pch;
3318        if(pch[0] == '?') {
3319            pch[0] = '\0';
3320            ++pch;
3321        }
3322   
3323        /* Map page to our static page definitions */
3324        for (i=0; i<pagescnt; i++) {
3325            if (!strcmp(path, pages[i])) pgidx = i;
3326        }
3327   
3328        parseParams(&params, pch);
3329   
3330        if(strlen(cfg.http_user) == 0 || strlen(cfg.http_pwd) == 0) authok = 1;
3331        else calculate_nonce(expectednonce);
3332   
3333        for (str1=strtok_r(tmp, "\n", &saveptr1); str1; str1=strtok_r(NULL, "\n", &saveptr1)) {
3334            len = strlen(str1);
3335            if(str1[len - 1] == '\r'){
3336                str1[len - 1] = '\0';
3337                --len;
3338            }
3339            if (len==0) {
3340                if (strcmp(method, "POST")==0) {
3341                    parseParams(&params, str1+2);
3342                }
3343                break;
3344            }
3345            if(authok == 0 && len > 50 && cs_strnicmp(str1, "Authorization:", 14) == 0 && strstr(str1, "Digest") != NULL) {
3346                if (cs_dblevel & D_CLIENT){
3347                    if(cs_realloc(&authheader, len + 1, -1))
3348                        cs_strncpy(authheader, str1, len);
3349                }
3350                authok = check_auth(str1, method, path, expectednonce);
3351            } else if (len > 40 && cs_strnicmp(str1, "If-Modified-Since:", 18) == 0){
3352                modifiedheader = parse_modifiedsince(str1);
3353            } else if (len > 20 && cs_strnicmp(str1, "If-None-Match:", 14) == 0){
3354                for(pch = str1 + 14; pch[0] != '"' && pch[0] != '\0'; ++pch);
3355                if(strlen(pch) > 5) etagheader = (uint32_t)strtoul(++pch, NULL, 10);
3356            } else if (len > 12 && cs_strnicmp(str1, "Connection: Keep-Alive", 22) == 0 && strcmp(method, "POST")){
3357                *keepalive = 1;
3358            }
3359        }
3360   
3361        if(authok != 1) {
3362            if(authok == 2)
3363                cs_debug_mask(D_TRACE, "WebIf: Received stale header from %s.", cs_inet_ntoa(addr));
3364            else if(authheader){
3365                cs_debug_mask(D_CLIENT, "WebIf: Received wrong auth header from %s:", cs_inet_ntoa(addr));
3366                cs_debug_mask(D_CLIENT, "%s", authheader);
3367            } else
3368                cs_debug_mask(D_CLIENT, "WebIf: Received no auth header from %s.", cs_inet_ntoa(addr));
3369            char temp[sizeof(AUTHREALM) + sizeof(expectednonce) + 100];
3370            snprintf(temp, sizeof(temp), "WWW-Authenticate: Digest algorithm=\"MD5\", realm=\"%s\", qop=\"auth\", opaque=\"\", nonce=\"%s\"", AUTHREALM, expectednonce);
3371            if(authok == 2) strncat(temp, ", stale=true", sizeof(temp));
3372            send_headers(f, 401, "Unauthorized", temp, "text/html", 0, 0, NULL, 0);
3373            NULLFREE(authheader);
3374            free(filebuf);
3375            if(*keepalive) continue;
3376            else return 0;
3377        } else NULLFREE(authheader);
3378   
3379        /*build page*/
3380        if(pgidx == 8) {
3381            send_file(f, "CSS", modifiedheader, etagheader);
3382        } else if (pgidx == 17) {
3383            send_file(f, "JS", modifiedheader, etagheader);
3384        } else {
3385            time_t t;
3386            struct templatevars *vars = tpl_create();
3387            if(vars == NULL){
3388                send_error500(f);
3389                free(filebuf);
3390                return 0;
3391            }
3392            struct tm lt, st;
3393            time(&t);
3394   
3395            localtime_r(&t, &lt);
3396   
3397            tpl_addVar(vars, TPLADD, "CS_VERSION", CS_VERSION);
3398            tpl_addVar(vars, TPLADD, "CS_SVN_VERSION", CS_SVN_VERSION);
3399            if(cfg.http_refresh > 0 && (pgidx == 3 || pgidx == -1)) {
3400                tpl_printf(vars, TPLADD, "REFRESHTIME", "%d", cfg.http_refresh);
3401                tpl_addVar(vars, TPLADD, "REFRESHURL", "status.html");
3402                tpl_addVar(vars, TPLADD, "REFRESH", tpl_getTpl(vars, "REFRESH"));
3403            }
3404   
3405            tpl_printf(vars, TPLADD, "CURDATE", "%02d.%02d.%02d", lt.tm_mday, lt.tm_mon+1, lt.tm_year%100);
3406            tpl_printf(vars, TPLADD, "CURTIME", "%02d:%02d:%02d", lt.tm_hour, lt.tm_min, lt.tm_sec);
3407            localtime_r(&first_client->login, &st);
3408            tpl_printf(vars, TPLADD, "STARTDATE", "%02d.%02d.%02d", st.tm_mday, st.tm_mon+1, st.tm_year%100);
3409            tpl_printf(vars, TPLADD, "STARTTIME", "%02d:%02d:%02d", st.tm_hour, st.tm_min, st.tm_sec);
3410            tpl_printf(vars, TPLADD, "PROCESSID", "%d", server_pid);
3411   
3412            time_t now = time((time_t)0);
3413            // XMLAPI
3414            if (pgidx == 18) {
3415                char tbuffer [30];
3416                strftime(tbuffer, 30, "%Y-%m-%dT%H:%M:%S%z", &st);
3417                tpl_addVar(vars, TPLADD, "APISTARTTIME", tbuffer);
3418                tpl_printf(vars, TPLADD, "APIUPTIME", "%u", now - first_client->login);
3419                tpl_printf(vars, TPLADD, "APIREADONLY", "%d", cfg.http_readonly);
3420            }
3421   
3422            // language code in helplink
3423            if (cfg.http_help_lang[0])
3424                tpl_addVar(vars, TPLADD, "LANGUAGE", cfg.http_help_lang);
3425            else
3426                tpl_addVar(vars, TPLADD, "LANGUAGE", "en");
3427   
3428            tpl_addVar(vars, TPLADD, "UPTIME", sec2timeformat(vars, (now - first_client->login)));
3429            tpl_addVar(vars, TPLADD, "CURIP", cs_inet_ntoa(addr));
3430            if(cfg.http_readonly)
3431                tpl_addVar(vars, TPLAPPEND, "BTNDISABLED", "DISABLED");
3432   
3433            char *result = NULL;
3434           
3435            // WebIf allows modifying many things. Thus, all pages except images/css are excpected to be non-threadsafe!
3436            if(pgidx != 19 && pgidx != 20) cs_lock(&http_lock);
3437            switch(pgidx) {
3438                case 0: result = send_oscam_config(vars, &params); break;
3439                case 1: result = send_oscam_reader(vars, &params); break;
3440                case 2: result = send_oscam_entitlement(vars, &params, 0); break;
3441                case 3: result = send_oscam_status(vars, &params, 0); break;
3442                case 4: result = send_oscam_user_config(vars, &params, 0); break;
3443                case 5: result = send_oscam_reader_config(vars, &params); break;
3444                case 6: result = send_oscam_services(vars, &params); break;
3445                case 7: result = send_oscam_user_config_edit(vars, &params); break;
3446                //case  8: css file
3447                case 9: result = send_oscam_services_edit(vars, &params); break;
3448                case 10: result = send_oscam_savetpls(vars); break;
3449                case 11: result = send_oscam_shutdown(vars, f, &params, 0, keepalive); break;
3450                case 12: result = send_oscam_script(vars); break;
3451                case 13: result = send_oscam_scanusb(vars); break;
3452                case 14: result = send_oscam_files(vars, &params); break;
3453#ifdef WITH_LB
3454                case 15: result = send_oscam_reader_stats(vars, &params, 0); break;
3455#endif
3456                case 16: result = send_oscam_failban(vars, &params); break;
3457                //case  17: js file
3458                case 18: result = send_oscam_api(vars, f, &params, keepalive); break;
3459                case 19: result = send_oscam_image(vars, f, &params, NULL, modifiedheader, etagheader); break;
3460                case 20: result = send_oscam_image(vars, f, &params, "ICMAI", modifiedheader, etagheader); break;
3461                default: result = send_oscam_status(vars, &params, 0); break;
3462            }
3463            if(pgidx != 19 && pgidx != 20) cs_unlock(&http_lock);
3464   
3465            if(result == NULL || !strcmp(result, "0") || strlen(result) == 0) send_error500(f);
3466            else if (strcmp(result, "1")) {
3467                //it doesn't make sense to check for modified etagheader here as standard template has timestamp in output and so site changes on every request
3468                if (pgidx == 18)
3469                    send_headers(f, 200, "OK", NULL, "text/xml", 0, strlen(result), NULL, 0);
3470                else
3471                    send_headers(f, 200, "OK", NULL, "text/html", 0, strlen(result), NULL, 0);
3472                webif_write(result, f);
3473            }
3474            tpl_clear(vars);
3475        }
3476        free(filebuf);
3477    } while (*keepalive == 1);
3478    return 0;
3479}
3480
3481#pragma GCC diagnostic ignored "-Wempty-body"
3482void *serve_process(void *conn){
3483    struct s_connection *myconn = (struct s_connection*)conn;
3484    int32_t s = myconn->socket;
3485    struct s_client *cl = myconn->cl;
3486    struct in_addr in = myconn->remote;
3487#ifdef WITH_SSL
3488    SSL *ssl = myconn->ssl;
3489    pthread_setspecific(getssl, ssl);
3490#endif
3491    free(myconn);
3492
3493    pthread_setspecific(getip, &in.s_addr);
3494    pthread_setspecific(getclient, cl);
3495
3496    int8_t keepalive = 0;
3497    pthread_setspecific(getkeepalive, &keepalive);
3498
3499#ifdef WITH_SSL
3500    if (ssl_active) {
3501        if(SSL_set_fd(ssl, s)){
3502            int32_t ok = (SSL_accept(ssl) != -1);
3503            if (!ok) {
3504                int8_t tries = 100;
3505                while (!ok && tries--) {
3506                    int32_t err = SSL_get_error(ssl, -1);
3507                    if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3508                        break;
3509                    else {
3510                        struct pollfd pfd;
3511                        pfd.fd = s;
3512                        pfd.events = POLLIN;
3513                        int32_t rc = poll(&pfd, 1, -1);
3514                        if (rc < 0) {
3515                            if (errno==EINTR) continue;
3516                            break;
3517                        }
3518                        if (rc == 1)
3519                            ok = (SSL_accept(ssl) != -1);
3520                    }
3521                }
3522            }
3523            if (ok){
3524                process_request((FILE *)ssl, in);
3525            } else {
3526                FILE *f;
3527                f = fdopen(s, "r+");
3528                if(f != NULL) {
3529                    char *ptr, *filebuf = NULL, *host = NULL;   
3530                    int32_t bufsize = readRequest(f, in, &filebuf, 1);
3531               
3532                    if (filebuf) {         
3533                        filebuf[bufsize]='\0';
3534                        host = strstr(filebuf, "Host: ");
3535                        if(host){
3536                            host += 6;
3537                            ptr = strchr(host, '\r');
3538                            if(ptr) ptr[0] = '\0';
3539                        }
3540                    }
3541                    if(host){
3542                        char extra[strlen(host) + 20];
3543                        snprintf(extra, sizeof(extra), "Location: https://%s", host);
3544                        send_error(f, 301, "Moved Permanently", extra, "This web server is running in SSL mode.", 1);
3545                    } else
3546                        send_error(f, 200, "Bad Request", NULL, "This web server is running in SSL mode.", 1);
3547                    fflush(f);
3548                    fclose(f);
3549                } else cs_log("WebIf: Error opening file descriptor using fdopen() (errno=%d %s)", errno, strerror(errno));
3550            }
3551        } else cs_log("WebIf: Error calling SSL_set_fd().");
3552        SSL_shutdown(ssl);
3553        close(s);
3554        SSL_free(ssl);
3555    } else
3556#endif
3557    {
3558        FILE *f;
3559        f = fdopen(s, "r+");
3560        if(f != NULL) {
3561            process_request(f, in);
3562            fflush(f);
3563            fclose(f);
3564        } else cs_log("WebIf: Error opening file descriptor using fdopen() (errno=%d %s)", errno, strerror(errno));
3565        shutdown(s, SHUT_WR);
3566        close(s);
3567    }
3568
3569    return NULL;
3570}
3571
3572void http_srv() {
3573    pthread_t workthread;
3574    pthread_attr_t attr;
3575    struct s_client * cl = create_client(first_client->ip);
3576    if (cl == NULL) return;
3577    httpthread = cl->thread = pthread_self();
3578    pthread_setspecific(getclient, cl);
3579    cl->typ = 'h';
3580    int32_t sock, s, reuse = 1;
3581    struct sockaddr_in sin;
3582    struct sockaddr_in remote;
3583    struct timeval stimeout;
3584    struct s_connection *conn;
3585
3586    socklen_t len = sizeof(remote);
3587    /* Create random string for nonce value generation */
3588    create_rand_str(noncekey,32);
3589   
3590    if(pthread_mutex_init(&http_lock, NULL)){
3591        cs_log("HTTP Server: Error creating mutex! (errno=%d %s)", errno, strerror(errno));
3592        return;
3593    };
3594
3595    if (pthread_key_create(&getip, NULL)) {
3596        cs_log("Could not create getip");
3597        return;
3598    }
3599    if (pthread_key_create(&getkeepalive, NULL)) {
3600        cs_log("Could not create getkeepalive");
3601        return;
3602    }
3603
3604    /* Startup server */
3605    if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
3606        cs_log("HTTP Server: Creating socket failed! (errno=%d %s)", errno, strerror(errno));
3607        return;
3608    }
3609    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) {
3610        cs_log("HTTP Server: Setting SO_REUSEADDR via setsockopt failed! (errno=%d %s)", errno, strerror(errno));
3611    }
3612
3613    stimeout.tv_sec = 20;
3614    stimeout.tv_usec = 0;
3615
3616    if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &stimeout, sizeof(stimeout)) < 0) {
3617            cs_log("HTTP Server: Setting SO_RCVTIMEO via setsockopt failed! (errno=%d %s)", errno, strerror(errno));
3618    }
3619
3620    if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &stimeout, sizeof(stimeout)) < 0) {
3621            cs_log("HTTP Server: Setting SO_SNDTIMEO via setsockopt failed! (errno=%d %s)", errno, strerror(errno));
3622    }
3623
3624    memset(&sin, 0, sizeof sin);
3625    sin.sin_family = AF_INET;
3626    sin.sin_addr.s_addr = INADDR_ANY;
3627    sin.sin_port = htons(cfg.http_port);
3628    if((bind(sock, (struct sockaddr *) &sin, sizeof(sin))) < 0) {
3629        cs_log("HTTP Server couldn't bind on port %d (errno=%d %s). Not starting HTTP!", cfg.http_port, errno, strerror(errno));
3630        close(sock);
3631        return;
3632    }
3633    if (listen(sock, SOMAXCONN) < 0) {
3634        cs_log("HTTP Server: Call to listen() failed! (errno=%d %s)", errno, strerror(errno));
3635        close(sock);
3636        return;
3637    }
3638    cs_log("HTTP Server listening on port %d%s", cfg.http_port, cfg.http_use_ssl ? " (SSL)" : "");
3639
3640#ifdef WITH_SSL
3641    SSL_CTX *ctx = NULL;
3642    if (cfg.http_use_ssl){
3643        ctx = SSL_Webif_Init();
3644        if (ctx==NULL)
3645            cs_log("SSL could not be initialized. Starting WebIf in plain mode.");
3646        else ssl_active = 1;
3647    } else ssl_active = 0;
3648#endif
3649
3650    while (running) {
3651        if((s = accept(sock, (struct sockaddr *) &remote, &len)) < 0) {
3652            if(errno != EAGAIN && errno != EINTR){
3653                cs_log("HTTP Server: Error calling accept() (errno=%d %s)", errno, strerror(errno));
3654                cs_sleepms(100);
3655            } else cs_sleepms(5);
3656            continue;
3657        } else {
3658            if(!cs_malloc(&conn, sizeof(struct s_connection), -1)){
3659                close(s);
3660                continue;
3661            }
3662            cur_client()->last = time((time_t)0); //reset last busy time
3663            conn->cl = cur_client();
3664            memcpy(&conn->remote, &remote.sin_addr, sizeof(struct in_addr));
3665            conn->socket = s;
3666#ifdef WITH_SSL
3667            conn->ssl = NULL;
3668            if (ssl_active){
3669                conn->ssl = SSL_new(ctx);
3670                if(conn->ssl == NULL){
3671                    close(s);
3672                    cs_log("WebIf: Error calling SSL_new().");
3673                    continue;
3674                }
3675            }
3676#endif
3677            pthread_attr_init(&attr);
3678#ifndef TUXBOX
3679            pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
3680#endif
3681            if (pthread_create(&workthread, &attr, serve_process, (void *)conn)) {
3682                cs_log("ERROR: can't create thread for webif");
3683                free(conn);
3684            }
3685            else
3686                pthread_detach(workthread);         
3687            pthread_attr_destroy(&attr);
3688        }
3689    }
3690    // Wait a bit so that we don't close ressources while http threads are active
3691    cs_sleepms(300);
3692#ifdef WITH_SSL
3693    if (ssl_active){
3694        int32_t i, num = CRYPTO_num_locks();;
3695        SSL_CTX_free(ctx);
3696        CRYPTO_set_dynlock_create_callback(NULL);
3697        CRYPTO_set_dynlock_lock_callback(NULL);
3698        CRYPTO_set_dynlock_destroy_callback(NULL);
3699        CRYPTO_set_locking_callback(NULL);
3700        CRYPTO_set_id_callback(NULL); 
3701        for (i = 0; i < num; ++i) {
3702            pthread_mutex_destroy(&lock_cs[i]);
3703        }
3704        OPENSSL_free(lock_cs);
3705        lock_cs = NULL;
3706    }
3707#endif
3708    pthread_mutex_destroy(&http_lock);
3709    cs_log("HTTP Server: Shutdown requested.");
3710    close(sock);
3711    //exit(SIGQUIT);
3712}
3713#endif
Note: See TracBrowser for help on using the repository browser.