mirror of
https://projects.vdr-developer.org/git/vdr-plugin-scraper2vdr.git
synced 2023-10-19 17:58:31 +02:00
813 lines
18 KiB
C
813 lines
18 KiB
C
|
/*
|
|||
|
* common.c:
|
|||
|
*
|
|||
|
* See the README file for copyright information and how to reach the author.
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
#include <sys/stat.h>
|
|||
|
|
|||
|
#ifdef USEUUID
|
|||
|
# include <uuid/uuid.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#include <stdarg.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <string.h>
|
|||
|
#include <syslog.h>
|
|||
|
#include <unistd.h>
|
|||
|
#include <zlib.h>
|
|||
|
|
|||
|
#ifdef USELIBARCHIVE
|
|||
|
# include <archive.h>
|
|||
|
# include <archive_entry.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef VDR_PLUGIN
|
|||
|
# include <vdr/thread.h>
|
|||
|
#endif
|
|||
|
|
|||
|
#include "common.h"
|
|||
|
#include "config.h"
|
|||
|
|
|||
|
#ifdef VDR_PLUGIN
|
|||
|
cMutex logMutex;
|
|||
|
#endif
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Debug
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
void tell(int eloquence, const char* format, ...)
|
|||
|
{
|
|||
|
if (EPG2VDRConfig.loglevel < eloquence)
|
|||
|
return ;
|
|||
|
|
|||
|
const int sizeBuffer = 100000;
|
|||
|
char t[sizeBuffer+100]; *t = 0;
|
|||
|
va_list ap;
|
|||
|
|
|||
|
#ifdef VDR_PLUGIN
|
|||
|
cMutexLock lock(&logMutex);
|
|||
|
#endif
|
|||
|
|
|||
|
va_start(ap, format);
|
|||
|
|
|||
|
#ifdef VDR_PLUGIN
|
|||
|
snprintf(t, sizeBuffer, "scraper2vdr: ");
|
|||
|
#endif
|
|||
|
|
|||
|
vsnprintf(t+strlen(t), sizeBuffer-strlen(t), format, ap);
|
|||
|
|
|||
|
if (EPG2VDRConfig.logstdout)
|
|||
|
{
|
|||
|
char buf[50+TB];
|
|||
|
time_t now;
|
|||
|
time(&now);
|
|||
|
strftime(buf, 50, "%y.%m.%d %H:%M:%S", localtime(&now));
|
|||
|
printf("%s %s\n", buf, t);
|
|||
|
}
|
|||
|
else
|
|||
|
syslog(LOG_ERR, "%s", t);
|
|||
|
|
|||
|
va_end(ap);
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Host ID
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
unsigned int getHostId()
|
|||
|
{
|
|||
|
static unsigned int id = gethostid() & 0xFFFFFFFF;
|
|||
|
return id;
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// String Operations
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
void toUpper(std::string& str)
|
|||
|
{
|
|||
|
const char* s = str.c_str();
|
|||
|
int lenSrc = str.length();
|
|||
|
|
|||
|
char* dest = (char*)malloc(lenSrc+TB); *dest = 0;
|
|||
|
char* d = dest;
|
|||
|
|
|||
|
int csSrc; // size of character
|
|||
|
|
|||
|
for (int ps = 0; ps < lenSrc; ps += csSrc)
|
|||
|
{
|
|||
|
csSrc = max(mblen(&s[ps], lenSrc-ps), 1);
|
|||
|
|
|||
|
if (csSrc == 1)
|
|||
|
*d++ = toupper(s[ps]);
|
|||
|
else if (csSrc == 2 && s[ps] == (char)0xc3 && s[ps+1] >= (char)0xa0)
|
|||
|
{
|
|||
|
*d++ = s[ps];
|
|||
|
*d++ = s[ps+1] - 32;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
for (int i = 0; i < csSrc; i++)
|
|||
|
*d++ = s[ps+i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*d = 0;
|
|||
|
|
|||
|
str = dest;
|
|||
|
free(dest);
|
|||
|
}
|
|||
|
|
|||
|
void removeChars(std::string& str, const char* ignore)
|
|||
|
{
|
|||
|
const char* s = str.c_str();
|
|||
|
int lenSrc = str.length();
|
|||
|
int lenIgn = strlen(ignore);
|
|||
|
|
|||
|
char* dest = (char*)malloc(lenSrc+TB); *dest = 0;
|
|||
|
char* d = dest;
|
|||
|
|
|||
|
int csSrc; // size of character
|
|||
|
int csIgn; //
|
|||
|
|
|||
|
for (int ps = 0; ps < lenSrc; ps += csSrc)
|
|||
|
{
|
|||
|
int skip = no;
|
|||
|
|
|||
|
csSrc = max(mblen(&s[ps], lenSrc-ps), 1);
|
|||
|
|
|||
|
for (int pi = 0; pi < lenIgn; pi += csIgn)
|
|||
|
{
|
|||
|
csIgn = max(mblen(&ignore[pi], lenIgn-pi), 1);
|
|||
|
|
|||
|
if (csSrc == csIgn && strncmp(&s[ps], &ignore[pi], csSrc) == 0)
|
|||
|
{
|
|||
|
skip = yes;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!skip)
|
|||
|
{
|
|||
|
for (int i = 0; i < csSrc; i++)
|
|||
|
*d++ = s[ps+i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*d = 0;
|
|||
|
|
|||
|
str = dest;
|
|||
|
free(dest);
|
|||
|
}
|
|||
|
|
|||
|
void removeCharsExcept(std::string& str, const char* except)
|
|||
|
{
|
|||
|
const char* s = str.c_str();
|
|||
|
int lenSrc = str.length();
|
|||
|
int lenIgn = strlen(except);
|
|||
|
|
|||
|
char* dest = (char*)malloc(lenSrc+TB); *dest = 0;
|
|||
|
char* d = dest;
|
|||
|
|
|||
|
int csSrc; // size of character
|
|||
|
int csIgn; //
|
|||
|
|
|||
|
for (int ps = 0; ps < lenSrc; ps += csSrc)
|
|||
|
{
|
|||
|
int skip = yes;
|
|||
|
|
|||
|
csSrc = max(mblen(&s[ps], lenSrc-ps), 1);
|
|||
|
|
|||
|
for (int pi = 0; pi < lenIgn; pi += csIgn)
|
|||
|
{
|
|||
|
csIgn = max(mblen(&except[pi], lenIgn-pi), 1);
|
|||
|
|
|||
|
if (csSrc == csIgn && strncmp(&s[ps], &except[pi], csSrc) == 0)
|
|||
|
{
|
|||
|
skip = no;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!skip)
|
|||
|
{
|
|||
|
for (int i = 0; i < csSrc; i++)
|
|||
|
*d++ = s[ps+i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*d = 0;
|
|||
|
|
|||
|
str = dest;
|
|||
|
free(dest);
|
|||
|
}
|
|||
|
|
|||
|
void removeWord(std::string& pattern, std::string word)
|
|||
|
{
|
|||
|
size_t pos;
|
|||
|
|
|||
|
if ((pos = pattern.find(word)) != std::string::npos)
|
|||
|
pattern.swap(pattern.erase(pos, word.length()));
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// String Manipulation
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
void prepareCompressed(std::string& pattern)
|
|||
|
{
|
|||
|
// const char* ignore = " (),.;:-_+*!#?=&%$<>§/'`´@~\"[]{}";
|
|||
|
const char* notignore = "ABCDEFGHIJKLMNOPQRSTUVWXYZßÖÄÜöäü0123456789";
|
|||
|
|
|||
|
toUpper(pattern);
|
|||
|
removeWord(pattern, " TEIL ");
|
|||
|
removeWord(pattern, " FOLGE ");
|
|||
|
removeCharsExcept(pattern, notignore);
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Left Trim
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
char* lTrim(char* buf)
|
|||
|
{
|
|||
|
if (buf)
|
|||
|
{
|
|||
|
char *tp = buf;
|
|||
|
|
|||
|
while (*tp && strchr("\n\r\t ",*tp))
|
|||
|
tp++;
|
|||
|
|
|||
|
memmove(buf, tp, strlen(tp) +1);
|
|||
|
}
|
|||
|
|
|||
|
return buf;
|
|||
|
}
|
|||
|
|
|||
|
//*************************************************************************
|
|||
|
// Right Trim
|
|||
|
//*************************************************************************
|
|||
|
|
|||
|
char* rTrim(char* buf)
|
|||
|
{
|
|||
|
if (buf)
|
|||
|
{
|
|||
|
char *tp = buf + strlen(buf);
|
|||
|
|
|||
|
while (tp >= buf && strchr("\n\r\t ",*tp))
|
|||
|
tp--;
|
|||
|
|
|||
|
*(tp+1) = 0;
|
|||
|
}
|
|||
|
|
|||
|
return buf;
|
|||
|
}
|
|||
|
|
|||
|
//*************************************************************************
|
|||
|
// All Trim
|
|||
|
//*************************************************************************
|
|||
|
|
|||
|
char* allTrim(char* buf)
|
|||
|
{
|
|||
|
return lTrim(rTrim(buf));
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Number to String
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
std::string num2Str(int num)
|
|||
|
{
|
|||
|
char txt[16];
|
|||
|
|
|||
|
snprintf(txt, sizeof(txt), "%d", num);
|
|||
|
|
|||
|
return std::string(txt);
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Long to Pretty Time
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
std::string l2pTime(time_t t)
|
|||
|
{
|
|||
|
char txt[30];
|
|||
|
tm* tmp = localtime(&t);
|
|||
|
|
|||
|
strftime(txt, sizeof(txt), "%d.%m.%Y %T", tmp);
|
|||
|
|
|||
|
return std::string(txt);
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// MS to Duration
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
std::string ms2Dur(uint64_t t)
|
|||
|
{
|
|||
|
char txt[30];
|
|||
|
|
|||
|
int s = t / 1000;
|
|||
|
int ms = t % 1000;
|
|||
|
|
|||
|
snprintf(txt, sizeof(txt), "%d.%03d seconds", s, ms);
|
|||
|
|
|||
|
return std::string(txt);
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Char to Char-String
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
const char* c2s(char c, char* buf)
|
|||
|
{
|
|||
|
sprintf(buf, "%c", c);
|
|||
|
|
|||
|
return buf;
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// TOOLS
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
int isEmpty(const char* str)
|
|||
|
{
|
|||
|
return !str || !*str;
|
|||
|
}
|
|||
|
|
|||
|
char* sstrcpy(char* dest, const char* src, int max)
|
|||
|
{
|
|||
|
if (!dest || !src)
|
|||
|
return 0;
|
|||
|
|
|||
|
strncpy(dest, src, max);
|
|||
|
dest[max-1] = 0;
|
|||
|
|
|||
|
return dest;
|
|||
|
}
|
|||
|
|
|||
|
int isLink(const char* path)
|
|||
|
{
|
|||
|
struct stat sb;
|
|||
|
|
|||
|
if (lstat(path, &sb) == 0)
|
|||
|
return S_ISLNK(sb.st_mode);
|
|||
|
|
|||
|
tell(0, "Error: Detecting state for '%s' failed, error was '%m'", path);
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
int fileSize(const char* path)
|
|||
|
{
|
|||
|
struct stat sb;
|
|||
|
|
|||
|
if (lstat(path, &sb) == 0)
|
|||
|
return sb.st_size;
|
|||
|
|
|||
|
tell(0, "Error: Detecting state for '%s' failed, error was '%m'", path);
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int fileExists(const char* path)
|
|||
|
{
|
|||
|
return access(path, F_OK) == 0;
|
|||
|
}
|
|||
|
|
|||
|
int createLink(const char* link, const char* dest, int force)
|
|||
|
{
|
|||
|
if (!fileExists(link) || force)
|
|||
|
{
|
|||
|
// may be the link exists and point to a wrong or already deleted destination ...
|
|||
|
// .. therefore we delete the link at first
|
|||
|
|
|||
|
unlink(link);
|
|||
|
|
|||
|
if (symlink(dest, link) != 0)
|
|||
|
{
|
|||
|
tell(0, "Failed to create symlink '%s', error was '%m'", link);
|
|||
|
return fail;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Remove File
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
int removeFile(const char* filename)
|
|||
|
{
|
|||
|
int lnk = isLink(filename);
|
|||
|
|
|||
|
if (unlink(filename) != 0)
|
|||
|
{
|
|||
|
tell(0, "Can't remove file '%s', '%m'", filename);
|
|||
|
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
tell(3, "Removed %s '%s'", lnk ? "link" : "file", filename);
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Check Dir
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
int chkDir(const char* path)
|
|||
|
{
|
|||
|
struct stat fs;
|
|||
|
|
|||
|
if (stat(path, &fs) != 0 || !S_ISDIR(fs.st_mode))
|
|||
|
{
|
|||
|
tell(0, "Creating directory '%s'", path);
|
|||
|
|
|||
|
if (mkdir(path, ACCESSPERMS) == -1)
|
|||
|
{
|
|||
|
tell(0, "Can't create directory '%m'");
|
|||
|
return fail;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
#ifdef USELIBXML
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Load XSLT
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
xsltStylesheetPtr loadXSLT(const char* name, const char* path, int utf8)
|
|||
|
{
|
|||
|
xsltStylesheetPtr stylesheet;
|
|||
|
char* xsltfile;
|
|||
|
|
|||
|
asprintf(&xsltfile, "%s/%s-%s.xsl", path, name, utf8 ? "utf-8" : "iso-8859-1");
|
|||
|
|
|||
|
if ((stylesheet = xsltParseStylesheetFile((const xmlChar*)xsltfile)) == 0)
|
|||
|
tell(0, "Error: Can't load xsltfile %s", xsltfile);
|
|||
|
else
|
|||
|
tell(0, "Info: Stylesheet '%s' loaded", xsltfile);
|
|||
|
|
|||
|
free(xsltfile);
|
|||
|
return stylesheet;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Gnu Unzip
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
int gunzip(MemoryStruct* zippedData, MemoryStruct* unzippedData)
|
|||
|
{
|
|||
|
const int growthStep = 1024;
|
|||
|
|
|||
|
z_stream stream = {0,0,0,0,0,0,0,0,0,0,0,Z_NULL,Z_NULL,Z_NULL};
|
|||
|
unsigned int resultSize = 0;
|
|||
|
int res = 0;
|
|||
|
|
|||
|
unzippedData->clear();
|
|||
|
|
|||
|
// determining the size in this way is taken from the sources of the gzip utility.
|
|||
|
|
|||
|
memcpy(&unzippedData->size, zippedData->memory + zippedData->size -4, 4);
|
|||
|
unzippedData->memory = (char*)malloc(unzippedData->size);
|
|||
|
|
|||
|
// zlib initialisation
|
|||
|
|
|||
|
stream.avail_in = zippedData->size;
|
|||
|
stream.next_in = (Bytef*)zippedData->memory;
|
|||
|
stream.avail_out = unzippedData->size;
|
|||
|
stream.next_out = (Bytef*)unzippedData->memory;
|
|||
|
|
|||
|
// The '+ 32' tells zlib to process zlib&gzlib headers
|
|||
|
|
|||
|
res = inflateInit2(&stream, MAX_WBITS + 32);
|
|||
|
|
|||
|
if (res != Z_OK)
|
|||
|
{
|
|||
|
tellZipError(res, " during zlib initialisation", stream.msg);
|
|||
|
inflateEnd(&stream);
|
|||
|
return fail;
|
|||
|
}
|
|||
|
|
|||
|
// skip the header
|
|||
|
|
|||
|
res = inflate(&stream, Z_BLOCK);
|
|||
|
|
|||
|
if (res != Z_OK)
|
|||
|
{
|
|||
|
tellZipError(res, " while skipping the header", stream.msg);
|
|||
|
inflateEnd(&stream);
|
|||
|
return fail;
|
|||
|
}
|
|||
|
|
|||
|
while (res == Z_OK)
|
|||
|
{
|
|||
|
if (stream.avail_out == 0)
|
|||
|
{
|
|||
|
unzippedData->size += growthStep;
|
|||
|
unzippedData->memory = (char*)realloc(unzippedData->memory, unzippedData->size);
|
|||
|
|
|||
|
// Set the stream pointers to the potentially changed buffer!
|
|||
|
|
|||
|
stream.avail_out = resultSize - stream.total_out;
|
|||
|
stream.next_out = (Bytef*)(unzippedData + stream.total_out);
|
|||
|
}
|
|||
|
|
|||
|
res = inflate(&stream, Z_SYNC_FLUSH);
|
|||
|
resultSize = stream.total_out;
|
|||
|
}
|
|||
|
|
|||
|
if (res != Z_STREAM_END)
|
|||
|
{
|
|||
|
tellZipError(res, " during inflating", stream.msg);
|
|||
|
inflateEnd(&stream);
|
|||
|
return fail;
|
|||
|
}
|
|||
|
|
|||
|
unzippedData->size = resultSize;
|
|||
|
inflateEnd(&stream);
|
|||
|
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
//*************************************************************************
|
|||
|
// tellZipError
|
|||
|
//*************************************************************************
|
|||
|
|
|||
|
void tellZipError(int errorCode, const char* op, const char* msg)
|
|||
|
{
|
|||
|
if (!op) op = "";
|
|||
|
if (!msg) msg = "None";
|
|||
|
|
|||
|
switch (errorCode)
|
|||
|
{
|
|||
|
case Z_OK: return;
|
|||
|
case Z_STREAM_END: return;
|
|||
|
case Z_MEM_ERROR: tell(0, "Error: Not enough memory to unzip file%s!\n", op); return;
|
|||
|
case Z_BUF_ERROR: tell(0, "Error: Couldn't unzip data due to output buffer size problem%s!\n", op); return;
|
|||
|
case Z_DATA_ERROR: tell(0, "Error: Zipped input data corrupted%s! Details: %s\n", op, msg); return;
|
|||
|
case Z_STREAM_ERROR: tell(0, "Error: Invalid stream structure%s. Details: %s\n", op, msg); return;
|
|||
|
default: tell(0, "Error: Couldn't unzip data for unknown reason (%6d)%s!\n", errorCode, op); return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//*************************************************************************
|
|||
|
// Host Data
|
|||
|
//*************************************************************************
|
|||
|
|
|||
|
#include <sys/utsname.h>
|
|||
|
#include <netdb.h>
|
|||
|
#include <ifaddrs.h>
|
|||
|
|
|||
|
static struct utsname info;
|
|||
|
|
|||
|
const char* getHostName()
|
|||
|
{
|
|||
|
// get info from kernel
|
|||
|
|
|||
|
if (uname(&info) == -1)
|
|||
|
return "";
|
|||
|
|
|||
|
return info.nodename;
|
|||
|
}
|
|||
|
|
|||
|
const char* getFirstIp()
|
|||
|
{
|
|||
|
struct ifaddrs *ifaddr, *ifa;
|
|||
|
static char host[NI_MAXHOST] = "";
|
|||
|
|
|||
|
if (getifaddrs(&ifaddr) == -1)
|
|||
|
{
|
|||
|
tell(0, "getifaddrs() failed");
|
|||
|
return "";
|
|||
|
}
|
|||
|
|
|||
|
// walk through linked interface list
|
|||
|
|
|||
|
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next)
|
|||
|
{
|
|||
|
if (!ifa->ifa_addr)
|
|||
|
continue;
|
|||
|
|
|||
|
// For an AF_INET interfaces
|
|||
|
|
|||
|
if (ifa->ifa_addr->sa_family == AF_INET) // || ifa->ifa_addr->sa_family == AF_INET6)
|
|||
|
{
|
|||
|
int res = getnameinfo(ifa->ifa_addr,
|
|||
|
(ifa->ifa_addr->sa_family == AF_INET) ? sizeof(struct sockaddr_in) :
|
|||
|
sizeof(struct sockaddr_in6),
|
|||
|
host, NI_MAXHOST, 0, 0, NI_NUMERICHOST);
|
|||
|
|
|||
|
if (res)
|
|||
|
{
|
|||
|
tell(0, "getnameinfo() failed: %s", gai_strerror(res));
|
|||
|
return "";
|
|||
|
}
|
|||
|
|
|||
|
// skip loopback interface
|
|||
|
|
|||
|
if (strcmp(host, "127.0.0.1") == 0)
|
|||
|
continue;
|
|||
|
|
|||
|
tell(5, "%-8s %-15s %s", ifa->ifa_name, host,
|
|||
|
ifa->ifa_addr->sa_family == AF_INET ? " (AF_INET)" :
|
|||
|
ifa->ifa_addr->sa_family == AF_INET6 ? " (AF_INET6)" : "");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
freeifaddrs(ifaddr);
|
|||
|
|
|||
|
return host;
|
|||
|
}
|
|||
|
|
|||
|
#ifdef USELIBARCHIVE
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// unzip <file> and get data of first content which name matches <filter>
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
int unzip(const char* file, const char* filter, char*& buffer, int& size, char* entryName)
|
|||
|
{
|
|||
|
const int step = 1024*10;
|
|||
|
|
|||
|
int bufSize = 0;
|
|||
|
int r;
|
|||
|
int res;
|
|||
|
|
|||
|
struct archive_entry* entry;
|
|||
|
struct archive* a = archive_read_new();
|
|||
|
|
|||
|
*entryName = 0;
|
|||
|
buffer = 0;
|
|||
|
size = 0;
|
|||
|
|
|||
|
archive_read_support_filter_all(a);
|
|||
|
archive_read_support_format_all(a);
|
|||
|
|
|||
|
r = archive_read_open_filename(a, file, 10204);
|
|||
|
|
|||
|
if (r != ARCHIVE_OK)
|
|||
|
{
|
|||
|
tell(0, "Error: Open '%s' failed - %m", file);
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
while (archive_read_next_header(a, &entry) == ARCHIVE_OK)
|
|||
|
{
|
|||
|
strcpy(entryName, archive_entry_pathname(entry));
|
|||
|
|
|||
|
if (strstr(entryName, filter))
|
|||
|
{
|
|||
|
bufSize = step;
|
|||
|
buffer = (char*)malloc(bufSize+1);
|
|||
|
|
|||
|
while ((res = archive_read_data(a, buffer+size, step)) > 0)
|
|||
|
{
|
|||
|
size += res;
|
|||
|
bufSize += step;
|
|||
|
|
|||
|
buffer = (char*)realloc(buffer, bufSize+1);
|
|||
|
}
|
|||
|
|
|||
|
buffer[size] = 0;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
r = archive_read_free(a);
|
|||
|
|
|||
|
if (r != ARCHIVE_OK)
|
|||
|
{
|
|||
|
size = 0;
|
|||
|
free(buffer);
|
|||
|
return fail;
|
|||
|
}
|
|||
|
|
|||
|
return size > 0 ? success : fail;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Class LogDuration
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
#ifdef VDR_PLUGIN
|
|||
|
|
|||
|
# include <vdr/plugin.h>
|
|||
|
|
|||
|
LogDuration::LogDuration(const char* aMessage, int aLogLevel)
|
|||
|
{
|
|||
|
logLevel = aLogLevel;
|
|||
|
strcpy(message, aMessage);
|
|||
|
|
|||
|
// at last !
|
|||
|
|
|||
|
durationStart = cTimeMs::Now();
|
|||
|
}
|
|||
|
|
|||
|
LogDuration::~LogDuration()
|
|||
|
{
|
|||
|
tell(logLevel, "duration '%s' was (%dms)",
|
|||
|
message, cTimeMs::Now() - durationStart);
|
|||
|
}
|
|||
|
|
|||
|
void LogDuration::show(const char* label)
|
|||
|
{
|
|||
|
tell(logLevel, "elapsed '%s' at '%s' was (%dms)",
|
|||
|
message, label, cTimeMs::Now() - durationStart);
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Get Unique ID
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
#ifdef USEUUID
|
|||
|
const char* getUniqueId()
|
|||
|
{
|
|||
|
static char uuid[sizeUuid+TB] = "";
|
|||
|
|
|||
|
uuid_t id;
|
|||
|
uuid_generate(id);
|
|||
|
uuid_unparse_upper(id, uuid);
|
|||
|
|
|||
|
return uuid;
|
|||
|
}
|
|||
|
#endif // USEUUID
|
|||
|
|
|||
|
//***************************************************************************
|
|||
|
// Create MD5
|
|||
|
//***************************************************************************
|
|||
|
|
|||
|
#ifdef USEMD5
|
|||
|
|
|||
|
int createMd5(const char* buf, md5* md5)
|
|||
|
{
|
|||
|
MD5_CTX c;
|
|||
|
unsigned char out[MD5_DIGEST_LENGTH];
|
|||
|
|
|||
|
MD5_Init(&c);
|
|||
|
MD5_Update(&c, buf, strlen(buf));
|
|||
|
MD5_Final(out, &c);
|
|||
|
|
|||
|
for (int n = 0; n < MD5_DIGEST_LENGTH; n++)
|
|||
|
sprintf(md5+2*n, "%02x", out[n]);
|
|||
|
|
|||
|
md5[sizeMd5] = 0;
|
|||
|
|
|||
|
return done;
|
|||
|
}
|
|||
|
|
|||
|
int createMd5OfFile(const char* path, const char* name, md5* md5)
|
|||
|
{
|
|||
|
FILE* f;
|
|||
|
char buffer[1000];
|
|||
|
int nread = 0;
|
|||
|
MD5_CTX c;
|
|||
|
unsigned char out[MD5_DIGEST_LENGTH];
|
|||
|
char* file = 0;
|
|||
|
|
|||
|
asprintf(&file, "%s/%s", path, name);
|
|||
|
|
|||
|
if (!(f = fopen(file, "r")))
|
|||
|
{
|
|||
|
tell(0, "Fatal: Can't access '%s'; %m", file);
|
|||
|
free(file);
|
|||
|
return fail;
|
|||
|
}
|
|||
|
|
|||
|
free(file);
|
|||
|
|
|||
|
MD5_Init(&c);
|
|||
|
|
|||
|
while ((nread = fread(buffer, 1, 1000, f)) > 0)
|
|||
|
MD5_Update(&c, buffer, nread);
|
|||
|
|
|||
|
fclose(f);
|
|||
|
|
|||
|
MD5_Final(out, &c);
|
|||
|
|
|||
|
for (int n = 0; n < MD5_DIGEST_LENGTH; n++)
|
|||
|
sprintf(md5+2*n, "%02x", out[n]);
|
|||
|
|
|||
|
md5[sizeMd5] = 0;
|
|||
|
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
#endif // USEMD5
|