Attempt to count descramblers used properly
[oscam.git] / oscam-conf-mk.c
blob1d660bd296cb7755f3dbae014f42302fa18567cc
1 #define MODULE_LOG_PREFIX "config"
3 #include "globals.h"
4 #include "oscam-conf-mk.h"
5 #include "oscam-net.h"
6 #include "oscam-string.h"
8 const char *shortDay[8] = {"SUN","MON","TUE","WED","THU","FRI","SAT","ALL"};
9 const char *weekdstr = "SUNMONTUEWEDTHUFRISATALL";
12 * Creates a string ready to write as a token into config or WebIf for CAIDs. You must free the returned value through free_mk_t().
14 char *mk_t_caidtab(CAIDTAB *caidtab)
16 if (!caidtab || !caidtab->ctnum) return "";
18 // Max entry length is strlen("1234&ffff:1234,") == 15
19 int32_t i, maxlen = 16 * caidtab->ctnum, pos = 0;
21 char *ret;
22 if (!cs_malloc(&ret, maxlen))
23 return "";
25 const char *comma = "";
27 for(i = 0; i < caidtab->ctnum; i++)
29 CAIDTAB_DATA *d = &caidtab->ctdata[i];
30 if (d->caid < 0x0100)
31 pos += snprintf(ret + pos, maxlen - pos, "%s%02X", comma, d->caid);
32 else
33 pos += snprintf(ret + pos, maxlen - pos, "%s%04X", comma, d->caid);
34 if (d->mask && d->mask != 0xffff)
35 pos += snprintf(ret + pos, maxlen - pos, "&%04X", d->mask);
36 if (d->cmap)
37 pos += snprintf(ret + pos, maxlen - pos, ":%04X", d->cmap);
38 comma = ",";
40 return ret;
44 * Creates a string ready to write as a token into config or WebIf for TunTabs. You must free the returned value through free_mk_t().
46 char *mk_t_tuntab(TUNTAB *ttab)
48 if (!ttab || !ttab->ttnum) return "";
50 // Each entry max length is strlen("aaaa.bbbb:cccc,") == 15
51 int32_t i, maxlen = 16 * ttab->ttnum, pos = 0;
53 char *ret;
54 if (!cs_malloc(&ret, maxlen))
55 return "";
57 const char *comma = "";
59 for(i = 0; i < ttab->ttnum; i++)
61 TUNTAB_DATA *d = &ttab->ttdata[i];
62 pos += snprintf(ret + pos, maxlen - pos, "%s%04X", comma, d->bt_caidfrom);
63 pos += snprintf(ret + pos, maxlen - pos, ".%04X", d->bt_srvid);
64 if (d->bt_caidto)
65 pos += snprintf(ret + pos, maxlen - pos, ":%04X", d->bt_caidto);
66 comma = ",";
68 return ret;
72 * Creates a string ready to write as a token into config or WebIf for groups. You must free the returned value through free_mk_t().
74 char *mk_t_group(uint64_t grp)
76 int32_t i = 0, needed = 1, pos = 0, dot = 0;
78 for(i = 0; i < 64; i++)
80 if(grp & ((uint64_t)1 << i))
82 needed += 2;
83 if(i > 9) { needed += 1; }
87 char *value;
88 if(needed == 1 || !cs_malloc(&value, needed)) { return ""; }
89 char *saveptr = value;
91 for(i = 0; i < 64; i++)
93 if(grp & ((uint64_t)1 << i))
95 if(dot == 0)
97 snprintf(value + pos, needed - (value - saveptr), "%d", i + 1);
98 if(i > 8) { pos += 2; }
99 else { pos += 1; }
100 dot = 1;
102 else
104 snprintf(value + pos, needed - (value - saveptr), ",%d", i + 1);
105 if(i > 8) { pos += 3; }
106 else { pos += 2; }
110 value[pos] = '\0';
111 return value;
115 * Creates a string ready to write as a token into config or WebIf for FTabs (CHID, Ident). You must free the returned value through free_mk_t().
117 char *mk_t_ftab(FTAB *ftab)
119 if (!ftab || !ftab->nfilts) return "";
121 // Worst case scenario where each entry have different
122 // caid, ident and only one length in it is strlen("1234:123456,") == 12
123 int32_t i, j, maxlen = 13 * ftab->nfilts, pos = 0;
125 for(i = 0; i < ftab->nfilts; i++)
127 maxlen += ftab->filts[i].nprids * 7; /* strlen("123456,") == 7 */
130 char *ret;
131 if (!cs_malloc(&ret, maxlen))
132 return "";
134 const char *semicolon = "", *comma = "";
136 for(i = 0; i < ftab->nfilts; i++)
138 FILTER *cur = &ftab->filts[i];
139 pos += snprintf(ret + pos, maxlen - pos, "%s%04X:", semicolon, cur->caid);
140 semicolon = ";";
141 comma = "";
143 for (j = 0; j < cur->nprids; j++)
145 pos += snprintf(ret + pos, maxlen - pos, "%s%06X", comma, cur->prids[j]);
146 comma = ",";
149 return ret;
153 * Creates a string ready to write as a token into config or WebIf for the camd35 tcp ports. You must free the returned value through free_mk_t().
155 char *mk_t_camd35tcp_port(void)
157 #if defined(MODULE_CAMD35) || defined(MODULE_CAMD35_TCP)
158 int32_t i, j, pos = 0, needed = 1;
160 /* Precheck to determine how long the resulting string will maximally be (might be a little bit smaller but that shouldn't hurt) */
161 for(i = 0; i < cfg.c35_tcp_ptab.nports; ++i)
163 /* Port is maximally 5 chars long, plus comma, plus the @caid, plus the :provid plus the ";" between ports */
164 needed += 18;
165 if(cfg.c35_tcp_ptab.ports[i].ncd && cfg.c35_tcp_ptab.ports[i].ncd->ncd_ftab.filts[0].nprids > 0)
167 needed += cfg.c35_tcp_ptab.ports[i].ncd->ncd_ftab.filts[0].nprids * 7;
171 char *value;
172 if(needed == 1 || !cs_malloc(&value, needed)) { return ""; }
173 char *saveptr = value;
174 char *dot1 = "", *dot2;
176 for(i = 0; i < cfg.c35_tcp_ptab.nports; ++i)
178 if(cfg.c35_tcp_ptab.ports[i].ncd && cfg.c35_tcp_ptab.ports[i].ncd->ncd_ftab.filts[0].caid)
180 pos += snprintf(value + pos, needed - (value - saveptr), "%s%d@%04X", dot1,
181 cfg.c35_tcp_ptab.ports[i].s_port,
182 cfg.c35_tcp_ptab.ports[i].ncd->ncd_ftab.filts[0].caid);
184 if(cfg.c35_tcp_ptab.ports[i].ncd->ncd_ftab.filts[0].nprids > 0)
186 dot2 = ":";
187 for(j = 0; j < cfg.c35_tcp_ptab.ports[i].ncd->ncd_ftab.filts[0].nprids; ++j)
189 pos += snprintf(value + pos, needed - (value - saveptr), "%s%06X",
190 dot2, cfg.c35_tcp_ptab.ports[i].ncd->ncd_ftab.filts[0].prids[j]);
191 dot2 = ",";
194 dot1 = ";";
196 else
198 pos += snprintf(value + pos, needed - (value - saveptr), "%s%d",
199 dot1, cfg.c35_tcp_ptab.ports[i].s_port);
200 dot1 = ";";
203 return value;
204 #else
205 return NULL;
206 #endif
209 #ifdef MODULE_CCCAM
211 * Creates a string ready to write as a token into config or WebIf for the cccam tcp ports. You must free the returned value through free_mk_t().
213 char *mk_t_cccam_port(void)
215 int32_t i, pos = 0, needed = CS_MAXPORTS * 6 + 8;
217 char *value;
218 if(!cs_malloc(&value, needed)) { return ""; }
219 char *dot = "";
221 for(i = 0; i < CS_MAXPORTS; i++)
223 if(!cfg.cc_port[i]) { break; }
225 pos += snprintf(value + pos, needed - pos, "%s%d", dot, cfg.cc_port[i]);
226 dot = ",";
228 return value;
230 #endif
232 #ifdef MODULE_GBOX
234 * Creates a string ready to write as a token into config or WebIf for the gbox udp ports. You must free the returned value through free_mk_t().
236 char *mk_t_gbox_port(void)
238 int32_t i, pos = 0, needed = CS_MAXPORTS * 6 + 8;
240 char *value;
241 if(!cs_malloc(&value, needed)) { return ""; }
242 char *dot = "";
244 for(i = 0; i < CS_MAXPORTS; i++)
246 if(!cfg.gbox_port[i]) { break; }
248 pos += snprintf(value + pos, needed - pos, "%s%d", dot, cfg.gbox_port[i]);
249 dot = ",";
251 return value;
255 * Creates a string ready to write as a token into config or WebIf for the gbox proxy card. You must free the returned value through free_mk_t().
257 char *mk_t_gbox_proxy_card(void)
259 int32_t i, pos = 0, needed = GBOX_MAX_PROXY_CARDS * 9 + 8;
261 char *value;
262 if(!cs_malloc(&value, needed)) { return ""; }
263 char *dot = "";
265 for(i = 0; i < GBOX_MAX_PROXY_CARDS; i++)
267 if(!cfg.gbox_proxy_card[i]) { break; }
269 pos += snprintf(value + pos, needed - pos, "%s%08lX", dot, cfg.gbox_proxy_card[i]);
270 dot = ",";
272 return value;
276 * Creates a string ready to write as a token into config or WebIf for the gbox ignore peer. You must free the returned value through free_mk_t().
278 char *mk_t_gbox_ignored_peer(void)
280 int32_t i, pos = 0, needed = GBOX_MAX_IGNORED_PEERS * 5 + 8;
282 char *value;
283 if(!cs_malloc(&value, needed)) { return ""; }
284 char *dot = "";
286 for(i = 0; i < GBOX_MAX_IGNORED_PEERS; i++)
288 if(!cfg.gbox_ignored_peer[i]) { break; }
290 pos += snprintf(value + pos, needed - pos, "%s%04hX", dot, cfg.gbox_ignored_peer[i]);
291 dot = ",";
293 return value;
297 * Creates a string ready to write as a token into config or WebIf for the gbox accept_remm_peer. You must free the returned value through free_mk_t().
299 char *mk_t_accept_remm_peer(void)
301 int32_t i, pos = 0, needed = GBOX_MAX_REMM_PEERS * 5 + 8;
303 char *value;
304 if(!cs_malloc(&value, needed)) { return ""; }
305 char *dot = "";
307 for(i = 0; i < GBOX_MAX_REMM_PEERS; i++)
309 if(!cfg.accept_remm_peer[i]) { break; }
311 pos += snprintf(value + pos, needed - pos, "%s%04hX", dot, cfg.accept_remm_peer[i]);
312 dot = ",";
314 return value;
318 * Creates a string ready to write as a token into config or WebIf for the gbox block ecm. You must free the returned value through free_mk_t().
320 char *mk_t_gbox_block_ecm(void)
322 int32_t i, pos = 0, needed = GBOX_MAX_BLOCKED_ECM * 5 + 8;
324 char *value;
325 if(!cs_malloc(&value, needed)) { return ""; }
326 char *dot = "";
328 for(i = 0; i < GBOX_MAX_BLOCKED_ECM; i++)
330 if(!cfg.gbox_block_ecm[i]) { break; }
332 pos += snprintf(value + pos, needed - pos, "%s%04hX", dot, cfg.gbox_block_ecm[i]);
333 dot = ",";
335 return value;
338 * Creates a string ready to write as a token into config or WebIf for the gbox SMS dest peers. You must free the returned value through free_mk_t().
340 char *mk_t_gbox_dest_peers(void)
342 int32_t i, pos = 0, needed = GBOX_MAX_DEST_PEERS * 5 + 8;
344 char *value;
345 if(!cs_malloc(&value, needed)) { return ""; }
346 char *dot = "";
348 for(i = 0; i < GBOX_MAX_DEST_PEERS; i++)
350 if(!cfg.gbox_dest_peers[i]) { break; }
351 pos += snprintf(value + pos, needed - pos, "%s%04hX", dot, cfg.gbox_dest_peers[i]);
352 dot = ",";
354 return value;
356 #endif
359 * Creates a string ready to write as a token into config or WebIf for AESKeys. You must free the returned value through free_mk_t().
361 char *mk_t_aeskeys(struct s_reader *rdr)
363 AES_ENTRY *current = rdr->aes_list;
364 int32_t i, pos = 0, needed = 1, prevKeyid = 0, prevCaid = 0;
365 uint32_t prevIdent = 0;
367 /* Precheck for the approximate size that we will need; it's a bit overestimated but we correct that at the end of the function */
368 while(current)
370 /* The caid, ident, "@" and the trailing ";" need to be output when they are changing */
371 if(prevCaid != current->caid || prevIdent != current->ident) { needed += 12 + (current->keyid * 2); }
372 /* "0" keys are not saved so we need to check for gaps */
373 else if(prevKeyid != current->keyid + 1) { needed += (current->keyid - prevKeyid - 1) * 2; }
374 /* The 32 byte key plus either the (heading) ":" or "," */
375 needed += 33;
376 prevCaid = current->caid;
377 prevIdent = current->ident;
378 prevKeyid = current->keyid;
379 current = current->next;
382 /* Set everything back and now create the string */
383 current = rdr->aes_list;
384 prevCaid = 0;
385 prevIdent = 0;
386 prevKeyid = 0;
387 char tmp[needed];
388 char dot;
389 if(needed == 1) { tmp[0] = '\0'; }
390 char tmpkey[33];
392 while(current)
394 /* A change in the ident or caid means that we need to output caid and ident */
395 if(prevCaid != current->caid || prevIdent != current->ident)
397 if(pos > 0)
399 tmp[pos] = ';';
400 ++pos;
402 pos += snprintf(tmp + pos, sizeof(tmp) - pos, "%04X@%06X", current->caid, current->ident);
403 prevKeyid = -1;
404 dot = ':';
406 else { dot = ','; }
408 /* "0" keys are not saved so we need to check for gaps and output them! */
409 for(i = prevKeyid + 1; i < current->keyid; ++i)
411 pos += snprintf(tmp + pos, sizeof(tmp) - pos, "%c0", dot);
412 dot = ',';
415 tmp[pos] = dot;
416 ++pos;
418 for(i = 0; i < 16; ++i)
420 snprintf(tmpkey + (i * 2), sizeof(tmpkey) - (i * 2), "%02X", current->plainkey[i]);
423 /* A key consisting of only FFs has a special meaning (just return what the card outputted) and can be specified more compact */
424 if(strcmp(tmpkey, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") == 0)
426 pos += snprintf(tmp + pos, sizeof(tmp) - pos, "FF");
428 else
430 pos += snprintf(tmp + pos, sizeof(tmp) - pos, "%s", tmpkey);
433 prevCaid = current->caid;
434 prevIdent = current->ident;
435 prevKeyid = current->keyid;
436 current = current->next;
439 /* copy to result array of correct size */
440 char *value;
441 if(pos == 0 || !cs_malloc(&value, pos + 1)) { return ""; }
442 memcpy(value, tmp, pos + 1);
443 return (value);
447 * Creates a string ready to write as a token into config or WebIf for the Newcamd Port. You must free the returned value through free_mk_t().
449 char *mk_t_newcamd_port(void)
451 #ifdef MODULE_NEWCAMD
452 int32_t i, j, k, pos = 0, needed = 1;
454 /* Precheck to determine how long the resulting string will maximally be (might be a little bit smaller but that shouldn't hurt) */
455 for(i = 0; i < cfg.ncd_ptab.nports; ++i)
457 /* Port is maximally 5 chars long, plus the @caid, plus the ";" between ports */
458 needed += 11;
459 if(cfg.ncd_ptab.ports[i].ncd)
461 if(cfg.ncd_ptab.ports[i].ncd->ncd_key_is_set) { needed += 30; }
463 if(cfg.ncd_ptab.ports[i].ncd->ncd_ftab.filts[0].nprids > 0)
465 needed += cfg.ncd_ptab.ports[i].ncd->ncd_ftab.filts[0].nprids * 7;
469 char *value;
470 if(needed == 1 || !cs_malloc(&value, needed)) { return ""; }
471 char *dot1 = "", *dot2;
473 for(i = 0; i < cfg.ncd_ptab.nports; ++i)
475 pos += snprintf(value + pos, needed - pos, "%s%d", dot1, cfg.ncd_ptab.ports[i].s_port);
477 // separate DES Key for this port
478 if(cfg.ncd_ptab.ports[i].ncd)
480 if(cfg.ncd_ptab.ports[i].ncd->ncd_key_is_set)
482 pos += snprintf(value + pos, needed - pos, "{");
483 for(k = 0; k < (int32_t)sizeof(cfg.ncd_ptab.ports[i].ncd->ncd_key); k++)
485 pos += snprintf(value + pos, needed - pos, "%02X", cfg.ncd_ptab.ports[i].ncd->ncd_key[k]);
487 pos += snprintf(value + pos, needed - pos, "}");
490 pos += snprintf(value + pos, needed - pos, "@%04X", cfg.ncd_ptab.ports[i].ncd->ncd_ftab.filts[0].caid);
492 if(cfg.ncd_ptab.ports[i].ncd->ncd_ftab.filts[0].nprids > 0)
494 dot2 = ":";
495 for(j = 0; j < cfg.ncd_ptab.ports[i].ncd->ncd_ftab.filts[0].nprids; ++j)
497 pos += snprintf(value + pos, needed - pos, "%s%06X", dot2, (int)cfg.ncd_ptab.ports[i].ncd->ncd_ftab.filts[0].prids[j]);
498 dot2 = ",";
502 dot1 = ";";
504 return value;
505 #else
506 return NULL;
507 #endif
511 * Creates a string ready to write as a token into config or WebIf for au readers. You must free the returned value through free_mk_t().
513 char *mk_t_aureader(struct s_auth *account)
515 int32_t pos = 0;
516 char *dot = "";
518 char *value;
519 if(ll_count(account->aureader_list) == 0 || !cs_malloc(&value, 256)) { return ""; }
520 value[0] = '\0';
522 struct s_reader *rdr;
523 LL_ITER itr = ll_iter_create(account->aureader_list);
524 while((rdr = ll_iter_next(&itr)))
526 pos += snprintf(value + pos, 256 - pos, "%s%s", dot, rdr->label);
527 dot = ",";
530 return value;
534 * Creates a string ready to write as a token into config or WebIf for blocknano and savenano. You must free the returned value through free_mk_t().
536 char *mk_t_nano(uint16_t nano)
538 int32_t i, pos = 0, needed = 0;
540 for(i = 0; i < 16; i++)
542 if((1 << i) & nano)
543 { needed++; }
546 char *value;
547 if(nano == 0xFFFF)
549 if(!cs_malloc(&value, 4)) { return ""; }
550 snprintf(value, 4, "all");
552 else
554 if(needed == 0 || !cs_malloc(&value, needed * 3 + 1)) { return ""; }
556 value[0] = '\0';
557 for(i = 0; i < 16; i++)
559 if((1 << i) & nano)
560 { pos += snprintf(value + pos, (needed * 3) + 1 - pos, "%s%02x", pos ? "," : "", (i + 0x80)); }
563 return value;
567 * Creates a string ready to write as a token into config or WebIf for the sidtab. You must free the returned value through free_mk_t().
569 char *mk_t_service(SIDTABS *sidtabs)
571 int32_t i, pos;
572 char *dot;
573 char *value;
574 struct s_sidtab *sidtab = cfg.sidtab;
575 if(!sidtab || (!sidtabs->ok && !sidtabs->no) || !cs_malloc(&value, 1024)) { return ""; }
577 value[0] = '\0';
579 for(i = pos = 0, dot = ""; sidtab; sidtab = sidtab->next, i++)
581 if(sidtabs->ok & ((SIDTABBITS)1 << i))
583 pos += snprintf(value + pos, 1024 - pos, "%s%s", dot, sidtab->label);
584 dot = ",";
586 if(sidtabs->no & ((SIDTABBITS)1 << i))
588 pos += snprintf(value + pos, 1024 - pos, "%s!%s", dot, sidtab->label);
589 dot = ",";
592 return value;
596 * Creates a string ready to write as a token into config or WebIf for the logfile parameter. You must free the returned value through free_mk_t().
598 char *mk_t_logfile(void)
600 int32_t pos = 0, needed = 1;
601 char *value, *dot = "";
603 if(cfg.logtostdout == 1) { needed += 7; }
604 if(cfg.logtosyslog == 1) { needed += 7; }
605 if(cfg.logfile) { needed += strlen(cfg.logfile); }
606 if(needed == 1 || !cs_malloc(&value, needed)) { return ""; }
608 if(cfg.logtostdout == 1)
610 pos += snprintf(value + pos, needed - pos, "stdout");
611 dot = ";";
614 if(cfg.logtosyslog == 1)
616 pos += snprintf(value + pos, needed - pos, "%ssyslog", dot);
617 dot = ";";
620 if(cfg.logfile)
622 pos += snprintf(value + pos, needed - pos, "%s%s", dot, cfg.logfile);
624 return value;
628 * Creates a string ready to write as a token into config or WebIf for the ecm whitelist. You must free the returned value through free_mk_t().
630 char *mk_t_ecm_whitelist(struct s_ecm_whitelist *ecm_whitelist)
632 if (!ecm_whitelist || !ecm_whitelist->ewnum) return "";
634 // Worst case scenario where each entry have different
635 // caid, ident and only one length in it is strlen("1234@123456:01;") == 15
636 int32_t i, maxlen = 16 * ecm_whitelist->ewnum, pos = 0;
637 char *ret;
638 if (!cs_malloc(&ret, maxlen))
639 return "";
641 const char *semicolon = "", *comma = "";
642 ECM_WHITELIST_DATA *last = NULL;
644 for(i = 0; i < ecm_whitelist->ewnum; i++)
646 ECM_WHITELIST_DATA *cur = &ecm_whitelist->ewdata[i];
647 bool change = !last || last->caid != cur->caid || last->ident != cur->ident;
649 if(change)
651 if(cur->caid && cur->ident)
652 pos += snprintf(ret + pos, maxlen - pos, "%s%04X@%06X:", semicolon, cur->caid, cur->ident);
653 else if(cur->caid)
654 pos += snprintf(ret + pos, maxlen - pos, "%s%04X:", semicolon, cur->caid);
655 else if(cur->ident)
656 pos += snprintf(ret + pos, maxlen - pos, "%s@%06X:", semicolon, cur->ident);
657 else
658 pos += snprintf(ret + pos, maxlen - pos, "%s", semicolon);
660 semicolon = ";";
661 comma = "";
663 pos += snprintf(ret + pos, maxlen - pos, "%s%02X", comma, cur->len);
664 comma = ",";
665 last = &ecm_whitelist->ewdata[i];
667 return ret;
671 * Creates a string ready to write as a token into config or WebIf for the ECM Headerwhitelist. You must free the returned value through free_mk_t().
673 char *mk_t_ecm_hdr_whitelist(struct s_ecm_hdr_whitelist *ecm_hdr_whitelist)
675 if(!ecm_hdr_whitelist || !ecm_hdr_whitelist->ehnum) return "";
677 // Worst case scenario where each entry have different
678 // caid, provid and only one header in it is strlen("1234@123456:0102030405060708091011121314151617181920;") == 52 ((sizeof(header) / 2) + 12)
679 int32_t i, r, maxlen = 53 * ecm_hdr_whitelist->ehnum, pos = 0;
680 char *ret;
681 if (!cs_malloc(&ret, maxlen))
682 return "";
684 const char *semicolon = "", *comma = "";
685 ECM_HDR_WHITELIST_DATA *last = NULL;
687 for(i = 0; i < ecm_hdr_whitelist->ehnum; i++)
689 ECM_HDR_WHITELIST_DATA *cur = &ecm_hdr_whitelist->ehdata[i];
690 bool change = !last || last->caid != cur->caid || last->provid != cur->provid;
691 if (change)
693 if (cur->caid && cur->provid)
694 pos += snprintf(ret + pos, maxlen - pos, "%s%04X@%06X:", semicolon, cur->caid, cur->provid);
695 else if (cur->caid)
696 pos += snprintf(ret + pos, maxlen - pos, "%s%04X:", semicolon, cur->caid);
697 else if (cur->provid)
698 pos += snprintf(ret + pos, maxlen - pos, "%s@%06X:", semicolon, cur->provid);
699 else
700 pos += snprintf(ret + pos, maxlen - pos, "%s", semicolon);
702 semicolon = ";";
703 comma = "";
705 pos += snprintf(ret + pos, maxlen - pos, "%s", comma);
706 for(r = 0; r < cur->len / 2; r++)
707 pos += snprintf(ret + pos, maxlen - pos, "%02X", cur->header[r]);
708 comma = ",";
709 last = &ecm_hdr_whitelist->ehdata[i];
711 return ret;
715 * Creates a string ready to write as a token into config or WebIf for an iprange. You must free the returned value through free_mk_t().
717 char *mk_t_iprange(struct s_ip *range)
719 struct s_ip *cip;
720 char *value, *dot = "";
721 int32_t needed = 1, pos = 0;
722 for(cip = range; cip; cip = cip->next) { needed += 32; }
724 char tmp[needed];
726 for(cip = range; cip; cip = cip->next)
728 pos += snprintf(tmp + pos, needed - pos, "%s%s", dot, cs_inet_ntoa(cip->ip[0]));
729 if(!IP_EQUAL(cip->ip[0], cip->ip[1])) { pos += snprintf(tmp + pos, needed - pos, "-%s", cs_inet_ntoa(cip->ip[1])); }
730 dot = ",";
733 if(pos == 0 || !cs_malloc(&value, pos + 1)) { return ""; }
735 memcpy(value, tmp, pos + 1);
736 return value;
740 * Creates a string ready to write as a token into config or WebIf for the class attribute. You must free the returned value through free_mk_t().
742 char *mk_t_cltab(CLASSTAB *clstab)
744 char *value, *dot = "";
745 int32_t i, needed = 1, pos = 0;
746 for(i = 0; i < clstab->an; ++i) { needed += 3; }
747 for(i = 0; i < clstab->bn; ++i) { needed += 4; }
749 char tmp[needed];
751 for(i = 0; i < clstab->an; ++i)
753 pos += snprintf(tmp + pos, needed - pos, "%s%02x", dot, (int32_t)clstab->aclass[i]);
754 dot = ",";
757 for(i = 0; i < clstab->bn; ++i)
759 pos += snprintf(tmp + pos, needed - pos, "%s!%02x", dot, (int32_t)clstab->bclass[i]);
760 dot = ",";
763 if(pos == 0 || !cs_malloc(&value, pos + 1)) { return ""; }
765 memcpy(value, tmp, pos + 1);
766 return value;
770 * Creates a string ready to write as a token into config or WebIf. You must free the returned value through free_mk_t().
772 char *mk_t_caidvaluetab(CAIDVALUETAB *caidvaluetab)
774 if (!caidvaluetab || !caidvaluetab->cvnum) return "";
776 // Max entry length is strlen("1234@65535,") == 11
777 int32_t i, maxlen = 12 * caidvaluetab->cvnum, pos = 0;
778 char *ret;
779 if (!cs_malloc(&ret, maxlen))
780 return "";
781 const char *comma = "";
783 for(i = 0; i < caidvaluetab->cvnum; i++)
785 CAIDVALUETAB_DATA *d = &caidvaluetab->cvdata[i];
786 if (d->caid < 0x0100)
787 pos += snprintf(ret + pos, maxlen - pos, "%s%02X:%d", comma, d->caid, d->value);
788 else
789 pos += snprintf(ret + pos, maxlen - pos, "%s%04X:%d", comma, d->caid, d->value);
791 comma = ",";
793 return ret;
796 char *mk_t_cacheex_valuetab(CECSPVALUETAB *tab)
798 if (!tab || !tab->cevnum) return "";
800 int32_t i, size = 2 + tab->cevnum * (4 + 1 + 4 + 1 + 6 + 1 + 4 + 1 + 5 + 1 + 5 + 1); // caid&mask@provid$servid:awtime:dwtime","
802 char *buf;
803 if(!cs_malloc(&buf, size))
804 { return ""; }
806 char *ptr = buf;
808 for(i = 0; i < tab->cevnum; i++)
810 CECSPVALUETAB_DATA *d = &tab->cevdata[i];
812 if(i) { ptr += snprintf(ptr, size - (ptr - buf), ","); }
814 if(d->caid >= 0)
816 if(d->caid == 0)
818 if(d->awtime > 0)
819 { ptr += snprintf(ptr, size - (ptr - buf), "%d", d->caid); }
821 else if(d->caid < 256) // Do not format 0D as 000D, its a shortcut for 0Dxx:
823 ptr += snprintf(ptr, size - (ptr - buf), "%02X", d->caid);
825 else
827 ptr += snprintf(ptr, size - (ptr - buf), "%04X", d->caid);
831 if(d->cmask >= 0)
832 { ptr += snprintf(ptr, size - (ptr - buf), "&%04X", d->cmask); }
834 if(d->prid >= 0)
835 { ptr += snprintf(ptr, size - (ptr - buf), "@%06X", d->prid); }
837 if(d->srvid >= 0)
838 { ptr += snprintf(ptr, size - (ptr - buf), "$%04X", d->srvid); }
840 if(d->awtime > 0)
841 { ptr += snprintf(ptr, size - (ptr - buf), ":%d", d->awtime); }
843 if(!(d->dwtime > 0))
844 { ptr += snprintf(ptr, size - (ptr - buf), ":0"); }
846 if(d->dwtime > 0)
848 if((d->caid <= 0) && (d->prid == -1) && (d->srvid == -1) && (d->srvid == -1) && (d->awtime <= 0))
850 ptr += snprintf(ptr, size - (ptr - buf), "%d", d->dwtime);
852 else
854 ptr += snprintf(ptr, size - (ptr - buf), ":%d", d->dwtime);
858 *ptr = 0;
859 return buf;
863 char *mk_t_cacheex_cwcheck_valuetab(CWCHECKTAB *tab)
865 if(!tab || !tab->cwchecknum) { return ""; }
867 int32_t i, size = 2 + tab->cwchecknum * (4 + 1 + 4 + 1 + 6 + 1 + 4 + 1 + 5 + 1 + 5 + 1); // caid[&mask][@provid][$servid]:mode:counter","
868 char *buf;
869 if(!cs_malloc(&buf, size))
870 { return ""; }
871 char *ptr = buf;
873 for(i = 0; i < tab->cwchecknum; i++)
875 CWCHECKTAB_DATA *d = &tab->cwcheckdata[i];
877 if(i) { ptr += snprintf(ptr, size - (ptr - buf), ","); }
879 if(d->caid >= 0)
881 if(d->caid == 0)
883 ptr += snprintf(ptr, size - (ptr - buf), "%d", d->caid);
885 else if(d->caid < 256) // Do not format 0D as 000D, its a shortcut for 0Dxx:
887 ptr += snprintf(ptr, size - (ptr - buf), "%02X", d->caid);
889 else
891 ptr += snprintf(ptr, size - (ptr - buf), "%04X", d->caid);
895 if(d->cmask >= 0)
896 { ptr += snprintf(ptr, size - (ptr - buf), "&%04X", d->cmask); }
898 if(d->prid >= 0)
899 { ptr += snprintf(ptr, size - (ptr - buf), "@%06X", d->prid); }
901 if(d->srvid >= 0)
902 { ptr += snprintf(ptr, size - (ptr - buf), "$%04X", d->srvid); }
904 if(d->mode >= 0)
905 { ptr += snprintf(ptr, size - (ptr - buf), ":%d", d->mode); }
907 if(d->counter > 0)
908 { ptr += snprintf(ptr, size - (ptr - buf), ":%d", d->counter); }
910 *ptr = 0;
911 return buf;
914 char *mk_t_cacheex_hitvaluetab(CECSPVALUETAB *tab)
916 if (!tab || !tab->cevnum) return "";
918 int32_t i, size = 2 + tab->cevnum * (4 + 1 + 4 + 1 + 6 + 1 + 4 + 1); // caid&mask@provid$servid","
919 char *buf;
920 if(!cs_malloc(&buf, size))
921 { return ""; }
922 char *ptr = buf;
924 for(i = 0; i < tab->cevnum; i++)
926 CECSPVALUETAB_DATA *d = &tab->cevdata[i];
928 if(i) { ptr += snprintf(ptr, size - (ptr - buf), ","); }
930 if(d->caid > 0)
932 if(d->caid < 256) // Do not format 0D as 000D, its a shortcut for 0Dxx:
934 ptr += snprintf(ptr, size - (ptr - buf), "%02X", d->caid);
936 else
938 ptr += snprintf(ptr, size - (ptr - buf), "%04X", d->caid);
941 if(d->cmask >= 0)
942 { ptr += snprintf(ptr, size - (ptr - buf), "&%04X", d->cmask); }
944 if(d->prid >= 0)
945 { ptr += snprintf(ptr, size - (ptr - buf), "@%06X", d->prid); }
947 if(d->srvid >= 0)
948 { ptr += snprintf(ptr, size - (ptr - buf), "$%04X", d->srvid); }
951 *ptr = 0;
952 return buf;
956 * returns string of comma separated values
958 char *mk_t_emmbylen(struct s_reader *rdr)
960 char *value, *pos, *dot = "";
961 int32_t num, needed = 0;
962 struct s_emmlen_range *blocklen;
964 if(!rdr->blockemmbylen)
965 { return ""; }
967 LL_ITER it = ll_iter_create(rdr->blockemmbylen);
968 while((blocklen = ll_iter_next(&it)))
970 needed += 5 + 1; // max digits of int16 + ","
971 if(blocklen->max == 0)
972 { needed += 1 + 1; } // "-" + ","
973 else if(blocklen->min != blocklen->max)
974 { needed += 1 + 5 + 1; } // "-" + max digits of int16 + ","
977 // the trailing zero is already included: it's the first ","
978 if(!cs_malloc(&value, needed))
979 { return ""; }
981 pos = value;
982 ll_iter_reset(&it);
983 while((blocklen = ll_iter_next(&it)))
985 if(blocklen->min == blocklen->max)
986 { num = snprintf(pos, needed, "%s%d", dot, blocklen->min); }
987 else if(blocklen->max == 0)
988 { num = snprintf(pos, needed, "%s%d-", dot, blocklen->min); }
989 else
990 { num = snprintf(pos, needed, "%s%d-%d", dot, blocklen->min, blocklen->max); }
992 pos += num;
993 needed -= num;
994 dot = ",";
996 return value;
1000 * makes string from binary structure
1002 char *mk_t_allowedprotocols(struct s_auth *account)
1004 if(!account->allowedprotocols)
1005 { return ""; }
1007 int16_t i, tmp = 1, pos = 0, needed = 255, tagcnt;
1008 char *tag[] = {"camd33", "cs357x", "cs378x", "newcamd", "cccam", "gbox", "radegast", "dvbapi", "constcw", "serial"};
1009 char *value, *dot = "";
1011 if(!cs_malloc(&value, needed))
1012 { return ""; }
1014 tagcnt = sizeof(tag) / sizeof(char *);
1015 for(i = 0; i < tagcnt; i++)
1017 if((account->allowedprotocols & tmp) == tmp)
1019 pos += snprintf(value + pos, needed, "%s%s", dot, tag[i]);
1020 dot = ",";
1022 tmp = tmp << 1;
1024 return value;
1028 * return allowed time frame string from internal array content
1032 char *mk_t_allowedtimeframe(struct s_auth *account)
1034 char *result;
1035 if(!cs_malloc(&result, MAXALLOWEDTF))
1036 { return ""; }
1038 if(account->allowedtimeframe_set)
1040 char mytime[6];
1041 uint8_t day;
1042 uint8_t value_in_day = 0;
1043 uint8_t intime = 0;
1044 uint16_t minutes =0;
1045 uint16_t hours;
1046 char septime[2] = {'\0'};
1047 char sepday[2] = {'\0'};
1049 for(day = 0; day < SIZE_SHORTDAY; day++)
1051 for(hours = 0; hours < 24; hours++)
1053 for(minutes = 0; minutes < 60; minutes++)
1055 if(CHECK_BIT(account->allowedtimeframe[day][hours][minutes / 30], (minutes % 30)))
1057 if(value_in_day == 0)
1059 strcat(result, &sepday[0]);
1060 strcat(result, shortDay[day]);
1061 strcat(result, "@");
1062 value_in_day = 1;
1063 intime = 0;
1064 sepday[0] = ';';
1065 septime[0] = '\0';
1068 if(!intime)
1070 strcat(result, &septime[0]);
1071 snprintf(mytime, 6, "%02d:%02d", hours, minutes);
1072 strcat(result, mytime);
1073 strcat(result, "-");
1074 septime[0] = ',';
1075 intime = 1;
1078 // Special case 23H59 is enabled we close the day at 24H00
1079 if(((hours * 60) + minutes) == 1439)
1081 strcat(result, "24:00");
1082 intime = 0;
1083 septime[0] = '\0';
1084 value_in_day = 0;
1087 else if(intime)
1089 snprintf(mytime, 6, "%02d:%02d", hours, minutes);
1090 strcat(result, mytime);
1091 septime[0] = ',';
1092 intime = 0;
1096 value_in_day = 0;
1099 else
1101 result = "";
1103 return result;
1107 * mk_t-functions give back a constant empty string when allocation fails or when the result is an empty string.
1108 * This function thus checks the stringlength and only frees if necessary.
1110 void free_mk_t(char *value)
1112 if(strlen(value) > 0) { NULLFREE(value); }