initial: modular iptv-dl with runtime config from ~/.iptv-downloader/config.json
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
#include "json.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
char *json_str(const char *json, const char *key) {
|
||||
if (!json || !key) return NULL;
|
||||
char needle[128]; snprintf(needle, sizeof(needle), "\"%s\"", key);
|
||||
const char *p = strstr(json, needle);
|
||||
if (!p) return NULL;
|
||||
p += strlen(needle);
|
||||
while (*p == ' ' || *p == ':') p++;
|
||||
if (*p == '"') {
|
||||
p++;
|
||||
const char *end = p;
|
||||
while (*end && !(*end == '"' && *(end-1) != '\\')) end++;
|
||||
size_t len = end - p;
|
||||
char *r = malloc(len+1); memcpy(r, p, len); r[len] = 0; return r;
|
||||
}
|
||||
const char *end = p;
|
||||
while (*end && *end != ',' && *end != '}' && *end != ']') end++;
|
||||
size_t len = end - p;
|
||||
char *r = malloc(len+1); memcpy(r, p, len); r[len] = 0; return r;
|
||||
}
|
||||
|
||||
char **json_array(const char *json, int *n) {
|
||||
*n = 0;
|
||||
if (!json) return NULL;
|
||||
const char *p = json;
|
||||
while (*p && *p != '[') p++;
|
||||
if (!*p) return NULL;
|
||||
p++;
|
||||
int cap = 64;
|
||||
char **arr = malloc(cap * sizeof(char*));
|
||||
int depth = 0; const char *obj_start = NULL; int in_str = 0;
|
||||
for (; *p; p++) {
|
||||
if (*p == '"' && (p == json || *(p-1) != '\\')) { in_str = !in_str; continue; }
|
||||
if (in_str) continue;
|
||||
if (*p == '{' || *p == '[') { if (depth == 0) obj_start = p; depth++; }
|
||||
else if (*p == '}' || *p == ']') {
|
||||
depth--;
|
||||
if (depth == 0 && obj_start) {
|
||||
size_t len = p - obj_start + 1;
|
||||
char *obj = malloc(len+1); memcpy(obj, obj_start, len); obj[len] = 0;
|
||||
if (*n >= cap) { cap *= 2; arr = realloc(arr, cap*sizeof(char*)); }
|
||||
arr[(*n)++] = obj;
|
||||
obj_start = NULL;
|
||||
if (*p == ']') break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
void urldecode(char *s) {
|
||||
char *w = s, *r = s;
|
||||
while (*r) {
|
||||
if (*r == '%' && r[1] && r[2]) {
|
||||
char hex[3] = {r[1], r[2], 0}; *w++ = (char)strtol(hex, NULL, 16); r += 3;
|
||||
} else if (*r == '+') { *w++ = ' '; r++; }
|
||||
else { *w++ = *r++; }
|
||||
}
|
||||
*w = 0;
|
||||
}
|
||||
|
||||
char *qparam(const char *qs, const char *key) {
|
||||
if (!qs || !key) return NULL;
|
||||
char needle[128]; snprintf(needle, sizeof(needle), "%s=", key);
|
||||
const char *p = strstr(qs, needle);
|
||||
if (!p) return NULL;
|
||||
p += strlen(needle);
|
||||
const char *end = strchr(p, '&');
|
||||
size_t len = end ? (size_t)(end-p) : strlen(p);
|
||||
char *r = malloc(len+1); memcpy(r, p, len); r[len] = 0;
|
||||
urldecode(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void html_esc(Buf *b, const char *s) {
|
||||
for (; *s; s++) {
|
||||
if (*s == '<') buf_str(b, "<");
|
||||
else if (*s == '>') buf_str(b, ">");
|
||||
else if (*s == '&') buf_str(b, "&");
|
||||
else if (*s == '"') buf_str(b, """);
|
||||
else buf_append(b, s, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void js_esc(Buf *b, const char *s) {
|
||||
for (; *s; s++) {
|
||||
if (*s == '\'') buf_str(b, "\\'");
|
||||
else if (*s == '\\') buf_str(b, "\\\\");
|
||||
else if (*s == '\n' || *s == '\r') {}
|
||||
else buf_append(b, s, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void fwrite_json_str(FILE *f, const char *s) {
|
||||
fputc('"', f);
|
||||
for (; *s; s++) {
|
||||
if (*s == '"' || *s == '\\') fputc('\\', f);
|
||||
if ((unsigned char)*s >= 0x20) fputc(*s, f);
|
||||
}
|
||||
fputc('"', f);
|
||||
}
|
||||
|
||||
int str_icontains(const char *hay, const char *needle) {
|
||||
if (!hay || !needle || !*needle) return 1;
|
||||
char h[2048], n[256];
|
||||
strncpy(h, hay, sizeof(h)-1); h[sizeof(h)-1] = 0;
|
||||
strncpy(n, needle, sizeof(n)-1); n[sizeof(n)-1] = 0;
|
||||
for (char *p = h; *p; p++) if (*p >= 'A' && *p <= 'Z') *p += 32;
|
||||
for (char *p = n; *p; p++) if (*p >= 'A' && *p <= 'Z') *p += 32;
|
||||
return strstr(h, n) != NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user